├── noVNC
├── .gitmodules
├── .eslintignore
├── snap
│ ├── hooks
│ │ └── configure
│ ├── local
│ │ └── svc_wrapper.sh
│ └── snapcraft.yaml
├── po
│ ├── .eslintrc
│ ├── Makefile
│ └── po2js
├── app
│ ├── sounds
│ │ ├── bell.mp3
│ │ ├── bell.oga
│ │ └── CREDITS
│ ├── locale
│ │ ├── README
│ │ ├── zh_TW.json
│ │ ├── zh_CN.json
│ │ ├── ko.json
│ │ ├── ja.json
│ │ ├── es.json
│ │ ├── tr.json
│ │ ├── pl.json
│ │ ├── cs.json
│ │ ├── de.json
│ │ ├── pt_BR.json
│ │ ├── it.json
│ │ ├── ru.json
│ │ ├── el.json
│ │ ├── nl.json
│ │ ├── fr.json
│ │ └── sv.json
│ ├── images
│ │ ├── icons
│ │ │ ├── novnc.ico
│ │ │ ├── novnc-ios-120.png
│ │ │ ├── novnc-ios-152.png
│ │ │ ├── novnc-ios-167.png
│ │ │ ├── novnc-ios-180.png
│ │ │ ├── novnc-ios-40.png
│ │ │ ├── novnc-ios-58.png
│ │ │ ├── novnc-ios-60.png
│ │ │ ├── novnc-ios-80.png
│ │ │ ├── novnc-ios-87.png
│ │ │ └── Makefile
│ │ ├── windows.svg
│ │ ├── handle.svg
│ │ ├── tab.svg
│ │ ├── expander.svg
│ │ ├── settings.svg
│ │ ├── error.svg
│ │ ├── fullscreen.svg
│ │ ├── info.svg
│ │ ├── ctrlaltdel.svg
│ │ ├── connect.svg
│ │ └── alt.svg
│ ├── styles
│ │ ├── Orbitron700.ttf
│ │ └── Orbitron700.woff
│ └── error-handler.js
├── docs
│ ├── rfbproto-3.3.pdf
│ ├── rfbproto-3.7.pdf
│ ├── rfbproto-3.8.pdf
│ ├── notes
│ ├── flash_policy.txt
│ ├── LIBRARY.md
│ ├── LICENSE.BSD-2-Clause
│ ├── novnc_proxy.1
│ ├── LICENSE.BSD-3-Clause
│ └── links
├── utils
│ ├── .eslintrc
│ ├── b64-to-binary.pl
│ ├── README.md
│ ├── validate
│ ├── u2x11
│ └── genkeysymdef.js
├── .gitignore
├── .github
│ ├── ISSUE_TEMPLATE
│ │ ├── config.yml
│ │ ├── feature_request.md
│ │ └── bug_report.md
│ └── workflows
│ │ ├── translate.yml
│ │ ├── lint.yml
│ │ ├── test.yml
│ │ └── deploy.yml
├── vendor
│ └── pako
│ │ ├── README.md
│ │ ├── lib
│ │ ├── zlib
│ │ │ ├── messages.js
│ │ │ ├── adler32.js
│ │ │ ├── crc32.js
│ │ │ ├── zstream.js
│ │ │ ├── gzheader.js
│ │ │ └── constants.js
│ │ └── utils
│ │ │ └── common.js
│ │ └── LICENSE
├── index.html
├── tests
│ ├── .eslintrc
│ ├── test.int.js
│ ├── vnc_playback.html
│ ├── test.base64.js
│ ├── test.localization.js
│ ├── fake.websocket.js
│ ├── test.deflator.js
│ ├── test.copyrect.js
│ ├── test.util.js
│ ├── test.inflator.js
│ ├── assertions.js
│ └── test.rre.js
├── core
│ ├── util
│ │ ├── int.js
│ │ ├── strings.js
│ │ ├── element.js
│ │ ├── eventtarget.js
│ │ └── logging.js
│ ├── decoders
│ │ ├── copyrect.js
│ │ ├── tightpng.js
│ │ ├── rre.js
│ │ └── raw.js
│ ├── encodings.js
│ ├── inflator.js
│ ├── deflator.js
│ └── input
│ │ └── vkeys.js
├── AUTHORS
├── LICENSE.txt
├── package.json
├── .eslintrc
└── karma.conf.js
├── tests
├── .DS_Store
├── screenshot.png
└── test_computer_use_server.py
├── .github
└── CODEOWNERS
├── .gitignore
├── computer_use_server
└── api_v2
│ ├── models.py
│ ├── logging_config.py
│ └── utils.py
├── iframe.html
├── desktop_files
├── firefox.desktop
└── 17344113245.desktop
├── start.sh
├── LICENSE
├── desktop-supervisord.conf
├── README.md
├── firefox-supervisord.conf
├── Dockerfile.desktop
└── Dockerfile.firefox
/noVNC/.gitmodules:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/noVNC/.eslintignore:
--------------------------------------------------------------------------------
1 | **/xtscancodes.js
2 |
--------------------------------------------------------------------------------
/noVNC/snap/hooks/configure:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 |
3 | snapctl restart novnc.novncsvc
4 |
--------------------------------------------------------------------------------
/noVNC/po/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | },
5 | }
6 |
--------------------------------------------------------------------------------
/tests/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/tests/.DS_Store
--------------------------------------------------------------------------------
/tests/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/tests/screenshot.png
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # All changes must be approved by either bayllama or the repository owner
2 | * @bayllama
--------------------------------------------------------------------------------
/noVNC/app/sounds/bell.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/sounds/bell.mp3
--------------------------------------------------------------------------------
/noVNC/app/sounds/bell.oga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/sounds/bell.oga
--------------------------------------------------------------------------------
/noVNC/docs/rfbproto-3.3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/docs/rfbproto-3.3.pdf
--------------------------------------------------------------------------------
/noVNC/docs/rfbproto-3.7.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/docs/rfbproto-3.7.pdf
--------------------------------------------------------------------------------
/noVNC/docs/rfbproto-3.8.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/docs/rfbproto-3.8.pdf
--------------------------------------------------------------------------------
/noVNC/app/locale/README:
--------------------------------------------------------------------------------
1 | DO NOT MODIFY THE FILES IN THIS FOLDER, THEY ARE AUTOMATICALLY GENERATED FROM THE PO-FILES.
2 |
--------------------------------------------------------------------------------
/noVNC/utils/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true
4 | },
5 | "rules": {
6 | "no-console": 0
7 | }
8 | }
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc.ico
--------------------------------------------------------------------------------
/noVNC/app/styles/Orbitron700.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/styles/Orbitron700.ttf
--------------------------------------------------------------------------------
/noVNC/app/styles/Orbitron700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/styles/Orbitron700.woff
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-120.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-152.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-167.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-180.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-40.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-58.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-60.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-80.png
--------------------------------------------------------------------------------
/noVNC/app/images/icons/novnc-ios-87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marinabox/marinabox-sandbox/HEAD/noVNC/app/images/icons/novnc-ios-87.png
--------------------------------------------------------------------------------
/noVNC/docs/notes:
--------------------------------------------------------------------------------
1 | Rebuilding inflator.js
2 |
3 | - Download pako from npm
4 | - Install browserify using npm
5 | - browserify core/inflator.mod.js -o core/inflator.js -s Inflator
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.o
3 | tests/data_*.js
4 | utils/rebind.so
5 | utils/websockify
6 | /node_modules
7 | /build
8 | /lib
9 | recordings
10 | *.swp
11 | *~
12 | noVNC-*.tgz
13 |
--------------------------------------------------------------------------------
/noVNC/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.o
3 | tests/data_*.js
4 | utils/rebind.so
5 | utils/websockify
6 | /node_modules
7 | /build
8 | /lib
9 | recordings
10 | *.swp
11 | *~
12 | noVNC-*.tgz
13 |
--------------------------------------------------------------------------------
/noVNC/app/sounds/CREDITS:
--------------------------------------------------------------------------------
1 | bell
2 | Copyright: Dr. Richard Boulanger et al
3 | URL: http://www.archive.org/details/Berklee44v12
4 | License: CC-BY Attribution 3.0 Unported
5 |
--------------------------------------------------------------------------------
/computer_use_server/api_v2/models.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel
2 |
3 |
4 | class Coordinates(BaseModel):
5 | x: int
6 | y: int
7 |
8 |
9 | class TextInput(BaseModel):
10 | text: str
11 |
12 |
--------------------------------------------------------------------------------
/noVNC/docs/flash_policy.txt:
--------------------------------------------------------------------------------
1 | Manual setup:
2 |
3 | DATA="echo \'\'"
4 | /usr/bin/socat -T 1 TCP-L:843,reuseaddr,fork,crlf SYSTEM:"$DATA"
5 |
--------------------------------------------------------------------------------
/noVNC/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Question or discussion
4 | url: https://groups.google.com/forum/?fromgroups#!forum/novnc
5 | about: Ask a question or start a discussion
6 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/README.md:
--------------------------------------------------------------------------------
1 | This is an ES6-modules-compatible version of
2 | https://github.com/nodeca/pako, based on pako version 1.0.3.
3 |
4 | It's more-or-less a direct translation of the original, with unused parts
5 | removed, and the dynamic support for non-typed arrays removed (since ES6
6 | modules don't work well with dynamic exports).
7 |
--------------------------------------------------------------------------------
/noVNC/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MarinaBox
5 |
9 |
10 |
11 | Connecting...
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/noVNC/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | "mocha": true
5 | },
6 | "globals": {
7 | "chai": false,
8 | "sinon": false
9 | },
10 | "rules": {
11 | "prefer-arrow-callback": 0,
12 | // Too many anonymous callbacks
13 | "func-names": "off",
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/noVNC/core/util/int.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2020 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | export function toUnsigned32bit(toConvert) {
10 | return toConvert >>> 0;
11 | }
12 |
13 | export function toSigned32bit(toConvert) {
14 | return toConvert | 0;
15 | }
16 |
--------------------------------------------------------------------------------
/noVNC/AUTHORS:
--------------------------------------------------------------------------------
1 | maintainers:
2 | - Samuel Mannehed for Cendio AB (@samhed)
3 | - Pierre Ossman for Cendio AB (@CendioOssman)
4 | maintainersEmeritus:
5 | - Joel Martin (@kanaka)
6 | - Solly Ross (@directxman12)
7 | - @astrand
8 | contributors:
9 | # There are a bunch of people that should be here.
10 | # If you want to be on this list, feel free send a PR
11 | # to add yourself.
12 | - jalf
13 | - NTT corp.
14 |
--------------------------------------------------------------------------------
/noVNC/.github/workflows/translate.yml:
--------------------------------------------------------------------------------
1 | name: Translate
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | translate:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v3
10 | - uses: actions/setup-node@v3
11 | - run: npm update
12 | - run: sudo apt-get install gettext
13 | - run: make -C po update-pot
14 | - run: make -C po update-po
15 | - run: make -C po update-js
16 |
--------------------------------------------------------------------------------
/noVNC/utils/b64-to-binary.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl
2 | use MIME::Base64;
3 |
4 | for (<>) {
5 | unless (/^'([{}])(\d+)\1(.+?)',$/) {
6 | print;
7 | next;
8 | }
9 |
10 | my ($dir, $amt, $b64) = ($1, $2, $3);
11 |
12 | my $decoded = MIME::Base64::decode($b64) or die "Could not base64-decode line `$_`";
13 |
14 | my $decoded_escaped = join "", map { "\\x$_" } unpack("(H2)*", $decoded);
15 |
16 | print "'${dir}${amt}${dir}${decoded_escaped}',\n";
17 | }
18 |
--------------------------------------------------------------------------------
/noVNC/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | eslint:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v3
10 | - uses: actions/setup-node@v3
11 | - run: npm update
12 | - run: npm run lint
13 | html:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v3
17 | - uses: actions/setup-node@v3
18 | - run: npm update
19 | - run: git ls-tree --name-only -r HEAD | grep -E "[.](html|css)$" | xargs ./utils/validate
20 |
--------------------------------------------------------------------------------
/noVNC/tests/test.int.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const expect = chai.expect;
3 |
4 | import { toUnsigned32bit, toSigned32bit } from '../core/util/int.js';
5 |
6 | describe('Integer casting', function () {
7 | it('should cast unsigned to signed', function () {
8 | let expected = 4294967286;
9 | expect(toUnsigned32bit(-10)).to.equal(expected);
10 | });
11 |
12 | it('should cast signed to unsigned', function () {
13 | let expected = -10;
14 | expect(toSigned32bit(4294967286)).to.equal(expected);
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/noVNC/utils/README.md:
--------------------------------------------------------------------------------
1 | ## WebSockets Proxy/Bridge
2 |
3 | Websockify has been forked out into its own project. `novnc_proxy` will
4 | automatically download it here if it is not already present and not
5 | installed as system-wide.
6 |
7 | For more detailed description and usage information please refer to
8 | the [websockify README](https://github.com/novnc/websockify/blob/master/README.md).
9 |
10 | The other versions of websockify (C, Node.js) and the associated test
11 | programs have been moved to
12 | [websockify](https://github.com/novnc/websockify). Websockify was
13 | formerly named wsproxy.
14 |
15 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/lib/zlib/messages.js:
--------------------------------------------------------------------------------
1 | export default {
2 | 2: 'need dictionary', /* Z_NEED_DICT 2 */
3 | 1: 'stream end', /* Z_STREAM_END 1 */
4 | 0: '', /* Z_OK 0 */
5 | '-1': 'file error', /* Z_ERRNO (-1) */
6 | '-2': 'stream error', /* Z_STREAM_ERROR (-2) */
7 | '-3': 'data error', /* Z_DATA_ERROR (-3) */
8 | '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */
9 | '-5': 'buffer error', /* Z_BUF_ERROR (-5) */
10 | '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */
11 | };
12 |
--------------------------------------------------------------------------------
/iframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | iframe Example
5 |
17 |
18 |
19 |
24 |
25 |
--------------------------------------------------------------------------------
/noVNC/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/noVNC/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | test:
7 | strategy:
8 | matrix:
9 | os:
10 | - ubuntu-latest
11 | - windows-latest
12 | browser:
13 | - ChromeHeadless
14 | - FirefoxHeadless
15 | include:
16 | - os: macos-latest
17 | browser: Safari
18 | - os: windows-latest
19 | browser: EdgeHeadless
20 | fail-fast: false
21 | runs-on: ${{ matrix.os }}
22 | steps:
23 | - uses: actions/checkout@v3
24 | - uses: actions/setup-node@v3
25 | - run: npm update
26 | - run: npm run test
27 | env:
28 | TEST_BROWSER_NAME: ${{ matrix.browser }}
29 |
--------------------------------------------------------------------------------
/noVNC/core/decoders/copyrect.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | *
8 | */
9 |
10 | export default class CopyRectDecoder {
11 | decodeRect(x, y, width, height, sock, display, depth) {
12 | if (sock.rQwait("COPYRECT", 4)) {
13 | return false;
14 | }
15 |
16 | let deltaX = sock.rQshift16();
17 | let deltaY = sock.rQshift16();
18 |
19 | if ((width === 0) || (height === 0)) {
20 | return true;
21 | }
22 |
23 | display.copyImage(deltaX, deltaY, x, y, width, height);
24 |
25 | return true;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/computer_use_server/api_v2/logging_config.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import logging.config
3 | import os
4 |
5 | def setup_logging() -> None:
6 | level = os.getenv("LOG_LEVEL", "INFO").upper()
7 | config = {
8 | "version": 1,
9 | "disable_existing_loggers": False,
10 | "formatters": {
11 | "standard": {"format": "%(asctime)s %(levelname)s %(name)s - %(message)s"},
12 | },
13 | "handlers": {
14 | "default": {
15 | "class": "logging.StreamHandler",
16 | "level": level,
17 | "formatter": "standard",
18 | "stream": "ext://sys.stdout",
19 | },
20 | },
21 | "root": {"handlers": ["default"], "level": level},
22 | }
23 | logging.config.dictConfig(config)
--------------------------------------------------------------------------------
/noVNC/tests/vnc_playback.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | VNC Playback
5 |
6 |
7 |
8 |
9 | Iterations:
10 | Perftest:
11 | Realtime:
12 |
13 |
14 |
15 |
16 |
17 | Results:
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/lib/zlib/adler32.js:
--------------------------------------------------------------------------------
1 | // Note: adler32 takes 12% for level 0 and 2% for level 6.
2 | // It doesn't worth to make additional optimizationa as in original.
3 | // Small size is preferable.
4 |
5 | export default function adler32(adler, buf, len, pos) {
6 | var s1 = (adler & 0xffff) |0,
7 | s2 = ((adler >>> 16) & 0xffff) |0,
8 | n = 0;
9 |
10 | while (len !== 0) {
11 | // Set limit ~ twice less than 5552, to keep
12 | // s2 in 31-bits, because we force signed ints.
13 | // in other case %= will fail.
14 | n = len > 2000 ? 2000 : len;
15 | len -= n;
16 |
17 | do {
18 | s1 = (s1 + buf[pos++]) |0;
19 | s2 = (s2 + s1) |0;
20 | } while (--n);
21 |
22 | s1 %= 65521;
23 | s2 %= 65521;
24 | }
25 |
26 | return (s1 | (s2 << 16)) |0;
27 | }
28 |
--------------------------------------------------------------------------------
/noVNC/core/decoders/tightpng.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | *
8 | */
9 |
10 | import TightDecoder from './tight.js';
11 |
12 | export default class TightPNGDecoder extends TightDecoder {
13 | _pngRect(x, y, width, height, sock, display, depth) {
14 | let data = this._readData(sock);
15 | if (data === null) {
16 | return false;
17 | }
18 |
19 | display.imageRect(x, y, width, height, "image/png", data);
20 |
21 | return true;
22 | }
23 |
24 | _basicRect(ctl, x, y, width, height, sock, display, depth) {
25 | throw new Error("BasicCompression received in TightPNG rect");
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/noVNC/utils/validate:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | RET=0
6 |
7 | OUT=`mktemp`
8 |
9 | for fn in "$@"; do
10 | echo "Validating $fn..."
11 | echo
12 |
13 | case $fn in
14 | *.html)
15 | type="text/html"
16 | ;;
17 | *.css)
18 | type="text/css"
19 | ;;
20 | *)
21 | echo "Unknown format!"
22 | echo
23 | RET=1
24 | continue
25 | ;;
26 | esac
27 |
28 | curl --silent \
29 | --header "Content-Type: ${type}; charset=utf-8" \
30 | --data-binary @${fn} \
31 | https://validator.w3.org/nu/?out=text > $OUT
32 | cat $OUT
33 | echo
34 |
35 | # We don't fail the check for warnings as some warnings are
36 | # not relevant for us, and we don't currently have a way to
37 | # ignore just those
38 | if grep -q -s -E "^Error:" $OUT; then
39 | RET=1
40 | fi
41 | done
42 |
43 | rm $OUT
44 |
45 | exit $RET
46 |
--------------------------------------------------------------------------------
/noVNC/core/util/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | // Decode from UTF-8
10 | export function decodeUTF8(utf8string, allowLatin1=false) {
11 | try {
12 | return decodeURIComponent(escape(utf8string));
13 | } catch (e) {
14 | if (e instanceof URIError) {
15 | if (allowLatin1) {
16 | // If we allow Latin1 we can ignore any decoding fails
17 | // and in these cases return the original string
18 | return utf8string;
19 | }
20 | }
21 | throw e;
22 | }
23 | }
24 |
25 | // Encode to UTF-8
26 | export function encodeUTF8(DOMString) {
27 | return unescape(encodeURIComponent(DOMString));
28 | }
29 |
--------------------------------------------------------------------------------
/noVNC/core/util/element.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2020 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | /*
10 | * HTML element utility functions
11 | */
12 |
13 | export function clientToElement(x, y, elem) {
14 | const bounds = elem.getBoundingClientRect();
15 | let pos = { x: 0, y: 0 };
16 | // Clip to target bounds
17 | if (x < bounds.left) {
18 | pos.x = 0;
19 | } else if (x >= bounds.right) {
20 | pos.x = bounds.width - 1;
21 | } else {
22 | pos.x = x - bounds.left;
23 | }
24 | if (y < bounds.top) {
25 | pos.y = 0;
26 | } else if (y >= bounds.bottom) {
27 | pos.y = bounds.height - 1;
28 | } else {
29 | pos.y = y - bounds.top;
30 | }
31 | return pos;
32 | }
33 |
--------------------------------------------------------------------------------
/desktop_files/firefox.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Version=1.0
3 | Name=Firefox
4 | GenericName=Web Browser
5 | Comment=Browse the World Wide Web
6 | Exec=/usr/bin/firefox --no-remote --new-instance
7 | StartupNotify=true
8 | Terminal=false
9 | Icon=firefox
10 | Type=Application
11 | Categories=Network;WebBrowser;
12 | MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;application/x-xpinstall;
13 | Actions=new-window;new-private-window;
14 | X-XFCE-Source=file:///usr/share/applications/firefox.desktop
15 |
16 | [Desktop Action new-window]
17 | Name=Open a New Window
18 | Exec=/usr/bin/firefox --no-remote --new-instance --new-window
19 |
20 | [Desktop Action new-private-window]
21 | Name=Open a New Private Window
22 | Exec=/usr/bin/firefox --no-remote --new-instance --private-window
23 |
24 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/lib/zlib/crc32.js:
--------------------------------------------------------------------------------
1 | // Note: we can't get significant speed boost here.
2 | // So write code to minimize size - no pregenerated tables
3 | // and array tools dependencies.
4 |
5 |
6 | // Use ordinary array, since untyped makes no boost here
7 | export default function makeTable() {
8 | var c, table = [];
9 |
10 | for (var n = 0; n < 256; n++) {
11 | c = n;
12 | for (var k = 0; k < 8; k++) {
13 | c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
14 | }
15 | table[n] = c;
16 | }
17 |
18 | return table;
19 | }
20 |
21 | // Create table on load. Just 255 signed longs. Not a problem.
22 | var crcTable = makeTable();
23 |
24 |
25 | function crc32(crc, buf, len, pos) {
26 | var t = crcTable,
27 | end = pos + len;
28 |
29 | crc ^= -1;
30 |
31 | for (var i = pos; i < end; i++) {
32 | crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
33 | }
34 |
35 | return (crc ^ (-1)); // >>> 0;
36 | }
37 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/lib/zlib/zstream.js:
--------------------------------------------------------------------------------
1 | export default function ZStream() {
2 | /* next input byte */
3 | this.input = null; // JS specific, because we have no pointers
4 | this.next_in = 0;
5 | /* number of bytes available at input */
6 | this.avail_in = 0;
7 | /* total number of input bytes read so far */
8 | this.total_in = 0;
9 | /* next output byte should be put there */
10 | this.output = null; // JS specific, because we have no pointers
11 | this.next_out = 0;
12 | /* remaining free space at output */
13 | this.avail_out = 0;
14 | /* total number of bytes output so far */
15 | this.total_out = 0;
16 | /* last error message, NULL if no error */
17 | this.msg = ''/*Z_NULL*/;
18 | /* not visible by applications */
19 | this.state = null;
20 | /* best guess about the data type: binary or text */
21 | this.data_type = 2/*Z_UNKNOWN*/;
22 | /* adler32 value of the uncompressed data */
23 | this.adler = 0;
24 | }
25 |
--------------------------------------------------------------------------------
/noVNC/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Client (please complete the following information):**
24 | - OS: [e.g. iOS]
25 | - Browser: [e.g. chrome, safari]
26 | - Browser version: [e.g. 22]
27 |
28 | **Server (please complete the following information):**
29 | - noVNC version: [e.g. 1.0.0 or git commit id]
30 | - VNC server: [e.g. QEMU, TigerVNC]
31 | - WebSocket proxy: [e.g. websockify]
32 |
33 | **Additional context**
34 | Add any other context about the problem here.
35 |
--------------------------------------------------------------------------------
/computer_use_server/api_v2/utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 |
4 | logger = logging.getLogger(__name__)
5 |
6 | def get_video_size_from_env() -> str:
7 | """
8 | Derive WIDTHxHEIGHT from RESOLUTION env var.
9 | Accepts formats like:
10 | - 1920x1080x24 -> uses 1920x1080
11 | - 1280x800 -> uses 1280x800
12 | Falls back to 1280x800 if parsing fails.
13 | """
14 | logger.debug(f"Getting resolution from env")
15 | resolution = os.getenv("RESOLUTION", "")
16 | logger.debug(f"Resolution: {resolution}")
17 | try:
18 | if resolution:
19 | parts = resolution.split("x")
20 | if len(parts) >= 2 and parts[0].isdigit() and parts[1].isdigit():
21 | width = parts[0]
22 | height = parts[1]
23 | return f"{width}x{height}"
24 | except Exception:
25 | logger.debug(f"Error getting resolution from env")
26 | raise Exception(f"Error getting resolution from env")
27 | return "1280x800"
28 |
29 |
30 |
--------------------------------------------------------------------------------
/noVNC/utils/u2x11:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Convert "U+..." commented entries in /usr/include/X11/keysymdef.h
4 | # into JavaScript for use by noVNC. Note this is likely to produce
5 | # a few duplicate properties with clashing values, that will need
6 | # resolving manually.
7 | #
8 | # Colin Dean
9 | #
10 |
11 | regex="^#define[ \t]+XK_[A-Za-z0-9_]+[ \t]+0x([0-9a-fA-F]+)[ \t]+\/\*[ \t]+U\+([0-9a-fA-F]+)[ \t]+[^*]+.[ \t]+\*\/[ \t]*$"
12 | echo "unicodeTable = {"
13 | while read line; do
14 | if echo "${line}" | egrep -qs "${regex}"; then
15 |
16 | x11=$(echo "${line}" | sed -r "s/${regex}/\1/")
17 | vnc=$(echo "${line}" | sed -r "s/${regex}/\2/")
18 |
19 | if echo "${vnc}" | egrep -qs "^00[2-9A-F][0-9A-F]$"; then
20 | : # skip ISO Latin-1 (U+0020 to U+00FF) as 1-to-1 mapping
21 | else
22 | # note 1-to-1 is possible (e.g. for Euro symbol, U+20AC)
23 | echo " 0x${vnc} : 0x${x11},"
24 | fi
25 | fi
26 | done < /usr/include/X11/keysymdef.h | uniq
27 | echo "};"
28 |
29 |
--------------------------------------------------------------------------------
/noVNC/core/util/eventtarget.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | export default class EventTargetMixin {
10 | constructor() {
11 | this._listeners = new Map();
12 | }
13 |
14 | addEventListener(type, callback) {
15 | if (!this._listeners.has(type)) {
16 | this._listeners.set(type, new Set());
17 | }
18 | this._listeners.get(type).add(callback);
19 | }
20 |
21 | removeEventListener(type, callback) {
22 | if (this._listeners.has(type)) {
23 | this._listeners.get(type).delete(callback);
24 | }
25 | }
26 |
27 | dispatchEvent(event) {
28 | if (!this._listeners.has(event.type)) {
29 | return true;
30 | }
31 | this._listeners.get(event.type)
32 | .forEach(callback => callback.call(this, event));
33 | return !event.defaultPrevented;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Set default resolution if not provided
4 | RESOLUTION=${RESOLUTION:-1920x1080x24}
5 |
6 | # Extract width, height and depth from resolution
7 | WIDTH=$(echo $RESOLUTION | cut -d'x' -f1)
8 | HEIGHT=$(echo $RESOLUTION | cut -d'x' -f2)
9 | DEPTH=$(echo $RESOLUTION | cut -d'x' -f3)
10 |
11 | # Create ffmpeg resolution (without depth)
12 | FFMPEG_RESOLUTION="${WIDTH}x${HEIGHT}"
13 |
14 | # Replace placeholders in supervisord config
15 | sed -i "s|RESOLUTION_PLACEHOLDER|$RESOLUTION|g" /etc/supervisor.d/supervisord.ini
16 | sed -i "s|FFMPEG_PLACEHOLDER|$FFMPEG_RESOLUTION|g" /etc/supervisor.d/supervisord.ini
17 | sed -i "s|WIDTH_PLACEHOLDER|$WIDTH|g" /etc/supervisor.d/supervisord.ini
18 | sed -i "s|HEIGHT_PLACEHOLDER|$HEIGHT|g" /etc/supervisor.d/supervisord.ini
19 |
20 | # Ensure XFCE default browser points to Firefox to avoid 'default web browser' I/O errors
21 | mkdir -p /root/.config/xfce4
22 | printf "[Helpers]\nWebBrowser=firefox\n" > /root/.config/xfce4/helpers.rc
23 |
24 | # Start supervisord
25 | exec /usr/bin/supervisord -n -c /etc/supervisor.d/supervisord.ini
--------------------------------------------------------------------------------
/desktop_files/17344113245.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Version=1.0
3 | Name=Chromium
4 | GenericName=Web Browser
5 | Comment=Access the Internet
6 | Exec=/usr/bin/chromium-browser --no-sandbox --password-store=basic --test-type --remote-allow-origins=* --ignore-certificate-errors --disable-web-security --disable-dev-shm-usage
7 | StartupNotify=true
8 | Terminal=false
9 | Icon=chromium
10 | Type=Application
11 | Categories=Network;WebBrowser;
12 | MimeType=application/pdf;application/rdf+xml;application/rss+xml;application/xhtml+xml;application/xhtml_xml;application/xml;image/gif;image/jpeg;image/png;image/webp;text/html;text/xml;x-scheme-handler/http;x-scheme-handler/https;
13 | Actions=new-window;new-private-window;
14 | X-XFCE-Source=file:///usr/share/applications/chromium.desktop
15 |
16 | [Desktop Action new-window]
17 | Name=New Window
18 | Exec=/usr/bin/chromium-browser --no-sandbox --disable-web-security --disable-dev-shm-usage
19 |
20 | [Desktop Action new-private-window]
21 | Name=New Incognito Window
22 | Exec=/usr/bin/chromium-browser --no-sandbox --disable-web-security --disable-dev-shm-usage
--------------------------------------------------------------------------------
/noVNC/po/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | .PHONY: update-po update-js update-pot
3 | .PHONY: FORCE
4 |
5 | LINGUAS := cs de el es fr it ja ko nl pl pt_BR ru sv tr zh_CN zh_TW
6 |
7 | VERSION := $(shell grep '"version"' ../package.json | cut -d '"' -f 4)
8 |
9 | POFILES := $(addsuffix .po,$(LINGUAS))
10 | JSONFILES := $(addprefix ../app/locale/,$(addsuffix .json,$(LINGUAS)))
11 |
12 | update-po: $(POFILES)
13 | update-js: $(JSONFILES)
14 |
15 | %.po: FORCE
16 | msgmerge --update --lang=$* $@ noVNC.pot
17 | ../app/locale/%.json: FORCE
18 | ./po2js $*.po $@
19 |
20 | update-pot:
21 | xgettext --output=noVNC.js.pot \
22 | --copyright-holder="The noVNC Authors" \
23 | --package-name="noVNC" \
24 | --package-version="$(VERSION)" \
25 | --msgid-bugs-address="novnc@googlegroups.com" \
26 | --add-comments=TRANSLATORS: \
27 | --from-code=UTF-8 \
28 | --sort-by-file \
29 | ../app/*.js \
30 | ../core/*.js \
31 | ../core/input/*.js
32 | ./xgettext-html --output=noVNC.html.pot \
33 | ../vnc.html
34 | msgcat --output-file=noVNC.pot \
35 | --sort-by-file noVNC.js.pot noVNC.html.pot
36 | rm -f noVNC.js.pot noVNC.html.pot
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 MarinaBox
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/noVNC/vendor/pako/LICENSE:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (C) 2014-2016 by Vitaly Puzrin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/noVNC/docs/LIBRARY.md:
--------------------------------------------------------------------------------
1 | # Using the noVNC JavaScript library
2 |
3 | This document describes how to make use of the noVNC JavaScript library for
4 | integration in your own VNC client application. If you wish to embed the more
5 | complete noVNC application with its included user interface then please see
6 | our [embedding documentation](EMBEDDING.md).
7 |
8 | ## API
9 |
10 | The API of noVNC consists of a single object called `RFB`. The formal
11 | documentation for that object can be found in our [API documentation](API.md).
12 |
13 | ## Example
14 |
15 | noVNC includes a small example application called `vnc_lite.html`. This does
16 | not make use of all the features of noVNC, but is a good start to see how to
17 | do things.
18 |
19 | ## Conversion of Modules
20 |
21 | noVNC is written using ECMAScript 6 modules. This is not supported by older
22 | versions of Node.js. To use noVNC with those older versions of Node.js the
23 | library must first be converted.
24 |
25 | Fortunately noVNC includes a script to handle this conversion. Please follow
26 | the following steps:
27 |
28 | 1. Install Node.js
29 | 2. Run `npm install` in the noVNC directory
30 |
31 | The result of the conversion is available in the `lib/` directory.
32 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/lib/utils/common.js:
--------------------------------------------------------------------------------
1 | // reduce buffer size, avoiding mem copy
2 | export function shrinkBuf (buf, size) {
3 | if (buf.length === size) { return buf; }
4 | if (buf.subarray) { return buf.subarray(0, size); }
5 | buf.length = size;
6 | return buf;
7 | };
8 |
9 |
10 | export function arraySet (dest, src, src_offs, len, dest_offs) {
11 | if (src.subarray && dest.subarray) {
12 | dest.set(src.subarray(src_offs, src_offs + len), dest_offs);
13 | return;
14 | }
15 | // Fallback to ordinary array
16 | for (var i = 0; i < len; i++) {
17 | dest[dest_offs + i] = src[src_offs + i];
18 | }
19 | }
20 |
21 | // Join array of chunks to single array.
22 | export function flattenChunks (chunks) {
23 | var i, l, len, pos, chunk, result;
24 |
25 | // calculate data length
26 | len = 0;
27 | for (i = 0, l = chunks.length; i < l; i++) {
28 | len += chunks[i].length;
29 | }
30 |
31 | // join chunks
32 | result = new Uint8Array(len);
33 | pos = 0;
34 | for (i = 0, l = chunks.length; i < l; i++) {
35 | chunk = chunks[i];
36 | result.set(chunk, pos);
37 | pos += chunk.length;
38 | }
39 |
40 | return result;
41 | }
42 |
43 | export var Buf8 = Uint8Array;
44 | export var Buf16 = Uint16Array;
45 | export var Buf32 = Int32Array;
46 |
--------------------------------------------------------------------------------
/noVNC/core/decoders/rre.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | *
8 | */
9 |
10 | export default class RREDecoder {
11 | constructor() {
12 | this._subrects = 0;
13 | }
14 |
15 | decodeRect(x, y, width, height, sock, display, depth) {
16 | if (this._subrects === 0) {
17 | if (sock.rQwait("RRE", 4 + 4)) {
18 | return false;
19 | }
20 |
21 | this._subrects = sock.rQshift32();
22 |
23 | let color = sock.rQshiftBytes(4); // Background
24 | display.fillRect(x, y, width, height, color);
25 | }
26 |
27 | while (this._subrects > 0) {
28 | if (sock.rQwait("RRE", 4 + 8)) {
29 | return false;
30 | }
31 |
32 | let color = sock.rQshiftBytes(4);
33 | let sx = sock.rQshift16();
34 | let sy = sock.rQshift16();
35 | let swidth = sock.rQshift16();
36 | let sheight = sock.rQshift16();
37 | display.fillRect(x + sx, y + sy, swidth, sheight, color);
38 |
39 | this._subrects--;
40 | }
41 |
42 | return true;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/noVNC/snap/local/svc_wrapper.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # `snapctl get services` returns a JSON array, example:
4 | #{
5 | #"n6801": {
6 | # "listen": 6801,
7 | # "vnc": "localhost:5901"
8 | #},
9 | #"n6802": {
10 | # "listen": 6802,
11 | # "vnc": "localhost:5902"
12 | #}
13 | #}
14 | snapctl get services | jq -c '.[]' | while read service; do # for each service the user sepcified..
15 | # get the important data for the service (listen port, VNC host:port)
16 | listen_port="$(echo $service | jq --raw-output '.listen')"
17 | vnc_host_port="$(echo $service | jq --raw-output '.vnc')" # --raw-output removes any quotation marks from the output
18 |
19 | # check whether those values are valid
20 | expr "$listen_port" : '^[0-9]\+$' > /dev/null
21 | listen_port_valid=$?
22 | if [ ! $listen_port_valid ] || [ -z "$vnc_host_port" ]; then
23 | # invalid values mean the service is disabled, do nothing except for printing a message (logged in /var/log/system or systemd journal)
24 | echo "novnc: not starting service ${service} with listen_port ${listen_port} and vnc_host_port ${vnc_host_port}"
25 | else
26 | # start (and fork with '&') the service using the specified listen port and VNC host:port
27 | $SNAP/novnc_proxy --listen $listen_port --vnc $vnc_host_port &
28 | fi
29 | done
30 |
--------------------------------------------------------------------------------
/noVNC/docs/LICENSE.BSD-2-Clause:
--------------------------------------------------------------------------------
1 | Copyright (c) ,
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
--------------------------------------------------------------------------------
/noVNC/tests/test.base64.js:
--------------------------------------------------------------------------------
1 | const expect = chai.expect;
2 |
3 | import Base64 from '../core/base64.js';
4 |
5 | describe('Base64 Tools', function () {
6 | "use strict";
7 |
8 | const BIN_ARR = new Array(256);
9 | for (let i = 0; i < 256; i++) {
10 | BIN_ARR[i] = i;
11 | }
12 |
13 | const B64_STR = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==";
14 |
15 |
16 | describe('encode', function () {
17 | it('should encode a binary string into Base64', function () {
18 | const encoded = Base64.encode(BIN_ARR);
19 | expect(encoded).to.equal(B64_STR);
20 | });
21 | });
22 |
23 | describe('decode', function () {
24 | it('should decode a Base64 string into a normal string', function () {
25 | const decoded = Base64.decode(B64_STR);
26 | expect(decoded).to.deep.equal(BIN_ARR);
27 | });
28 |
29 | it('should throw an error if we have extra characters at the end of the string', function () {
30 | expect(() => Base64.decode(B64_STR+'abcdef')).to.throw(Error);
31 | });
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/lib/zlib/gzheader.js:
--------------------------------------------------------------------------------
1 | export default function GZheader() {
2 | /* true if compressed data believed to be text */
3 | this.text = 0;
4 | /* modification time */
5 | this.time = 0;
6 | /* extra flags (not used when writing a gzip file) */
7 | this.xflags = 0;
8 | /* operating system */
9 | this.os = 0;
10 | /* pointer to extra field or Z_NULL if none */
11 | this.extra = null;
12 | /* extra field length (valid if extra != Z_NULL) */
13 | this.extra_len = 0; // Actually, we don't need it in JS,
14 | // but leave for few code modifications
15 |
16 | //
17 | // Setup limits is not necessary because in js we should not preallocate memory
18 | // for inflate use constant limit in 65536 bytes
19 | //
20 |
21 | /* space at extra (only when reading header) */
22 | // this.extra_max = 0;
23 | /* pointer to zero-terminated file name or Z_NULL */
24 | this.name = '';
25 | /* space at name (only when reading header) */
26 | // this.name_max = 0;
27 | /* pointer to zero-terminated comment or Z_NULL */
28 | this.comment = '';
29 | /* space at comment (only when reading header) */
30 | // this.comm_max = 0;
31 | /* true if there was or will be a header crc */
32 | this.hcrc = 0;
33 | /* true when done reading gzip header (not used when writing a gzip file) */
34 | this.done = false;
35 | }
36 |
--------------------------------------------------------------------------------
/noVNC/app/images/icons/Makefile:
--------------------------------------------------------------------------------
1 | BROWSER_SIZES := 16 24 32 48 64
2 | #ANDROID_SIZES := 72 96 144 192
3 | # FIXME: The ICO is limited to 8 icons due to a Chrome bug:
4 | # https://bugs.chromium.org/p/chromium/issues/detail?id=1381393
5 | ANDROID_SIZES := 96 144 192
6 | WEB_ICON_SIZES := $(BROWSER_SIZES) $(ANDROID_SIZES)
7 |
8 | #IOS_1X_SIZES := 20 29 40 76 # No such devices exist anymore
9 | IOS_2X_SIZES := 40 58 80 120 152 167
10 | IOS_3X_SIZES := 60 87 120 180
11 | ALL_IOS_SIZES := $(IOS_1X_SIZES) $(IOS_2X_SIZES) $(IOS_3X_SIZES)
12 |
13 | ALL_ICONS := \
14 | $(ALL_IOS_SIZES:%=novnc-ios-%.png) \
15 | novnc.ico
16 |
17 | all: $(ALL_ICONS)
18 |
19 | # Our testing shows that the ICO file need to be sorted in largest to
20 | # smallest to get the apporpriate behviour
21 | WEB_ICON_SIZES_REVERSE := $(shell echo $(WEB_ICON_SIZES) | tr ' ' '\n' | sort -nr | tr '\n' ' ')
22 | WEB_BASE_ICONS := $(WEB_ICON_SIZES_REVERSE:%=novnc-%.png)
23 | .INTERMEDIATE: $(WEB_BASE_ICONS)
24 |
25 | novnc.ico: $(WEB_BASE_ICONS)
26 | convert $(WEB_BASE_ICONS) "$@"
27 |
28 | # General conversion
29 | novnc-%.png: novnc-icon.svg
30 | convert -depth 8 -background transparent \
31 | -size $*x$* "$(lastword $^)" "$@"
32 |
33 | # iOS icons use their own SVG
34 | novnc-ios-%.png: novnc-ios-icon.svg
35 | convert -depth 8 -background transparent \
36 | -size $*x$* "$(lastword $^)" "$@"
37 |
38 | # The smallest sizes are generated using a different SVG
39 | novnc-16.png novnc-24.png novnc-32.png: novnc-icon-sm.svg
40 |
41 | clean:
42 | rm -f *.png
43 |
--------------------------------------------------------------------------------
/noVNC/vendor/pako/lib/zlib/constants.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | /* Allowed flush values; see deflate() and inflate() below for details */
4 | Z_NO_FLUSH: 0,
5 | Z_PARTIAL_FLUSH: 1,
6 | Z_SYNC_FLUSH: 2,
7 | Z_FULL_FLUSH: 3,
8 | Z_FINISH: 4,
9 | Z_BLOCK: 5,
10 | Z_TREES: 6,
11 |
12 | /* Return codes for the compression/decompression functions. Negative values
13 | * are errors, positive values are used for special but normal events.
14 | */
15 | Z_OK: 0,
16 | Z_STREAM_END: 1,
17 | Z_NEED_DICT: 2,
18 | Z_ERRNO: -1,
19 | Z_STREAM_ERROR: -2,
20 | Z_DATA_ERROR: -3,
21 | //Z_MEM_ERROR: -4,
22 | Z_BUF_ERROR: -5,
23 | //Z_VERSION_ERROR: -6,
24 |
25 | /* compression levels */
26 | Z_NO_COMPRESSION: 0,
27 | Z_BEST_SPEED: 1,
28 | Z_BEST_COMPRESSION: 9,
29 | Z_DEFAULT_COMPRESSION: -1,
30 |
31 |
32 | Z_FILTERED: 1,
33 | Z_HUFFMAN_ONLY: 2,
34 | Z_RLE: 3,
35 | Z_FIXED: 4,
36 | Z_DEFAULT_STRATEGY: 0,
37 |
38 | /* Possible values of the data_type field (though see inflate()) */
39 | Z_BINARY: 0,
40 | Z_TEXT: 1,
41 | //Z_ASCII: 1, // = Z_TEXT (deprecated)
42 | Z_UNKNOWN: 2,
43 |
44 | /* The deflate compression method */
45 | Z_DEFLATED: 8
46 | //Z_NULL: null // Use -1 or null inline, depending on var type
47 | };
48 |
--------------------------------------------------------------------------------
/tests/test_computer_use_server.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import base64
3 |
4 | def get_screenshot(api_url="http://localhost:8000"):
5 | try:
6 | # Make request to the screenshot endpoint
7 | response = requests.get(f"{api_url}/screenshot")
8 | response.raise_for_status() # Raise exception for bad status codes
9 |
10 | # Get the base64 image data
11 | image_data = response.json()["image"]
12 |
13 | # Decode base64 and save to file
14 | image_bytes = base64.b64decode(image_data)
15 |
16 | # Save to local file
17 | with open("screenshot.png", "wb") as f:
18 | f.write(image_bytes)
19 |
20 | print("Screenshot saved successfully as 'screenshot.png'")
21 |
22 | except requests.exceptions.RequestException as e:
23 | print(f"Error making request: {e}")
24 | except Exception as e:
25 | print(f"Error: {e}")
26 |
27 | def get_cursor_position(api_url="http://localhost:8000"):
28 | try:
29 | response = requests.post(f"{api_url}/input/cursor_position")
30 | response.raise_for_status()
31 |
32 | position = response.json()
33 | print(f"Cursor position - X: {position['x']}, Y: {position['y']}")
34 | return position
35 |
36 | except requests.exceptions.RequestException as e:
37 | print(f"Error making request: {e}")
38 | except Exception as e:
39 | print(f"Error: {e}")
40 |
41 | if __name__ == "__main__":
42 | get_screenshot()
43 | get_cursor_position()
--------------------------------------------------------------------------------
/noVNC/docs/novnc_proxy.1:
--------------------------------------------------------------------------------
1 | .TH novnc_proxy 1 "June 25, 2020" "version 1.2.0" "USER COMMANDS"
2 |
3 | .SH NAME
4 | novnc_proxy - noVNC proxy server
5 | .SH SYNOPSIS
6 | .B novnc_proxy [--listen PORT] [--vnc VNC_HOST:PORT] [--cert CERT] [--ssl-only]
7 |
8 | Starts the WebSockets proxy and a mini-webserver and
9 | provides a cut-and-paste URL to go to.
10 |
11 | --listen PORT Port for proxy/webserver to listen on
12 | Default: 6080
13 | --vnc VNC_HOST:PORT VNC server host:port proxy target
14 | Default: localhost:5900
15 | --cert CERT Path to combined cert/key file, or just
16 | the cert file if used with --key
17 | Default: self.pem
18 | --key KEY Path to key file, when not combined with cert
19 | --web WEB Path to web files (e.g. vnc.html)
20 | Default: ./
21 | --ssl-only Disable non-https connections.
22 |
23 | --record FILE Record traffic to FILE.session.js
24 |
25 | --syslog SERVER Can be local socket such as /dev/log, or a UDP host:port pair.
26 |
27 | --heartbeat SEC send a ping to the client every SEC seconds
28 | --timeout SEC after SEC seconds exit when not connected
29 | --idle-timeout SEC server exits after SEC seconds if there are no
30 | active connections
31 |
32 | .SH AUTHOR
33 | The noVNC Authors
34 | https://github.com/novnc/noVNC
35 |
36 | .SH SEE ALSO
37 | websockify(1), nova-novncproxy(1)
38 |
--------------------------------------------------------------------------------
/noVNC/core/util/logging.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | /*
10 | * Logging/debug routines
11 | */
12 |
13 | let _logLevel = 'warn';
14 |
15 | let Debug = () => {};
16 | let Info = () => {};
17 | let Warn = () => {};
18 | let Error = () => {};
19 |
20 | export function initLogging(level) {
21 | if (typeof level === 'undefined') {
22 | level = _logLevel;
23 | } else {
24 | _logLevel = level;
25 | }
26 |
27 | Debug = Info = Warn = Error = () => {};
28 |
29 | if (typeof window.console !== "undefined") {
30 | /* eslint-disable no-console, no-fallthrough */
31 | switch (level) {
32 | case 'debug':
33 | Debug = console.debug.bind(window.console);
34 | case 'info':
35 | Info = console.info.bind(window.console);
36 | case 'warn':
37 | Warn = console.warn.bind(window.console);
38 | case 'error':
39 | Error = console.error.bind(window.console);
40 | case 'none':
41 | break;
42 | default:
43 | throw new window.Error("invalid logging type '" + level + "'");
44 | }
45 | /* eslint-enable no-console, no-fallthrough */
46 | }
47 | }
48 |
49 | export function getLogging() {
50 | return _logLevel;
51 | }
52 |
53 | export { Debug, Info, Warn, Error };
54 |
55 | // Initialize logging level
56 | initLogging();
57 |
--------------------------------------------------------------------------------
/noVNC/docs/LICENSE.BSD-3-Clause:
--------------------------------------------------------------------------------
1 | Copyright (c) ,
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of the nor the
12 | names of its contributors may be used to endorse or promote products
13 | derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/noVNC/po/po2js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /*
3 | * ps2js: gettext .po to noVNC .js converter
4 | * Copyright (C) 2018 The noVNC Authors
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | const getopt = require('node-getopt');
21 | const fs = require('fs');
22 | const po2json = require("po2json");
23 |
24 | const opt = getopt.create([
25 | ['h', 'help', 'display this help'],
26 | ]).bindHelp().parseSystem();
27 |
28 | if (opt.argv.length != 2) {
29 | console.error("Incorrect number of arguments given");
30 | process.exit(1);
31 | }
32 |
33 | const data = po2json.parseFileSync(opt.argv[0]);
34 |
35 | const bodyPart = Object.keys(data).filter(msgid => msgid !== "").map((msgid) => {
36 | if (msgid === "") return;
37 | const msgstr = data[msgid][1];
38 | return " " + JSON.stringify(msgid) + ": " + JSON.stringify(msgstr);
39 | }).join(",\n");
40 |
41 | const output = "{\n" + bodyPart + "\n}";
42 |
43 | fs.writeFileSync(opt.argv[1], output);
44 |
--------------------------------------------------------------------------------
/noVNC/snap/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: novnc
2 | base: core18 # the base snap is the execution environment for this snap
3 | version: git
4 | summary: Open Source VNC client using HTML5 (WebSockets, Canvas)
5 | description: |
6 | Open Source VNC client using HTML5 (WebSockets, Canvas).
7 | noVNC is both a VNC client JavaScript library as well as an
8 | application built on top of that library. noVNC runs well in any
9 | modern browser including mobile browsers (iOS and Android).
10 |
11 | grade: stable
12 | confinement: strict
13 |
14 | parts:
15 | novnc:
16 | source: .
17 | plugin: dump
18 | organize:
19 | utils/novnc_proxy: /
20 | stage:
21 | - vnc.html
22 | - app
23 | - core/**/*.js
24 | - vendor/**/*.js
25 | - novnc_proxy
26 |
27 | novnc-deps:
28 | plugin: nil
29 | stage-packages:
30 | - bash
31 |
32 | svc-script:
33 | source: snap/local
34 | plugin: dump
35 | stage:
36 | - svc_wrapper.sh
37 |
38 | svc-script-deps:
39 | plugin: nil
40 | stage-packages:
41 | - bash
42 | - jq
43 |
44 | websockify:
45 | source: https://github.com/novnc/websockify/archive/v0.9.0.tar.gz
46 | plugin: python
47 | stage-packages:
48 | - python3-numpy
49 |
50 | hooks:
51 | configure:
52 | plugs: [network, network-bind]
53 |
54 | apps:
55 | novnc:
56 | command: ./novnc_proxy
57 | plugs: [network, network-bind]
58 | novncsvc:
59 | command: ./svc_wrapper.sh
60 | daemon: forking
61 | plugs: [network, network-bind]
62 |
--------------------------------------------------------------------------------
/noVNC/core/encodings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | export const encodings = {
10 | encodingRaw: 0,
11 | encodingCopyRect: 1,
12 | encodingRRE: 2,
13 | encodingHextile: 5,
14 | encodingTight: 7,
15 | encodingZRLE: 16,
16 | encodingTightPNG: -260,
17 | encodingJPEG: 21,
18 |
19 | pseudoEncodingQualityLevel9: -23,
20 | pseudoEncodingQualityLevel0: -32,
21 | pseudoEncodingDesktopSize: -223,
22 | pseudoEncodingLastRect: -224,
23 | pseudoEncodingCursor: -239,
24 | pseudoEncodingQEMUExtendedKeyEvent: -258,
25 | pseudoEncodingDesktopName: -307,
26 | pseudoEncodingExtendedDesktopSize: -308,
27 | pseudoEncodingXvp: -309,
28 | pseudoEncodingFence: -312,
29 | pseudoEncodingContinuousUpdates: -313,
30 | pseudoEncodingCompressLevel9: -247,
31 | pseudoEncodingCompressLevel0: -256,
32 | pseudoEncodingVMwareCursor: 0x574d5664,
33 | pseudoEncodingExtendedClipboard: 0xc0a1e5ce
34 | };
35 |
36 | export function encodingName(num) {
37 | switch (num) {
38 | case encodings.encodingRaw: return "Raw";
39 | case encodings.encodingCopyRect: return "CopyRect";
40 | case encodings.encodingRRE: return "RRE";
41 | case encodings.encodingHextile: return "Hextile";
42 | case encodings.encodingTight: return "Tight";
43 | case encodings.encodingZRLE: return "ZRLE";
44 | case encodings.encodingTightPNG: return "TightPNG";
45 | case encodings.encodingJPEG: return "JPEG";
46 | default: return "[unknown encoding " + num + "]";
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/noVNC/core/decoders/raw.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | *
8 | */
9 |
10 | export default class RawDecoder {
11 | constructor() {
12 | this._lines = 0;
13 | }
14 |
15 | decodeRect(x, y, width, height, sock, display, depth) {
16 | if ((width === 0) || (height === 0)) {
17 | return true;
18 | }
19 |
20 | if (this._lines === 0) {
21 | this._lines = height;
22 | }
23 |
24 | const pixelSize = depth == 8 ? 1 : 4;
25 | const bytesPerLine = width * pixelSize;
26 |
27 | if (sock.rQwait("RAW", bytesPerLine)) {
28 | return false;
29 | }
30 |
31 | const curY = y + (height - this._lines);
32 | const currHeight = Math.min(this._lines,
33 | Math.floor(sock.rQlen / bytesPerLine));
34 | const pixels = width * currHeight;
35 |
36 | let data = sock.rQ;
37 | let index = sock.rQi;
38 |
39 | // Convert data if needed
40 | if (depth == 8) {
41 | const newdata = new Uint8Array(pixels * 4);
42 | for (let i = 0; i < pixels; i++) {
43 | newdata[i * 4 + 0] = ((data[index + i] >> 0) & 0x3) * 255 / 3;
44 | newdata[i * 4 + 1] = ((data[index + i] >> 2) & 0x3) * 255 / 3;
45 | newdata[i * 4 + 2] = ((data[index + i] >> 4) & 0x3) * 255 / 3;
46 | newdata[i * 4 + 3] = 255;
47 | }
48 | data = newdata;
49 | index = 0;
50 | }
51 |
52 | // Max sure the image is fully opaque
53 | for (let i = 0; i < pixels; i++) {
54 | data[index + i * 4 + 3] = 255;
55 | }
56 |
57 | display.blitImage(x, curY, width, currHeight, data, index);
58 | sock.rQskipBytes(currHeight * bytesPerLine);
59 | this._lines -= currHeight;
60 | if (this._lines > 0) {
61 | return false;
62 | }
63 |
64 | return true;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/noVNC/core/inflator.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2020 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | import { inflateInit, inflate, inflateReset } from "../vendor/pako/lib/zlib/inflate.js";
10 | import ZStream from "../vendor/pako/lib/zlib/zstream.js";
11 |
12 | export default class Inflate {
13 | constructor() {
14 | this.strm = new ZStream();
15 | this.chunkSize = 1024 * 10 * 10;
16 | this.strm.output = new Uint8Array(this.chunkSize);
17 | this.windowBits = 5;
18 |
19 | inflateInit(this.strm, this.windowBits);
20 | }
21 |
22 | setInput(data) {
23 | if (!data) {
24 | //FIXME: flush remaining data.
25 | /* eslint-disable camelcase */
26 | this.strm.input = null;
27 | this.strm.avail_in = 0;
28 | this.strm.next_in = 0;
29 | } else {
30 | this.strm.input = data;
31 | this.strm.avail_in = this.strm.input.length;
32 | this.strm.next_in = 0;
33 | /* eslint-enable camelcase */
34 | }
35 | }
36 |
37 | inflate(expected) {
38 | // resize our output buffer if it's too small
39 | // (we could just use multiple chunks, but that would cause an extra
40 | // allocation each time to flatten the chunks)
41 | if (expected > this.chunkSize) {
42 | this.chunkSize = expected;
43 | this.strm.output = new Uint8Array(this.chunkSize);
44 | }
45 |
46 | /* eslint-disable camelcase */
47 | this.strm.next_out = 0;
48 | this.strm.avail_out = expected;
49 | /* eslint-enable camelcase */
50 |
51 | let ret = inflate(this.strm, 0); // Flush argument not used.
52 | if (ret < 0) {
53 | throw new Error("zlib inflate failed");
54 | }
55 |
56 | if (this.strm.next_out != expected) {
57 | throw new Error("Incomplete zlib block");
58 | }
59 |
60 | return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
61 | }
62 |
63 | reset() {
64 | inflateReset(this.strm);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/desktop-supervisord.conf:
--------------------------------------------------------------------------------
1 | [supervisord]
2 | nodaemon=true
3 | logfile=/var/log/supervisord.log
4 | pidfile=/var/run/supervisord.pid
5 | socketfile=/var/run/supervisord.sock
6 |
7 | [unix_http_server]
8 | file=/var/run/supervisord.sock
9 | chmod=0700
10 |
11 | [rpcinterface:supervisor]
12 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
13 |
14 | [supervisorctl]
15 | serverurl=unix:///var/run/supervisord.sock
16 |
17 | [program:dbus]
18 | command=/bin/sh -c "mkdir -p /var/run/dbus && dbus-daemon --system --nofork"
19 | priority=1
20 | stderr_logfile=/var/log/dbus.stderr.log
21 |
22 | [program:Xvfb]
23 | command=Xvfb :99 -screen 0 RESOLUTION_PLACEHOLDER -ac
24 | stderr_logfile=/var/log/Xvfb.stderr.log
25 | priority=2
26 |
27 | [program:x11vnc]
28 | command=/usr/bin/x11vnc -display :99 -forever -shared -nopw
29 | priority=4
30 |
31 | [program:novnc]
32 | command=websockify --web=/usr/share/novnc 6081 localhost:5900
33 | priority=5
34 |
35 | [program:update-launcher]
36 | command=sh -c 'mkdir -p /root/.config/xfce4/panel/launcher-19 && rm -rf /root/.config/xfce4/panel/launcher-19/* && cp -r /root/desktop_files/* /root/.config/xfce4/panel/launcher-19/ && chmod +x /root/.config/xfce4/panel/launcher-19/*.desktop'
37 | environment=DISPLAY=:99
38 | priority=3
39 | startretries=0
40 | startsecs=0
41 | autorestart=false
42 | stderr_logfile=/var/log/update-launcher.stderr.log
43 |
44 | [program:xfce]
45 | command=dbus-launch --exit-with-session startxfce4
46 | environment=DISPLAY=:99
47 | priority=6
48 | stderr_logfile=/var/log/xfce.stderr.log
49 |
50 | [program:ffmpeg]
51 | command=ffmpeg -f x11grab -video_size FFMPEG_PLACEHOLDER -r 30 -i :99 -c:v libx264 -preset ultrafast -pix_fmt yuv420p -movflags +faststart /tmp/session.mp4
52 | priority=10
53 | autorestart=false
54 | stderr_logfile=/var/log/ffmpeg.err.log
55 |
56 | [program:api_server]
57 | command=/opt/venv/bin/uvicorn api:app --host 0.0.0.0 --port 8000
58 | directory=/computer_use_server/api
59 | environment=DISPLAY=:99
60 | priority=11
61 | stderr_logfile=/var/log/api_server.stderr.log
62 |
63 | [program:api_server_v2]
64 | command=/opt/venv/bin/uvicorn computer_use_server.api_v2.api:app --host 0.0.0.0 --port 2000
65 | directory=/
66 | environment=DISPLAY=:99
67 | priority=12
68 | stdout_logfile=/dev/stdout
69 | stdout_logfile_maxbytes=0
70 | redirect_stderr=true
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MarinaBox Sandbox
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | This repository contains the Docker configurations and build files for MarinaBox's sandbox environments. It provides two main sandbox types:
11 | - Browser Sandbox: A containerized Chrome browser environment
12 | - Desktop Sandbox: A containerized Linux desktop environment
13 |
14 | ## Overview
15 |
16 | MarinaBox sandboxes are isolated environments that can be controlled remotely. Each sandbox includes:
17 | - VNC server for remote viewing
18 | - Video recording capabilities
19 | - Secure isolation from host system
20 | - Computer Use command support
21 |
22 | ## Sandbox Types
23 |
24 | ### Browser Sandbox
25 | - Chromium-based browser environment
26 | - Remote debugging support
27 | - Ideal for web automation and testing
28 | - Minimal footprint
29 |
30 | ### Desktop Sandbox
31 | - Full Linux desktop environment
32 | - Support for multiple applications
33 | - Suitable for complex workflows
34 | - Complete desktop interaction capabilities
35 |
36 | ## Building Images
37 |
38 | ### Browser Sandbox
39 | ```
40 | docker build -f Dockerfile.chromium -t marinabox/marinabox-browser .
41 | ```
42 |
43 | ### Desktop Sandbox
44 | ```
45 | docker build -f Dockerfile.desktop -t marinabox/marinabox-desktop .
46 | ```
47 |
48 | ## License
49 |
50 | MarinaBox Sandbox is released under the MIT License. See the [LICENSE](LICENSE) file for details.
51 |
52 | ## Acknowledgments
53 |
54 | This project makes significant use of:
55 | - [noVNC](https://github.com/novnc/noVNC), an open source VNC client using HTML5 (WebSockets, Canvas). noVNC is licensed under the MPL-2.0 License.
56 | - [Anthropic Quickstarts](https://github.com/anthropics/anthropic-quickstarts), specifically the Computer Use Demo which provided inspiration for the sandbox implementation. Licensed under the MIT License.
57 |
--------------------------------------------------------------------------------
/noVNC/app/locale/zh_TW.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "連線中...",
3 | "Disconnecting...": "正在中斷連線...",
4 | "Reconnecting...": "重新連線中...",
5 | "Internal error": "內部錯誤",
6 | "Must set host": "請提供主機資訊",
7 | "Connected (encrypted) to ": "已加密連線到",
8 | "Connected (unencrypted) to ": "未加密連線到",
9 | "Something went wrong, connection is closed": "發生錯誤,連線已關閉",
10 | "Failed to connect to server": "無法連線到伺服器",
11 | "Disconnected": "連線已中斷",
12 | "New connection has been rejected with reason: ": "連線被拒絕,原因:",
13 | "New connection has been rejected": "連線被拒絕",
14 | "Password is required": "請提供密碼",
15 | "noVNC encountered an error:": "noVNC 遇到一個錯誤:",
16 | "Hide/Show the control bar": "顯示/隱藏控制列",
17 | "Move/Drag Viewport": "拖放顯示範圍",
18 | "viewport drag": "顯示範圍拖放",
19 | "Active Mouse Button": "啟用滑鼠按鍵",
20 | "No mousebutton": "無滑鼠按鍵",
21 | "Left mousebutton": "滑鼠左鍵",
22 | "Middle mousebutton": "滑鼠中鍵",
23 | "Right mousebutton": "滑鼠右鍵",
24 | "Keyboard": "鍵盤",
25 | "Show Keyboard": "顯示鍵盤",
26 | "Extra keys": "額外按鍵",
27 | "Show Extra Keys": "顯示額外按鍵",
28 | "Ctrl": "Ctrl",
29 | "Toggle Ctrl": "切換 Ctrl",
30 | "Alt": "Alt",
31 | "Toggle Alt": "切換 Alt",
32 | "Send Tab": "送出 Tab 鍵",
33 | "Tab": "Tab",
34 | "Esc": "Esc",
35 | "Send Escape": "送出 Escape 鍵",
36 | "Ctrl+Alt+Del": "Ctrl-Alt-Del",
37 | "Send Ctrl-Alt-Del": "送出 Ctrl-Alt-Del 快捷鍵",
38 | "Shutdown/Reboot": "關機/重新啟動",
39 | "Shutdown/Reboot...": "關機/重新啟動...",
40 | "Power": "電源",
41 | "Shutdown": "關機",
42 | "Reboot": "重新啟動",
43 | "Reset": "重設",
44 | "Clipboard": "剪貼簿",
45 | "Clear": "清除",
46 | "Fullscreen": "全螢幕",
47 | "Settings": "設定",
48 | "Shared Mode": "分享模式",
49 | "View Only": "僅檢視",
50 | "Clip to Window": "限制/裁切視窗大小",
51 | "Scaling Mode:": "縮放模式:",
52 | "None": "無",
53 | "Local Scaling": "本機縮放",
54 | "Remote Resizing": "遠端調整大小",
55 | "Advanced": "進階",
56 | "Repeater ID:": "中繼站 ID",
57 | "WebSocket": "WebSocket",
58 | "Encrypt": "加密",
59 | "Host:": "主機:",
60 | "Port:": "連接埠:",
61 | "Path:": "路徑:",
62 | "Automatic Reconnect": "自動重新連線",
63 | "Reconnect Delay (ms):": "重新連線間隔 (ms):",
64 | "Logging:": "日誌級別:",
65 | "Disconnect": "中斷連線",
66 | "Connect": "連線",
67 | "Password:": "密碼:",
68 | "Cancel": "取消"
69 | }
--------------------------------------------------------------------------------
/noVNC/app/locale/zh_CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "连接中...",
3 | "Disconnecting...": "正在断开连接...",
4 | "Reconnecting...": "重新连接中...",
5 | "Internal error": "内部错误",
6 | "Must set host": "请提供主机名",
7 | "Connected (encrypted) to ": "已连接到(加密)",
8 | "Connected (unencrypted) to ": "已连接到(未加密)",
9 | "Something went wrong, connection is closed": "发生错误,连接已关闭",
10 | "Failed to connect to server": "无法连接到服务器",
11 | "Disconnected": "已断开连接",
12 | "New connection has been rejected with reason: ": "连接被拒绝,原因:",
13 | "New connection has been rejected": "连接被拒绝",
14 | "Password is required": "请提供密码",
15 | "noVNC encountered an error:": "noVNC 遇到一个错误:",
16 | "Hide/Show the control bar": "显示/隐藏控制栏",
17 | "Move/Drag Viewport": "拖放显示范围",
18 | "viewport drag": "显示范围拖放",
19 | "Active Mouse Button": "启动鼠标按鍵",
20 | "No mousebutton": "禁用鼠标按鍵",
21 | "Left mousebutton": "鼠标左鍵",
22 | "Middle mousebutton": "鼠标中鍵",
23 | "Right mousebutton": "鼠标右鍵",
24 | "Keyboard": "键盘",
25 | "Show Keyboard": "显示键盘",
26 | "Extra keys": "额外按键",
27 | "Show Extra Keys": "显示额外按键",
28 | "Ctrl": "Ctrl",
29 | "Toggle Ctrl": "切换 Ctrl",
30 | "Alt": "Alt",
31 | "Toggle Alt": "切换 Alt",
32 | "Send Tab": "发送 Tab 键",
33 | "Tab": "Tab",
34 | "Esc": "Esc",
35 | "Send Escape": "发送 Escape 键",
36 | "Ctrl+Alt+Del": "Ctrl-Alt-Del",
37 | "Send Ctrl-Alt-Del": "发送 Ctrl-Alt-Del 键",
38 | "Shutdown/Reboot": "关机/重新启动",
39 | "Shutdown/Reboot...": "关机/重新启动...",
40 | "Power": "电源",
41 | "Shutdown": "关机",
42 | "Reboot": "重新启动",
43 | "Reset": "重置",
44 | "Clipboard": "剪贴板",
45 | "Clear": "清除",
46 | "Fullscreen": "全屏",
47 | "Settings": "设置",
48 | "Shared Mode": "分享模式",
49 | "View Only": "仅查看",
50 | "Clip to Window": "限制/裁切窗口大小",
51 | "Scaling Mode:": "缩放模式:",
52 | "None": "无",
53 | "Local Scaling": "本地缩放",
54 | "Remote Resizing": "远程调整大小",
55 | "Advanced": "高级",
56 | "Repeater ID:": "中继站 ID",
57 | "WebSocket": "WebSocket",
58 | "Encrypt": "加密",
59 | "Host:": "主机:",
60 | "Port:": "端口:",
61 | "Path:": "路径:",
62 | "Automatic Reconnect": "自动重新连接",
63 | "Reconnect Delay (ms):": "重新连接间隔 (ms):",
64 | "Logging:": "日志级别:",
65 | "Disconnect": "中断连接",
66 | "Connect": "连接",
67 | "Password:": "密码:",
68 | "Cancel": "取消"
69 | }
--------------------------------------------------------------------------------
/noVNC/LICENSE.txt:
--------------------------------------------------------------------------------
1 | noVNC is Copyright (C) 2022 The noVNC Authors
2 | (./AUTHORS)
3 |
4 | The noVNC core library files are licensed under the MPL 2.0 (Mozilla
5 | Public License 2.0). The noVNC core library is composed of the
6 | Javascript code necessary for full noVNC operation. This includes (but
7 | is not limited to):
8 |
9 | core/**/*.js
10 | app/*.js
11 | test/playback.js
12 |
13 | The HTML, CSS, font and images files that included with the noVNC
14 | source distibution (or repository) are not considered part of the
15 | noVNC core library and are licensed under more permissive licenses.
16 | The intent is to allow easy integration of noVNC into existing web
17 | sites and web applications.
18 |
19 | The HTML, CSS, font and image files are licensed as follows:
20 |
21 | *.html : 2-Clause BSD license
22 |
23 | app/styles/*.css : 2-Clause BSD license
24 |
25 | app/styles/Orbitron* : SIL Open Font License 1.1
26 | (Copyright 2009 Matt McInerney)
27 |
28 | app/images/ : Creative Commons Attribution-ShareAlike
29 | http://creativecommons.org/licenses/by-sa/3.0/
30 |
31 | Some portions of noVNC are copyright to their individual authors.
32 | Please refer to the individual source files and/or to the noVNC commit
33 | history: https://github.com/novnc/noVNC/commits/master
34 |
35 | The are several files and projects that have been incorporated into
36 | the noVNC core library. Here is a list of those files and the original
37 | licenses (all MPL 2.0 compatible):
38 |
39 | core/base64.js : MPL 2.0
40 |
41 | core/des.js : Various BSD style licenses
42 |
43 | vendor/pako/ : MIT
44 |
45 | Any other files not mentioned above are typically marked with
46 | a copyright/license header at the top of the file. The default noVNC
47 | license is MPL-2.0.
48 |
49 | The following license texts are included:
50 |
51 | docs/LICENSE.MPL-2.0
52 | docs/LICENSE.OFL-1.1
53 | docs/LICENSE.BSD-3-Clause (New BSD)
54 | docs/LICENSE.BSD-2-Clause (Simplified BSD / FreeBSD)
55 | vendor/pako/LICENSE (MIT)
56 |
57 | Or alternatively the license texts may be found here:
58 |
59 | http://www.mozilla.org/MPL/2.0/
60 | http://scripts.sil.org/OFL
61 | http://en.wikipedia.org/wiki/BSD_licenses
62 | https://opensource.org/licenses/MIT
63 |
--------------------------------------------------------------------------------
/firefox-supervisord.conf:
--------------------------------------------------------------------------------
1 | [supervisord]
2 | nodaemon=true
3 | logfile=/var/log/supervisord.log
4 | pidfile=/var/run/supervisord.pid
5 | socketfile=/var/run/supervisord.sock
6 |
7 | [unix_http_server]
8 | file=/var/run/supervisord.sock
9 | chmod=0700
10 |
11 | [rpcinterface:supervisor]
12 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
13 |
14 | [supervisorctl]
15 | serverurl=unix:///var/run/supervisord.sock
16 |
17 | [program:dbus]
18 | command=/bin/sh -c "mkdir -p /var/run/dbus && dbus-daemon --system --nofork"
19 | priority=1
20 | stderr_logfile=/var/log/dbus.stderr.log
21 |
22 | [program:Xvfb]
23 | command=Xvfb :99 -screen 0 RESOLUTION_PLACEHOLDER -ac
24 | stderr_logfile=/var/log/Xvfb.stderr.log
25 | priority=2
26 |
27 | [program:firefox]
28 | command=/bin/sh -c "sleep 2 && exec /usr/bin/firefox --kiosk --no-remote --new-instance --width WIDTH_PLACEHOLDER --height HEIGHT_PLACEHOLDER ${INITIAL_URL:-about:blank}"
29 | environment=DISPLAY=:99
30 | stderr_logfile=/var/log/firefox.err.log
31 | stdout_logfile=/var/log/firefox.out.log
32 | priority=3
33 | autorestart=true
34 |
35 | [program:firefox_fullscreen]
36 | command=/bin/sh -c "sleep 8 && xdotool search --sync --class 'firefox' windowactivate --sync windowmove 0 0 windowsize WIDTH_PLACEHOLDER HEIGHT_PLACEHOLDER key F11 || true"
37 | environment=DISPLAY=:99
38 | priority=4
39 | startsecs=0
40 | autorestart=false
41 | stderr_logfile=/var/log/firefox_fullscreen.stderr.log
42 |
43 | [program:x11vnc]
44 | command=/usr/bin/x11vnc -display :99 -forever -shared -nopw
45 | priority=5
46 |
47 | [program:novnc]
48 | command=websockify --web=/usr/share/novnc 6081 localhost:5900
49 | priority=6
50 |
51 | [program:ffmpeg]
52 | command=ffmpeg -f x11grab -video_size FFMPEG_PLACEHOLDER -r 30 -i :99 -c:v libx264 -preset ultrafast -pix_fmt yuv420p -movflags +faststart /tmp/session.mp4
53 | priority=7
54 | autorestart=false
55 | stderr_logfile=/var/log/ffmpeg.err.log
56 |
57 | [program:api_server]
58 | command=/opt/venv/bin/uvicorn api:app --host 0.0.0.0 --port 8000
59 | directory=/computer_use_server/api
60 | environment=DISPLAY=:99
61 | priority=8
62 | stderr_logfile=/var/log/api_server.stderr.log
63 |
64 | [program:api_server_v2]
65 | command=/opt/venv/bin/uvicorn computer_use_server.api_v2.api:app --host 0.0.0.0 --port 2000
66 | directory=/
67 | environment=DISPLAY=:99
68 | priority=9
69 | stdout_logfile=/dev/stdout
70 | stdout_logfile_maxbytes=0
71 | redirect_stderr=true
72 |
73 |
--------------------------------------------------------------------------------
/noVNC/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@novnc/novnc",
3 | "version": "1.4.0",
4 | "description": "An HTML5 VNC client",
5 | "browser": "lib/rfb",
6 | "directories": {
7 | "lib": "lib",
8 | "doc": "docs",
9 | "test": "tests"
10 | },
11 | "files": [
12 | "lib",
13 | "AUTHORS",
14 | "VERSION",
15 | "docs/API.md",
16 | "docs/LIBRARY.md",
17 | "docs/LICENSE*",
18 | "core",
19 | "vendor/pako"
20 | ],
21 | "scripts": {
22 | "lint": "eslint app core po/po2js po/xgettext-html tests utils",
23 | "test": "karma start karma.conf.js",
24 | "prepublish": "node ./utils/convert.js --clean"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "git+https://github.com/novnc/noVNC.git"
29 | },
30 | "author": "Joel Martin (https://github.com/kanaka)",
31 | "contributors": [
32 | "Samuel Mannehed (https://github.com/samhed)",
33 | "Pierre Ossman (https://github.com/CendioOssman)"
34 | ],
35 | "license": "MPL-2.0",
36 | "bugs": {
37 | "url": "https://github.com/novnc/noVNC/issues"
38 | },
39 | "homepage": "https://github.com/novnc/noVNC",
40 | "devDependencies": {
41 | "@babel/core": "latest",
42 | "@babel/plugin-syntax-dynamic-import": "latest",
43 | "@babel/plugin-transform-modules-commonjs": "latest",
44 | "@babel/preset-env": "latest",
45 | "@babel/cli": "latest",
46 | "babel-plugin-import-redirect": "latest",
47 | "browserify": "latest",
48 | "babelify": "latest",
49 | "core-js": "latest",
50 | "chai": "latest",
51 | "commander": "latest",
52 | "es-module-loader": "latest",
53 | "eslint": "latest",
54 | "fs-extra": "latest",
55 | "jsdom": "latest",
56 | "karma": "latest",
57 | "karma-mocha": "latest",
58 | "karma-chrome-launcher": "latest",
59 | "@chiragrupani/karma-chromium-edge-launcher": "latest",
60 | "karma-firefox-launcher": "latest",
61 | "karma-ie-launcher": "latest",
62 | "karma-mocha-reporter": "latest",
63 | "karma-safari-launcher": "latest",
64 | "karma-script-launcher": "latest",
65 | "karma-sinon-chai": "latest",
66 | "mocha": "latest",
67 | "node-getopt": "latest",
68 | "po2json": "latest",
69 | "sinon": "latest",
70 | "sinon-chai": "latest"
71 | },
72 | "dependencies": {},
73 | "keywords": [
74 | "vnc",
75 | "rfb",
76 | "novnc",
77 | "websockify"
78 | ]
79 | }
80 |
--------------------------------------------------------------------------------
/noVNC/app/locale/ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "연결중...",
3 | "Disconnecting...": "연결 해제중...",
4 | "Reconnecting...": "재연결중...",
5 | "Internal error": "내부 오류",
6 | "Must set host": "호스트는 설정되어야 합니다.",
7 | "Connected (encrypted) to ": "다음과 (암호화되어) 연결되었습니다:",
8 | "Connected (unencrypted) to ": "다음과 (암호화 없이) 연결되었습니다:",
9 | "Something went wrong, connection is closed": "무언가 잘못되었습니다, 연결이 닫혔습니다.",
10 | "Failed to connect to server": "서버에 연결하지 못했습니다.",
11 | "Disconnected": "연결이 해제되었습니다.",
12 | "New connection has been rejected with reason: ": "새 연결이 다음 이유로 거부되었습니다:",
13 | "New connection has been rejected": "새 연결이 거부되었습니다.",
14 | "Password is required": "비밀번호가 필요합니다.",
15 | "noVNC encountered an error:": "noVNC에 오류가 발생했습니다:",
16 | "Hide/Show the control bar": "컨트롤 바 숨기기/보이기",
17 | "Move/Drag Viewport": "움직이기/드래그 뷰포트",
18 | "viewport drag": "뷰포트 드래그",
19 | "Active Mouse Button": "마우스 버튼 활성화",
20 | "No mousebutton": "마우스 버튼 없음",
21 | "Left mousebutton": "왼쪽 마우스 버튼",
22 | "Middle mousebutton": "중간 마우스 버튼",
23 | "Right mousebutton": "오른쪽 마우스 버튼",
24 | "Keyboard": "키보드",
25 | "Show Keyboard": "키보드 보이기",
26 | "Extra keys": "기타 키들",
27 | "Show Extra Keys": "기타 키들 보이기",
28 | "Ctrl": "Ctrl",
29 | "Toggle Ctrl": "Ctrl 켜기/끄기",
30 | "Alt": "Alt",
31 | "Toggle Alt": "Alt 켜기/끄기",
32 | "Send Tab": "Tab 보내기",
33 | "Tab": "Tab",
34 | "Esc": "Esc",
35 | "Send Escape": "Esc 보내기",
36 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
37 | "Send Ctrl-Alt-Del": "Ctrl+Alt+Del 보내기",
38 | "Shutdown/Reboot": "셧다운/리붓",
39 | "Shutdown/Reboot...": "셧다운/리붓...",
40 | "Power": "전원",
41 | "Shutdown": "셧다운",
42 | "Reboot": "리붓",
43 | "Reset": "리셋",
44 | "Clipboard": "클립보드",
45 | "Clear": "지우기",
46 | "Fullscreen": "전체화면",
47 | "Settings": "설정",
48 | "Shared Mode": "공유 모드",
49 | "View Only": "보기 전용",
50 | "Clip to Window": "창에 클립",
51 | "Scaling Mode:": "스케일링 모드:",
52 | "None": "없음",
53 | "Local Scaling": "로컬 스케일링",
54 | "Remote Resizing": "원격 크기 조절",
55 | "Advanced": "고급",
56 | "Repeater ID:": "중계 ID",
57 | "WebSocket": "웹소켓",
58 | "Encrypt": "암호화",
59 | "Host:": "호스트:",
60 | "Port:": "포트:",
61 | "Path:": "위치:",
62 | "Automatic Reconnect": "자동 재연결",
63 | "Reconnect Delay (ms):": "재연결 지연 시간 (ms)",
64 | "Logging:": "로깅",
65 | "Disconnect": "연결 해제",
66 | "Connect": "연결",
67 | "Password:": "비밀번호:",
68 | "Send Password": "비밀번호 전송",
69 | "Cancel": "취소"
70 | }
--------------------------------------------------------------------------------
/noVNC/docs/links:
--------------------------------------------------------------------------------
1 | New tight PNG protocol:
2 | http://wiki.qemu.org/VNC_Tight_PNG
3 | http://xf.iksaif.net/blog/index.php?post/2010/06/14/QEMU:-Tight-PNG-and-some-profiling
4 |
5 | RFB protocol and extensions:
6 | http://tigervnc.org/cgi-bin/rfbproto
7 |
8 | Canvas Browser Compatibility:
9 | http://philip.html5.org/tests/canvas/suite/tests/results.html
10 |
11 | WebSockets API standard:
12 | http://www.whatwg.org/specs/web-apps/current-work/complete.html#websocket
13 | http://dev.w3.org/html5/websockets/
14 | http://www.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-00.txt
15 |
16 | Browser Keyboard Events detailed:
17 | http://unixpapa.com/js/key.html
18 |
19 | ActionScript (Flash) WebSocket implementation:
20 | http://github.com/gimite/web-socket-js
21 |
22 | ActionScript (Flash) crypto/TLS library:
23 | http://code.google.com/p/as3crypto
24 | http://github.com/lyokato/as3crypto_patched
25 |
26 | TLS Protocol:
27 | http://en.wikipedia.org/wiki/Transport_Layer_Security
28 |
29 | Generate self-signed certificate:
30 | http://docs.python.org/dev/library/ssl.html#certificates
31 |
32 | Cursor appearance/style (for Cursor pseudo-encoding):
33 | http://en.wikipedia.org/wiki/ICO_(file_format)
34 | http://www.daubnet.com/en/file-format-cur
35 | https://developer.mozilla.org/en/Using_URL_values_for_the_cursor_property
36 | http://www.fileformat.info/format/bmp/egff.htm
37 |
38 | Icon/Cursor file format:
39 | http://msdn.microsoft.com/en-us/library/ms997538
40 | http://msdn.microsoft.com/en-us/library/aa921550.aspx
41 | http://msdn.microsoft.com/en-us/library/aa930622.aspx
42 |
43 |
44 | RDP Protocol specification:
45 | http://msdn.microsoft.com/en-us/library/cc240445(v=PROT.10).aspx
46 |
47 |
48 | Related projects:
49 |
50 | guacamole: http://guacamole.sourceforge.net/
51 |
52 | - Web client, but Java servlet does pre-processing
53 |
54 | jsvnc: http://code.google.com/p/jsvnc/
55 |
56 | - No releases
57 |
58 | webvnc: http://code.google.com/p/webvnc/
59 |
60 | - Jetty web server gateway, no updates since April 2008.
61 |
62 | RealVNC Java applet: http://www.realvnc.com/support/javavncviewer.html
63 |
64 | - Java applet
65 |
66 | Flashlight-VNC: http://www.wizhelp.com/flashlight-vnc/
67 |
68 | - Adobe Flash implementation
69 |
70 | FVNC: http://osflash.org/fvnc
71 |
72 | - Adbove Flash implementation
73 |
74 | CanVNC: http://canvnc.sourceforge.net/
75 |
76 | - HTML client with REST to VNC python proxy. Mostly vapor.
77 |
--------------------------------------------------------------------------------
/noVNC/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2020": true
5 | },
6 | "parserOptions": {
7 | "sourceType": "module",
8 | "ecmaVersion": 2020
9 | },
10 | "extends": "eslint:recommended",
11 | "rules": {
12 | // Unsafe or confusing stuff that we forbid
13 |
14 | "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
15 | "no-constant-condition": ["error", { "checkLoops": false }],
16 | "no-var": "error",
17 | "no-useless-constructor": "error",
18 | "object-shorthand": ["error", "methods", { "avoidQuotes": true }],
19 | "prefer-arrow-callback": "error",
20 | "arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": false } ],
21 | "arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
22 | "arrow-spacing": ["error"],
23 | "no-confusing-arrow": ["error", { "allowParens": true }],
24 |
25 | // Enforced coding style
26 |
27 | "brace-style": ["error", "1tbs", { "allowSingleLine": true }],
28 | "indent": ["error", 4, { "SwitchCase": 1,
29 | "VariableDeclarator": "first",
30 | "FunctionDeclaration": { "parameters": "first" },
31 | "FunctionExpression": { "parameters": "first" },
32 | "CallExpression": { "arguments": "first" },
33 | "ArrayExpression": "first",
34 | "ObjectExpression": "first",
35 | "ImportDeclaration": "first",
36 | "ignoreComments": true }],
37 | "comma-spacing": ["error"],
38 | "comma-style": ["error"],
39 | "curly": ["error", "multi-line"],
40 | "func-call-spacing": ["error"],
41 | "func-names": ["error"],
42 | "func-style": ["error", "declaration", { "allowArrowFunctions": true }],
43 | "key-spacing": ["error"],
44 | "keyword-spacing": ["error"],
45 | "no-trailing-spaces": ["error"],
46 | "semi": ["error"],
47 | "space-before-blocks": ["error"],
48 | "space-before-function-paren": ["error", { "anonymous": "always",
49 | "named": "never",
50 | "asyncArrow": "always" }],
51 | "switch-colon-spacing": ["error"],
52 | "camelcase": ["error", { allow: ["^XK_", "^XF86XK_"] }],
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/noVNC/app/locale/ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "接続しています...",
3 | "Disconnecting...": "切断しています...",
4 | "Reconnecting...": "再接続しています...",
5 | "Internal error": "内部エラー",
6 | "Must set host": "ホストを設定する必要があります",
7 | "Connected (encrypted) to ": "接続しました (暗号化済み): ",
8 | "Connected (unencrypted) to ": "接続しました (暗号化されていません): ",
9 | "Something went wrong, connection is closed": "何らかの問題で、接続が閉じられました",
10 | "Failed to connect to server": "サーバーへの接続に失敗しました",
11 | "Disconnected": "切断しました",
12 | "New connection has been rejected with reason: ": "新規接続は次の理由で拒否されました: ",
13 | "New connection has been rejected": "新規接続は拒否されました",
14 | "Credentials are required": "資格情報が必要です",
15 | "noVNC encountered an error:": "noVNC でエラーが発生しました:",
16 | "Hide/Show the control bar": "コントロールバーを隠す/表示する",
17 | "Drag": "ドラッグ",
18 | "Move/Drag Viewport": "ビューポートを移動/ドラッグ",
19 | "Keyboard": "キーボード",
20 | "Show Keyboard": "キーボードを表示",
21 | "Extra keys": "追加キー",
22 | "Show Extra Keys": "追加キーを表示",
23 | "Ctrl": "Ctrl",
24 | "Toggle Ctrl": "Ctrl キーを切り替え",
25 | "Alt": "Alt",
26 | "Toggle Alt": "Alt キーを切り替え",
27 | "Toggle Windows": "Windows キーを切り替え",
28 | "Windows": "Windows",
29 | "Send Tab": "Tab キーを送信",
30 | "Tab": "Tab",
31 | "Esc": "Esc",
32 | "Send Escape": "Escape キーを送信",
33 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
34 | "Send Ctrl-Alt-Del": "Ctrl-Alt-Del を送信",
35 | "Shutdown/Reboot": "シャットダウン/再起動",
36 | "Shutdown/Reboot...": "シャットダウン/再起動...",
37 | "Power": "電源",
38 | "Shutdown": "シャットダウン",
39 | "Reboot": "再起動",
40 | "Reset": "リセット",
41 | "Clipboard": "クリップボード",
42 | "Clear": "クリア",
43 | "Fullscreen": "全画面表示",
44 | "Settings": "設定",
45 | "Shared Mode": "共有モード",
46 | "View Only": "表示のみ",
47 | "Clip to Window": "ウィンドウにクリップ",
48 | "Scaling Mode:": "スケーリングモード:",
49 | "None": "なし",
50 | "Local Scaling": "ローカルスケーリング",
51 | "Remote Resizing": "リモートでリサイズ",
52 | "Advanced": "高度",
53 | "Quality:": "品質:",
54 | "Compression level:": "圧縮レベル:",
55 | "Repeater ID:": "リピーター ID:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "暗号化",
58 | "Host:": "ホスト:",
59 | "Port:": "ポート:",
60 | "Path:": "パス:",
61 | "Automatic Reconnect": "自動再接続",
62 | "Reconnect Delay (ms):": "再接続する遅延 (ミリ秒):",
63 | "Show Dot when No Cursor": "カーソルがないときにドットを表示",
64 | "Logging:": "ロギング:",
65 | "Version:": "バージョン:",
66 | "Disconnect": "切断",
67 | "Connect": "接続",
68 | "Username:": "ユーザー名:",
69 | "Password:": "パスワード:",
70 | "Send Credentials": "資格情報を送信",
71 | "Cancel": "キャンセル"
72 | }
--------------------------------------------------------------------------------
/noVNC/app/images/windows.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/noVNC/tests/test.localization.js:
--------------------------------------------------------------------------------
1 | const expect = chai.expect;
2 | import { l10n } from '../app/localization.js';
3 |
4 | describe('Localization', function () {
5 | "use strict";
6 |
7 | describe('language selection', function () {
8 | let origNavigator;
9 | beforeEach(function () {
10 | // window.navigator is a protected read-only property in many
11 | // environments, so we need to redefine it whilst running these
12 | // tests.
13 | origNavigator = Object.getOwnPropertyDescriptor(window, "navigator");
14 |
15 | Object.defineProperty(window, "navigator", {value: {}});
16 | window.navigator.languages = [];
17 | });
18 | afterEach(function () {
19 | Object.defineProperty(window, "navigator", origNavigator);
20 | });
21 |
22 | it('should use English by default', function () {
23 | expect(l10n.language).to.equal('en');
24 | });
25 | it('should use English if no user language matches', function () {
26 | window.navigator.languages = ["nl", "de"];
27 | l10n.setup(["es", "fr"]);
28 | expect(l10n.language).to.equal('en');
29 | });
30 | it('should use the most preferred user language', function () {
31 | window.navigator.languages = ["nl", "de", "fr"];
32 | l10n.setup(["es", "fr", "de"]);
33 | expect(l10n.language).to.equal('de');
34 | });
35 | it('should prefer sub-languages languages', function () {
36 | window.navigator.languages = ["pt-BR"];
37 | l10n.setup(["pt", "pt-BR"]);
38 | expect(l10n.language).to.equal('pt-BR');
39 | });
40 | it('should fall back to language "parents"', function () {
41 | window.navigator.languages = ["pt-BR"];
42 | l10n.setup(["fr", "pt", "de"]);
43 | expect(l10n.language).to.equal('pt');
44 | });
45 | it('should not use specific language when user asks for a generic language', function () {
46 | window.navigator.languages = ["pt", "de"];
47 | l10n.setup(["fr", "pt-BR", "de"]);
48 | expect(l10n.language).to.equal('de');
49 | });
50 | it('should handle underscore as a separator', function () {
51 | window.navigator.languages = ["pt-BR"];
52 | l10n.setup(["pt_BR"]);
53 | expect(l10n.language).to.equal('pt_BR');
54 | });
55 | it('should handle difference in case', function () {
56 | window.navigator.languages = ["pt-br"];
57 | l10n.setup(["pt-BR"]);
58 | expect(l10n.language).to.equal('pt-BR');
59 | });
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/noVNC/tests/fake.websocket.js:
--------------------------------------------------------------------------------
1 | import Base64 from '../core/base64.js';
2 |
3 | export default class FakeWebSocket {
4 | constructor(uri, protocols) {
5 | this.url = uri;
6 | this.binaryType = "arraybuffer";
7 | this.extensions = "";
8 |
9 | this.onerror = null;
10 | this.onmessage = null;
11 | this.onopen = null;
12 |
13 | if (!protocols || typeof protocols === 'string') {
14 | this.protocol = protocols;
15 | } else {
16 | this.protocol = protocols[0];
17 | }
18 |
19 | this._sendQueue = new Uint8Array(20000);
20 |
21 | this.readyState = FakeWebSocket.CONNECTING;
22 | this.bufferedAmount = 0;
23 |
24 | this._isFake = true;
25 | }
26 |
27 | close(code, reason) {
28 | this.readyState = FakeWebSocket.CLOSED;
29 | if (this.onclose) {
30 | this.onclose(new CloseEvent("close", { 'code': code, 'reason': reason, 'wasClean': true }));
31 | }
32 | }
33 |
34 | send(data) {
35 | if (this.protocol == 'base64') {
36 | data = Base64.decode(data);
37 | } else {
38 | data = new Uint8Array(data);
39 | }
40 | this._sendQueue.set(data, this.bufferedAmount);
41 | this.bufferedAmount += data.length;
42 | }
43 |
44 | _getSentData() {
45 | const res = new Uint8Array(this._sendQueue.buffer, 0, this.bufferedAmount);
46 | this.bufferedAmount = 0;
47 | return res;
48 | }
49 |
50 | _open() {
51 | this.readyState = FakeWebSocket.OPEN;
52 | if (this.onopen) {
53 | this.onopen(new Event('open'));
54 | }
55 | }
56 |
57 | _receiveData(data) {
58 | // Break apart the data to expose bugs where we assume data is
59 | // neatly packaged
60 | for (let i = 0;i < data.length;i++) {
61 | let buf = data.subarray(i, i+1);
62 | this.onmessage(new MessageEvent("message", { 'data': buf }));
63 | }
64 | }
65 | }
66 |
67 | FakeWebSocket.OPEN = WebSocket.OPEN;
68 | FakeWebSocket.CONNECTING = WebSocket.CONNECTING;
69 | FakeWebSocket.CLOSING = WebSocket.CLOSING;
70 | FakeWebSocket.CLOSED = WebSocket.CLOSED;
71 |
72 | FakeWebSocket._isFake = true;
73 |
74 | FakeWebSocket.replace = () => {
75 | if (!WebSocket._isFake) {
76 | const realVersion = WebSocket;
77 | // eslint-disable-next-line no-global-assign
78 | WebSocket = FakeWebSocket;
79 | FakeWebSocket._realVersion = realVersion;
80 | }
81 | };
82 |
83 | FakeWebSocket.restore = () => {
84 | if (WebSocket._isFake) {
85 | // eslint-disable-next-line no-global-assign
86 | WebSocket = WebSocket._realVersion;
87 | }
88 | };
89 |
--------------------------------------------------------------------------------
/noVNC/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 |
3 | // The Safari launcher is broken, so construct our own
4 | function SafariBrowser(id, baseBrowserDecorator, args) {
5 | baseBrowserDecorator(this);
6 |
7 | this._start = function(url) {
8 | this._execCommand('/usr/bin/open', ['-W', '-n', '-a', 'Safari', url]);
9 | }
10 | }
11 |
12 | SafariBrowser.prototype = {
13 | name: 'Safari'
14 | }
15 |
16 | module.exports = (config) => {
17 | let browsers = [];
18 |
19 | if (process.env.TEST_BROWSER_NAME) {
20 | browsers = process.env.TEST_BROWSER_NAME.split(',');
21 | }
22 |
23 | const my_conf = {
24 |
25 | // base path that will be used to resolve all patterns (eg. files, exclude)
26 | basePath: '',
27 |
28 | // frameworks to use
29 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
30 | frameworks: ['mocha', 'sinon-chai'],
31 |
32 | // list of files / patterns to load in the browser (loaded in order)
33 | files: [
34 | { pattern: 'app/localization.js', included: false, type: 'module' },
35 | { pattern: 'app/webutil.js', included: false, type: 'module' },
36 | { pattern: 'core/**/*.js', included: false, type: 'module' },
37 | { pattern: 'vendor/pako/**/*.js', included: false, type: 'module' },
38 | { pattern: 'tests/test.*.js', type: 'module' },
39 | { pattern: 'tests/fake.*.js', included: false, type: 'module' },
40 | { pattern: 'tests/assertions.js', type: 'module' },
41 | ],
42 |
43 | client: {
44 | mocha: {
45 | // replace Karma debug page with mocha display
46 | 'reporter': 'html',
47 | 'ui': 'bdd'
48 | }
49 | },
50 |
51 | // list of files to exclude
52 | exclude: [
53 | ],
54 |
55 | plugins: [
56 | 'karma-*',
57 | '@chiragrupani/karma-chromium-edge-launcher',
58 | { 'launcher:Safari': [ 'type', SafariBrowser ] },
59 | ],
60 |
61 | // start these browsers
62 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
63 | browsers: browsers,
64 |
65 | // test results reporter to use
66 | // possible values: 'dots', 'progress'
67 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
68 | reporters: ['mocha'],
69 |
70 |
71 | // level of logging
72 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
73 | logLevel: config.LOG_INFO,
74 |
75 |
76 | // enable / disable watching file and executing tests whenever any file changes
77 | autoWatch: false,
78 |
79 | // Continuous Integration mode
80 | // if true, Karma captures browsers, runs the tests and exits
81 | singleRun: true,
82 | };
83 |
84 | config.set(my_conf);
85 | };
86 |
--------------------------------------------------------------------------------
/noVNC/tests/test.deflator.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const expect = chai.expect;
3 |
4 | import { inflateInit, inflate } from "../vendor/pako/lib/zlib/inflate.js";
5 | import ZStream from "../vendor/pako/lib/zlib/zstream.js";
6 | import Deflator from "../core/deflator.js";
7 |
8 | function _inflator(compText, expected) {
9 | let strm = new ZStream();
10 | let chunkSize = 1024 * 10 * 10;
11 | strm.output = new Uint8Array(chunkSize);
12 |
13 | inflateInit(strm, 5);
14 |
15 | if (expected > chunkSize) {
16 | chunkSize = expected;
17 | strm.output = new Uint8Array(chunkSize);
18 | }
19 |
20 | /* eslint-disable camelcase */
21 | strm.input = compText;
22 | strm.avail_in = strm.input.length;
23 | strm.next_in = 0;
24 |
25 | strm.next_out = 0;
26 | strm.avail_out = expected.length;
27 | /* eslint-enable camelcase */
28 |
29 | let ret = inflate(strm, 0);
30 |
31 | // Check that return code is not an error
32 | expect(ret).to.be.greaterThan(-1);
33 |
34 | return new Uint8Array(strm.output.buffer, 0, strm.next_out);
35 | }
36 |
37 | describe('Deflate data', function () {
38 |
39 | it('should be able to deflate messages', function () {
40 | let deflator = new Deflator();
41 |
42 | let text = "123asdf";
43 | let preText = new Uint8Array(text.length);
44 | for (let i = 0; i < preText.length; i++) {
45 | preText[i] = text.charCodeAt(i);
46 | }
47 |
48 | let compText = deflator.deflate(preText);
49 |
50 | let inflatedText = _inflator(compText, text.length);
51 | expect(inflatedText).to.array.equal(preText);
52 |
53 | });
54 |
55 | it('should be able to deflate large messages', function () {
56 | let deflator = new Deflator();
57 |
58 | /* Generate a big string with random characters. Used because
59 | repetition of letters might be deflated more effectively than
60 | random ones. */
61 | let text = "";
62 | let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
63 | for (let i = 0; i < 300000; i++) {
64 | text += characters.charAt(Math.floor(Math.random() * characters.length));
65 | }
66 |
67 | let preText = new Uint8Array(text.length);
68 | for (let i = 0; i < preText.length; i++) {
69 | preText[i] = text.charCodeAt(i);
70 | }
71 |
72 | let compText = deflator.deflate(preText);
73 |
74 | //Check that the compressed size is expected size
75 | expect(compText.length).to.be.greaterThan((1024 * 10 * 10) * 2);
76 |
77 | let inflatedText = _inflator(compText, text.length);
78 |
79 | expect(inflatedText).to.array.equal(preText);
80 |
81 | });
82 | });
83 |
--------------------------------------------------------------------------------
/noVNC/app/images/handle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
83 |
--------------------------------------------------------------------------------
/noVNC/app/locale/es.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Conectando...",
3 | "Connected (encrypted) to ": "Conectado (con encriptación) a",
4 | "Connected (unencrypted) to ": "Conectado (sin encriptación) a",
5 | "Disconnecting...": "Desconectando...",
6 | "Disconnected": "Desconectado",
7 | "Must set host": "Se debe configurar el host",
8 | "Reconnecting...": "Reconectando...",
9 | "Password is required": "La contraseña es obligatoria",
10 | "Disconnect timeout": "Tiempo de desconexión agotado",
11 | "noVNC encountered an error:": "noVNC ha encontrado un error:",
12 | "Hide/Show the control bar": "Ocultar/Mostrar la barra de control",
13 | "Move/Drag Viewport": "Mover/Arrastrar la ventana",
14 | "viewport drag": "Arrastrar la ventana",
15 | "Active Mouse Button": "Botón activo del ratón",
16 | "No mousebutton": "Ningún botón del ratón",
17 | "Left mousebutton": "Botón izquierdo del ratón",
18 | "Middle mousebutton": "Botón central del ratón",
19 | "Right mousebutton": "Botón derecho del ratón",
20 | "Keyboard": "Teclado",
21 | "Show Keyboard": "Mostrar teclado",
22 | "Extra keys": "Teclas adicionales",
23 | "Show Extra Keys": "Mostrar Teclas Adicionales",
24 | "Ctrl": "Ctrl",
25 | "Toggle Ctrl": "Pulsar/Soltar Ctrl",
26 | "Alt": "Alt",
27 | "Toggle Alt": "Pulsar/Soltar Alt",
28 | "Send Tab": "Enviar Tabulación",
29 | "Tab": "Tabulación",
30 | "Esc": "Esc",
31 | "Send Escape": "Enviar Escape",
32 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
33 | "Send Ctrl-Alt-Del": "Enviar Ctrl+Alt+Del",
34 | "Shutdown/Reboot": "Apagar/Reiniciar",
35 | "Shutdown/Reboot...": "Apagar/Reiniciar...",
36 | "Power": "Encender",
37 | "Shutdown": "Apagar",
38 | "Reboot": "Reiniciar",
39 | "Reset": "Restablecer",
40 | "Clipboard": "Portapapeles",
41 | "Clear": "Vaciar",
42 | "Fullscreen": "Pantalla Completa",
43 | "Settings": "Configuraciones",
44 | "Encrypt": "Encriptar",
45 | "Shared Mode": "Modo Compartido",
46 | "View Only": "Solo visualización",
47 | "Clip to Window": "Recortar al tamaño de la ventana",
48 | "Scaling Mode:": "Modo de escalado:",
49 | "None": "Ninguno",
50 | "Local Scaling": "Escalado Local",
51 | "Local Downscaling": "Reducción de escala local",
52 | "Remote Resizing": "Cambio de tamaño remoto",
53 | "Advanced": "Avanzado",
54 | "Local Cursor": "Cursor Local",
55 | "Repeater ID:": "ID del Repetidor:",
56 | "WebSocket": "WebSocket",
57 | "Host:": "Host:",
58 | "Port:": "Puerto:",
59 | "Path:": "Ruta:",
60 | "Automatic Reconnect": "Reconexión automática",
61 | "Reconnect Delay (ms):": "Retraso en la reconexión (ms):",
62 | "Logging:": "Registrando:",
63 | "Disconnect": "Desconectar",
64 | "Connect": "Conectar",
65 | "Password:": "Contraseña:",
66 | "Cancel": "Cancelar",
67 | "Canvas not supported.": "Canvas no soportado."
68 | }
--------------------------------------------------------------------------------
/noVNC/core/deflator.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2020 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | import { deflateInit, deflate } from "../vendor/pako/lib/zlib/deflate.js";
10 | import { Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js";
11 | import ZStream from "../vendor/pako/lib/zlib/zstream.js";
12 |
13 | export default class Deflator {
14 | constructor() {
15 | this.strm = new ZStream();
16 | this.chunkSize = 1024 * 10 * 10;
17 | this.outputBuffer = new Uint8Array(this.chunkSize);
18 | this.windowBits = 5;
19 |
20 | deflateInit(this.strm, this.windowBits);
21 | }
22 |
23 | deflate(inData) {
24 | /* eslint-disable camelcase */
25 | this.strm.input = inData;
26 | this.strm.avail_in = this.strm.input.length;
27 | this.strm.next_in = 0;
28 | this.strm.output = this.outputBuffer;
29 | this.strm.avail_out = this.chunkSize;
30 | this.strm.next_out = 0;
31 | /* eslint-enable camelcase */
32 |
33 | let lastRet = deflate(this.strm, Z_FULL_FLUSH);
34 | let outData = new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
35 |
36 | if (lastRet < 0) {
37 | throw new Error("zlib deflate failed");
38 | }
39 |
40 | if (this.strm.avail_in > 0) {
41 | // Read chunks until done
42 |
43 | let chunks = [outData];
44 | let totalLen = outData.length;
45 | do {
46 | /* eslint-disable camelcase */
47 | this.strm.output = new Uint8Array(this.chunkSize);
48 | this.strm.next_out = 0;
49 | this.strm.avail_out = this.chunkSize;
50 | /* eslint-enable camelcase */
51 |
52 | lastRet = deflate(this.strm, Z_FULL_FLUSH);
53 |
54 | if (lastRet < 0) {
55 | throw new Error("zlib deflate failed");
56 | }
57 |
58 | let chunk = new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
59 | totalLen += chunk.length;
60 | chunks.push(chunk);
61 | } while (this.strm.avail_in > 0);
62 |
63 | // Combine chunks into a single data
64 |
65 | let newData = new Uint8Array(totalLen);
66 | let offset = 0;
67 |
68 | for (let i = 0; i < chunks.length; i++) {
69 | newData.set(chunks[i], offset);
70 | offset += chunks[i].length;
71 | }
72 |
73 | outData = newData;
74 | }
75 |
76 | /* eslint-disable camelcase */
77 | this.strm.input = null;
78 | this.strm.avail_in = 0;
79 | this.strm.next_in = 0;
80 | /* eslint-enable camelcase */
81 |
82 | return outData;
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/noVNC/app/locale/tr.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Bağlanıyor...",
3 | "Disconnecting...": "Bağlantı kesiliyor...",
4 | "Reconnecting...": "Yeniden bağlantı kuruluyor...",
5 | "Internal error": "İç hata",
6 | "Must set host": "Sunucuyu kur",
7 | "Connected (encrypted) to ": "Bağlı (şifrelenmiş)",
8 | "Connected (unencrypted) to ": "Bağlandı (şifrelenmemiş)",
9 | "Something went wrong, connection is closed": "Bir şeyler ters gitti, bağlantı kesildi",
10 | "Disconnected": "Bağlantı kesildi",
11 | "New connection has been rejected with reason: ": "Bağlantı aşağıdaki nedenlerden dolayı reddedildi: ",
12 | "New connection has been rejected": "Bağlantı reddedildi",
13 | "Password is required": "Şifre gerekli",
14 | "noVNC encountered an error:": "Bir hata oluştu:",
15 | "Hide/Show the control bar": "Denetim masasını Gizle/Göster",
16 | "Move/Drag Viewport": "Görünümü Taşı/Sürükle",
17 | "viewport drag": "Görüntü penceresini sürükle",
18 | "Active Mouse Button": "Aktif Fare Düğmesi",
19 | "No mousebutton": "Fare düğmesi yok",
20 | "Left mousebutton": "Farenin sol düğmesi",
21 | "Middle mousebutton": "Farenin orta düğmesi",
22 | "Right mousebutton": "Farenin sağ düğmesi",
23 | "Keyboard": "Klavye",
24 | "Show Keyboard": "Klavye Düzenini Göster",
25 | "Extra keys": "Ekstra tuşlar",
26 | "Show Extra Keys": "Ekstra tuşları göster",
27 | "Ctrl": "Ctrl",
28 | "Toggle Ctrl": "Ctrl Değiştir ",
29 | "Alt": "Alt",
30 | "Toggle Alt": "Alt Değiştir",
31 | "Send Tab": "Sekme Gönder",
32 | "Tab": "Sekme",
33 | "Esc": "Esc",
34 | "Send Escape": "Boşluk Gönder",
35 | "Ctrl+Alt+Del": "Ctrl + Alt + Del",
36 | "Send Ctrl-Alt-Del": "Ctrl-Alt-Del Gönder",
37 | "Shutdown/Reboot": "Kapat/Yeniden Başlat",
38 | "Shutdown/Reboot...": "Kapat/Yeniden Başlat...",
39 | "Power": "Güç",
40 | "Shutdown": "Kapat",
41 | "Reboot": "Yeniden Başlat",
42 | "Reset": "Sıfırla",
43 | "Clipboard": "Pano",
44 | "Clear": "Temizle",
45 | "Fullscreen": "Tam Ekran",
46 | "Settings": "Ayarlar",
47 | "Shared Mode": "Paylaşım Modu",
48 | "View Only": "Sadece Görüntüle",
49 | "Clip to Window": "Pencereye Tıkla",
50 | "Scaling Mode:": "Ölçekleme Modu:",
51 | "None": "Bilinmeyen",
52 | "Local Scaling": "Yerel Ölçeklendirme",
53 | "Remote Resizing": "Uzaktan Yeniden Boyutlandırma",
54 | "Advanced": "Gelişmiş",
55 | "Repeater ID:": "Tekralayıcı ID:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Şifrele",
58 | "Host:": "Ana makine:",
59 | "Port:": "Port:",
60 | "Path:": "Yol:",
61 | "Automatic Reconnect": "Otomatik Yeniden Bağlan",
62 | "Reconnect Delay (ms):": "Yeniden Bağlanma Süreci (ms):",
63 | "Logging:": "Giriş yapılıyor:",
64 | "Disconnect": "Bağlantıyı Kes",
65 | "Connect": "Bağlan",
66 | "Password:": "Parola:",
67 | "Cancel": "Vazgeç",
68 | "Canvas not supported.": "Tuval desteklenmiyor."
69 | }
--------------------------------------------------------------------------------
/noVNC/app/error-handler.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2019 The noVNC Authors
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | // Fallback for all uncought errors
10 | function handleError(event, err) {
11 | try {
12 | const msg = document.getElementById('noVNC_fallback_errormsg');
13 |
14 | // Work around Firefox bug:
15 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1685038
16 | if (event.message === "ResizeObserver loop completed with undelivered notifications.") {
17 | return false;
18 | }
19 |
20 | // Only show the initial error
21 | if (msg.hasChildNodes()) {
22 | return false;
23 | }
24 |
25 | let div = document.createElement("div");
26 | div.classList.add('noVNC_message');
27 | div.appendChild(document.createTextNode(event.message));
28 | msg.appendChild(div);
29 |
30 | if (event.filename) {
31 | div = document.createElement("div");
32 | div.className = 'noVNC_location';
33 | let text = event.filename;
34 | if (event.lineno !== undefined) {
35 | text += ":" + event.lineno;
36 | if (event.colno !== undefined) {
37 | text += ":" + event.colno;
38 | }
39 | }
40 | div.appendChild(document.createTextNode(text));
41 | msg.appendChild(div);
42 | }
43 |
44 | if (err && err.stack) {
45 | div = document.createElement("div");
46 | div.className = 'noVNC_stack';
47 | div.appendChild(document.createTextNode(err.stack));
48 | msg.appendChild(div);
49 | }
50 |
51 | document.getElementById('noVNC_fallback_error')
52 | .classList.add("noVNC_open");
53 |
54 | } catch (exc) {
55 | document.write("noVNC encountered an error.");
56 | }
57 |
58 | // Try to disable keyboard interaction, best effort
59 | try {
60 | // Remove focus from the currently focused element in order to
61 | // prevent keyboard interaction from continuing
62 | if (document.activeElement) { document.activeElement.blur(); }
63 |
64 | // Don't let any element be focusable when showing the error
65 | let keyboardFocusable = 'a[href], button, input, textarea, select, details, [tabindex]';
66 | document.querySelectorAll(keyboardFocusable).forEach((elem) => {
67 | elem.setAttribute("tabindex", "-1");
68 | });
69 | } catch (exc) {
70 | // Do nothing
71 | }
72 |
73 | // Don't return true since this would prevent the error
74 | // from being printed to the browser console.
75 | return false;
76 | }
77 |
78 | window.addEventListener('error', evt => handleError(evt, evt.error));
79 | window.addEventListener('unhandledrejection', evt => handleError(evt.reason, evt.reason));
80 |
--------------------------------------------------------------------------------
/noVNC/app/locale/pl.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Łączenie...",
3 | "Disconnecting...": "Rozłączanie...",
4 | "Reconnecting...": "Łączenie...",
5 | "Internal error": "Błąd wewnętrzny",
6 | "Must set host": "Host i port są wymagane",
7 | "Connected (encrypted) to ": "Połączenie (szyfrowane) z ",
8 | "Connected (unencrypted) to ": "Połączenie (nieszyfrowane) z ",
9 | "Something went wrong, connection is closed": "Coś poszło źle, połączenie zostało zamknięte",
10 | "Disconnected": "Rozłączony",
11 | "New connection has been rejected with reason: ": "Nowe połączenie zostało odrzucone z powodu: ",
12 | "New connection has been rejected": "Nowe połączenie zostało odrzucone",
13 | "Password is required": "Hasło jest wymagane",
14 | "noVNC encountered an error:": "noVNC napotkało błąd:",
15 | "Hide/Show the control bar": "Pokaż/Ukryj pasek ustawień",
16 | "Move/Drag Viewport": "Ruszaj/Przeciągaj Viewport",
17 | "viewport drag": "przeciągnij viewport",
18 | "Active Mouse Button": "Aktywny Przycisk Myszy",
19 | "No mousebutton": "Brak przycisku myszy",
20 | "Left mousebutton": "Lewy przycisk myszy",
21 | "Middle mousebutton": "Środkowy przycisk myszy",
22 | "Right mousebutton": "Prawy przycisk myszy",
23 | "Keyboard": "Klawiatura",
24 | "Show Keyboard": "Pokaż klawiaturę",
25 | "Extra keys": "Przyciski dodatkowe",
26 | "Show Extra Keys": "Pokaż przyciski dodatkowe",
27 | "Ctrl": "Ctrl",
28 | "Toggle Ctrl": "Przełącz Ctrl",
29 | "Alt": "Alt",
30 | "Toggle Alt": "Przełącz Alt",
31 | "Send Tab": "Wyślij Tab",
32 | "Tab": "Tab",
33 | "Esc": "Esc",
34 | "Send Escape": "Wyślij Escape",
35 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
36 | "Send Ctrl-Alt-Del": "Wyślij Ctrl-Alt-Del",
37 | "Shutdown/Reboot": "Wyłącz/Uruchom ponownie",
38 | "Shutdown/Reboot...": "Wyłącz/Uruchom ponownie...",
39 | "Power": "Włączony",
40 | "Shutdown": "Wyłącz",
41 | "Reboot": "Uruchom ponownie",
42 | "Reset": "Resetuj",
43 | "Clipboard": "Schowek",
44 | "Clear": "Wyczyść",
45 | "Fullscreen": "Pełny ekran",
46 | "Settings": "Ustawienia",
47 | "Shared Mode": "Tryb Współdzielenia",
48 | "View Only": "Tylko Podgląd",
49 | "Clip to Window": "Przytnij do Okna",
50 | "Scaling Mode:": "Tryb Skalowania:",
51 | "None": "Brak",
52 | "Local Scaling": "Skalowanie lokalne",
53 | "Remote Resizing": "Skalowanie zdalne",
54 | "Advanced": "Zaawansowane",
55 | "Repeater ID:": "ID Repeatera:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Szyfrowanie",
58 | "Host:": "Host:",
59 | "Port:": "Port:",
60 | "Path:": "Ścieżka:",
61 | "Automatic Reconnect": "Automatycznie wznawiaj połączenie",
62 | "Reconnect Delay (ms):": "Opóźnienie wznawiania (ms):",
63 | "Logging:": "Poziom logowania:",
64 | "Disconnect": "Rozłącz",
65 | "Connect": "Połącz",
66 | "Password:": "Hasło:",
67 | "Cancel": "Anuluj",
68 | "Canvas not supported.": "Element Canvas nie jest wspierany."
69 | }
--------------------------------------------------------------------------------
/noVNC/app/locale/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Připojení...",
3 | "Disconnecting...": "Odpojení...",
4 | "Reconnecting...": "Obnova připojení...",
5 | "Internal error": "Vnitřní chyba",
6 | "Must set host": "Hostitel musí být nastavení",
7 | "Connected (encrypted) to ": "Připojení (šifrované) k ",
8 | "Connected (unencrypted) to ": "Připojení (nešifrované) k ",
9 | "Something went wrong, connection is closed": "Něco se pokazilo, odpojeno",
10 | "Failed to connect to server": "Chyba připojení k serveru",
11 | "Disconnected": "Odpojeno",
12 | "New connection has been rejected with reason: ": "Nové připojení bylo odmítnuto s odůvodněním: ",
13 | "New connection has been rejected": "Nové připojení bylo odmítnuto",
14 | "Password is required": "Je vyžadováno heslo",
15 | "noVNC encountered an error:": "noVNC narazilo na chybu:",
16 | "Hide/Show the control bar": "Skrýt/zobrazit ovládací panel",
17 | "Move/Drag Viewport": "Přesunout/přetáhnout výřez",
18 | "viewport drag": "přesun výřezu",
19 | "Active Mouse Button": "Aktivní tlačítka myši",
20 | "No mousebutton": "Žádné",
21 | "Left mousebutton": "Levé tlačítko myši",
22 | "Middle mousebutton": "Prostřední tlačítko myši",
23 | "Right mousebutton": "Pravé tlačítko myši",
24 | "Keyboard": "Klávesnice",
25 | "Show Keyboard": "Zobrazit klávesnici",
26 | "Extra keys": "Extra klávesy",
27 | "Show Extra Keys": "Zobrazit extra klávesy",
28 | "Ctrl": "Ctrl",
29 | "Toggle Ctrl": "Přepnout Ctrl",
30 | "Alt": "Alt",
31 | "Toggle Alt": "Přepnout Alt",
32 | "Send Tab": "Odeslat tabulátor",
33 | "Tab": "Tab",
34 | "Esc": "Esc",
35 | "Send Escape": "Odeslat Esc",
36 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
37 | "Send Ctrl-Alt-Del": "Poslat Ctrl-Alt-Del",
38 | "Shutdown/Reboot": "Vypnutí/Restart",
39 | "Shutdown/Reboot...": "Vypnutí/Restart...",
40 | "Power": "Napájení",
41 | "Shutdown": "Vypnout",
42 | "Reboot": "Restart",
43 | "Reset": "Reset",
44 | "Clipboard": "Schránka",
45 | "Clear": "Vymazat",
46 | "Fullscreen": "Celá obrazovka",
47 | "Settings": "Nastavení",
48 | "Shared Mode": "Sdílený režim",
49 | "View Only": "Pouze prohlížení",
50 | "Clip to Window": "Přizpůsobit oknu",
51 | "Scaling Mode:": "Přizpůsobení velikosti",
52 | "None": "Žádné",
53 | "Local Scaling": "Místní",
54 | "Remote Resizing": "Vzdálené",
55 | "Advanced": "Pokročilé",
56 | "Repeater ID:": "ID opakovače",
57 | "WebSocket": "WebSocket",
58 | "Encrypt": "Šifrování:",
59 | "Host:": "Hostitel:",
60 | "Port:": "Port:",
61 | "Path:": "Cesta",
62 | "Automatic Reconnect": "Automatická obnova připojení",
63 | "Reconnect Delay (ms):": "Zpoždění připojení (ms)",
64 | "Show Dot when No Cursor": "Tečka místo chybějícího kurzoru myši",
65 | "Logging:": "Logování:",
66 | "Disconnect": "Odpojit",
67 | "Connect": "Připojit",
68 | "Password:": "Heslo",
69 | "Send Password": "Odeslat heslo",
70 | "Cancel": "Zrušit"
71 | }
--------------------------------------------------------------------------------
/noVNC/app/locale/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Verbinden...",
3 | "Disconnecting...": "Verbindung trennen...",
4 | "Reconnecting...": "Verbindung wiederherstellen...",
5 | "Internal error": "Interner Fehler",
6 | "Must set host": "Richten Sie den Server ein",
7 | "Connected (encrypted) to ": "Verbunden mit (verschlüsselt) ",
8 | "Connected (unencrypted) to ": "Verbunden mit (unverschlüsselt) ",
9 | "Something went wrong, connection is closed": "Etwas lief schief, Verbindung wurde getrennt",
10 | "Disconnected": "Verbindung zum Server getrennt",
11 | "New connection has been rejected with reason: ": "Verbindung wurde aus folgendem Grund abgelehnt: ",
12 | "New connection has been rejected": "Verbindung wurde abgelehnt",
13 | "Password is required": "Passwort ist erforderlich",
14 | "noVNC encountered an error:": "Ein Fehler ist aufgetreten:",
15 | "Hide/Show the control bar": "Kontrollleiste verstecken/anzeigen",
16 | "Move/Drag Viewport": "Ansichtsfenster verschieben/ziehen",
17 | "viewport drag": "Ansichtsfenster ziehen",
18 | "Active Mouse Button": "Aktive Maustaste",
19 | "No mousebutton": "Keine Maustaste",
20 | "Left mousebutton": "Linke Maustaste",
21 | "Middle mousebutton": "Mittlere Maustaste",
22 | "Right mousebutton": "Rechte Maustaste",
23 | "Keyboard": "Tastatur",
24 | "Show Keyboard": "Tastatur anzeigen",
25 | "Extra keys": "Zusatztasten",
26 | "Show Extra Keys": "Zusatztasten anzeigen",
27 | "Ctrl": "Strg",
28 | "Toggle Ctrl": "Strg umschalten",
29 | "Alt": "Alt",
30 | "Toggle Alt": "Alt umschalten",
31 | "Send Tab": "Tab senden",
32 | "Tab": "Tab",
33 | "Esc": "Esc",
34 | "Send Escape": "Escape senden",
35 | "Ctrl+Alt+Del": "Strg+Alt+Entf",
36 | "Send Ctrl-Alt-Del": "Strg+Alt+Entf senden",
37 | "Shutdown/Reboot": "Herunterfahren/Neustarten",
38 | "Shutdown/Reboot...": "Herunterfahren/Neustarten...",
39 | "Power": "Energie",
40 | "Shutdown": "Herunterfahren",
41 | "Reboot": "Neustarten",
42 | "Reset": "Zurücksetzen",
43 | "Clipboard": "Zwischenablage",
44 | "Clear": "Löschen",
45 | "Fullscreen": "Vollbild",
46 | "Settings": "Einstellungen",
47 | "Shared Mode": "Geteilter Modus",
48 | "View Only": "Nur betrachten",
49 | "Clip to Window": "Auf Fenster begrenzen",
50 | "Scaling Mode:": "Skalierungsmodus:",
51 | "None": "Keiner",
52 | "Local Scaling": "Lokales skalieren",
53 | "Remote Resizing": "Serverseitiges skalieren",
54 | "Advanced": "Erweitert",
55 | "Repeater ID:": "Repeater ID:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Verschlüsselt",
58 | "Host:": "Server:",
59 | "Port:": "Port:",
60 | "Path:": "Pfad:",
61 | "Automatic Reconnect": "Automatisch wiederverbinden",
62 | "Reconnect Delay (ms):": "Wiederverbindungsverzögerung (ms):",
63 | "Logging:": "Protokollierung:",
64 | "Disconnect": "Verbindung trennen",
65 | "Connect": "Verbinden",
66 | "Password:": "Passwort:",
67 | "Cancel": "Abbrechen",
68 | "Canvas not supported.": "Canvas nicht unterstützt."
69 | }
--------------------------------------------------------------------------------
/noVNC/core/input/vkeys.js:
--------------------------------------------------------------------------------
1 | /*
2 | * noVNC: HTML5 VNC client
3 | * Copyright (C) 2018 The noVNC Authors
4 | * Licensed under MPL 2.0 or any later version (see LICENSE.txt)
5 | */
6 |
7 | /*
8 | * Mapping between Microsoft® Windows® Virtual-Key codes and
9 | * HTML key codes.
10 | */
11 |
12 | export default {
13 | 0x08: 'Backspace',
14 | 0x09: 'Tab',
15 | 0x0a: 'NumpadClear',
16 | 0x0d: 'Enter',
17 | 0x10: 'ShiftLeft',
18 | 0x11: 'ControlLeft',
19 | 0x12: 'AltLeft',
20 | 0x13: 'Pause',
21 | 0x14: 'CapsLock',
22 | 0x15: 'Lang1',
23 | 0x19: 'Lang2',
24 | 0x1b: 'Escape',
25 | 0x1c: 'Convert',
26 | 0x1d: 'NonConvert',
27 | 0x20: 'Space',
28 | 0x21: 'PageUp',
29 | 0x22: 'PageDown',
30 | 0x23: 'End',
31 | 0x24: 'Home',
32 | 0x25: 'ArrowLeft',
33 | 0x26: 'ArrowUp',
34 | 0x27: 'ArrowRight',
35 | 0x28: 'ArrowDown',
36 | 0x29: 'Select',
37 | 0x2c: 'PrintScreen',
38 | 0x2d: 'Insert',
39 | 0x2e: 'Delete',
40 | 0x2f: 'Help',
41 | 0x30: 'Digit0',
42 | 0x31: 'Digit1',
43 | 0x32: 'Digit2',
44 | 0x33: 'Digit3',
45 | 0x34: 'Digit4',
46 | 0x35: 'Digit5',
47 | 0x36: 'Digit6',
48 | 0x37: 'Digit7',
49 | 0x38: 'Digit8',
50 | 0x39: 'Digit9',
51 | 0x5b: 'MetaLeft',
52 | 0x5c: 'MetaRight',
53 | 0x5d: 'ContextMenu',
54 | 0x5f: 'Sleep',
55 | 0x60: 'Numpad0',
56 | 0x61: 'Numpad1',
57 | 0x62: 'Numpad2',
58 | 0x63: 'Numpad3',
59 | 0x64: 'Numpad4',
60 | 0x65: 'Numpad5',
61 | 0x66: 'Numpad6',
62 | 0x67: 'Numpad7',
63 | 0x68: 'Numpad8',
64 | 0x69: 'Numpad9',
65 | 0x6a: 'NumpadMultiply',
66 | 0x6b: 'NumpadAdd',
67 | 0x6c: 'NumpadDecimal',
68 | 0x6d: 'NumpadSubtract',
69 | 0x6e: 'NumpadDecimal', // Duplicate, because buggy on Windows
70 | 0x6f: 'NumpadDivide',
71 | 0x70: 'F1',
72 | 0x71: 'F2',
73 | 0x72: 'F3',
74 | 0x73: 'F4',
75 | 0x74: 'F5',
76 | 0x75: 'F6',
77 | 0x76: 'F7',
78 | 0x77: 'F8',
79 | 0x78: 'F9',
80 | 0x79: 'F10',
81 | 0x7a: 'F11',
82 | 0x7b: 'F12',
83 | 0x7c: 'F13',
84 | 0x7d: 'F14',
85 | 0x7e: 'F15',
86 | 0x7f: 'F16',
87 | 0x80: 'F17',
88 | 0x81: 'F18',
89 | 0x82: 'F19',
90 | 0x83: 'F20',
91 | 0x84: 'F21',
92 | 0x85: 'F22',
93 | 0x86: 'F23',
94 | 0x87: 'F24',
95 | 0x90: 'NumLock',
96 | 0x91: 'ScrollLock',
97 | 0xa6: 'BrowserBack',
98 | 0xa7: 'BrowserForward',
99 | 0xa8: 'BrowserRefresh',
100 | 0xa9: 'BrowserStop',
101 | 0xaa: 'BrowserSearch',
102 | 0xab: 'BrowserFavorites',
103 | 0xac: 'BrowserHome',
104 | 0xad: 'AudioVolumeMute',
105 | 0xae: 'AudioVolumeDown',
106 | 0xaf: 'AudioVolumeUp',
107 | 0xb0: 'MediaTrackNext',
108 | 0xb1: 'MediaTrackPrevious',
109 | 0xb2: 'MediaStop',
110 | 0xb3: 'MediaPlayPause',
111 | 0xb4: 'LaunchMail',
112 | 0xb5: 'MediaSelect',
113 | 0xb6: 'LaunchApp1',
114 | 0xb7: 'LaunchApp2',
115 | 0xe1: 'AltRight', // Only when it is AltGraph
116 | };
117 |
--------------------------------------------------------------------------------
/noVNC/app/locale/pt_BR.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Conectando...",
3 | "Disconnecting...": "Desconectando...",
4 | "Reconnecting...": "Reconectando...",
5 | "Internal error": "Erro interno",
6 | "Must set host": "É necessário definir o host",
7 | "Connected (encrypted) to ": "Conectado (com criptografia) a ",
8 | "Connected (unencrypted) to ": "Conectado (sem criptografia) a ",
9 | "Something went wrong, connection is closed": "Algo deu errado. A conexão foi encerrada.",
10 | "Failed to connect to server": "Falha ao conectar-se ao servidor",
11 | "Disconnected": "Desconectado",
12 | "New connection has been rejected with reason: ": "A nova conexão foi rejeitada pelo motivo: ",
13 | "New connection has been rejected": "A nova conexão foi rejeitada",
14 | "Credentials are required": "Credenciais são obrigatórias",
15 | "noVNC encountered an error:": "O noVNC encontrou um erro:",
16 | "Hide/Show the control bar": "Esconder/mostrar a barra de controles",
17 | "Drag": "Arrastar",
18 | "Move/Drag Viewport": "Mover/arrastar a janela",
19 | "Keyboard": "Teclado",
20 | "Show Keyboard": "Mostrar teclado",
21 | "Extra keys": "Teclas adicionais",
22 | "Show Extra Keys": "Mostar teclas adicionais",
23 | "Ctrl": "Ctrl",
24 | "Toggle Ctrl": "Pressionar/soltar Ctrl",
25 | "Alt": "Alt",
26 | "Toggle Alt": "Pressionar/soltar Alt",
27 | "Toggle Windows": "Pressionar/soltar Windows",
28 | "Windows": "Windows",
29 | "Send Tab": "Enviar Tab",
30 | "Tab": "Tab",
31 | "Esc": "Esc",
32 | "Send Escape": "Enviar Esc",
33 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
34 | "Send Ctrl-Alt-Del": "Enviar Ctrl-Alt-Del",
35 | "Shutdown/Reboot": "Desligar/reiniciar",
36 | "Shutdown/Reboot...": "Desligar/reiniciar...",
37 | "Power": "Ligar",
38 | "Shutdown": "Desligar",
39 | "Reboot": "Reiniciar",
40 | "Reset": "Reiniciar (forçado)",
41 | "Clipboard": "Área de transferência",
42 | "Clear": "Limpar",
43 | "Fullscreen": "Tela cheia",
44 | "Settings": "Configurações",
45 | "Shared Mode": "Modo compartilhado",
46 | "View Only": "Apenas visualizar",
47 | "Clip to Window": "Recortar à janela",
48 | "Scaling Mode:": "Modo de dimensionamento:",
49 | "None": "Nenhum",
50 | "Local Scaling": "Local",
51 | "Remote Resizing": "Remoto",
52 | "Advanced": "Avançado",
53 | "Quality:": "Qualidade:",
54 | "Compression level:": "Nível de compressão:",
55 | "Repeater ID:": "ID do repetidor:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Criptografar",
58 | "Host:": "Host:",
59 | "Port:": "Porta:",
60 | "Path:": "Caminho:",
61 | "Automatic Reconnect": "Reconexão automática",
62 | "Reconnect Delay (ms):": "Atraso da reconexão (ms)",
63 | "Show Dot when No Cursor": "Mostrar ponto quando não há cursor",
64 | "Logging:": "Registros:",
65 | "Version:": "Versão:",
66 | "Disconnect": "Desconectar",
67 | "Connect": "Conectar",
68 | "Username:": "Nome de usuário:",
69 | "Password:": "Senha:",
70 | "Send Credentials": "Enviar credenciais",
71 | "Cancel": "Cancelar"
72 | }
--------------------------------------------------------------------------------
/noVNC/app/locale/it.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Connessione in corso...",
3 | "Disconnecting...": "Disconnessione...",
4 | "Reconnecting...": "Riconnessione...",
5 | "Internal error": "Errore interno",
6 | "Must set host": "Devi impostare l'host",
7 | "Connected (encrypted) to ": "Connesso (crittografato) a ",
8 | "Connected (unencrypted) to ": "Connesso (non crittografato) a",
9 | "Something went wrong, connection is closed": "Qualcosa è andato storto, la connessione è stata chiusa",
10 | "Failed to connect to server": "Impossibile connettersi al server",
11 | "Disconnected": "Disconnesso",
12 | "New connection has been rejected with reason: ": "La nuova connessione è stata rifiutata con motivo: ",
13 | "New connection has been rejected": "La nuova connessione è stata rifiutata",
14 | "Credentials are required": "Le credenziali sono obbligatorie",
15 | "noVNC encountered an error:": "noVNC ha riscontrato un errore:",
16 | "Hide/Show the control bar": "Nascondi/Mostra la barra di controllo",
17 | "Drag": "",
18 | "Move/Drag Viewport": "",
19 | "Keyboard": "Tastiera",
20 | "Show Keyboard": "Mostra tastiera",
21 | "Extra keys": "Tasti Aggiuntivi",
22 | "Show Extra Keys": "Mostra Tasti Aggiuntivi",
23 | "Ctrl": "Ctrl",
24 | "Toggle Ctrl": "Tieni premuto Ctrl",
25 | "Alt": "Alt",
26 | "Toggle Alt": "Tieni premuto Alt",
27 | "Toggle Windows": "Tieni premuto Windows",
28 | "Windows": "Windows",
29 | "Send Tab": "Invia Tab",
30 | "Tab": "Tab",
31 | "Esc": "Esc",
32 | "Send Escape": "Invia Esc",
33 | "Ctrl+Alt+Del": "Ctrl+Alt+Canc",
34 | "Send Ctrl-Alt-Del": "Invia Ctrl-Alt-Canc",
35 | "Shutdown/Reboot": "Spegnimento/Riavvio",
36 | "Shutdown/Reboot...": "Spegnimento/Riavvio...",
37 | "Power": "Alimentazione",
38 | "Shutdown": "Spegnimento",
39 | "Reboot": "Riavvio",
40 | "Reset": "Reset",
41 | "Clipboard": "Clipboard",
42 | "Clear": "Pulisci",
43 | "Fullscreen": "Schermo intero",
44 | "Settings": "Impostazioni",
45 | "Shared Mode": "Modalità condivisa",
46 | "View Only": "Sola Visualizzazione",
47 | "Clip to Window": "",
48 | "Scaling Mode:": "Modalità di ridimensionamento:",
49 | "None": "Nessuna",
50 | "Local Scaling": "Ridimensionamento Locale",
51 | "Remote Resizing": "Ridimensionamento Remoto",
52 | "Advanced": "Avanzate",
53 | "Quality:": "Qualità:",
54 | "Compression level:": "Livello Compressione:",
55 | "Repeater ID:": "ID Ripetitore:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Crittografa",
58 | "Host:": "Host:",
59 | "Port:": "Porta:",
60 | "Path:": "Percorso:",
61 | "Automatic Reconnect": "Riconnessione Automatica",
62 | "Reconnect Delay (ms):": "Ritardo Riconnessione (ms):",
63 | "Show Dot when No Cursor": "Mostra Punto quando Nessun Cursore",
64 | "Logging:": "",
65 | "Version:": "Versione:",
66 | "Disconnect": "Disconnetti",
67 | "Connect": "Connetti",
68 | "Username:": "Utente:",
69 | "Password:": "Password:",
70 | "Send Credentials": "Invia Credenziale",
71 | "Cancel": "Annulla"
72 | }
--------------------------------------------------------------------------------
/noVNC/app/locale/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Подключение...",
3 | "Disconnecting...": "Отключение...",
4 | "Reconnecting...": "Переподключение...",
5 | "Internal error": "Внутренняя ошибка",
6 | "Must set host": "Задайте имя сервера или IP",
7 | "Connected (encrypted) to ": "Подключено (с шифрованием) к ",
8 | "Connected (unencrypted) to ": "Подключено (без шифрования) к ",
9 | "Something went wrong, connection is closed": "Что-то пошло не так, подключение разорвано",
10 | "Failed to connect to server": "Ошибка подключения к серверу",
11 | "Disconnected": "Отключено",
12 | "New connection has been rejected with reason: ": "Новое соединение отклонено по причине: ",
13 | "New connection has been rejected": "Новое соединение отклонено",
14 | "Credentials are required": "Требуются учетные данные",
15 | "noVNC encountered an error:": "Ошибка noVNC: ",
16 | "Hide/Show the control bar": "Скрыть/Показать контрольную панель",
17 | "Drag": "Переместить",
18 | "Move/Drag Viewport": "Переместить окно",
19 | "Keyboard": "Клавиатура",
20 | "Show Keyboard": "Показать клавиатуру",
21 | "Extra keys": "Дополнительные Кнопки",
22 | "Show Extra Keys": "Показать Дополнительные Кнопки",
23 | "Ctrl": "Ctrl",
24 | "Toggle Ctrl": "Переключение нажатия Ctrl",
25 | "Alt": "Alt",
26 | "Toggle Alt": "Переключение нажатия Alt",
27 | "Toggle Windows": "Переключение вкладок",
28 | "Windows": "Вкладка",
29 | "Send Tab": "Передать нажатие Tab",
30 | "Tab": "Tab",
31 | "Esc": "Esc",
32 | "Send Escape": "Передать нажатие Escape",
33 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
34 | "Send Ctrl-Alt-Del": "Передать нажатие Ctrl-Alt-Del",
35 | "Shutdown/Reboot": "Выключить/Перезагрузить",
36 | "Shutdown/Reboot...": "Выключить/Перезагрузить...",
37 | "Power": "Питание",
38 | "Shutdown": "Выключить",
39 | "Reboot": "Перезагрузить",
40 | "Reset": "Сброс",
41 | "Clipboard": "Буфер обмена",
42 | "Clear": "Очистить",
43 | "Fullscreen": "Во весь экран",
44 | "Settings": "Настройки",
45 | "Shared Mode": "Общий режим",
46 | "View Only": "Только Просмотр",
47 | "Clip to Window": "В окно",
48 | "Scaling Mode:": "Масштаб:",
49 | "None": "Нет",
50 | "Local Scaling": "Локльный масштаб",
51 | "Remote Resizing": "Удаленная перенастройка размера",
52 | "Advanced": "Дополнительно",
53 | "Quality:": "Качество",
54 | "Compression level:": "Уровень Сжатия",
55 | "Repeater ID:": "Идентификатор ID:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Шифрование",
58 | "Host:": "Сервер:",
59 | "Port:": "Порт:",
60 | "Path:": "Путь:",
61 | "Automatic Reconnect": "Автоматическое переподключение",
62 | "Reconnect Delay (ms):": "Задержка переподключения (мс):",
63 | "Show Dot when No Cursor": "Показать точку вместо курсора",
64 | "Logging:": "Лог:",
65 | "Version:": "Версия",
66 | "Disconnect": "Отключение",
67 | "Connect": "Подключение",
68 | "Username:": "Имя Пользователя",
69 | "Password:": "Пароль:",
70 | "Send Credentials": "Передача Учетных Данных",
71 | "Cancel": "Выход"
72 | }
--------------------------------------------------------------------------------
/noVNC/app/locale/el.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Συνδέεται...",
3 | "Disconnecting...": "Aποσυνδέεται...",
4 | "Reconnecting...": "Επανασυνδέεται...",
5 | "Internal error": "Εσωτερικό σφάλμα",
6 | "Must set host": "Πρέπει να οριστεί ο διακομιστής",
7 | "Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ",
8 | "Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ",
9 | "Something went wrong, connection is closed": "Κάτι πήγε στραβά, η σύνδεση διακόπηκε",
10 | "Disconnected": "Αποσυνδέθηκε",
11 | "New connection has been rejected with reason: ": "Η νέα σύνδεση απορρίφθηκε διότι: ",
12 | "New connection has been rejected": "Η νέα σύνδεση απορρίφθηκε ",
13 | "Password is required": "Απαιτείται ο κωδικός πρόσβασης",
14 | "noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:",
15 | "Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου",
16 | "Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου",
17 | "viewport drag": "σύρσιμο θεατού πεδίου",
18 | "Active Mouse Button": "Ενεργό Πλήκτρο Ποντικιού",
19 | "No mousebutton": "Χωρίς Πλήκτρο Ποντικιού",
20 | "Left mousebutton": "Αριστερό Πλήκτρο Ποντικιού",
21 | "Middle mousebutton": "Μεσαίο Πλήκτρο Ποντικιού",
22 | "Right mousebutton": "Δεξί Πλήκτρο Ποντικιού",
23 | "Keyboard": "Πληκτρολόγιο",
24 | "Show Keyboard": "Εμφάνιση Πληκτρολογίου",
25 | "Extra keys": "Επιπλέον πλήκτρα",
26 | "Show Extra Keys": "Εμφάνιση Επιπλέον Πλήκτρων",
27 | "Ctrl": "Ctrl",
28 | "Toggle Ctrl": "Εναλλαγή Ctrl",
29 | "Alt": "Alt",
30 | "Toggle Alt": "Εναλλαγή Alt",
31 | "Send Tab": "Αποστολή Tab",
32 | "Tab": "Tab",
33 | "Esc": "Esc",
34 | "Send Escape": "Αποστολή Escape",
35 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
36 | "Send Ctrl-Alt-Del": "Αποστολή Ctrl-Alt-Del",
37 | "Shutdown/Reboot": "Κλείσιμο/Επανεκκίνηση",
38 | "Shutdown/Reboot...": "Κλείσιμο/Επανεκκίνηση...",
39 | "Power": "Απενεργοποίηση",
40 | "Shutdown": "Κλείσιμο",
41 | "Reboot": "Επανεκκίνηση",
42 | "Reset": "Επαναφορά",
43 | "Clipboard": "Πρόχειρο",
44 | "Clear": "Καθάρισμα",
45 | "Fullscreen": "Πλήρης Οθόνη",
46 | "Settings": "Ρυθμίσεις",
47 | "Shared Mode": "Κοινόχρηστη Λειτουργία",
48 | "View Only": "Μόνο Θέαση",
49 | "Clip to Window": "Αποκοπή στο όριο του Παράθυρου",
50 | "Scaling Mode:": "Λειτουργία Κλιμάκωσης:",
51 | "None": "Καμία",
52 | "Local Scaling": "Τοπική Κλιμάκωση",
53 | "Remote Resizing": "Απομακρυσμένη Αλλαγή μεγέθους",
54 | "Advanced": "Για προχωρημένους",
55 | "Repeater ID:": "Repeater ID:",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Κρυπτογράφηση",
58 | "Host:": "Όνομα διακομιστή:",
59 | "Port:": "Πόρτα διακομιστή:",
60 | "Path:": "Διαδρομή:",
61 | "Automatic Reconnect": "Αυτόματη επανασύνδεση",
62 | "Reconnect Delay (ms):": "Καθυστέρηση επανασύνδεσης (ms):",
63 | "Logging:": "Καταγραφή:",
64 | "Disconnect": "Αποσύνδεση",
65 | "Connect": "Σύνδεση",
66 | "Password:": "Κωδικός Πρόσβασης:",
67 | "Cancel": "Ακύρωση",
68 | "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas"
69 | }
--------------------------------------------------------------------------------
/Dockerfile.desktop:
--------------------------------------------------------------------------------
1 | FROM alpine:3.19
2 |
3 | # Install required packages
4 | RUN apk add --no-cache \
5 | xvfb \
6 | x11vnc \
7 | supervisor \
8 | websockify \
9 | firefox \
10 | bash \
11 | curl \
12 | ffmpeg \
13 | imagemagick \
14 | python3 \
15 | py3-pip \
16 | xfce4 \
17 | xfce4-terminal \
18 | dbus \
19 | dbus-x11 \
20 | python3-dev \
21 | py3-virtualenv \
22 | xdotool
23 |
24 | # Initialize dbus machine-id and create necessary directories
25 | RUN mkdir -p /var/run/dbus && \
26 | dbus-uuidgen > /var/lib/dbus/machine-id
27 |
28 | # Create and activate virtual environment
29 | ENV VIRTUAL_ENV=/opt/venv
30 | RUN python3 -m venv $VIRTUAL_ENV
31 | ENV PATH="$VIRTUAL_ENV/bin:$PATH"
32 |
33 | # Install Python packages in virtual environment
34 | RUN pip3 install --no-cache-dir \
35 | fastapi \
36 | uvicorn \
37 | python-multipart
38 |
39 | # Modify Firefox desktop entry to use appropriate flags
40 | RUN sed -i 's|^Exec=.*|Exec=/usr/bin/firefox --no-remote --new-instance|' /usr/share/applications/firefox.desktop || true
41 |
42 | # Configure Firefox to skip first-run pages
43 | RUN mkdir -p /root/.mozilla/firefox && \
44 | echo '[General]' > /root/.mozilla/firefox/profiles.ini && \
45 | echo 'StartWithLastProfile=1' >> /root/.mozilla/firefox/profiles.ini && \
46 | echo '' >> /root/.mozilla/firefox/profiles.ini && \
47 | echo '[Profile0]' >> /root/.mozilla/firefox/profiles.ini && \
48 | echo 'Name=default' >> /root/.mozilla/firefox/profiles.ini && \
49 | echo 'IsRelative=1' >> /root/.mozilla/firefox/profiles.ini && \
50 | echo 'Path=default.default' >> /root/.mozilla/firefox/profiles.ini && \
51 | echo 'Default=1' >> /root/.mozilla/firefox/profiles.ini && \
52 | mkdir -p /root/.mozilla/firefox/default.default && \
53 | echo 'user_pref("browser.startup.homepage_override.mstone", "ignore");' > /root/.mozilla/firefox/default.default/user.js && \
54 | echo 'user_pref("startup.homepage_welcome_url", "");' >> /root/.mozilla/firefox/default.default/user.js && \
55 | echo 'user_pref("startup.homepage_welcome_url.additional", "");' >> /root/.mozilla/firefox/default.default/user.js && \
56 | echo 'user_pref("browser.aboutwelcome.enabled", false);' >> /root/.mozilla/firefox/default.default/user.js && \
57 | echo 'user_pref("trailhead.firstrun.didSeeAboutWelcome", true);' >> /root/.mozilla/firefox/default.default/user.js && \
58 | echo 'user_pref("browser.startup.firstrunSkipsHomepage", false);' >> /root/.mozilla/firefox/default.default/user.js
59 |
60 | # Create supervisor config directory
61 | RUN mkdir -p /etc/supervisor.d
62 |
63 | COPY noVNC /usr/share/novnc
64 | # index.html redirects to vnc.html with autoconnect and resize parameters
65 |
66 | # Copy supervisor config
67 | COPY desktop-supervisord.conf /etc/supervisor.d/supervisord.ini
68 |
69 | COPY desktop_files /root/desktop_files
70 |
71 | # Add computer_use_server directory
72 | COPY computer_use_server /computer_use_server
73 |
74 | # Copy start script and make it executable
75 | COPY start.sh /start.sh
76 | RUN chmod +x /start.sh
77 |
78 | # Expose VNC, noVNC, and API ports
79 | EXPOSE 5900 6081 8000 2000
80 |
81 | CMD ["/start.sh"]
--------------------------------------------------------------------------------
/noVNC/app/images/tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
87 |
--------------------------------------------------------------------------------
/noVNC/app/locale/nl.json:
--------------------------------------------------------------------------------
1 | {
2 | "Connecting...": "Verbinden...",
3 | "Disconnecting...": "Verbinding verbreken...",
4 | "Reconnecting...": "Opnieuw verbinding maken...",
5 | "Internal error": "Interne fout",
6 | "Must set host": "Host moeten worden ingesteld",
7 | "Connected (encrypted) to ": "Verbonden (versleuteld) met ",
8 | "Connected (unencrypted) to ": "Verbonden (onversleuteld) met ",
9 | "Something went wrong, connection is closed": "Er iets fout gelopen, verbinding werd verbroken",
10 | "Failed to connect to server": "Verbinding maken met server is mislukt",
11 | "Disconnected": "Verbinding verbroken",
12 | "New connection has been rejected with reason: ": "Nieuwe verbinding is geweigerd omwille van de volgende reden: ",
13 | "New connection has been rejected": "Nieuwe verbinding is geweigerd",
14 | "Password is required": "Wachtwoord is vereist",
15 | "noVNC encountered an error:": "noVNC heeft een fout bemerkt:",
16 | "Hide/Show the control bar": "Verberg/Toon de bedieningsbalk",
17 | "Move/Drag Viewport": "Verplaats/Versleep Kijkvenster",
18 | "viewport drag": "kijkvenster slepen",
19 | "Active Mouse Button": "Actieve Muisknop",
20 | "No mousebutton": "Geen muisknop",
21 | "Left mousebutton": "Linker muisknop",
22 | "Middle mousebutton": "Middelste muisknop",
23 | "Right mousebutton": "Rechter muisknop",
24 | "Keyboard": "Toetsenbord",
25 | "Show Keyboard": "Toon Toetsenbord",
26 | "Extra keys": "Extra toetsen",
27 | "Show Extra Keys": "Toon Extra Toetsen",
28 | "Ctrl": "Ctrl",
29 | "Toggle Ctrl": "Ctrl omschakelen",
30 | "Alt": "Alt",
31 | "Toggle Alt": "Alt omschakelen",
32 | "Toggle Windows": "Windows omschakelen",
33 | "Windows": "Windows",
34 | "Send Tab": "Tab Sturen",
35 | "Tab": "Tab",
36 | "Esc": "Esc",
37 | "Send Escape": "Escape Sturen",
38 | "Ctrl+Alt+Del": "Ctrl-Alt-Del",
39 | "Send Ctrl-Alt-Del": "Ctrl-Alt-Del Sturen",
40 | "Shutdown/Reboot": "Uitschakelen/Herstarten",
41 | "Shutdown/Reboot...": "Uitschakelen/Herstarten...",
42 | "Power": "Systeem",
43 | "Shutdown": "Uitschakelen",
44 | "Reboot": "Herstarten",
45 | "Reset": "Resetten",
46 | "Clipboard": "Klembord",
47 | "Clear": "Wissen",
48 | "Fullscreen": "Volledig Scherm",
49 | "Settings": "Instellingen",
50 | "Shared Mode": "Gedeelde Modus",
51 | "View Only": "Alleen Kijken",
52 | "Clip to Window": "Randen buiten venster afsnijden",
53 | "Scaling Mode:": "Schaalmodus:",
54 | "None": "Geen",
55 | "Local Scaling": "Lokaal Schalen",
56 | "Remote Resizing": "Op Afstand Formaat Wijzigen",
57 | "Advanced": "Geavanceerd",
58 | "Repeater ID:": "Repeater ID:",
59 | "WebSocket": "WebSocket",
60 | "Encrypt": "Versleutelen",
61 | "Host:": "Host:",
62 | "Port:": "Poort:",
63 | "Path:": "Pad:",
64 | "Automatic Reconnect": "Automatisch Opnieuw Verbinden",
65 | "Reconnect Delay (ms):": "Vertraging voor Opnieuw Verbinden (ms):",
66 | "Show Dot when No Cursor": "Geef stip weer indien geen cursor",
67 | "Logging:": "Logmeldingen:",
68 | "Disconnect": "Verbinding verbreken",
69 | "Connect": "Verbinden",
70 | "Password:": "Wachtwoord:",
71 | "Send Password": "Verzend Wachtwoord:",
72 | "Cancel": "Annuleren"
73 | }
--------------------------------------------------------------------------------
/noVNC/app/images/expander.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
70 |
--------------------------------------------------------------------------------
/noVNC/tests/test.copyrect.js:
--------------------------------------------------------------------------------
1 | const expect = chai.expect;
2 |
3 | import Websock from '../core/websock.js';
4 | import Display from '../core/display.js';
5 |
6 | import CopyRectDecoder from '../core/decoders/copyrect.js';
7 |
8 | import FakeWebSocket from './fake.websocket.js';
9 |
10 | function testDecodeRect(decoder, x, y, width, height, data, display, depth) {
11 | let sock;
12 |
13 | sock = new Websock;
14 | sock.open("ws://example.com");
15 |
16 | sock.on('message', () => {
17 | decoder.decodeRect(x, y, width, height, sock, display, depth);
18 | });
19 |
20 | // Empty messages are filtered at multiple layers, so we need to
21 | // do a direct call
22 | if (data.length === 0) {
23 | decoder.decodeRect(x, y, width, height, sock, display, depth);
24 | } else {
25 | sock._websocket._receiveData(new Uint8Array(data));
26 | }
27 |
28 | display.flip();
29 | }
30 |
31 | describe('CopyRect Decoder', function () {
32 | let decoder;
33 | let display;
34 |
35 | before(FakeWebSocket.replace);
36 | after(FakeWebSocket.restore);
37 |
38 | beforeEach(function () {
39 | decoder = new CopyRectDecoder();
40 | display = new Display(document.createElement('canvas'));
41 | display.resize(4, 4);
42 | });
43 |
44 | it('should handle the CopyRect encoding', function () {
45 | // seed some initial data to copy
46 | display.fillRect(0, 0, 4, 4, [ 0x11, 0x22, 0x33 ]);
47 | display.fillRect(0, 0, 2, 2, [ 0x00, 0x00, 0xff ]);
48 | display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
49 |
50 | testDecodeRect(decoder, 0, 2, 2, 2,
51 | [0x00, 0x02, 0x00, 0x00],
52 | display, 24);
53 | testDecodeRect(decoder, 2, 2, 2, 2,
54 | [0x00, 0x00, 0x00, 0x00],
55 | display, 24);
56 |
57 | let targetData = new Uint8Array([
58 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
59 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
60 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
61 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
62 | ]);
63 |
64 | expect(display).to.have.displayed(targetData);
65 | });
66 |
67 | it('should handle empty rects', function () {
68 | display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
69 | display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
70 | display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
71 |
72 | testDecodeRect(decoder, 1, 2, 0, 0, [0x00, 0x00, 0x00, 0x00], display, 24);
73 |
74 | let targetData = new Uint8Array([
75 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
76 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
77 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
78 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
79 | ]);
80 |
81 | expect(display).to.have.displayed(targetData);
82 | });
83 | });
84 |
--------------------------------------------------------------------------------
/noVNC/app/images/settings.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
77 |
--------------------------------------------------------------------------------
/noVNC/app/images/error.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
82 |
--------------------------------------------------------------------------------
/noVNC/app/images/fullscreen.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
94 |
--------------------------------------------------------------------------------
/noVNC/app/images/info.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
82 |
--------------------------------------------------------------------------------
/noVNC/app/locale/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "HTTPS is required for full functionality": "",
3 | "Connecting...": "En cours de connexion...",
4 | "Disconnecting...": "Déconnexion en cours...",
5 | "Reconnecting...": "Reconnexion en cours...",
6 | "Internal error": "Erreur interne",
7 | "Must set host": "Doit définir l'hôte",
8 | "Connected (encrypted) to ": "Connecté (chiffré) à ",
9 | "Connected (unencrypted) to ": "Connecté (non chiffré) à ",
10 | "Something went wrong, connection is closed": "Quelque chose s'est mal passé, la connexion a été fermée",
11 | "Failed to connect to server": "Échec de connexion au serveur",
12 | "Disconnected": "Déconnecté",
13 | "New connection has been rejected with reason: ": "Une nouvelle connexion a été rejetée avec motif : ",
14 | "New connection has been rejected": "Une nouvelle connexion a été rejetée",
15 | "Credentials are required": "Les identifiants sont requis",
16 | "noVNC encountered an error:": "noVNC a rencontré une erreur :",
17 | "Hide/Show the control bar": "Masquer/Afficher la barre de contrôle",
18 | "Drag": "Faire glisser",
19 | "Move/Drag Viewport": "Déplacer/faire glisser le Viewport",
20 | "Keyboard": "Clavier",
21 | "Show Keyboard": "Afficher le clavier",
22 | "Extra keys": "Touches supplémentaires",
23 | "Show Extra Keys": "Afficher les touches supplémentaires",
24 | "Ctrl": "Ctrl",
25 | "Toggle Ctrl": "Basculer Ctrl",
26 | "Alt": "Alt",
27 | "Toggle Alt": "Basculer Alt",
28 | "Toggle Windows": "Basculer Windows",
29 | "Windows": "Windows",
30 | "Send Tab": "Envoyer l'onglet",
31 | "Tab": "l'onglet",
32 | "Esc": "Esc",
33 | "Send Escape": "Envoyer Escape",
34 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
35 | "Send Ctrl-Alt-Del": "Envoyer Ctrl-Alt-Del",
36 | "Shutdown/Reboot": "Arrêter/Redémarrer",
37 | "Shutdown/Reboot...": "Arrêter/Redémarrer...",
38 | "Power": "Alimentation",
39 | "Shutdown": "Arrêter",
40 | "Reboot": "Redémarrer",
41 | "Reset": "Réinitialiser",
42 | "Clipboard": "Presse-papiers",
43 | "Edit clipboard content in the textarea below.": "",
44 | "Settings": "Paramètres",
45 | "Shared Mode": "Mode partagé",
46 | "View Only": "Afficher uniquement",
47 | "Clip to Window": "Clip à fenêtre",
48 | "Scaling Mode:": "Mode mise à l'échelle :",
49 | "None": "Aucun",
50 | "Local Scaling": "Mise à l'échelle locale",
51 | "Remote Resizing": "Redimensionnement à distance",
52 | "Advanced": "Avancé",
53 | "Quality:": "Qualité :",
54 | "Compression level:": "Niveau de compression :",
55 | "Repeater ID:": "ID Répéteur :",
56 | "WebSocket": "WebSocket",
57 | "Encrypt": "Chiffrer",
58 | "Host:": "Hôte :",
59 | "Port:": "Port :",
60 | "Path:": "Chemin :",
61 | "Automatic Reconnect": "Reconnecter automatiquemen",
62 | "Reconnect Delay (ms):": "Délai de reconnexion (ms) :",
63 | "Show Dot when No Cursor": "Afficher le point lorsqu'il n'y a pas de curseur",
64 | "Logging:": "Se connecter :",
65 | "Version:": "Version :",
66 | "Disconnect": "Déconnecter",
67 | "Connect": "Connecter",
68 | "Server identity": "",
69 | "The server has provided the following identifying information:": "",
70 | "Fingerprint:": "",
71 | "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "",
72 | "Approve": "",
73 | "Reject": "",
74 | "Username:": "Nom d'utilisateur :",
75 | "Password:": "Mot de passe :",
76 | "Send Credentials": "Envoyer les identifiants",
77 | "Cancel": "Annuler"
78 | }
--------------------------------------------------------------------------------
/noVNC/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Publish
2 |
3 | on:
4 | push:
5 | pull_request:
6 | release:
7 | types: [published]
8 |
9 | jobs:
10 | npm:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v3
14 | - run: |
15 | GITREV=$(git rev-parse --short HEAD)
16 | echo $GITREV
17 | sed -i "s/^\(.*\"version\".*\)\"\([^\"]\+\)\"\(.*\)\$/\1\"\2-g$GITREV\"\3/" package.json
18 | if: github.event_name != 'release'
19 | - uses: actions/setup-node@v3
20 | with:
21 | # Needs to be explicitly specified for auth to work
22 | registry-url: 'https://registry.npmjs.org'
23 | - run: npm install
24 | - uses: actions/upload-artifact@v3
25 | with:
26 | name: npm
27 | path: lib
28 | - run: npm publish --access public
29 | env:
30 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
31 | if: |
32 | github.repository == 'novnc/noVNC' &&
33 | github.event_name == 'release' &&
34 | !github.event.release.prerelease
35 | - run: npm publish --access public --tag beta
36 | env:
37 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
38 | if: |
39 | github.repository == 'novnc/noVNC' &&
40 | github.event_name == 'release' &&
41 | github.event.release.prerelease
42 | - run: npm publish --access public --tag dev
43 | env:
44 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
45 | if: |
46 | github.repository == 'novnc/noVNC' &&
47 | github.event_name == 'push' &&
48 | github.event.ref == 'refs/heads/master'
49 | snap:
50 | runs-on: ubuntu-latest
51 | steps:
52 | - uses: actions/checkout@v3
53 | - run: |
54 | GITREV=$(git rev-parse --short HEAD)
55 | echo $GITREV
56 | sed -i "s/^\(.*\"version\".*\)\"\([^\"]\+\)\"\(.*\)\$/\1\"\2-g$GITREV\"\3/" package.json
57 | if: github.event_name != 'release'
58 | - run: |
59 | VERSION=$(grep '"version"' package.json | cut -d '"' -f 4)
60 | echo $VERSION
61 | sed -i "s/^version:.*/version: '$VERSION'/" snap/snapcraft.yaml
62 | - uses: snapcore/action-build@v1
63 | id: snapcraft
64 | - uses: actions/upload-artifact@v3
65 | with:
66 | name: snap
67 | path: ${{ steps.snapcraft.outputs.snap }}
68 | - uses: snapcore/action-publish@v1
69 | with:
70 | snap: ${{ steps.snapcraft.outputs.snap }}
71 | release: stable
72 | env:
73 | SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }}
74 | if: |
75 | github.repository == 'novnc/noVNC' &&
76 | github.event_name == 'release' &&
77 | !github.event.release.prerelease
78 | - uses: snapcore/action-publish@v1
79 | with:
80 | snap: ${{ steps.snapcraft.outputs.snap }}
81 | release: beta
82 | env:
83 | SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }}
84 | if: |
85 | github.repository == 'novnc/noVNC' &&
86 | github.event_name == 'release' &&
87 | github.event.release.prerelease
88 | - uses: snapcore/action-publish@v1
89 | with:
90 | snap: ${{ steps.snapcraft.outputs.snap }}
91 | release: edge
92 | env:
93 | SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }}
94 | if: |
95 | github.repository == 'novnc/noVNC' &&
96 | github.event_name == 'push' &&
97 | github.event.ref == 'refs/heads/master'
98 |
--------------------------------------------------------------------------------
/Dockerfile.firefox:
--------------------------------------------------------------------------------
1 | FROM alpine:3.19
2 |
3 | # Install required packages (matching desktop version + browser essentials)
4 | RUN apk add --no-cache \
5 | xvfb \
6 | x11vnc \
7 | supervisor \
8 | websockify \
9 | firefox \
10 | bash \
11 | curl \
12 | ffmpeg \
13 | imagemagick \
14 | python3 \
15 | py3-pip \
16 | dbus \
17 | dbus-x11 \
18 | python3-dev \
19 | py3-virtualenv \
20 | xdotool \
21 | mesa-dri-gallium \
22 | vulkan-loader \
23 | mesa \
24 | mesa-gl \
25 | mesa-egl \
26 | mesa-gles
27 |
28 | # Initialize dbus machine-id and create necessary directories
29 | RUN mkdir -p /var/run/dbus && \
30 | dbus-uuidgen > /var/lib/dbus/machine-id && \
31 | mkdir -p /var/log
32 |
33 | # Create and activate virtual environment
34 | ENV VIRTUAL_ENV=/opt/venv
35 | RUN python3 -m venv $VIRTUAL_ENV
36 | ENV PATH="$VIRTUAL_ENV/bin:$PATH"
37 |
38 | # Install Python packages in virtual environment
39 | RUN pip3 install --no-cache-dir \
40 | fastapi \
41 | uvicorn \
42 | python-multipart
43 |
44 | # Configure Firefox to skip first-run pages and run in kiosk mode
45 | RUN mkdir -p /root/.mozilla/firefox && \
46 | echo '[General]' > /root/.mozilla/firefox/profiles.ini && \
47 | echo 'StartWithLastProfile=1' >> /root/.mozilla/firefox/profiles.ini && \
48 | echo '' >> /root/.mozilla/firefox/profiles.ini && \
49 | echo '[Profile0]' >> /root/.mozilla/firefox/profiles.ini && \
50 | echo 'Name=default' >> /root/.mozilla/firefox/profiles.ini && \
51 | echo 'IsRelative=1' >> /root/.mozilla/firefox/profiles.ini && \
52 | echo 'Path=default.default' >> /root/.mozilla/firefox/profiles.ini && \
53 | echo 'Default=1' >> /root/.mozilla/firefox/profiles.ini && \
54 | mkdir -p /root/.mozilla/firefox/default.default && \
55 | echo 'user_pref("browser.startup.homepage_override.mstone", "ignore");' > /root/.mozilla/firefox/default.default/user.js && \
56 | echo 'user_pref("startup.homepage_welcome_url", "");' >> /root/.mozilla/firefox/default.default/user.js && \
57 | echo 'user_pref("startup.homepage_welcome_url.additional", "");' >> /root/.mozilla/firefox/default.default/user.js && \
58 | echo 'user_pref("browser.aboutwelcome.enabled", false);' >> /root/.mozilla/firefox/default.default/user.js && \
59 | echo 'user_pref("trailhead.firstrun.didSeeAboutWelcome", true);' >> /root/.mozilla/firefox/default.default/user.js && \
60 | echo 'user_pref("browser.startup.firstrunSkipsHomepage", false);' >> /root/.mozilla/firefox/default.default/user.js && \
61 | echo 'user_pref("browser.shell.checkDefaultBrowser", false);' >> /root/.mozilla/firefox/default.default/user.js && \
62 | echo 'user_pref("browser.tabs.warnOnClose", false);' >> /root/.mozilla/firefox/default.default/user.js && \
63 | echo 'user_pref("browser.sessionstore.resume_from_crash", false);' >> /root/.mozilla/firefox/default.default/user.js && \
64 | echo 'user_pref("toolkit.startup.max_resumed_crashes", -1);' >> /root/.mozilla/firefox/default.default/user.js
65 |
66 | # Create supervisor config directory
67 | RUN mkdir -p /etc/supervisor.d
68 |
69 | COPY noVNC /usr/share/novnc
70 | # index.html redirects to vnc.html with autoconnect and resize parameters
71 |
72 | # Copy supervisor config
73 | COPY firefox-supervisord.conf /etc/supervisor.d/supervisord.ini
74 |
75 | # Add computer_use_server directory
76 | COPY computer_use_server /computer_use_server
77 |
78 | # Copy start script and make it executable
79 | COPY start.sh /start.sh
80 | RUN chmod +x /start.sh
81 |
82 | # Expose VNC, noVNC, and API ports
83 | EXPOSE 5900 6081 8000 2000
84 |
85 | CMD ["/start.sh"]
86 |
87 |
--------------------------------------------------------------------------------
/noVNC/tests/test.util.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const expect = chai.expect;
3 |
4 | import * as Log from '../core/util/logging.js';
5 | import { encodeUTF8, decodeUTF8 } from '../core/util/strings.js';
6 |
7 | describe('Utils', function () {
8 | "use strict";
9 |
10 | describe('logging functions', function () {
11 | beforeEach(function () {
12 | sinon.spy(console, 'log');
13 | sinon.spy(console, 'debug');
14 | sinon.spy(console, 'warn');
15 | sinon.spy(console, 'error');
16 | sinon.spy(console, 'info');
17 | });
18 |
19 | afterEach(function () {
20 | console.log.restore();
21 | console.debug.restore();
22 | console.warn.restore();
23 | console.error.restore();
24 | console.info.restore();
25 | Log.initLogging();
26 | });
27 |
28 | it('should use noop for levels lower than the min level', function () {
29 | Log.initLogging('warn');
30 | Log.Debug('hi');
31 | Log.Info('hello');
32 | expect(console.log).to.not.have.been.called;
33 | });
34 |
35 | it('should use console.debug for Debug', function () {
36 | Log.initLogging('debug');
37 | Log.Debug('dbg');
38 | expect(console.debug).to.have.been.calledWith('dbg');
39 | });
40 |
41 | it('should use console.info for Info', function () {
42 | Log.initLogging('debug');
43 | Log.Info('inf');
44 | expect(console.info).to.have.been.calledWith('inf');
45 | });
46 |
47 | it('should use console.warn for Warn', function () {
48 | Log.initLogging('warn');
49 | Log.Warn('wrn');
50 | expect(console.warn).to.have.been.called;
51 | expect(console.warn).to.have.been.calledWith('wrn');
52 | });
53 |
54 | it('should use console.error for Error', function () {
55 | Log.initLogging('error');
56 | Log.Error('err');
57 | expect(console.error).to.have.been.called;
58 | expect(console.error).to.have.been.calledWith('err');
59 | });
60 | });
61 |
62 | describe('string functions', function () {
63 | it('should decode UTF-8 to DOMString correctly', function () {
64 | const utf8string = '\xd0\x9f';
65 | const domstring = decodeUTF8(utf8string);
66 | expect(domstring).to.equal("П");
67 | });
68 |
69 | it('should encode DOMString to UTF-8 correctly', function () {
70 | const domstring = "åäöa";
71 | const utf8string = encodeUTF8(domstring);
72 | expect(utf8string).to.equal('\xc3\xa5\xc3\xa4\xc3\xb6\x61');
73 | });
74 |
75 | it('should allow Latin-1 strings if allowLatin1 is set when decoding', function () {
76 | const latin1string = '\xe5\xe4\xf6';
77 | expect(() => decodeUTF8(latin1string)).to.throw(Error);
78 | expect(decodeUTF8(latin1string, true)).to.equal('åäö');
79 | });
80 | });
81 |
82 | // TODO(directxman12): test the conf_default and conf_defaults methods
83 | // TODO(directxman12): test the event methods (addEvent, removeEvent, stopEvent)
84 | // TODO(directxman12): figure out a good way to test getPosition and getEventPosition
85 | // TODO(directxman12): figure out how to test the browser detection functions properly
86 | // (we can't really test them against the browsers, except for Gecko
87 | // via PhantomJS, the default test driver)
88 | });
89 | /* eslint-enable no-console */
90 |
--------------------------------------------------------------------------------
/noVNC/app/locale/sv.json:
--------------------------------------------------------------------------------
1 | {
2 | "HTTPS is required for full functionality": "HTTPS krävs för full funktionalitet",
3 | "Connecting...": "Ansluter...",
4 | "Disconnecting...": "Kopplar ner...",
5 | "Reconnecting...": "Återansluter...",
6 | "Internal error": "Internt fel",
7 | "Must set host": "Du måste specifiera en värd",
8 | "Connected (encrypted) to ": "Ansluten (krypterat) till ",
9 | "Connected (unencrypted) to ": "Ansluten (okrypterat) till ",
10 | "Something went wrong, connection is closed": "Något gick fel, anslutningen avslutades",
11 | "Failed to connect to server": "Misslyckades att ansluta till servern",
12 | "Disconnected": "Frånkopplad",
13 | "New connection has been rejected with reason: ": "Ny anslutning har blivit nekad med följande skäl: ",
14 | "New connection has been rejected": "Ny anslutning har blivit nekad",
15 | "Credentials are required": "Användaruppgifter krävs",
16 | "noVNC encountered an error:": "noVNC stötte på ett problem:",
17 | "Hide/Show the control bar": "Göm/Visa kontrollbaren",
18 | "Drag": "Dra",
19 | "Move/Drag Viewport": "Flytta/Dra Vyn",
20 | "Keyboard": "Tangentbord",
21 | "Show Keyboard": "Visa Tangentbord",
22 | "Extra keys": "Extraknappar",
23 | "Show Extra Keys": "Visa Extraknappar",
24 | "Ctrl": "Ctrl",
25 | "Toggle Ctrl": "Växla Ctrl",
26 | "Alt": "Alt",
27 | "Toggle Alt": "Växla Alt",
28 | "Toggle Windows": "Växla Windows",
29 | "Windows": "Windows",
30 | "Send Tab": "Skicka Tab",
31 | "Tab": "Tab",
32 | "Esc": "Esc",
33 | "Send Escape": "Skicka Escape",
34 | "Ctrl+Alt+Del": "Ctrl+Alt+Del",
35 | "Send Ctrl-Alt-Del": "Skicka Ctrl-Alt-Del",
36 | "Shutdown/Reboot": "Stäng av/Boota om",
37 | "Shutdown/Reboot...": "Stäng av/Boota om...",
38 | "Power": "Ström",
39 | "Shutdown": "Stäng av",
40 | "Reboot": "Boota om",
41 | "Reset": "Återställ",
42 | "Clipboard": "Urklipp",
43 | "Edit clipboard content in the textarea below.": "Redigera urklippets innehåll i fältet nedan.",
44 | "Full Screen": "Fullskärm",
45 | "Settings": "Inställningar",
46 | "Shared Mode": "Delat Läge",
47 | "View Only": "Endast Visning",
48 | "Clip to Window": "Begränsa till Fönster",
49 | "Scaling Mode:": "Skalningsläge:",
50 | "None": "Ingen",
51 | "Local Scaling": "Lokal Skalning",
52 | "Remote Resizing": "Ändra Storlek",
53 | "Advanced": "Avancerat",
54 | "Quality:": "Kvalitet:",
55 | "Compression level:": "Kompressionsnivå:",
56 | "Repeater ID:": "Repeater-ID:",
57 | "WebSocket": "WebSocket",
58 | "Encrypt": "Kryptera",
59 | "Host:": "Värd:",
60 | "Port:": "Port:",
61 | "Path:": "Sökväg:",
62 | "Automatic Reconnect": "Automatisk Återanslutning",
63 | "Reconnect Delay (ms):": "Fördröjning (ms):",
64 | "Show Dot when No Cursor": "Visa prick när ingen muspekare finns",
65 | "Logging:": "Loggning:",
66 | "Version:": "Version:",
67 | "Disconnect": "Koppla från",
68 | "Connect": "Anslut",
69 | "Server identity": "Server-identitet",
70 | "The server has provided the following identifying information:": "Servern har gett följande identifierande information:",
71 | "Fingerprint:": "Fingeravtryck:",
72 | "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Kontrollera att informationen är korrekt och tryck sedan \"Godkänn\". Tryck annars \"Neka\".",
73 | "Approve": "Godkänn",
74 | "Reject": "Neka",
75 | "Credentials": "Användaruppgifter",
76 | "Username:": "Användarnamn:",
77 | "Password:": "Lösenord:",
78 | "Send Credentials": "Skicka Användaruppgifter",
79 | "Cancel": "Avbryt"
80 | }
--------------------------------------------------------------------------------
/noVNC/app/images/ctrlaltdel.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
101 |
--------------------------------------------------------------------------------
/noVNC/app/images/connect.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
97 |
--------------------------------------------------------------------------------
/noVNC/utils/genkeysymdef.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /*
3 | * genkeysymdef: X11 keysymdef.h to JavaScript converter
4 | * Copyright (C) 2018 The noVNC Authors
5 | * Licensed under MPL 2.0 (see LICENSE.txt)
6 | */
7 |
8 | "use strict";
9 |
10 | const fs = require('fs');
11 |
12 | let showHelp = process.argv.length === 2;
13 | let filename;
14 |
15 | for (let i = 2; i < process.argv.length; ++i) {
16 | switch (process.argv[i]) {
17 | case "--help":
18 | case "-h":
19 | showHelp = true;
20 | break;
21 | case "--file":
22 | case "-f":
23 | default:
24 | filename = process.argv[i];
25 | }
26 | }
27 |
28 | if (!filename) {
29 | showHelp = true;
30 | console.log("Error: No filename specified\n");
31 | }
32 |
33 | if (showHelp) {
34 | console.log("Parses a *nix keysymdef.h to generate Unicode code point mappings");
35 | console.log("Usage: node parse.js [options] filename:");
36 | console.log(" -h [ --help ] Produce this help message");
37 | console.log(" filename The keysymdef.h file to parse");
38 | process.exit(0);
39 | }
40 |
41 | const buf = fs.readFileSync(filename);
42 | const str = buf.toString('utf8');
43 |
44 | const re = /^#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-fA-F]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/m;
45 |
46 | const arr = str.split('\n');
47 |
48 | const codepoints = {};
49 |
50 | for (let i = 0; i < arr.length; ++i) {
51 | const result = re.exec(arr[i]);
52 | if (result) {
53 | const keyname = result[1];
54 | const keysym = parseInt(result[2], 16);
55 | const remainder = result[3];
56 |
57 | const unicodeRes = /U\+([0-9a-fA-F]+)/.exec(remainder);
58 | if (unicodeRes) {
59 | const unicode = parseInt(unicodeRes[1], 16);
60 | // The first entry is the preferred one
61 | if (!codepoints[unicode]) {
62 | codepoints[unicode] = { keysym: keysym, name: keyname };
63 | }
64 | }
65 | }
66 | }
67 |
68 | let out =
69 | "/*\n" +
70 | " * Mapping from Unicode codepoints to X11/RFB keysyms\n" +
71 | " *\n" +
72 | " * This file was automatically generated from keysymdef.h\n" +
73 | " * DO NOT EDIT!\n" +
74 | " */\n" +
75 | "\n" +
76 | "/* Functions at the bottom */\n" +
77 | "\n" +
78 | "const codepoints = {\n";
79 |
80 | function toHex(num) {
81 | let s = num.toString(16);
82 | if (s.length < 4) {
83 | s = ("0000" + s).slice(-4);
84 | }
85 | return "0x" + s;
86 | }
87 |
88 | for (let codepoint in codepoints) {
89 | codepoint = parseInt(codepoint);
90 |
91 | // Latin-1?
92 | if ((codepoint >= 0x20) && (codepoint <= 0xff)) {
93 | continue;
94 | }
95 |
96 | // Handled by the general Unicode mapping?
97 | if ((codepoint | 0x01000000) === codepoints[codepoint].keysym) {
98 | continue;
99 | }
100 |
101 | out += " " + toHex(codepoint) + ": " +
102 | toHex(codepoints[codepoint].keysym) +
103 | ", // XK_" + codepoints[codepoint].name + "\n";
104 | }
105 |
106 | out +=
107 | "};\n" +
108 | "\n" +
109 | "export default {\n" +
110 | " lookup(u) {\n" +
111 | " // Latin-1 is one-to-one mapping\n" +
112 | " if ((u >= 0x20) && (u <= 0xff)) {\n" +
113 | " return u;\n" +
114 | " }\n" +
115 | "\n" +
116 | " // Lookup table (fairly random)\n" +
117 | " const keysym = codepoints[u];\n" +
118 | " if (keysym !== undefined) {\n" +
119 | " return keysym;\n" +
120 | " }\n" +
121 | "\n" +
122 | " // General mapping as final fallback\n" +
123 | " return 0x01000000 | u;\n" +
124 | " },\n" +
125 | "};";
126 |
127 | console.log(out);
128 |
--------------------------------------------------------------------------------
/noVNC/app/images/alt.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
93 |
--------------------------------------------------------------------------------
/noVNC/tests/test.inflator.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const expect = chai.expect;
3 |
4 | import { deflateInit, deflate, Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js";
5 | import ZStream from "../vendor/pako/lib/zlib/zstream.js";
6 | import Inflator from "../core/inflator.js";
7 |
8 | function _deflator(data) {
9 | let strm = new ZStream();
10 |
11 | deflateInit(strm, 5);
12 |
13 | /* eslint-disable camelcase */
14 | strm.input = data;
15 | strm.avail_in = strm.input.length;
16 | strm.next_in = 0;
17 | /* eslint-enable camelcase */
18 |
19 | let chunks = [];
20 | let totalLen = 0;
21 | while (strm.avail_in > 0) {
22 | /* eslint-disable camelcase */
23 | strm.output = new Uint8Array(1024 * 10 * 10);
24 | strm.avail_out = strm.output.length;
25 | strm.next_out = 0;
26 | /* eslint-enable camelcase */
27 |
28 | let ret = deflate(strm, Z_FULL_FLUSH);
29 |
30 | // Check that return code is not an error
31 | expect(ret).to.be.greaterThan(-1);
32 |
33 | let chunk = new Uint8Array(strm.output.buffer, 0, strm.next_out);
34 | totalLen += chunk.length;
35 | chunks.push(chunk);
36 | }
37 |
38 | // Combine chunks into a single data
39 |
40 | let outData = new Uint8Array(totalLen);
41 | let offset = 0;
42 |
43 | for (let i = 0; i < chunks.length; i++) {
44 | outData.set(chunks[i], offset);
45 | offset += chunks[i].length;
46 | }
47 |
48 | return outData;
49 | }
50 |
51 | describe('Inflate data', function () {
52 |
53 | it('should be able to inflate messages', function () {
54 | let inflator = new Inflator();
55 |
56 | let text = "123asdf";
57 | let preText = new Uint8Array(text.length);
58 | for (let i = 0; i < preText.length; i++) {
59 | preText[i] = text.charCodeAt(i);
60 | }
61 |
62 | let compText = _deflator(preText);
63 |
64 | inflator.setInput(compText);
65 | let inflatedText = inflator.inflate(preText.length);
66 |
67 | expect(inflatedText).to.array.equal(preText);
68 |
69 | });
70 |
71 | it('should be able to inflate large messages', function () {
72 | let inflator = new Inflator();
73 |
74 | /* Generate a big string with random characters. Used because
75 | repetition of letters might be deflated more effectively than
76 | random ones. */
77 | let text = "";
78 | let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
79 | for (let i = 0; i < 300000; i++) {
80 | text += characters.charAt(Math.floor(Math.random() * characters.length));
81 | }
82 |
83 | let preText = new Uint8Array(text.length);
84 | for (let i = 0; i < preText.length; i++) {
85 | preText[i] = text.charCodeAt(i);
86 | }
87 |
88 | let compText = _deflator(preText);
89 |
90 | //Check that the compressed size is expected size
91 | expect(compText.length).to.be.greaterThan((1024 * 10 * 10) * 2);
92 |
93 | inflator.setInput(compText);
94 | let inflatedText = inflator.inflate(preText.length);
95 |
96 | expect(inflatedText).to.array.equal(preText);
97 | });
98 |
99 | it('should throw an error on insufficient data', function () {
100 | let inflator = new Inflator();
101 |
102 | let text = "123asdf";
103 | let preText = new Uint8Array(text.length);
104 | for (let i = 0; i < preText.length; i++) {
105 | preText[i] = text.charCodeAt(i);
106 | }
107 |
108 | let compText = _deflator(preText);
109 |
110 | inflator.setInput(compText);
111 | expect(() => inflator.inflate(preText.length * 2)).to.throw();
112 | });
113 | });
114 |
--------------------------------------------------------------------------------
/noVNC/tests/assertions.js:
--------------------------------------------------------------------------------
1 | // noVNC specific assertions
2 | chai.use(function (_chai, utils) {
3 | function _equal(a, b) {
4 | return a === b;
5 | }
6 | _chai.Assertion.addMethod('displayed', function (targetData, cmp=_equal) {
7 | const obj = this._obj;
8 | const ctx = obj._target.getContext('2d');
9 | const data = ctx.getImageData(0, 0, obj._target.width, obj._target.height).data;
10 | const len = data.length;
11 | new chai.Assertion(len).to.be.equal(targetData.length, "unexpected display size");
12 | let same = true;
13 | for (let i = 0; i < len; i++) {
14 | if (!cmp(data[i], targetData[i])) {
15 | same = false;
16 | break;
17 | }
18 | }
19 | if (!same) {
20 | // eslint-disable-next-line no-console
21 | console.log("expected data: %o, actual data: %o", targetData, data);
22 | }
23 | this.assert(same,
24 | "expected #{this} to have displayed the image #{exp}, but instead it displayed #{act}",
25 | "expected #{this} not to have displayed the image #{act}",
26 | targetData,
27 | data);
28 | });
29 |
30 | _chai.Assertion.addMethod('sent', function (targetData) {
31 | const obj = this._obj;
32 | const data = obj._websocket._getSentData();
33 | let same = true;
34 | if (data.length != targetData.length) {
35 | same = false;
36 | } else {
37 | for (let i = 0; i < data.length; i++) {
38 | if (data[i] != targetData[i]) {
39 | same = false;
40 | break;
41 | }
42 | }
43 | }
44 | if (!same) {
45 | // eslint-disable-next-line no-console
46 | console.log("expected data: %o, actual data: %o", targetData, data);
47 | }
48 | this.assert(same,
49 | "expected #{this} to have sent the data #{exp}, but it actually sent #{act}",
50 | "expected #{this} not to have sent the data #{act}",
51 | Array.prototype.slice.call(targetData),
52 | Array.prototype.slice.call(data));
53 | });
54 |
55 | _chai.Assertion.addProperty('array', function () {
56 | utils.flag(this, 'array', true);
57 | });
58 |
59 | _chai.Assertion.overwriteMethod('equal', function (_super) {
60 | return function assertArrayEqual(target) {
61 | if (utils.flag(this, 'array')) {
62 | const obj = this._obj;
63 |
64 | let same = true;
65 |
66 | if (utils.flag(this, 'deep')) {
67 | for (let i = 0; i < obj.length; i++) {
68 | if (!utils.eql(obj[i], target[i])) {
69 | same = false;
70 | break;
71 | }
72 | }
73 |
74 | this.assert(same,
75 | "expected #{this} to have elements deeply equal to #{exp}",
76 | "expected #{this} not to have elements deeply equal to #{exp}",
77 | Array.prototype.slice.call(target));
78 | } else {
79 | for (let i = 0; i < obj.length; i++) {
80 | if (obj[i] != target[i]) {
81 | same = false;
82 | break;
83 | }
84 | }
85 |
86 | this.assert(same,
87 | "expected #{this} to have elements equal to #{exp}",
88 | "expected #{this} not to have elements equal to #{exp}",
89 | Array.prototype.slice.call(target));
90 | }
91 | } else {
92 | _super.apply(this, arguments);
93 | }
94 | };
95 | });
96 | });
97 |
--------------------------------------------------------------------------------
/noVNC/tests/test.rre.js:
--------------------------------------------------------------------------------
1 | const expect = chai.expect;
2 |
3 | import Websock from '../core/websock.js';
4 | import Display from '../core/display.js';
5 |
6 | import RREDecoder from '../core/decoders/rre.js';
7 |
8 | import FakeWebSocket from './fake.websocket.js';
9 |
10 | function testDecodeRect(decoder, x, y, width, height, data, display, depth) {
11 | let sock;
12 |
13 | sock = new Websock;
14 | sock.open("ws://example.com");
15 |
16 | sock.on('message', () => {
17 | decoder.decodeRect(x, y, width, height, sock, display, depth);
18 | });
19 |
20 | // Empty messages are filtered at multiple layers, so we need to
21 | // do a direct call
22 | if (data.length === 0) {
23 | decoder.decodeRect(x, y, width, height, sock, display, depth);
24 | } else {
25 | sock._websocket._receiveData(new Uint8Array(data));
26 | }
27 |
28 | display.flip();
29 | }
30 |
31 | function push16(arr, num) {
32 | arr.push((num >> 8) & 0xFF,
33 | num & 0xFF);
34 | }
35 |
36 | function push32(arr, num) {
37 | arr.push((num >> 24) & 0xFF,
38 | (num >> 16) & 0xFF,
39 | (num >> 8) & 0xFF,
40 | num & 0xFF);
41 | }
42 |
43 | describe('RRE Decoder', function () {
44 | let decoder;
45 | let display;
46 |
47 | before(FakeWebSocket.replace);
48 | after(FakeWebSocket.restore);
49 |
50 | beforeEach(function () {
51 | decoder = new RREDecoder();
52 | display = new Display(document.createElement('canvas'));
53 | display.resize(4, 4);
54 | });
55 |
56 | // TODO(directxman12): test rre_chunk_sz?
57 |
58 | it('should handle the RRE encoding', function () {
59 | let data = [];
60 | push32(data, 2); // 2 subrects
61 | push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color
62 | data.push(0x00); // becomes 0000ff00 --> #0000FF fg color
63 | data.push(0x00);
64 | data.push(0xff);
65 | data.push(0x00);
66 | push16(data, 0); // x: 0
67 | push16(data, 0); // y: 0
68 | push16(data, 2); // width: 2
69 | push16(data, 2); // height: 2
70 | data.push(0x00); // becomes 0000ff00 --> #0000FF fg color
71 | data.push(0x00);
72 | data.push(0xff);
73 | data.push(0x00);
74 | push16(data, 2); // x: 2
75 | push16(data, 2); // y: 2
76 | push16(data, 2); // width: 2
77 | push16(data, 2); // height: 2
78 |
79 | testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24);
80 |
81 | let targetData = new Uint8Array([
82 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
83 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
84 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
85 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
86 | ]);
87 |
88 | expect(display).to.have.displayed(targetData);
89 | });
90 |
91 | it('should handle empty rects', function () {
92 | display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
93 | display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
94 | display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
95 |
96 | testDecodeRect(decoder, 1, 2, 0, 0, [ 0x00, 0xff, 0xff, 0xff, 0xff ], display, 24);
97 |
98 | let targetData = new Uint8Array([
99 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
100 | 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
101 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
102 | 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
103 | ]);
104 |
105 | expect(display).to.have.displayed(targetData);
106 | });
107 | });
108 |
--------------------------------------------------------------------------------