Merge remote-tracking branch 'remotes/base/master'
This commit is contained in:
commit
d109185fa2
|
|
@ -1 +0,0 @@
|
|||
**/xtscancodes.js
|
||||
54
.eslintrc
54
.eslintrc
|
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2020": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"rules": {
|
||||
// Unsafe or confusing stuff that we forbid
|
||||
|
||||
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
|
||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||
"no-var": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"object-shorthand": ["error", "methods", { "avoidQuotes": true }],
|
||||
"prefer-arrow-callback": "error",
|
||||
"arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": false } ],
|
||||
"arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
|
||||
"arrow-spacing": ["error"],
|
||||
"no-confusing-arrow": ["error", { "allowParens": true }],
|
||||
|
||||
// Enforced coding style
|
||||
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||
"indent": ["error", 4, { "SwitchCase": 1,
|
||||
"VariableDeclarator": "first",
|
||||
"FunctionDeclaration": { "parameters": "first" },
|
||||
"FunctionExpression": { "parameters": "first" },
|
||||
"CallExpression": { "arguments": "first" },
|
||||
"ArrayExpression": "first",
|
||||
"ObjectExpression": "first",
|
||||
"ImportDeclaration": "first",
|
||||
"ignoreComments": true }],
|
||||
"comma-spacing": ["error"],
|
||||
"comma-style": ["error"],
|
||||
"curly": ["error", "multi-line"],
|
||||
"func-call-spacing": ["error"],
|
||||
"func-names": ["error"],
|
||||
"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
|
||||
"key-spacing": ["error"],
|
||||
"keyword-spacing": ["error"],
|
||||
"no-trailing-spaces": ["error"],
|
||||
"semi": ["error"],
|
||||
"space-before-blocks": ["error"],
|
||||
"space-before-function-paren": ["error", { "anonymous": "always",
|
||||
"named": "never",
|
||||
"asyncArrow": "always" }],
|
||||
"switch-colon-spacing": ["error"],
|
||||
"camelcase": ["error", { allow: ["^XK_", "^XF86XK_"] }],
|
||||
}
|
||||
}
|
||||
|
|
@ -10,18 +10,18 @@ jobs:
|
|||
npm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
GITREV=$(git rev-parse --short HEAD)
|
||||
echo $GITREV
|
||||
sed -i "s/^\(.*\"version\".*\)\"\([^\"]\+\)\"\(.*\)\$/\1\"\2-g$GITREV\"\3/" package.json
|
||||
if: github.event_name != 'release'
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
# Needs to be explicitly specified for auth to work
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- run: npm install
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: npm
|
||||
path: lib
|
||||
|
|
@ -49,7 +49,7 @@ jobs:
|
|||
snap:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
GITREV=$(git rev-parse --short HEAD)
|
||||
echo $GITREV
|
||||
|
|
@ -61,7 +61,7 @@ jobs:
|
|||
sed -i "s/^version:.*/version: '$VERSION'/" snap/snapcraft.yaml
|
||||
- uses: snapcore/action-build@v1
|
||||
id: snapcraft
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: snap
|
||||
path: ${{ steps.snapcraft.outputs.snap }}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ jobs:
|
|||
eslint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- run: npm update
|
||||
- run: npm run lint
|
||||
html:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- run: npm update
|
||||
- run: git ls-tree --name-only -r HEAD | grep -E "[.](html|css)$" | xargs ./utils/validate
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ jobs:
|
|||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- run: npm update
|
||||
- run: npm run test
|
||||
env:
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ jobs:
|
|||
translate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- run: npm update
|
||||
- run: sudo apt-get install gettext
|
||||
- run: make -C po update-pot
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ for a more complete list with additional info and links.
|
|||
### News/help/contact
|
||||
|
||||
The project website is found at [novnc.com](http://novnc.com).
|
||||
Notable commits, announcements and news are posted to
|
||||
[@noVNC](http://www.twitter.com/noVNC).
|
||||
|
||||
If you are a noVNC developer/integrator/user (or want to be) please join the
|
||||
[noVNC discussion group](https://groups.google.com/forum/?fromgroups#!forum/novnc).
|
||||
|
|
@ -59,7 +57,6 @@ profits such as:
|
|||
[Electronic Frontier Foundation](https://www.eff.org/),
|
||||
[Against Malaria Foundation](http://www.againstmalaria.com/),
|
||||
[Nothing But Nets](http://www.nothingbutnets.net/), etc.
|
||||
Please tweet [@noVNC](http://www.twitter.com/noVNC) if you do.
|
||||
|
||||
|
||||
### Features
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"HTTPS is required for full functionality": "Το HTTPS είναι απαιτούμενο για πλήρη λειτουργικότητα",
|
||||
"Connecting...": "Συνδέεται...",
|
||||
"Disconnecting...": "Aποσυνδέεται...",
|
||||
"Reconnecting...": "Επανασυνδέεται...",
|
||||
|
|
@ -7,19 +8,15 @@
|
|||
"Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ",
|
||||
"Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ",
|
||||
"Something went wrong, connection is closed": "Κάτι πήγε στραβά, η σύνδεση διακόπηκε",
|
||||
"Failed to connect to server": "Αποτυχία στη σύνδεση με το διακομιστή",
|
||||
"Disconnected": "Αποσυνδέθηκε",
|
||||
"New connection has been rejected with reason: ": "Η νέα σύνδεση απορρίφθηκε διότι: ",
|
||||
"New connection has been rejected": "Η νέα σύνδεση απορρίφθηκε ",
|
||||
"Password is required": "Απαιτείται ο κωδικός πρόσβασης",
|
||||
"Credentials are required": "Απαιτούνται διαπιστευτήρια",
|
||||
"noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:",
|
||||
"Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου",
|
||||
"Drag": "Σύρσιμο",
|
||||
"Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου",
|
||||
"viewport drag": "σύρσιμο θεατού πεδίου",
|
||||
"Active Mouse Button": "Ενεργό Πλήκτρο Ποντικιού",
|
||||
"No mousebutton": "Χωρίς Πλήκτρο Ποντικιού",
|
||||
"Left mousebutton": "Αριστερό Πλήκτρο Ποντικιού",
|
||||
"Middle mousebutton": "Μεσαίο Πλήκτρο Ποντικιού",
|
||||
"Right mousebutton": "Δεξί Πλήκτρο Ποντικιού",
|
||||
"Keyboard": "Πληκτρολόγιο",
|
||||
"Show Keyboard": "Εμφάνιση Πληκτρολογίου",
|
||||
"Extra keys": "Επιπλέον πλήκτρα",
|
||||
|
|
@ -28,6 +25,8 @@
|
|||
"Toggle Ctrl": "Εναλλαγή Ctrl",
|
||||
"Alt": "Alt",
|
||||
"Toggle Alt": "Εναλλαγή Alt",
|
||||
"Toggle Windows": "Εναλλαγή Παράθυρων",
|
||||
"Windows": "Παράθυρα",
|
||||
"Send Tab": "Αποστολή Tab",
|
||||
"Tab": "Tab",
|
||||
"Esc": "Esc",
|
||||
|
|
@ -41,8 +40,7 @@
|
|||
"Reboot": "Επανεκκίνηση",
|
||||
"Reset": "Επαναφορά",
|
||||
"Clipboard": "Πρόχειρο",
|
||||
"Clear": "Καθάρισμα",
|
||||
"Fullscreen": "Πλήρης Οθόνη",
|
||||
"Edit clipboard content in the textarea below.": "Επεξεργαστείτε το περιεχόμενο του πρόχειρου στην περιοχή κειμένου παρακάτω.",
|
||||
"Settings": "Ρυθμίσεις",
|
||||
"Shared Mode": "Κοινόχρηστη Λειτουργία",
|
||||
"View Only": "Μόνο Θέαση",
|
||||
|
|
@ -52,6 +50,8 @@
|
|||
"Local Scaling": "Τοπική Κλιμάκωση",
|
||||
"Remote Resizing": "Απομακρυσμένη Αλλαγή μεγέθους",
|
||||
"Advanced": "Για προχωρημένους",
|
||||
"Quality:": "Ποιότητα:",
|
||||
"Compression level:": "Επίπεδο συμπίεσης:",
|
||||
"Repeater ID:": "Repeater ID:",
|
||||
"WebSocket": "WebSocket",
|
||||
"Encrypt": "Κρυπτογράφηση",
|
||||
|
|
@ -60,10 +60,20 @@
|
|||
"Path:": "Διαδρομή:",
|
||||
"Automatic Reconnect": "Αυτόματη επανασύνδεση",
|
||||
"Reconnect Delay (ms):": "Καθυστέρηση επανασύνδεσης (ms):",
|
||||
"Show Dot when No Cursor": "Εμφάνιση Τελείας όταν δεν υπάρχει Δρομέας",
|
||||
"Logging:": "Καταγραφή:",
|
||||
"Version:": "Έκδοση:",
|
||||
"Disconnect": "Αποσύνδεση",
|
||||
"Connect": "Σύνδεση",
|
||||
"Server identity": "Ταυτότητα Διακομιστή",
|
||||
"The server has provided the following identifying information:": "Ο διακομιστής παρείχε την ακόλουθη πληροφορία ταυτοποίησης:",
|
||||
"Fingerprint:": "Δακτυλικό αποτύπωμα:",
|
||||
"Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Παρακαλώ επαληθεύσετε ότι η πληροφορία είναι σωστή και πιέστε \"Αποδοχή\". Αλλιώς πιέστε \"Απόρριψη\".",
|
||||
"Approve": "Αποδοχή",
|
||||
"Reject": "Απόρριψη",
|
||||
"Credentials": "Διαπιστευτήρια",
|
||||
"Username:": "Κωδικός Χρήστη:",
|
||||
"Password:": "Κωδικός Πρόσβασης:",
|
||||
"Cancel": "Ακύρωση",
|
||||
"Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas"
|
||||
"Send Credentials": "Αποστολή Διαπιστευτηρίων",
|
||||
"Cancel": "Ακύρωση"
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
"HTTPS is required for full functionality": "",
|
||||
"Connecting...": "En cours de connexion...",
|
||||
"Disconnecting...": "Déconnexion en cours...",
|
||||
"Reconnecting...": "Reconnexion en cours...",
|
||||
|
|
@ -40,7 +39,8 @@
|
|||
"Reboot": "Redémarrer",
|
||||
"Reset": "Réinitialiser",
|
||||
"Clipboard": "Presse-papiers",
|
||||
"Edit clipboard content in the textarea below.": "",
|
||||
"Clear": "Effacer",
|
||||
"Fullscreen": "Plein écran",
|
||||
"Settings": "Paramètres",
|
||||
"Shared Mode": "Mode partagé",
|
||||
"View Only": "Afficher uniquement",
|
||||
|
|
@ -65,12 +65,6 @@
|
|||
"Version:": "Version :",
|
||||
"Disconnect": "Déconnecter",
|
||||
"Connect": "Connecter",
|
||||
"Server identity": "",
|
||||
"The server has provided the following identifying information:": "",
|
||||
"Fingerprint:": "",
|
||||
"Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "",
|
||||
"Approve": "",
|
||||
"Reject": "",
|
||||
"Username:": "Nom d'utilisateur :",
|
||||
"Password:": "Mot de passe :",
|
||||
"Send Credentials": "Envoyer les identifiants",
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
"Credentials are required": "Le credenziali sono obbligatorie",
|
||||
"noVNC encountered an error:": "noVNC ha riscontrato un errore:",
|
||||
"Hide/Show the control bar": "Nascondi/Mostra la barra di controllo",
|
||||
"Drag": "",
|
||||
"Move/Drag Viewport": "",
|
||||
"Keyboard": "Tastiera",
|
||||
"Show Keyboard": "Mostra tastiera",
|
||||
"Extra keys": "Tasti Aggiuntivi",
|
||||
|
|
@ -44,7 +42,6 @@
|
|||
"Settings": "Impostazioni",
|
||||
"Shared Mode": "Modalità condivisa",
|
||||
"View Only": "Sola Visualizzazione",
|
||||
"Clip to Window": "",
|
||||
"Scaling Mode:": "Modalità di ridimensionamento:",
|
||||
"None": "Nessuna",
|
||||
"Local Scaling": "Ridimensionamento Locale",
|
||||
|
|
@ -61,7 +58,6 @@
|
|||
"Automatic Reconnect": "Riconnessione Automatica",
|
||||
"Reconnect Delay (ms):": "Ritardo Riconnessione (ms):",
|
||||
"Show Dot when No Cursor": "Mostra Punto quando Nessun Cursore",
|
||||
"Logging:": "",
|
||||
"Version:": "Versione:",
|
||||
"Disconnect": "Disconnetti",
|
||||
"Connect": "Connetti",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"HTTPS is required for full functionality": "すべての機能を使用するにはHTTPS接続が必要です",
|
||||
"Connecting...": "接続しています...",
|
||||
"Disconnecting...": "切断しています...",
|
||||
"Reconnecting...": "再接続しています...",
|
||||
|
|
@ -21,10 +22,10 @@
|
|||
"Extra keys": "追加キー",
|
||||
"Show Extra Keys": "追加キーを表示",
|
||||
"Ctrl": "Ctrl",
|
||||
"Toggle Ctrl": "Ctrl キーを切り替え",
|
||||
"Toggle Ctrl": "Ctrl キーをトグル",
|
||||
"Alt": "Alt",
|
||||
"Toggle Alt": "Alt キーを切り替え",
|
||||
"Toggle Windows": "Windows キーを切り替え",
|
||||
"Toggle Alt": "Alt キーをトグル",
|
||||
"Toggle Windows": "Windows キーをトグル",
|
||||
"Windows": "Windows",
|
||||
"Send Tab": "Tab キーを送信",
|
||||
"Tab": "Tab",
|
||||
|
|
@ -39,11 +40,11 @@
|
|||
"Reboot": "再起動",
|
||||
"Reset": "リセット",
|
||||
"Clipboard": "クリップボード",
|
||||
"Clear": "クリア",
|
||||
"Fullscreen": "全画面表示",
|
||||
"Edit clipboard content in the textarea below.": "以下の入力欄からクリップボードの内容を編集できます。",
|
||||
"Full Screen": "全画面表示",
|
||||
"Settings": "設定",
|
||||
"Shared Mode": "共有モード",
|
||||
"View Only": "表示のみ",
|
||||
"View Only": "表示専用",
|
||||
"Clip to Window": "ウィンドウにクリップ",
|
||||
"Scaling Mode:": "スケーリングモード:",
|
||||
"None": "なし",
|
||||
|
|
@ -60,11 +61,18 @@
|
|||
"Path:": "パス:",
|
||||
"Automatic Reconnect": "自動再接続",
|
||||
"Reconnect Delay (ms):": "再接続する遅延 (ミリ秒):",
|
||||
"Show Dot when No Cursor": "カーソルがないときにドットを表示",
|
||||
"Show Dot when No Cursor": "カーソルがないときにドットを表示する",
|
||||
"Logging:": "ロギング:",
|
||||
"Version:": "バージョン:",
|
||||
"Disconnect": "切断",
|
||||
"Connect": "接続",
|
||||
"Server identity": "サーバーの識別情報",
|
||||
"The server has provided the following identifying information:": "サーバーは以下の識別情報を提供しています:",
|
||||
"Fingerprint:": "フィンガープリント:",
|
||||
"Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "この情報が正しい場合は「承認」を、そうでない場合は「拒否」を押してください。",
|
||||
"Approve": "承認",
|
||||
"Reject": "拒否",
|
||||
"Credentials": "資格情報",
|
||||
"Username:": "ユーザー名:",
|
||||
"Password:": "パスワード:",
|
||||
"Send Credentials": "資格情報を送信",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
{
|
||||
"HTTPS is required for full functionality": "HTTPS krävs för full funktionalitet",
|
||||
"Running without HTTPS is not recommended, crashes or other issues are likely.": "Det är ej rekommenderat att köra utan HTTPS, krascher och andra problem är troliga.",
|
||||
"Connecting...": "Ansluter...",
|
||||
"Disconnecting...": "Kopplar ner...",
|
||||
"Reconnecting...": "Återansluter...",
|
||||
"Internal error": "Internt fel",
|
||||
"Must set host": "Du måste specifiera en värd",
|
||||
"Failed to connect to server: ": "Misslyckades att ansluta till servern: ",
|
||||
"Connected (encrypted) to ": "Ansluten (krypterat) till ",
|
||||
"Connected (unencrypted) to ": "Ansluten (okrypterat) till ",
|
||||
"Something went wrong, connection is closed": "Något gick fel, anslutningen avslutades",
|
||||
|
|
|
|||
|
|
@ -1,69 +1,69 @@
|
|||
{
|
||||
"Connecting...": "连接中...",
|
||||
"Connected (encrypted) to ": "已连接(已加密)到",
|
||||
"Connected (unencrypted) to ": "已连接(未加密)到",
|
||||
"Disconnecting...": "正在断开连接...",
|
||||
"Reconnecting...": "重新连接中...",
|
||||
"Internal error": "内部错误",
|
||||
"Must set host": "请提供主机名",
|
||||
"Connected (encrypted) to ": "已连接到(加密)",
|
||||
"Connected (unencrypted) to ": "已连接到(未加密)",
|
||||
"Something went wrong, connection is closed": "发生错误,连接已关闭",
|
||||
"Failed to connect to server": "无法连接到服务器",
|
||||
"Disconnected": "已断开连接",
|
||||
"New connection has been rejected with reason: ": "连接被拒绝,原因:",
|
||||
"New connection has been rejected": "连接被拒绝",
|
||||
"Must set host": "必须设置主机",
|
||||
"Reconnecting...": "重新连接中...",
|
||||
"Password is required": "请提供密码",
|
||||
"Disconnect timeout": "超时断开",
|
||||
"noVNC encountered an error:": "noVNC 遇到一个错误:",
|
||||
"Hide/Show the control bar": "显示/隐藏控制栏",
|
||||
"Move/Drag Viewport": "拖放显示范围",
|
||||
"viewport drag": "显示范围拖放",
|
||||
"Active Mouse Button": "启动鼠标按鍵",
|
||||
"No mousebutton": "禁用鼠标按鍵",
|
||||
"Left mousebutton": "鼠标左鍵",
|
||||
"Middle mousebutton": "鼠标中鍵",
|
||||
"Right mousebutton": "鼠标右鍵",
|
||||
"Move/Drag Viewport": "移动/拖动窗口",
|
||||
"viewport drag": "窗口拖动",
|
||||
"Active Mouse Button": "启动鼠标按键",
|
||||
"No mousebutton": "禁用鼠标按键",
|
||||
"Left mousebutton": "鼠标左键",
|
||||
"Middle mousebutton": "鼠标中键",
|
||||
"Right mousebutton": "鼠标右键",
|
||||
"Keyboard": "键盘",
|
||||
"Show Keyboard": "显示键盘",
|
||||
"Extra keys": "额外按键",
|
||||
"Show Extra Keys": "显示额外按键",
|
||||
"Ctrl": "Ctrl",
|
||||
"Toggle Ctrl": "切换 Ctrl",
|
||||
"Edit clipboard content in the textarea below.": "在下面的文本区域中编辑剪贴板内容。",
|
||||
"Alt": "Alt",
|
||||
"Toggle Alt": "切换 Alt",
|
||||
"Send Tab": "发送 Tab 键",
|
||||
"Tab": "Tab",
|
||||
"Esc": "Esc",
|
||||
"Send Escape": "发送 Escape 键",
|
||||
"Ctrl+Alt+Del": "Ctrl-Alt-Del",
|
||||
"Send Ctrl-Alt-Del": "发送 Ctrl-Alt-Del 键",
|
||||
"Shutdown/Reboot": "关机/重新启动",
|
||||
"Shutdown/Reboot...": "关机/重新启动...",
|
||||
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
|
||||
"Send Ctrl-Alt-Del": "发送 Ctrl+Alt+Del 键",
|
||||
"Shutdown/Reboot": "关机/重启",
|
||||
"Shutdown/Reboot...": "关机/重启...",
|
||||
"Power": "电源",
|
||||
"Shutdown": "关机",
|
||||
"Reboot": "重新启动",
|
||||
"Reboot": "重启",
|
||||
"Reset": "重置",
|
||||
"Clipboard": "剪贴板",
|
||||
"Clear": "清除",
|
||||
"Fullscreen": "全屏",
|
||||
"Settings": "设置",
|
||||
"Encrypt": "加密",
|
||||
"Shared Mode": "分享模式",
|
||||
"View Only": "仅查看",
|
||||
"Clip to Window": "限制/裁切窗口大小",
|
||||
"Scaling Mode:": "缩放模式:",
|
||||
"None": "无",
|
||||
"Local Scaling": "本地缩放",
|
||||
"Local Downscaling": "降低本地尺寸",
|
||||
"Remote Resizing": "远程调整大小",
|
||||
"Advanced": "高级",
|
||||
"Local Cursor": "本地光标",
|
||||
"Repeater ID:": "中继站 ID",
|
||||
"WebSocket": "WebSocket",
|
||||
"Encrypt": "加密",
|
||||
"Host:": "主机:",
|
||||
"Port:": "端口:",
|
||||
"Path:": "路径:",
|
||||
"Automatic Reconnect": "自动重新连接",
|
||||
"Reconnect Delay (ms):": "重新连接间隔 (ms):",
|
||||
"Logging:": "日志级别:",
|
||||
"Disconnect": "中断连接",
|
||||
"Disconnect": "断开连接",
|
||||
"Connect": "连接",
|
||||
"Password:": "密码:",
|
||||
"Cancel": "取消"
|
||||
"Cancel": "取消",
|
||||
"Canvas not supported.": "不支持 Canvas。"
|
||||
}
|
||||
18
app/ui.js
18
app/ui.js
|
|
@ -67,7 +67,7 @@ const UI = {
|
|||
// insecure context
|
||||
if (!window.isSecureContext) {
|
||||
// FIXME: This gets hidden when connecting
|
||||
UI.showStatus(_("HTTPS is required for full functionality"), 'error');
|
||||
UI.showStatus(_("Running without HTTPS is not recommended, crashes or other issues are likely."), 'error');
|
||||
}
|
||||
|
||||
// Try to fetch version number
|
||||
|
|
@ -1097,10 +1097,18 @@ const UI = {
|
|||
}
|
||||
url += '/' + path;
|
||||
|
||||
UI.rfb = new RFB(document.getElementById('noVNC_container'), url,
|
||||
{ shared: UI.getSetting('shared'),
|
||||
repeaterID: UI.getSetting('repeaterID'),
|
||||
credentials: { password: password } });
|
||||
try {
|
||||
UI.rfb = new RFB(document.getElementById('noVNC_container'), url,
|
||||
{ shared: UI.getSetting('shared'),
|
||||
repeaterID: UI.getSetting('repeaterID'),
|
||||
credentials: { password: password } });
|
||||
} catch (exc) {
|
||||
Log.Error("Failed to connect to server: " + exc);
|
||||
UI.updateVisualState('disconnected');
|
||||
UI.showStatus(_("Failed to connect to server: ") + exc, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
UI.rfb.addEventListener("connect", UI.connectFinished);
|
||||
UI.rfb.addEventListener("disconnect", UI.disconnectFinished);
|
||||
UI.rfb.addEventListener("serververification", UI.serverVerify);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ function localStorageGet(name) {
|
|||
try {
|
||||
r = localStorage.getItem(name);
|
||||
} catch (e) {
|
||||
if (e instanceof DOMException || !localStorage) {
|
||||
if (e instanceof DOMException) {
|
||||
logOnce(cookiesMsg);
|
||||
logOnce("'localStorage.getItem(" + name + ")' failed: " + e,
|
||||
"debug");
|
||||
|
|
|
|||
|
|
@ -285,7 +285,73 @@ export default class TightDecoder {
|
|||
}
|
||||
|
||||
_gradientFilter(streamId, x, y, width, height, sock, display, depth) {
|
||||
throw new Error("Gradient filter not implemented");
|
||||
// assume the TPIXEL is 3 bytes long
|
||||
const uncompressedSize = width * height * 3;
|
||||
let data;
|
||||
|
||||
if (uncompressedSize === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (uncompressedSize < 12) {
|
||||
if (sock.rQwait("TIGHT", uncompressedSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data = sock.rQshiftBytes(uncompressedSize);
|
||||
} else {
|
||||
data = this._readData(sock);
|
||||
if (data === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._zlibs[streamId].setInput(data);
|
||||
data = this._zlibs[streamId].inflate(uncompressedSize);
|
||||
this._zlibs[streamId].setInput(null);
|
||||
}
|
||||
|
||||
let rgbx = new Uint8Array(4 * width * height);
|
||||
|
||||
let rgbxIndex = 0, dataIndex = 0;
|
||||
let left = new Uint8Array(3);
|
||||
for (let x = 0; x < width; x++) {
|
||||
for (let c = 0; c < 3; c++) {
|
||||
const prediction = left[c];
|
||||
const value = data[dataIndex++] + prediction;
|
||||
rgbx[rgbxIndex++] = value;
|
||||
left[c] = value;
|
||||
}
|
||||
rgbx[rgbxIndex++] = 255;
|
||||
}
|
||||
|
||||
let upperIndex = 0;
|
||||
let upper = new Uint8Array(3),
|
||||
upperleft = new Uint8Array(3);
|
||||
for (let y = 1; y < height; y++) {
|
||||
left.fill(0);
|
||||
upperleft.fill(0);
|
||||
for (let x = 0; x < width; x++) {
|
||||
for (let c = 0; c < 3; c++) {
|
||||
upper[c] = rgbx[upperIndex++];
|
||||
let prediction = left[c] + upper[c] - upperleft[c];
|
||||
if (prediction < 0) {
|
||||
prediction = 0;
|
||||
} else if (prediction > 255) {
|
||||
prediction = 255;
|
||||
}
|
||||
const value = data[dataIndex++] + prediction;
|
||||
rgbx[rgbxIndex++] = value;
|
||||
upperleft[c] = upper[c];
|
||||
left[c] = value;
|
||||
}
|
||||
rgbx[rgbxIndex++] = 255;
|
||||
upperIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
display.blitImage(x, y, width, height, rgbx, 0, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_readData(sock) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { deflateInit, deflate } from "../vendor/pako/lib/zlib/deflate.js";
|
||||
import { Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js";
|
||||
import { Z_FULL_FLUSH, Z_DEFAULT_COMPRESSION } from "../vendor/pako/lib/zlib/deflate.js";
|
||||
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
|
||||
|
||||
export default class Deflator {
|
||||
|
|
@ -15,9 +15,8 @@ export default class Deflator {
|
|||
this.strm = new ZStream();
|
||||
this.chunkSize = 1024 * 10 * 10;
|
||||
this.outputBuffer = new Uint8Array(this.chunkSize);
|
||||
this.windowBits = 5;
|
||||
|
||||
deflateInit(this.strm, this.windowBits);
|
||||
deflateInit(this.strm, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
deflate(inData) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const encodings = {
|
|||
pseudoEncodingLastRect: -224,
|
||||
pseudoEncodingCursor: -239,
|
||||
pseudoEncodingQEMUExtendedKeyEvent: -258,
|
||||
pseudoEncodingQEMULedEvent: -261,
|
||||
pseudoEncodingDesktopName: -307,
|
||||
pseudoEncodingExtendedDesktopSize: -308,
|
||||
pseudoEncodingXvp: -309,
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ export default class Inflate {
|
|||
this.strm = new ZStream();
|
||||
this.chunkSize = 1024 * 10 * 10;
|
||||
this.strm.output = new Uint8Array(this.chunkSize);
|
||||
this.windowBits = 5;
|
||||
|
||||
inflateInit(this.strm, this.windowBits);
|
||||
inflateInit(this.strm);
|
||||
}
|
||||
|
||||
setInput(data) {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export default class Keyboard {
|
|||
|
||||
// ===== PRIVATE METHODS =====
|
||||
|
||||
_sendKeyEvent(keysym, code, down) {
|
||||
_sendKeyEvent(keysym, code, down, numlock = null, capslock = null) {
|
||||
if (down) {
|
||||
this._keyDownList[code] = keysym;
|
||||
} else {
|
||||
|
|
@ -48,8 +48,9 @@ export default class Keyboard {
|
|||
}
|
||||
|
||||
Log.Debug("onkeyevent " + (down ? "down" : "up") +
|
||||
", keysym: " + keysym, ", code: " + code);
|
||||
this.onkeyevent(keysym, code, down);
|
||||
", keysym: " + keysym, ", code: " + code +
|
||||
", numlock: " + numlock + ", capslock: " + capslock);
|
||||
this.onkeyevent(keysym, code, down, numlock, capslock);
|
||||
}
|
||||
|
||||
_getKeyCode(e) {
|
||||
|
|
@ -86,6 +87,14 @@ export default class Keyboard {
|
|||
_handleKeyDown(e) {
|
||||
const code = this._getKeyCode(e);
|
||||
let keysym = KeyboardUtil.getKeysym(e);
|
||||
let numlock = e.getModifierState('NumLock');
|
||||
let capslock = e.getModifierState('CapsLock');
|
||||
|
||||
// getModifierState for NumLock is not supported on mac and ios and always returns false.
|
||||
// Set to null to indicate unknown/unsupported instead.
|
||||
if (browser.isMac() || browser.isIOS()) {
|
||||
numlock = null;
|
||||
}
|
||||
|
||||
// Windows doesn't have a proper AltGr, but handles it using
|
||||
// fake Ctrl+Alt. However the remote end might not be Windows,
|
||||
|
|
@ -107,7 +116,7 @@ export default class Keyboard {
|
|||
// key to "AltGraph".
|
||||
keysym = KeyTable.XK_ISO_Level3_Shift;
|
||||
} else {
|
||||
this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true);
|
||||
this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true, numlock, capslock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,8 +127,8 @@ export default class Keyboard {
|
|||
// If it's a virtual keyboard then it should be
|
||||
// sufficient to just send press and release right
|
||||
// after each other
|
||||
this._sendKeyEvent(keysym, code, true);
|
||||
this._sendKeyEvent(keysym, code, false);
|
||||
this._sendKeyEvent(keysym, code, true, numlock, capslock);
|
||||
this._sendKeyEvent(keysym, code, false, numlock, capslock);
|
||||
}
|
||||
|
||||
stopEvent(e);
|
||||
|
|
@ -157,8 +166,8 @@ export default class Keyboard {
|
|||
// while meta is held down
|
||||
if ((browser.isMac() || browser.isIOS()) &&
|
||||
(e.metaKey && code !== 'MetaLeft' && code !== 'MetaRight')) {
|
||||
this._sendKeyEvent(keysym, code, true);
|
||||
this._sendKeyEvent(keysym, code, false);
|
||||
this._sendKeyEvent(keysym, code, true, numlock, capslock);
|
||||
this._sendKeyEvent(keysym, code, false, numlock, capslock);
|
||||
stopEvent(e);
|
||||
return;
|
||||
}
|
||||
|
|
@ -168,8 +177,8 @@ export default class Keyboard {
|
|||
// which toggles on each press, but not on release. So pretend
|
||||
// it was a quick press and release of the button.
|
||||
if ((browser.isMac() || browser.isIOS()) && (code === 'CapsLock')) {
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', true);
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', false);
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', true, numlock, capslock);
|
||||
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', false, numlock, capslock);
|
||||
stopEvent(e);
|
||||
return;
|
||||
}
|
||||
|
|
@ -182,8 +191,8 @@ export default class Keyboard {
|
|||
KeyTable.XK_Hiragana,
|
||||
KeyTable.XK_Romaji ];
|
||||
if (browser.isWindows() && jpBadKeys.includes(keysym)) {
|
||||
this._sendKeyEvent(keysym, code, true);
|
||||
this._sendKeyEvent(keysym, code, false);
|
||||
this._sendKeyEvent(keysym, code, true, numlock, capslock);
|
||||
this._sendKeyEvent(keysym, code, false, numlock, capslock);
|
||||
stopEvent(e);
|
||||
return;
|
||||
}
|
||||
|
|
@ -199,7 +208,7 @@ export default class Keyboard {
|
|||
return;
|
||||
}
|
||||
|
||||
this._sendKeyEvent(keysym, code, true);
|
||||
this._sendKeyEvent(keysym, code, true, numlock, capslock);
|
||||
}
|
||||
|
||||
_handleKeyUp(e) {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export function getKeycode(evt) {
|
|||
// Get 'KeyboardEvent.key', handling legacy browsers
|
||||
export function getKey(evt) {
|
||||
// Are we getting a proper key value?
|
||||
if (evt.key !== undefined) {
|
||||
if ((evt.key !== undefined) && (evt.key !== 'Unidentified')) {
|
||||
// Mozilla isn't fully in sync with the spec yet
|
||||
switch (evt.key) {
|
||||
case 'OS': return 'Meta';
|
||||
|
|
|
|||
66
core/rfb.js
66
core/rfb.js
|
|
@ -260,6 +260,8 @@ export default class RFB extends EventTargetMixin {
|
|||
|
||||
this._keyboard = new Keyboard(this._canvas);
|
||||
this._keyboard.onkeyevent = this._handleKeyEvent.bind(this);
|
||||
this._remoteCapsLock = null; // Null indicates unknown or irrelevant
|
||||
this._remoteNumLock = null;
|
||||
|
||||
this._gestures = new GestureHandler();
|
||||
|
||||
|
|
@ -996,11 +998,39 @@ export default class RFB extends EventTargetMixin {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
_sendPingMessage() {
|
||||
window.parent.postMessage(JSON.stringify({method: 'noVNCPing'}), '*');
|
||||
}
|
||||
_handleKeyEvent(keysym, code, down, numlock, capslock) {
|
||||
// If remote state of capslock is known, and it doesn't match the local led state of
|
||||
// the keyboard, we send a capslock keypress first to bring it into sync.
|
||||
// If we just pressed CapsLock, or we toggled it remotely due to it being out of sync
|
||||
// we clear the remote state so that we don't send duplicate or spurious fixes,
|
||||
// since it may take some time to receive the new remote CapsLock state.
|
||||
if (code == 'CapsLock' && down) {
|
||||
this._remoteCapsLock = null;
|
||||
}
|
||||
if (this._remoteCapsLock !== null && capslock !== null && this._remoteCapsLock !== capslock && down) {
|
||||
Log.Debug("Fixing remote caps lock");
|
||||
|
||||
_handleKeyEvent(keysym, code, down) {
|
||||
this.sendKey(KeyTable.XK_Caps_Lock, 'CapsLock', true);
|
||||
this.sendKey(KeyTable.XK_Caps_Lock, 'CapsLock', false);
|
||||
// We clear the remote capsLock state when we do this to prevent issues with doing this twice
|
||||
// before we receive an update of the the remote state.
|
||||
this._remoteCapsLock = null;
|
||||
}
|
||||
|
||||
// Logic for numlock is exactly the same.
|
||||
if (code == 'NumLock' && down) {
|
||||
this._remoteNumLock = null;
|
||||
}
|
||||
if (this._remoteNumLock !== null && numlock !== null && this._remoteNumLock !== numlock && down) {
|
||||
Log.Debug("Fixing remote num lock");
|
||||
this.sendKey(KeyTable.XK_Num_Lock, 'NumLock', true);
|
||||
this.sendKey(KeyTable.XK_Num_Lock, 'NumLock', false);
|
||||
this._remoteNumLock = null;
|
||||
}
|
||||
this._sendPingMessage();
|
||||
this.sendKey(keysym, code, down);
|
||||
}
|
||||
|
|
@ -1938,7 +1968,11 @@ export default class RFB extends EventTargetMixin {
|
|||
_negotiateAuthentication() {
|
||||
switch (this._rfbAuthScheme) {
|
||||
case securityTypeNone:
|
||||
this._rfbInitState = 'SecurityResult';
|
||||
if (this._rfbVersion >= 3.8) {
|
||||
this._rfbInitState = 'SecurityResult';
|
||||
} else {
|
||||
this._rfbInitState = 'ClientInitialisation';
|
||||
}
|
||||
return true;
|
||||
|
||||
case securityTypeXVP:
|
||||
|
|
@ -1975,13 +2009,6 @@ export default class RFB extends EventTargetMixin {
|
|||
}
|
||||
|
||||
_handleSecurityResult() {
|
||||
// There is no security choice, and hence no security result
|
||||
// until RFB 3.7
|
||||
if (this._rfbVersion < 3.7) {
|
||||
this._rfbInitState = 'ClientInitialisation';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._sock.rQwait('VNC auth response ', 4)) { return false; }
|
||||
|
||||
const status = this._sock.rQshift32();
|
||||
|
|
@ -2117,6 +2144,7 @@ export default class RFB extends EventTargetMixin {
|
|||
encs.push(encodings.pseudoEncodingDesktopSize);
|
||||
encs.push(encodings.pseudoEncodingLastRect);
|
||||
encs.push(encodings.pseudoEncodingQEMUExtendedKeyEvent);
|
||||
encs.push(encodings.pseudoEncodingQEMULedEvent);
|
||||
encs.push(encodings.pseudoEncodingExtendedDesktopSize);
|
||||
encs.push(encodings.pseudoEncodingXvp);
|
||||
encs.push(encodings.pseudoEncodingFence);
|
||||
|
|
@ -2341,7 +2369,7 @@ export default class RFB extends EventTargetMixin {
|
|||
textData = textData.slice(0, -1);
|
||||
}
|
||||
|
||||
textData = textData.replace("\r\n", "\n");
|
||||
textData = textData.replaceAll("\r\n", "\n");
|
||||
|
||||
this.dispatchEvent(new CustomEvent(
|
||||
"clipboard",
|
||||
|
|
@ -2552,6 +2580,9 @@ export default class RFB extends EventTargetMixin {
|
|||
case encodings.pseudoEncodingExtendedDesktopSize:
|
||||
return this._handleExtendedDesktopSize();
|
||||
|
||||
case encodings.pseudoEncodingQEMULedEvent:
|
||||
return this._handleLedEvent();
|
||||
|
||||
default:
|
||||
return this._handleDataRect();
|
||||
}
|
||||
|
|
@ -2729,6 +2760,21 @@ export default class RFB extends EventTargetMixin {
|
|||
return true;
|
||||
}
|
||||
|
||||
_handleLedEvent() {
|
||||
if (this._sock.rQwait("LED Status", 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let data = this._sock.rQshift8();
|
||||
// ScrollLock state can be retrieved with data & 1. This is currently not needed.
|
||||
let numLock = data & 2 ? true : false;
|
||||
let capsLock = data & 4 ? true : false;
|
||||
this._remoteCapsLock = capsLock;
|
||||
this._remoteNumLock = numLock;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_handleExtendedDesktopSize() {
|
||||
if (this._sock.rQwait("ExtendedDesktopSize", 4)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -69,7 +69,9 @@ export default class Cursor {
|
|||
this._target.removeEventListener('mousemove', this._eventHandlers.mousemove, options);
|
||||
this._target.removeEventListener('mouseup', this._eventHandlers.mouseup, options);
|
||||
|
||||
document.body.removeChild(this._canvas);
|
||||
if (document.contains(this._canvas)) {
|
||||
document.body.removeChild(this._canvas);
|
||||
}
|
||||
}
|
||||
|
||||
this._target = null;
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
.SH NAME
|
||||
novnc_proxy - noVNC proxy server
|
||||
.SH SYNOPSIS
|
||||
.B novnc_proxy [--listen PORT] [--vnc VNC_HOST:PORT] [--cert CERT] [--ssl-only]
|
||||
.B novnc_proxy [--listen [HOST:]PORT] [--vnc VNC_HOST:PORT] [--cert CERT] [--ssl-only]
|
||||
|
||||
Starts the WebSockets proxy and a mini-webserver and
|
||||
provides a cut-and-paste URL to go to.
|
||||
|
||||
--listen PORT Port for proxy/webserver to listen on
|
||||
Default: 6080
|
||||
--listen [HOST:]PORT Port for proxy/webserver to listen on
|
||||
Default: 6080 (on all interfaces)
|
||||
--vnc VNC_HOST:PORT VNC server host:port proxy target
|
||||
Default: localhost:5900
|
||||
--cert CERT Path to combined cert/key file, or just
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
import globals from "globals";
|
||||
import js from "@eslint/js";
|
||||
|
||||
export default [
|
||||
js.configs.recommended,
|
||||
{
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: "module",
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.es2020,
|
||||
}
|
||||
},
|
||||
ignores: ["**/xtscancodes.js"],
|
||||
rules: {
|
||||
// Unsafe or confusing stuff that we forbid
|
||||
|
||||
"no-unused-vars": ["error", { "vars": "all",
|
||||
"args": "none",
|
||||
"ignoreRestSiblings": true,
|
||||
"caughtErrors": "none" }],
|
||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||
"no-var": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"object-shorthand": ["error", "methods", { "avoidQuotes": true }],
|
||||
"prefer-arrow-callback": "error",
|
||||
"arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": false } ],
|
||||
"arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
|
||||
"arrow-spacing": ["error"],
|
||||
"no-confusing-arrow": ["error", { "allowParens": true }],
|
||||
|
||||
// Enforced coding style
|
||||
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||
"indent": ["error", 4, { "SwitchCase": 1,
|
||||
"VariableDeclarator": "first",
|
||||
"FunctionDeclaration": { "parameters": "first" },
|
||||
"FunctionExpression": { "parameters": "first" },
|
||||
"CallExpression": { "arguments": "first" },
|
||||
"ArrayExpression": "first",
|
||||
"ObjectExpression": "first",
|
||||
"ImportDeclaration": "first",
|
||||
"ignoreComments": true }],
|
||||
"comma-spacing": ["error"],
|
||||
"comma-style": ["error"],
|
||||
"curly": ["error", "multi-line"],
|
||||
"func-call-spacing": ["error"],
|
||||
"func-names": ["error"],
|
||||
"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
|
||||
"key-spacing": ["error"],
|
||||
"keyword-spacing": ["error"],
|
||||
"no-trailing-spaces": ["error"],
|
||||
"semi": ["error"],
|
||||
"space-before-blocks": ["error"],
|
||||
"space-before-function-paren": ["error", { "anonymous": "always",
|
||||
"named": "never",
|
||||
"asyncArrow": "always" }],
|
||||
"switch-colon-spacing": ["error"],
|
||||
"camelcase": ["error", { "allow": ["^XK_", "^XF86XK_"] }],
|
||||
"no-console": ["error"],
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["po/po2js", "po/xgettext-html"],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"no-console": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["tests/*"],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.mocha,
|
||||
sinon: false,
|
||||
chai: false,
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"prefer-arrow-callback": 0,
|
||||
// Too many anonymous callbacks
|
||||
"func-names": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["utils/*"],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"no-console": 0,
|
||||
},
|
||||
},
|
||||
];
|
||||
13
package.json
13
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@novnc/novnc",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"description": "An HTML5 VNC client",
|
||||
"browser": "lib/rfb",
|
||||
"directories": {
|
||||
|
|
@ -14,9 +14,7 @@
|
|||
"VERSION",
|
||||
"docs/API.md",
|
||||
"docs/LIBRARY.md",
|
||||
"docs/LICENSE*",
|
||||
"core",
|
||||
"vendor/pako"
|
||||
"docs/LICENSE*"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint app core po/po2js po/xgettext-html tests utils",
|
||||
|
|
@ -39,19 +37,14 @@
|
|||
"homepage": "https://github.com/novnc/noVNC",
|
||||
"devDependencies": {
|
||||
"@babel/core": "latest",
|
||||
"@babel/plugin-syntax-dynamic-import": "latest",
|
||||
"@babel/plugin-transform-modules-commonjs": "latest",
|
||||
"@babel/preset-env": "latest",
|
||||
"@babel/cli": "latest",
|
||||
"babel-plugin-import-redirect": "latest",
|
||||
"browserify": "latest",
|
||||
"babelify": "latest",
|
||||
"core-js": "latest",
|
||||
"chai": "latest",
|
||||
"commander": "latest",
|
||||
"es-module-loader": "latest",
|
||||
"eslint": "latest",
|
||||
"fs-extra": "latest",
|
||||
"globals": "latest",
|
||||
"jsdom": "latest",
|
||||
"karma": "latest",
|
||||
"karma-mocha": "latest",
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
},
|
||||
}
|
||||
262
po/el.po
262
po/el.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: noVNC 0.6.1\n"
|
||||
"Report-Msgid-Bugs-To: novnc@googlegroups.com\n"
|
||||
"POT-Creation-Date: 2017-11-17 21:40+0200\n"
|
||||
"POT-Creation-Date: 2022-12-27 15:24+0100\n"
|
||||
"PO-Revision-Date: 2017-10-11 16:16+0200\n"
|
||||
"Last-Translator: Giannis Kosmas <kosmasgiannis@gmail.com>\n"
|
||||
"Language-Team: none\n"
|
||||
|
|
@ -17,273 +17,349 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ../app/ui.js:404
|
||||
#: ../app/ui.js:69
|
||||
msgid "HTTPS is required for full functionality"
|
||||
msgstr "Το HTTPS είναι απαιτούμενο για πλήρη λειτουργικότητα"
|
||||
|
||||
#: ../app/ui.js:410
|
||||
msgid "Connecting..."
|
||||
msgstr "Συνδέεται..."
|
||||
|
||||
#: ../app/ui.js:411
|
||||
#: ../app/ui.js:417
|
||||
msgid "Disconnecting..."
|
||||
msgstr "Aποσυνδέεται..."
|
||||
|
||||
#: ../app/ui.js:417
|
||||
#: ../app/ui.js:423
|
||||
msgid "Reconnecting..."
|
||||
msgstr "Επανασυνδέεται..."
|
||||
|
||||
#: ../app/ui.js:422
|
||||
#: ../app/ui.js:428
|
||||
msgid "Internal error"
|
||||
msgstr "Εσωτερικό σφάλμα"
|
||||
|
||||
#: ../app/ui.js:1019
|
||||
#: ../app/ui.js:1026
|
||||
msgid "Must set host"
|
||||
msgstr "Πρέπει να οριστεί ο διακομιστής"
|
||||
|
||||
#: ../app/ui.js:1099
|
||||
#: ../app/ui.js:1110
|
||||
msgid "Connected (encrypted) to "
|
||||
msgstr "Συνδέθηκε (κρυπτογραφημένα) με το "
|
||||
|
||||
#: ../app/ui.js:1101
|
||||
#: ../app/ui.js:1112
|
||||
msgid "Connected (unencrypted) to "
|
||||
msgstr "Συνδέθηκε (μη κρυπτογραφημένα) με το "
|
||||
|
||||
#: ../app/ui.js:1119
|
||||
#: ../app/ui.js:1135
|
||||
msgid "Something went wrong, connection is closed"
|
||||
msgstr "Κάτι πήγε στραβά, η σύνδεση διακόπηκε"
|
||||
|
||||
#: ../app/ui.js:1129
|
||||
#: ../app/ui.js:1138
|
||||
msgid "Failed to connect to server"
|
||||
msgstr "Αποτυχία στη σύνδεση με το διακομιστή"
|
||||
|
||||
#: ../app/ui.js:1150
|
||||
msgid "Disconnected"
|
||||
msgstr "Αποσυνδέθηκε"
|
||||
|
||||
#: ../app/ui.js:1142
|
||||
#: ../app/ui.js:1165
|
||||
msgid "New connection has been rejected with reason: "
|
||||
msgstr "Η νέα σύνδεση απορρίφθηκε διότι: "
|
||||
|
||||
#: ../app/ui.js:1145
|
||||
#: ../app/ui.js:1168
|
||||
msgid "New connection has been rejected"
|
||||
msgstr "Η νέα σύνδεση απορρίφθηκε "
|
||||
|
||||
#: ../app/ui.js:1166
|
||||
msgid "Password is required"
|
||||
msgstr "Απαιτείται ο κωδικός πρόσβασης"
|
||||
#: ../app/ui.js:1234
|
||||
msgid "Credentials are required"
|
||||
msgstr "Απαιτούνται διαπιστευτήρια"
|
||||
|
||||
#: ../vnc.html:89
|
||||
#: ../vnc.html:57
|
||||
msgid "noVNC encountered an error:"
|
||||
msgstr "το noVNC αντιμετώπισε ένα σφάλμα:"
|
||||
|
||||
#: ../vnc.html:99
|
||||
#: ../vnc.html:67
|
||||
msgid "Hide/Show the control bar"
|
||||
msgstr "Απόκρυψη/Εμφάνιση γραμμής ελέγχου"
|
||||
|
||||
#: ../vnc.html:106
|
||||
#: ../vnc.html:76
|
||||
msgid "Drag"
|
||||
msgstr "Σύρσιμο"
|
||||
|
||||
#: ../vnc.html:76
|
||||
msgid "Move/Drag Viewport"
|
||||
msgstr "Μετακίνηση/Σύρσιμο Θεατού πεδίου"
|
||||
|
||||
#: ../vnc.html:106
|
||||
msgid "viewport drag"
|
||||
msgstr "σύρσιμο θεατού πεδίου"
|
||||
|
||||
#: ../vnc.html:112 ../vnc.html:115 ../vnc.html:118 ../vnc.html:121
|
||||
msgid "Active Mouse Button"
|
||||
msgstr "Ενεργό Πλήκτρο Ποντικιού"
|
||||
|
||||
#: ../vnc.html:112
|
||||
msgid "No mousebutton"
|
||||
msgstr "Χωρίς Πλήκτρο Ποντικιού"
|
||||
|
||||
#: ../vnc.html:115
|
||||
msgid "Left mousebutton"
|
||||
msgstr "Αριστερό Πλήκτρο Ποντικιού"
|
||||
|
||||
#: ../vnc.html:118
|
||||
msgid "Middle mousebutton"
|
||||
msgstr "Μεσαίο Πλήκτρο Ποντικιού"
|
||||
|
||||
#: ../vnc.html:121
|
||||
msgid "Right mousebutton"
|
||||
msgstr "Δεξί Πλήκτρο Ποντικιού"
|
||||
|
||||
#: ../vnc.html:124
|
||||
#: ../vnc.html:82
|
||||
msgid "Keyboard"
|
||||
msgstr "Πληκτρολόγιο"
|
||||
|
||||
#: ../vnc.html:124
|
||||
#: ../vnc.html:82
|
||||
msgid "Show Keyboard"
|
||||
msgstr "Εμφάνιση Πληκτρολογίου"
|
||||
|
||||
#: ../vnc.html:131
|
||||
#: ../vnc.html:87
|
||||
msgid "Extra keys"
|
||||
msgstr "Επιπλέον πλήκτρα"
|
||||
|
||||
#: ../vnc.html:131
|
||||
#: ../vnc.html:87
|
||||
msgid "Show Extra Keys"
|
||||
msgstr "Εμφάνιση Επιπλέον Πλήκτρων"
|
||||
|
||||
#: ../vnc.html:136
|
||||
#: ../vnc.html:92
|
||||
msgid "Ctrl"
|
||||
msgstr "Ctrl"
|
||||
|
||||
#: ../vnc.html:136
|
||||
#: ../vnc.html:92
|
||||
msgid "Toggle Ctrl"
|
||||
msgstr "Εναλλαγή Ctrl"
|
||||
|
||||
#: ../vnc.html:139
|
||||
#: ../vnc.html:95
|
||||
msgid "Alt"
|
||||
msgstr "Alt"
|
||||
|
||||
#: ../vnc.html:139
|
||||
#: ../vnc.html:95
|
||||
msgid "Toggle Alt"
|
||||
msgstr "Εναλλαγή Alt"
|
||||
|
||||
#: ../vnc.html:142
|
||||
#: ../vnc.html:98
|
||||
msgid "Toggle Windows"
|
||||
msgstr "Εναλλαγή Παράθυρων"
|
||||
|
||||
#: ../vnc.html:98
|
||||
msgid "Windows"
|
||||
msgstr "Παράθυρα"
|
||||
|
||||
#: ../vnc.html:101
|
||||
msgid "Send Tab"
|
||||
msgstr "Αποστολή Tab"
|
||||
|
||||
#: ../vnc.html:142
|
||||
#: ../vnc.html:101
|
||||
msgid "Tab"
|
||||
msgstr "Tab"
|
||||
|
||||
#: ../vnc.html:145
|
||||
#: ../vnc.html:104
|
||||
msgid "Esc"
|
||||
msgstr "Esc"
|
||||
|
||||
#: ../vnc.html:145
|
||||
#: ../vnc.html:104
|
||||
msgid "Send Escape"
|
||||
msgstr "Αποστολή Escape"
|
||||
|
||||
#: ../vnc.html:148
|
||||
#: ../vnc.html:107
|
||||
msgid "Ctrl+Alt+Del"
|
||||
msgstr "Ctrl+Alt+Del"
|
||||
|
||||
#: ../vnc.html:148
|
||||
#: ../vnc.html:107
|
||||
msgid "Send Ctrl-Alt-Del"
|
||||
msgstr "Αποστολή Ctrl-Alt-Del"
|
||||
|
||||
#: ../vnc.html:156
|
||||
#: ../vnc.html:114
|
||||
msgid "Shutdown/Reboot"
|
||||
msgstr "Κλείσιμο/Επανεκκίνηση"
|
||||
|
||||
#: ../vnc.html:156
|
||||
#: ../vnc.html:114
|
||||
msgid "Shutdown/Reboot..."
|
||||
msgstr "Κλείσιμο/Επανεκκίνηση..."
|
||||
|
||||
#: ../vnc.html:162
|
||||
#: ../vnc.html:120
|
||||
msgid "Power"
|
||||
msgstr "Απενεργοποίηση"
|
||||
|
||||
#: ../vnc.html:164
|
||||
#: ../vnc.html:122
|
||||
msgid "Shutdown"
|
||||
msgstr "Κλείσιμο"
|
||||
|
||||
#: ../vnc.html:165
|
||||
#: ../vnc.html:123
|
||||
msgid "Reboot"
|
||||
msgstr "Επανεκκίνηση"
|
||||
|
||||
#: ../vnc.html:166
|
||||
#: ../vnc.html:124
|
||||
msgid "Reset"
|
||||
msgstr "Επαναφορά"
|
||||
|
||||
#: ../vnc.html:171 ../vnc.html:177
|
||||
#: ../vnc.html:129 ../vnc.html:135
|
||||
msgid "Clipboard"
|
||||
msgstr "Πρόχειρο"
|
||||
|
||||
#: ../vnc.html:181
|
||||
msgid "Clear"
|
||||
msgstr "Καθάρισμα"
|
||||
#: ../vnc.html:137
|
||||
msgid "Edit clipboard content in the textarea below."
|
||||
msgstr "Επεξεργαστείτε το περιεχόμενο του πρόχειρου στην περιοχή κειμένου παρακάτω."
|
||||
|
||||
#: ../vnc.html:187
|
||||
msgid "Fullscreen"
|
||||
#: ../vnc.html:145
|
||||
#, fuzzy
|
||||
msgid "Full Screen"
|
||||
msgstr "Πλήρης Οθόνη"
|
||||
|
||||
#: ../vnc.html:192 ../vnc.html:199
|
||||
#: ../vnc.html:150 ../vnc.html:156
|
||||
msgid "Settings"
|
||||
msgstr "Ρυθμίσεις"
|
||||
|
||||
#: ../vnc.html:202
|
||||
#: ../vnc.html:160
|
||||
msgid "Shared Mode"
|
||||
msgstr "Κοινόχρηστη Λειτουργία"
|
||||
|
||||
#: ../vnc.html:205
|
||||
#: ../vnc.html:163
|
||||
msgid "View Only"
|
||||
msgstr "Μόνο Θέαση"
|
||||
|
||||
#: ../vnc.html:209
|
||||
#: ../vnc.html:167
|
||||
msgid "Clip to Window"
|
||||
msgstr "Αποκοπή στο όριο του Παράθυρου"
|
||||
|
||||
#: ../vnc.html:212
|
||||
#: ../vnc.html:170
|
||||
msgid "Scaling Mode:"
|
||||
msgstr "Λειτουργία Κλιμάκωσης:"
|
||||
|
||||
#: ../vnc.html:214
|
||||
#: ../vnc.html:172
|
||||
msgid "None"
|
||||
msgstr "Καμία"
|
||||
|
||||
#: ../vnc.html:215
|
||||
#: ../vnc.html:173
|
||||
msgid "Local Scaling"
|
||||
msgstr "Τοπική Κλιμάκωση"
|
||||
|
||||
#: ../vnc.html:216
|
||||
#: ../vnc.html:174
|
||||
msgid "Remote Resizing"
|
||||
msgstr "Απομακρυσμένη Αλλαγή μεγέθους"
|
||||
|
||||
#: ../vnc.html:221
|
||||
#: ../vnc.html:179
|
||||
msgid "Advanced"
|
||||
msgstr "Για προχωρημένους"
|
||||
|
||||
#: ../vnc.html:224
|
||||
#: ../vnc.html:182
|
||||
msgid "Quality:"
|
||||
msgstr "Ποιότητα:"
|
||||
|
||||
#: ../vnc.html:186
|
||||
msgid "Compression level:"
|
||||
msgstr "Επίπεδο συμπίεσης:"
|
||||
|
||||
#: ../vnc.html:191
|
||||
msgid "Repeater ID:"
|
||||
msgstr "Repeater ID:"
|
||||
|
||||
#: ../vnc.html:228
|
||||
#: ../vnc.html:195
|
||||
msgid "WebSocket"
|
||||
msgstr "WebSocket"
|
||||
|
||||
#: ../vnc.html:231
|
||||
#: ../vnc.html:198
|
||||
msgid "Encrypt"
|
||||
msgstr "Κρυπτογράφηση"
|
||||
|
||||
#: ../vnc.html:234
|
||||
#: ../vnc.html:201
|
||||
msgid "Host:"
|
||||
msgstr "Όνομα διακομιστή:"
|
||||
|
||||
#: ../vnc.html:238
|
||||
#: ../vnc.html:205
|
||||
msgid "Port:"
|
||||
msgstr "Πόρτα διακομιστή:"
|
||||
|
||||
#: ../vnc.html:242
|
||||
#: ../vnc.html:209
|
||||
msgid "Path:"
|
||||
msgstr "Διαδρομή:"
|
||||
|
||||
#: ../vnc.html:249
|
||||
#: ../vnc.html:216
|
||||
msgid "Automatic Reconnect"
|
||||
msgstr "Αυτόματη επανασύνδεση"
|
||||
|
||||
#: ../vnc.html:252
|
||||
#: ../vnc.html:219
|
||||
msgid "Reconnect Delay (ms):"
|
||||
msgstr "Καθυστέρηση επανασύνδεσης (ms):"
|
||||
|
||||
#: ../vnc.html:258
|
||||
#: ../vnc.html:224
|
||||
msgid "Show Dot when No Cursor"
|
||||
msgstr "Εμφάνιση Τελείας όταν δεν υπάρχει Δρομέας"
|
||||
|
||||
#: ../vnc.html:229
|
||||
msgid "Logging:"
|
||||
msgstr "Καταγραφή:"
|
||||
|
||||
#: ../vnc.html:270
|
||||
#: ../vnc.html:238
|
||||
msgid "Version:"
|
||||
msgstr "Έκδοση:"
|
||||
|
||||
#: ../vnc.html:246
|
||||
msgid "Disconnect"
|
||||
msgstr "Αποσύνδεση"
|
||||
|
||||
#: ../vnc.html:289
|
||||
#: ../vnc.html:269
|
||||
msgid "Connect"
|
||||
msgstr "Σύνδεση"
|
||||
|
||||
#: ../vnc.html:299
|
||||
#: ../vnc.html:278
|
||||
msgid "Server identity"
|
||||
msgstr "Ταυτότητα Διακομιστή"
|
||||
|
||||
#: ../vnc.html:281
|
||||
msgid "The server has provided the following identifying information:"
|
||||
msgstr "Ο διακομιστής παρείχε την ακόλουθη πληροφορία ταυτοποίησης:"
|
||||
|
||||
#: ../vnc.html:285
|
||||
msgid "Fingerprint:"
|
||||
msgstr "Δακτυλικό αποτύπωμα:"
|
||||
|
||||
#: ../vnc.html:288
|
||||
msgid ""
|
||||
"Please verify that the information is correct and press \"Approve\". "
|
||||
"Otherwise press \"Reject\"."
|
||||
msgstr ""
|
||||
"Παρακαλώ επαληθεύσετε ότι η πληροφορία είναι σωστή και πιέστε \"Αποδοχή\". "
|
||||
"Αλλιώς πιέστε \"Απόρριψη\"."
|
||||
|
||||
#: ../vnc.html:293
|
||||
msgid "Approve"
|
||||
msgstr "Αποδοχή"
|
||||
|
||||
#: ../vnc.html:294
|
||||
msgid "Reject"
|
||||
msgstr "Απόρριψη"
|
||||
|
||||
#: ../vnc.html:302
|
||||
msgid "Credentials"
|
||||
msgstr "Διαπιστευτήρια"
|
||||
|
||||
#: ../vnc.html:306
|
||||
msgid "Username:"
|
||||
msgstr "Κωδικός Χρήστη:"
|
||||
|
||||
#: ../vnc.html:310
|
||||
msgid "Password:"
|
||||
msgstr "Κωδικός Πρόσβασης:"
|
||||
|
||||
#: ../vnc.html:313
|
||||
#: ../vnc.html:314
|
||||
msgid "Send Credentials"
|
||||
msgstr "Αποστολή Διαπιστευτηρίων"
|
||||
|
||||
#: ../vnc.html:323
|
||||
msgid "Cancel"
|
||||
msgstr "Ακύρωση"
|
||||
|
||||
#: ../vnc.html:329
|
||||
msgid "Canvas not supported."
|
||||
msgstr "Δεν υποστηρίζεται το στοιχείο Canvas"
|
||||
#~ msgid "Password is required"
|
||||
#~ msgstr "Απαιτείται ο κωδικός πρόσβασης"
|
||||
|
||||
#~ msgid "viewport drag"
|
||||
#~ msgstr "σύρσιμο θεατού πεδίου"
|
||||
|
||||
#~ msgid "Active Mouse Button"
|
||||
#~ msgstr "Ενεργό Πλήκτρο Ποντικιού"
|
||||
|
||||
#~ msgid "No mousebutton"
|
||||
#~ msgstr "Χωρίς Πλήκτρο Ποντικιού"
|
||||
|
||||
#~ msgid "Left mousebutton"
|
||||
#~ msgstr "Αριστερό Πλήκτρο Ποντικιού"
|
||||
|
||||
#~ msgid "Middle mousebutton"
|
||||
#~ msgstr "Μεσαίο Πλήκτρο Ποντικιού"
|
||||
|
||||
#~ msgid "Right mousebutton"
|
||||
#~ msgstr "Δεξί Πλήκτρο Ποντικιού"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Καθάρισμα"
|
||||
|
||||
#~ msgid "Canvas not supported."
|
||||
#~ msgstr "Δεν υποστηρίζεται το στοιχείο Canvas"
|
||||
|
||||
#~ msgid "Disconnect timeout"
|
||||
#~ msgstr "Παρέλευση χρονικού ορίου αποσύνδεσης"
|
||||
|
|
|
|||
155
po/noVNC.pot
155
po/noVNC.pot
|
|
@ -6,9 +6,9 @@
|
|||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: noVNC 1.4.0\n"
|
||||
"Project-Id-Version: noVNC 1.5.0\n"
|
||||
"Report-Msgid-Bugs-To: novnc@googlegroups.com\n"
|
||||
"POT-Creation-Date: 2022-12-27 15:24+0100\n"
|
||||
"POT-Creation-Date: 2024-06-03 14:10+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -18,7 +18,8 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../app/ui.js:69
|
||||
msgid "HTTPS is required for full functionality"
|
||||
msgid ""
|
||||
"Running without HTTPS is not recommended, crashes or other issues are likely."
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:410
|
||||
|
|
@ -41,292 +42,296 @@ msgstr ""
|
|||
msgid "Must set host"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1110
|
||||
#: ../app/ui.js:1052
|
||||
msgid "Failed to connect to server: "
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1118
|
||||
msgid "Connected (encrypted) to "
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1112
|
||||
#: ../app/ui.js:1120
|
||||
msgid "Connected (unencrypted) to "
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1135
|
||||
#: ../app/ui.js:1143
|
||||
msgid "Something went wrong, connection is closed"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1138
|
||||
#: ../app/ui.js:1146
|
||||
msgid "Failed to connect to server"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1150
|
||||
#: ../app/ui.js:1158
|
||||
msgid "Disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1165
|
||||
#: ../app/ui.js:1173
|
||||
msgid "New connection has been rejected with reason: "
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1168
|
||||
#: ../app/ui.js:1176
|
||||
msgid "New connection has been rejected"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1234
|
||||
#: ../app/ui.js:1242
|
||||
msgid "Credentials are required"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:57
|
||||
#: ../vnc.html:55
|
||||
msgid "noVNC encountered an error:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:67
|
||||
#: ../vnc.html:65
|
||||
msgid "Hide/Show the control bar"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:76
|
||||
#: ../vnc.html:74
|
||||
msgid "Drag"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:76
|
||||
#: ../vnc.html:74
|
||||
msgid "Move/Drag Viewport"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:82
|
||||
#: ../vnc.html:80
|
||||
msgid "Keyboard"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:82
|
||||
#: ../vnc.html:80
|
||||
msgid "Show Keyboard"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:87
|
||||
#: ../vnc.html:85
|
||||
msgid "Extra keys"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:87
|
||||
#: ../vnc.html:85
|
||||
msgid "Show Extra Keys"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:92
|
||||
#: ../vnc.html:90
|
||||
msgid "Ctrl"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:92
|
||||
#: ../vnc.html:90
|
||||
msgid "Toggle Ctrl"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:95
|
||||
#: ../vnc.html:93
|
||||
msgid "Alt"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:95
|
||||
#: ../vnc.html:93
|
||||
msgid "Toggle Alt"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:98
|
||||
#: ../vnc.html:96
|
||||
msgid "Toggle Windows"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:98
|
||||
#: ../vnc.html:96
|
||||
msgid "Windows"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:101
|
||||
#: ../vnc.html:99
|
||||
msgid "Send Tab"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:101
|
||||
#: ../vnc.html:99
|
||||
msgid "Tab"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:104
|
||||
#: ../vnc.html:102
|
||||
msgid "Esc"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:104
|
||||
#: ../vnc.html:102
|
||||
msgid "Send Escape"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:107
|
||||
#: ../vnc.html:105
|
||||
msgid "Ctrl+Alt+Del"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:107
|
||||
#: ../vnc.html:105
|
||||
msgid "Send Ctrl-Alt-Del"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:114
|
||||
#: ../vnc.html:112
|
||||
msgid "Shutdown/Reboot"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:114
|
||||
#: ../vnc.html:112
|
||||
msgid "Shutdown/Reboot..."
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:120
|
||||
#: ../vnc.html:118
|
||||
msgid "Power"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:122
|
||||
#: ../vnc.html:120
|
||||
msgid "Shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:123
|
||||
#: ../vnc.html:121
|
||||
msgid "Reboot"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:124
|
||||
#: ../vnc.html:122
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:129 ../vnc.html:135
|
||||
#: ../vnc.html:127 ../vnc.html:133
|
||||
msgid "Clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:137
|
||||
#: ../vnc.html:135
|
||||
msgid "Edit clipboard content in the textarea below."
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:145
|
||||
#: ../vnc.html:143
|
||||
msgid "Full Screen"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:150 ../vnc.html:156
|
||||
#: ../vnc.html:148 ../vnc.html:154
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:160
|
||||
#: ../vnc.html:158
|
||||
msgid "Shared Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:163
|
||||
#: ../vnc.html:161
|
||||
msgid "View Only"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:167
|
||||
#: ../vnc.html:165
|
||||
msgid "Clip to Window"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:170
|
||||
#: ../vnc.html:168
|
||||
msgid "Scaling Mode:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:172
|
||||
#: ../vnc.html:170
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:173
|
||||
#: ../vnc.html:171
|
||||
msgid "Local Scaling"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:174
|
||||
#: ../vnc.html:172
|
||||
msgid "Remote Resizing"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:179
|
||||
#: ../vnc.html:177
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:182
|
||||
#: ../vnc.html:180
|
||||
msgid "Quality:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:186
|
||||
#: ../vnc.html:184
|
||||
msgid "Compression level:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:191
|
||||
#: ../vnc.html:189
|
||||
msgid "Repeater ID:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:195
|
||||
#: ../vnc.html:193
|
||||
msgid "WebSocket"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:198
|
||||
#: ../vnc.html:196
|
||||
msgid "Encrypt"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:201
|
||||
#: ../vnc.html:199
|
||||
msgid "Host:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:205
|
||||
#: ../vnc.html:203
|
||||
msgid "Port:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:209
|
||||
#: ../vnc.html:207
|
||||
msgid "Path:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:216
|
||||
#: ../vnc.html:214
|
||||
msgid "Automatic Reconnect"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:219
|
||||
#: ../vnc.html:217
|
||||
msgid "Reconnect Delay (ms):"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:224
|
||||
#: ../vnc.html:222
|
||||
msgid "Show Dot when No Cursor"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:229
|
||||
#: ../vnc.html:227
|
||||
msgid "Logging:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:238
|
||||
#: ../vnc.html:236
|
||||
msgid "Version:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:246
|
||||
#: ../vnc.html:244
|
||||
msgid "Disconnect"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:269
|
||||
#: ../vnc.html:267
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:278
|
||||
#: ../vnc.html:276
|
||||
msgid "Server identity"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:281
|
||||
#: ../vnc.html:279
|
||||
msgid "The server has provided the following identifying information:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:285
|
||||
#: ../vnc.html:283
|
||||
msgid "Fingerprint:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:288
|
||||
#: ../vnc.html:286
|
||||
msgid ""
|
||||
"Please verify that the information is correct and press \"Approve\". "
|
||||
"Otherwise press \"Reject\"."
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:293
|
||||
#: ../vnc.html:291
|
||||
msgid "Approve"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:294
|
||||
#: ../vnc.html:292
|
||||
msgid "Reject"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:302
|
||||
#: ../vnc.html:300
|
||||
msgid "Credentials"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:306
|
||||
#: ../vnc.html:304
|
||||
msgid "Username:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:310
|
||||
#: ../vnc.html:308
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:314
|
||||
#: ../vnc.html:312
|
||||
msgid "Send Credentials"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:323
|
||||
#: ../vnc.html:321
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
|
|
|||
12
po/po2js
12
po/po2js
|
|
@ -32,11 +32,13 @@ if (opt.argv.length != 2) {
|
|||
|
||||
const data = po2json.parseFileSync(opt.argv[0]);
|
||||
|
||||
const bodyPart = Object.keys(data).filter(msgid => msgid !== "").map((msgid) => {
|
||||
if (msgid === "") return;
|
||||
const msgstr = data[msgid][1];
|
||||
return " " + JSON.stringify(msgid) + ": " + JSON.stringify(msgstr);
|
||||
}).join(",\n");
|
||||
const bodyPart = Object.keys(data)
|
||||
.filter(msgid => msgid !== "")
|
||||
.filter(msgid => data[msgid][1] !== "")
|
||||
.map((msgid) => {
|
||||
const msgstr = data[msgid][1];
|
||||
return " " + JSON.stringify(msgid) + ": " + JSON.stringify(msgstr);
|
||||
}).join(",\n");
|
||||
|
||||
const output = "{\n" + bodyPart + "\n}";
|
||||
|
||||
|
|
|
|||
42
po/sv.po
42
po/sv.po
|
|
@ -8,20 +8,23 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: noVNC 1.3.0\n"
|
||||
"Report-Msgid-Bugs-To: novnc@googlegroups.com\n"
|
||||
"POT-Creation-Date: 2023-01-20 12:54+0100\n"
|
||||
"PO-Revision-Date: 2023-01-20 12:58+0100\n"
|
||||
"Last-Translator: Samuel Mannehed <samuel@cendio.se>\n"
|
||||
"POT-Creation-Date: 2024-06-03 14:10+0200\n"
|
||||
"PO-Revision-Date: 2024-06-18 13:52+0200\n"
|
||||
"Last-Translator: Pierre Ossman <ossman@cendio.se>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
"X-Generator: Poedit 3.4.4\n"
|
||||
|
||||
#: ../app/ui.js:69
|
||||
msgid "HTTPS is required for full functionality"
|
||||
msgstr "HTTPS krävs för full funktionalitet"
|
||||
msgid ""
|
||||
"Running without HTTPS is not recommended, crashes or other issues are likely."
|
||||
msgstr ""
|
||||
"Det är ej rekommenderat att köra utan HTTPS, krascher och andra problem är "
|
||||
"troliga."
|
||||
|
||||
#: ../app/ui.js:410
|
||||
msgid "Connecting..."
|
||||
|
|
@ -43,35 +46,39 @@ msgstr "Internt fel"
|
|||
msgid "Must set host"
|
||||
msgstr "Du måste specifiera en värd"
|
||||
|
||||
#: ../app/ui.js:1110
|
||||
#: ../app/ui.js:1052
|
||||
msgid "Failed to connect to server: "
|
||||
msgstr "Misslyckades att ansluta till servern: "
|
||||
|
||||
#: ../app/ui.js:1118
|
||||
msgid "Connected (encrypted) to "
|
||||
msgstr "Ansluten (krypterat) till "
|
||||
|
||||
#: ../app/ui.js:1112
|
||||
#: ../app/ui.js:1120
|
||||
msgid "Connected (unencrypted) to "
|
||||
msgstr "Ansluten (okrypterat) till "
|
||||
|
||||
#: ../app/ui.js:1135
|
||||
#: ../app/ui.js:1143
|
||||
msgid "Something went wrong, connection is closed"
|
||||
msgstr "Något gick fel, anslutningen avslutades"
|
||||
|
||||
#: ../app/ui.js:1138
|
||||
#: ../app/ui.js:1146
|
||||
msgid "Failed to connect to server"
|
||||
msgstr "Misslyckades att ansluta till servern"
|
||||
|
||||
#: ../app/ui.js:1150
|
||||
#: ../app/ui.js:1158
|
||||
msgid "Disconnected"
|
||||
msgstr "Frånkopplad"
|
||||
|
||||
#: ../app/ui.js:1165
|
||||
#: ../app/ui.js:1173
|
||||
msgid "New connection has been rejected with reason: "
|
||||
msgstr "Ny anslutning har blivit nekad med följande skäl: "
|
||||
|
||||
#: ../app/ui.js:1168
|
||||
#: ../app/ui.js:1176
|
||||
msgid "New connection has been rejected"
|
||||
msgstr "Ny anslutning har blivit nekad"
|
||||
|
||||
#: ../app/ui.js:1234
|
||||
#: ../app/ui.js:1242
|
||||
msgid "Credentials are required"
|
||||
msgstr "Användaruppgifter krävs"
|
||||
|
||||
|
|
@ -304,8 +311,8 @@ msgid ""
|
|||
"Please verify that the information is correct and press \"Approve\". "
|
||||
"Otherwise press \"Reject\"."
|
||||
msgstr ""
|
||||
"Kontrollera att informationen är korrekt och tryck sedan "
|
||||
"\"Godkänn\". Tryck annars \"Neka\"."
|
||||
"Kontrollera att informationen är korrekt och tryck sedan \"Godkänn\". Tryck "
|
||||
"annars \"Neka\"."
|
||||
|
||||
#: ../vnc.html:291
|
||||
msgid "Approve"
|
||||
|
|
@ -335,5 +342,8 @@ msgstr "Skicka Användaruppgifter"
|
|||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#~ msgid "HTTPS is required for full functionality"
|
||||
#~ msgstr "HTTPS krävs för full funktionalitet"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Rensa"
|
||||
|
|
|
|||
136
po/zh_CN.po
136
po/zh_CN.po
|
|
@ -15,58 +15,42 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../app/ui.js:395
|
||||
#: ../app/ui.js:430
|
||||
msgid "Connecting..."
|
||||
msgstr "连接中..."
|
||||
|
||||
#: ../app/ui.js:402
|
||||
#: ../app/ui.js:438
|
||||
msgid "Connected (encrypted) to "
|
||||
msgstr "已连接(已加密)到"
|
||||
|
||||
#: ../app/ui.js:440
|
||||
msgid "Connected (unencrypted) to "
|
||||
msgstr "已连接(未加密)到"
|
||||
|
||||
#: ../app/ui.js:446
|
||||
msgid "Disconnecting..."
|
||||
msgstr "正在断开连接..."
|
||||
|
||||
#: ../app/ui.js:408
|
||||
msgid "Reconnecting..."
|
||||
msgstr "重新连接中..."
|
||||
|
||||
#: ../app/ui.js:413
|
||||
msgid "Internal error"
|
||||
msgstr "内部错误"
|
||||
|
||||
#: ../app/ui.js:1015
|
||||
msgid "Must set host"
|
||||
msgstr "请提供主机名"
|
||||
|
||||
#: ../app/ui.js:1097
|
||||
msgid "Connected (encrypted) to "
|
||||
msgstr "已连接到(加密)"
|
||||
|
||||
#: ../app/ui.js:1099
|
||||
msgid "Connected (unencrypted) to "
|
||||
msgstr "已连接到(未加密)"
|
||||
|
||||
#: ../app/ui.js:1120
|
||||
msgid "Something went wrong, connection is closed"
|
||||
msgstr "发生错误,连接已关闭"
|
||||
|
||||
#: ../app/ui.js:1123
|
||||
msgid "Failed to connect to server"
|
||||
msgstr "无法连接到服务器"
|
||||
|
||||
#: ../app/ui.js:1133
|
||||
#: ../app/ui.js:450
|
||||
msgid "Disconnected"
|
||||
msgstr "已断开连接"
|
||||
|
||||
#: ../app/ui.js:1146
|
||||
msgid "New connection has been rejected with reason: "
|
||||
msgstr "连接被拒绝,原因:"
|
||||
#: ../app/ui.js:1052 ../core/rfb.js:248
|
||||
msgid "Must set host"
|
||||
msgstr "必须设置主机"
|
||||
|
||||
#: ../app/ui.js:1149
|
||||
msgid "New connection has been rejected"
|
||||
msgstr "连接被拒绝"
|
||||
#: ../app/ui.js:1101
|
||||
msgid "Reconnecting..."
|
||||
msgstr "重新连接中..."
|
||||
|
||||
#: ../app/ui.js:1170
|
||||
#: ../app/ui.js:1140
|
||||
msgid "Password is required"
|
||||
msgstr "请提供密码"
|
||||
|
||||
#: ../core/rfb.js:548
|
||||
msgid "Disconnect timeout"
|
||||
msgstr "超时断开"
|
||||
|
||||
#: ../vnc.html:89
|
||||
msgid "noVNC encountered an error:"
|
||||
msgstr "noVNC 遇到一个错误:"
|
||||
|
|
@ -77,31 +61,31 @@ msgstr "显示/隐藏控制栏"
|
|||
|
||||
#: ../vnc.html:106
|
||||
msgid "Move/Drag Viewport"
|
||||
msgstr "拖放显示范围"
|
||||
msgstr "移动/拖动窗口"
|
||||
|
||||
#: ../vnc.html:106
|
||||
msgid "viewport drag"
|
||||
msgstr "显示范围拖放"
|
||||
msgstr "窗口拖动"
|
||||
|
||||
#: ../vnc.html:112 ../vnc.html:115 ../vnc.html:118 ../vnc.html:121
|
||||
msgid "Active Mouse Button"
|
||||
msgstr "启动鼠标按鍵"
|
||||
msgstr "启动鼠标按键"
|
||||
|
||||
#: ../vnc.html:112
|
||||
msgid "No mousebutton"
|
||||
msgstr "禁用鼠标按鍵"
|
||||
msgstr "禁用鼠标按键"
|
||||
|
||||
#: ../vnc.html:115
|
||||
msgid "Left mousebutton"
|
||||
msgstr "鼠标左鍵"
|
||||
msgstr "鼠标左键"
|
||||
|
||||
#: ../vnc.html:118
|
||||
msgid "Middle mousebutton"
|
||||
msgstr "鼠标中鍵"
|
||||
msgstr "鼠标中键"
|
||||
|
||||
#: ../vnc.html:121
|
||||
msgid "Right mousebutton"
|
||||
msgstr "鼠标右鍵"
|
||||
msgstr "鼠标右键"
|
||||
|
||||
#: ../vnc.html:124
|
||||
msgid "Keyboard"
|
||||
|
|
@ -127,6 +111,10 @@ msgstr "Ctrl"
|
|||
msgid "Toggle Ctrl"
|
||||
msgstr "切换 Ctrl"
|
||||
|
||||
#: ../vnc.html:136
|
||||
msgid "Edit clipboard content in the textarea below."
|
||||
msgstr "在下面的文本区域中编辑剪贴板内容。"
|
||||
|
||||
#: ../vnc.html:139
|
||||
msgid "Alt"
|
||||
msgstr "Alt"
|
||||
|
|
@ -153,19 +141,19 @@ msgstr "发送 Escape 键"
|
|||
|
||||
#: ../vnc.html:148
|
||||
msgid "Ctrl+Alt+Del"
|
||||
msgstr "Ctrl-Alt-Del"
|
||||
msgstr "Ctrl+Alt+Del"
|
||||
|
||||
#: ../vnc.html:148
|
||||
msgid "Send Ctrl-Alt-Del"
|
||||
msgstr "发送 Ctrl-Alt-Del 键"
|
||||
msgstr "发送 Ctrl+Alt+Del 键"
|
||||
|
||||
#: ../vnc.html:156
|
||||
msgid "Shutdown/Reboot"
|
||||
msgstr "关机/重新启动"
|
||||
msgstr "关机/重启"
|
||||
|
||||
#: ../vnc.html:156
|
||||
msgid "Shutdown/Reboot..."
|
||||
msgstr "关机/重新启动..."
|
||||
msgstr "关机/重启..."
|
||||
|
||||
#: ../vnc.html:162
|
||||
msgid "Power"
|
||||
|
|
@ -177,7 +165,7 @@ msgstr "关机"
|
|||
|
||||
#: ../vnc.html:165
|
||||
msgid "Reboot"
|
||||
msgstr "重新启动"
|
||||
msgstr "重启"
|
||||
|
||||
#: ../vnc.html:166
|
||||
msgid "Reset"
|
||||
|
|
@ -199,6 +187,10 @@ msgstr "全屏"
|
|||
msgid "Settings"
|
||||
msgstr "设置"
|
||||
|
||||
#: ../vnc.html:200
|
||||
msgid "Encrypt"
|
||||
msgstr "加密"
|
||||
|
||||
#: ../vnc.html:202
|
||||
msgid "Shared Mode"
|
||||
msgstr "分享模式"
|
||||
|
|
@ -224,61 +216,69 @@ msgid "Local Scaling"
|
|||
msgstr "本地缩放"
|
||||
|
||||
#: ../vnc.html:216
|
||||
msgid "Local Downscaling"
|
||||
msgstr "降低本地尺寸"
|
||||
|
||||
#: ../vnc.html:217
|
||||
msgid "Remote Resizing"
|
||||
msgstr "远程调整大小"
|
||||
|
||||
#: ../vnc.html:221
|
||||
#: ../vnc.html:222
|
||||
msgid "Advanced"
|
||||
msgstr "高级"
|
||||
|
||||
#: ../vnc.html:224
|
||||
#: ../vnc.html:225
|
||||
msgid "Local Cursor"
|
||||
msgstr "本地光标"
|
||||
|
||||
#: ../vnc.html:229
|
||||
msgid "Repeater ID:"
|
||||
msgstr "中继站 ID"
|
||||
|
||||
#: ../vnc.html:228
|
||||
#: ../vnc.html:233
|
||||
msgid "WebSocket"
|
||||
msgstr "WebSocket"
|
||||
|
||||
#: ../vnc.html:231
|
||||
msgid "Encrypt"
|
||||
msgstr "加密"
|
||||
|
||||
#: ../vnc.html:234
|
||||
#: ../vnc.html:239
|
||||
msgid "Host:"
|
||||
msgstr "主机:"
|
||||
|
||||
#: ../vnc.html:238
|
||||
#: ../vnc.html:243
|
||||
msgid "Port:"
|
||||
msgstr "端口:"
|
||||
|
||||
#: ../vnc.html:242
|
||||
#: ../vnc.html:247
|
||||
msgid "Path:"
|
||||
msgstr "路径:"
|
||||
|
||||
#: ../vnc.html:249
|
||||
#: ../vnc.html:254
|
||||
msgid "Automatic Reconnect"
|
||||
msgstr "自动重新连接"
|
||||
|
||||
#: ../vnc.html:252
|
||||
#: ../vnc.html:257
|
||||
msgid "Reconnect Delay (ms):"
|
||||
msgstr "重新连接间隔 (ms):"
|
||||
|
||||
#: ../vnc.html:258
|
||||
#: ../vnc.html:263
|
||||
msgid "Logging:"
|
||||
msgstr "日志级别:"
|
||||
|
||||
#: ../vnc.html:270
|
||||
#: ../vnc.html:275
|
||||
msgid "Disconnect"
|
||||
msgstr "中断连接"
|
||||
msgstr "断开连接"
|
||||
|
||||
#: ../vnc.html:289
|
||||
#: ../vnc.html:294
|
||||
msgid "Connect"
|
||||
msgstr "连接"
|
||||
|
||||
#: ../vnc.html:299
|
||||
#: ../vnc.html:304
|
||||
msgid "Password:"
|
||||
msgstr "密码:"
|
||||
|
||||
#: ../vnc.html:313
|
||||
#: ../vnc.html:318
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: ../vnc.html:334
|
||||
msgid "Canvas not supported."
|
||||
msgstr "不支持 Canvas。"
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
name: novnc
|
||||
base: core18 # the base snap is the execution environment for this snap
|
||||
base: core22 # the base snap is the execution environment for this snap
|
||||
version: git
|
||||
summary: Open Source VNC client using HTML5 (WebSockets, Canvas)
|
||||
description: |
|
||||
|
|
@ -42,7 +42,7 @@ parts:
|
|||
- jq
|
||||
|
||||
websockify:
|
||||
source: https://github.com/novnc/websockify/archive/v0.11.0.tar.gz
|
||||
source: https://github.com/novnc/websockify/archive/v0.12.0.tar.gz
|
||||
plugin: python
|
||||
stage-packages:
|
||||
- python3-numpy
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"globals": {
|
||||
"chai": false,
|
||||
"sinon": false
|
||||
},
|
||||
"rules": {
|
||||
"prefer-arrow-callback": 0,
|
||||
// Too many anonymous callbacks
|
||||
"func-names": "off",
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable no-console */
|
||||
const expect = chai.expect;
|
||||
|
||||
import { isMac, isWindows, isIOS, isAndroid, isChromeOS,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable no-console */
|
||||
const expect = chai.expect;
|
||||
|
||||
import { inflateInit, inflate } from "../vendor/pako/lib/zlib/inflate.js";
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@ describe('Helpers', function () {
|
|||
});
|
||||
it('should use charCode if no key', function () {
|
||||
expect(KeyboardUtil.getKey({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.be.equal('Š');
|
||||
// Broken Oculus browser
|
||||
expect(KeyboardUtil.getKey({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43, key: 'Unidentified'})).to.be.equal('Š');
|
||||
});
|
||||
it('should return Unidentified when it cannot map the key', function () {
|
||||
expect(KeyboardUtil.getKey({keycode: 0x42})).to.be.equal('Unidentified');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable no-console */
|
||||
const expect = chai.expect;
|
||||
|
||||
import { deflateInit, deflate, Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable no-console */
|
||||
const expect = chai.expect;
|
||||
|
||||
import { toUnsigned32bit, toSigned32bit } from '../core/util/int.js';
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ describe('Key Event Handling', function () {
|
|||
}
|
||||
e.stopPropagation = sinon.spy();
|
||||
e.preventDefault = sinon.spy();
|
||||
e.getModifierState = function (key) {
|
||||
return e[key];
|
||||
};
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
@ -310,6 +314,50 @@ describe('Key Event Handling', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Modifier status info', function () {
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
// tests.
|
||||
origNavigator = Object.getOwnPropertyDescriptor(window, "navigator");
|
||||
|
||||
Object.defineProperty(window, "navigator", {value: {}});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
Object.defineProperty(window, "navigator", origNavigator);
|
||||
});
|
||||
|
||||
it('should provide caps lock state', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'A', NumLock: false, CapsLock: true}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0x41, "KeyA", true, false, true);
|
||||
});
|
||||
|
||||
it('should provide num lock state', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'A', NumLock: true, CapsLock: false}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0x41, "KeyA", true, true, false);
|
||||
});
|
||||
|
||||
it('should have no num lock state on mac', function () {
|
||||
window.navigator.platform = "Mac";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'A', NumLock: false, CapsLock: true}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0x41, "KeyA", true, null, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Japanese IM keys on Windows', function () {
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ const expect = chai.expect;
|
|||
import RFB from '../core/rfb.js';
|
||||
import Websock from '../core/websock.js';
|
||||
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
|
||||
import { deflateInit, deflate } from "../vendor/pako/lib/zlib/deflate.js";
|
||||
import { deflateInit, deflate, Z_DEFAULT_COMPRESSION } from "../vendor/pako/lib/zlib/deflate.js";
|
||||
import { encodings } from '../core/encodings.js';
|
||||
import { toUnsigned32bit } from '../core/util/int.js';
|
||||
import { encodeUTF8 } from '../core/util/strings.js';
|
||||
|
|
@ -54,7 +54,7 @@ function deflateWithSize(data) {
|
|||
let strm = new ZStream();
|
||||
let chunkSize = 1024 * 10 * 10;
|
||||
strm.output = new Uint8Array(chunkSize);
|
||||
deflateInit(strm, 5);
|
||||
deflateInit(strm, Z_DEFAULT_COMPRESSION);
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
strm.input = unCompData;
|
||||
|
|
@ -1257,6 +1257,14 @@ describe('Remote Frame Buffer Protocol Client', function () {
|
|||
client._sock._websocket._receiveData(new Uint8Array([0, 0, 0, 1]));
|
||||
expect(client._rfbInitState).to.equal('ServerInitialisation');
|
||||
});
|
||||
|
||||
it('should transition straight to ServerInitialisation on "no auth" for versions < 3.8', function () {
|
||||
sendVer('003.007\n', client);
|
||||
client._sock._websocket._getSentData();
|
||||
|
||||
sendSecurity(1, client);
|
||||
expect(client._rfbInitState).to.equal('ServerInitialisation');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Authentication', function () {
|
||||
|
|
@ -2230,16 +2238,36 @@ describe('Remote Frame Buffer Protocol Client', function () {
|
|||
});
|
||||
|
||||
describe('Legacy SecurityResult', function () {
|
||||
beforeEach(function () {
|
||||
sendVer('003.007\n', client);
|
||||
client._sock._websocket._getSentData();
|
||||
sendSecurity(1, client);
|
||||
client._sock._websocket._getSentData();
|
||||
});
|
||||
|
||||
it('should not include reason in securityfailure event', function () {
|
||||
it('should not include reason in securityfailure event for versions < 3.7', function () {
|
||||
client.addEventListener("credentialsrequired", () => {
|
||||
client.sendCredentials({ password: 'passwd' });
|
||||
});
|
||||
const spy = sinon.spy();
|
||||
client.addEventListener("securityfailure", spy);
|
||||
sendVer('003.006\n', client);
|
||||
client._sock._websocket._receiveData(new Uint8Array([0, 0, 0, 2]));
|
||||
const challenge = [];
|
||||
for (let i = 0; i < 16; i++) { challenge[i] = i; }
|
||||
client._sock._websocket._receiveData(new Uint8Array(challenge));
|
||||
|
||||
client._sock._websocket._receiveData(new Uint8Array([0, 0, 0, 2]));
|
||||
expect(spy).to.have.been.calledOnce;
|
||||
expect(spy.args[0][0].detail.status).to.equal(2);
|
||||
expect('reason' in spy.args[0][0].detail).to.be.false;
|
||||
});
|
||||
|
||||
it('should not include reason in securityfailure event for versions < 3.8', function () {
|
||||
client.addEventListener("credentialsrequired", () => {
|
||||
client.sendCredentials({ password: 'passwd' });
|
||||
});
|
||||
const spy = sinon.spy();
|
||||
client.addEventListener("securityfailure", spy);
|
||||
sendVer('003.007\n', client);
|
||||
sendSecurity(2, client);
|
||||
const challenge = [];
|
||||
for (let i = 0; i < 16; i++) { challenge[i] = i; }
|
||||
client._sock._websocket._receiveData(new Uint8Array(challenge));
|
||||
|
||||
client._sock._websocket._receiveData(new Uint8Array([0, 0, 0, 2]));
|
||||
expect(spy).to.have.been.calledOnce;
|
||||
expect(spy.args[0][0].detail.status).to.equal(2);
|
||||
|
|
@ -2979,6 +3007,149 @@ describe('Remote Frame Buffer Protocol Client', function () {
|
|||
expect(spy.args[0][0].detail.name).to.equal('som€ nam€');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Caps Lock and Num Lock remote fixup', function () {
|
||||
function sendLedStateUpdate(state) {
|
||||
let data = [];
|
||||
push8(data, state);
|
||||
sendFbuMsg([{ x: 0, y: 0, width: 0, height: 0, encoding: -261 }], [data], client);
|
||||
}
|
||||
|
||||
let client;
|
||||
beforeEach(function () {
|
||||
client = makeRFB();
|
||||
sinon.stub(client, 'sendKey');
|
||||
});
|
||||
|
||||
it('should toggle caps lock if remote caps lock is on and local is off', function () {
|
||||
sendLedStateUpdate(0b100);
|
||||
client._handleKeyEvent(0x61, 'KeyA', true, null, false);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledThrice;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
expect(client.sendKey.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(client.sendKey.thirdCall).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
});
|
||||
|
||||
it('should toggle caps lock if remote caps lock is off and local is on', function () {
|
||||
sendLedStateUpdate(0b011);
|
||||
client._handleKeyEvent(0x41, 'KeyA', true, null, true);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledThrice;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
expect(client.sendKey.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(client.sendKey.thirdCall).to.have.been.calledWith(0x41, "KeyA", true);
|
||||
});
|
||||
|
||||
it('should not toggle caps lock if remote caps lock is on and local is on', function () {
|
||||
sendLedStateUpdate(0b100);
|
||||
client._handleKeyEvent(0x41, 'KeyA', true, null, true);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0x41, "KeyA", true);
|
||||
});
|
||||
|
||||
it('should not toggle caps lock if remote caps lock is off and local is off', function () {
|
||||
sendLedStateUpdate(0b011);
|
||||
client._handleKeyEvent(0x61, 'KeyA', true, null, false);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
});
|
||||
|
||||
it('should not toggle caps lock if the key is caps lock', function () {
|
||||
sendLedStateUpdate(0b011);
|
||||
client._handleKeyEvent(0xFFE5, 'CapsLock', true, null, true);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
});
|
||||
|
||||
it('should toggle caps lock only once', function () {
|
||||
sendLedStateUpdate(0b100);
|
||||
client._handleKeyEvent(0x61, 'KeyA', true, null, false);
|
||||
client._handleKeyEvent(0x61, 'KeyA', true, null, false);
|
||||
|
||||
expect(client.sendKey).to.have.callCount(4);
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
expect(client.sendKey.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(client.sendKey.thirdCall).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
expect(client.sendKey.lastCall).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
});
|
||||
|
||||
it('should retain remote caps lock state on capslock key up', function () {
|
||||
sendLedStateUpdate(0b100);
|
||||
client._handleKeyEvent(0xFFE5, 'CapsLock', false, null, true);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(client._remoteCapsLock).to.equal(true);
|
||||
});
|
||||
|
||||
it('should toggle num lock if remote num lock is on and local is off', function () {
|
||||
sendLedStateUpdate(0b010);
|
||||
client._handleKeyEvent(0xFF9C, 'NumPad1', true, false, null);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledThrice;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFF7F, "NumLock", true);
|
||||
expect(client.sendKey.secondCall).to.have.been.calledWith(0xFF7F, "NumLock", false);
|
||||
expect(client.sendKey.thirdCall).to.have.been.calledWith(0xFF9C, "NumPad1", true);
|
||||
});
|
||||
|
||||
it('should toggle num lock if remote num lock is off and local is on', function () {
|
||||
sendLedStateUpdate(0b101);
|
||||
client._handleKeyEvent(0xFFB1, 'NumPad1', true, true, null);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledThrice;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFF7F, "NumLock", true);
|
||||
expect(client.sendKey.secondCall).to.have.been.calledWith(0xFF7F, "NumLock", false);
|
||||
expect(client.sendKey.thirdCall).to.have.been.calledWith(0xFFB1, "NumPad1", true);
|
||||
});
|
||||
|
||||
it('should not toggle num lock if remote num lock is on and local is on', function () {
|
||||
sendLedStateUpdate(0b010);
|
||||
client._handleKeyEvent(0xFFB1, 'NumPad1', true, true, null);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFFB1, "NumPad1", true);
|
||||
});
|
||||
|
||||
it('should not toggle num lock if remote num lock is off and local is off', function () {
|
||||
sendLedStateUpdate(0b101);
|
||||
client._handleKeyEvent(0xFF9C, 'NumPad1', true, false, null);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFF9C, "NumPad1", true);
|
||||
});
|
||||
|
||||
it('should not toggle num lock if the key is num lock', function () {
|
||||
sendLedStateUpdate(0b101);
|
||||
client._handleKeyEvent(0xFF7F, 'NumLock', true, true, null);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFF7F, "NumLock", true);
|
||||
});
|
||||
|
||||
it('should not toggle num lock if local state is unknown', function () {
|
||||
sendLedStateUpdate(0b010);
|
||||
client._handleKeyEvent(0xFFB1, 'NumPad1', true, null, null);
|
||||
|
||||
expect(client.sendKey).to.have.been.calledOnce;
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFFB1, "NumPad1", true);
|
||||
});
|
||||
|
||||
it('should toggle num lock only once', function () {
|
||||
sendLedStateUpdate(0b010);
|
||||
client._handleKeyEvent(0xFF9C, 'NumPad1', true, false, null);
|
||||
client._handleKeyEvent(0xFF9C, 'NumPad1', true, false, null);
|
||||
|
||||
expect(client.sendKey).to.have.callCount(4);
|
||||
expect(client.sendKey.firstCall).to.have.been.calledWith(0xFF7F, "NumLock", true);
|
||||
expect(client.sendKey.secondCall).to.have.been.calledWith(0xFF7F, "NumLock", false);
|
||||
expect(client.sendKey.thirdCall).to.have.been.calledWith(0xFF9C, "NumPad1", true);
|
||||
expect(client.sendKey.lastCall).to.have.been.calledWith(0xFF9C, "NumPad1", true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('XVP Message Handling', function () {
|
||||
|
|
@ -3092,11 +3263,11 @@ describe('Remote Frame Buffer Protocol Client', function () {
|
|||
});
|
||||
|
||||
it('should update clipboard with correct escape characters from a Provide message ', function () {
|
||||
let expectedData = "Oh\nmy!";
|
||||
let expectedData = "Oh\nmy\n!";
|
||||
let data = [3, 0, 0, 0];
|
||||
const flags = [0x10, 0x00, 0x00, 0x01];
|
||||
|
||||
let text = encodeUTF8("Oh\r\nmy!\0");
|
||||
let text = encodeUTF8("Oh\r\nmy\r\n!\0");
|
||||
|
||||
let deflatedText = deflateWithSize(text);
|
||||
|
||||
|
|
|
|||
|
|
@ -228,12 +228,59 @@ describe('Tight Decoder', function () {
|
|||
expect(display).to.have.displayed(targetData);
|
||||
});
|
||||
|
||||
it.skip('should handle uncompressed gradient rects', function () {
|
||||
// Not implemented yet
|
||||
it('should handle uncompressed gradient rects', function () {
|
||||
let done;
|
||||
let blueData = [ 0x40, 0x02, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00 ];
|
||||
let greenData = [ 0x40, 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 ];
|
||||
|
||||
done = testDecodeRect(decoder, 0, 0, 2, 1, blueData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
done = testDecodeRect(decoder, 0, 1, 2, 1, blueData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
done = testDecodeRect(decoder, 2, 0, 2, 1, greenData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
done = testDecodeRect(decoder, 2, 1, 2, 1, greenData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
done = testDecodeRect(decoder, 0, 2, 2, 1, greenData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
done = testDecodeRect(decoder, 0, 3, 2, 1, greenData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
done = testDecodeRect(decoder, 2, 2, 2, 1, blueData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
done = testDecodeRect(decoder, 2, 3, 2, 1, blueData, display, 24);
|
||||
expect(done).to.be.true;
|
||||
|
||||
let targetData = new Uint8Array([
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
||||
]);
|
||||
|
||||
expect(display).to.have.displayed(targetData);
|
||||
});
|
||||
|
||||
it.skip('should handle compressed gradient rects', function () {
|
||||
// Not implemented yet
|
||||
it('should handle compressed gradient rects', function () {
|
||||
let data = [
|
||||
// Control byte
|
||||
0x40, 0x02,
|
||||
// Pixels (compressed)
|
||||
0x18,
|
||||
0x78, 0x9c, 0x62, 0x60, 0xf8, 0xcf, 0x00, 0x04,
|
||||
0xff, 0x19, 0x19, 0xd0, 0x00, 0x44, 0x84, 0xf1,
|
||||
0x3f, 0x9a, 0x30, 0x00, 0x00, 0x00, 0xff, 0xff ];
|
||||
|
||||
let done = testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24);
|
||||
|
||||
let targetData = new Uint8Array([
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
||||
]);
|
||||
|
||||
expect(done).to.be.true;
|
||||
expect(display).to.have.displayed(targetData);
|
||||
});
|
||||
|
||||
it('should handle empty copy rects', function () {
|
||||
|
|
@ -275,6 +322,25 @@ describe('Tight Decoder', function () {
|
|||
expect(display).to.have.displayed(targetData);
|
||||
});
|
||||
|
||||
it('should handle empty gradient rects', function () {
|
||||
display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
|
||||
display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
|
||||
display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]);
|
||||
|
||||
let done = testDecodeRect(decoder, 1, 2, 0, 0,
|
||||
[ 0x40, 0x02 ], display, 24);
|
||||
|
||||
let targetData = new Uint8Array([
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
||||
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
||||
]);
|
||||
|
||||
expect(done).to.be.true;
|
||||
expect(display).to.have.displayed(targetData);
|
||||
});
|
||||
|
||||
it('should handle empty fill rects', function () {
|
||||
display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]);
|
||||
display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]);
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path');
|
||||
const program = require('commander');
|
||||
const { program } = require('commander');
|
||||
const fs = require('fs');
|
||||
const fse = require('fs-extra');
|
||||
const babel = require('@babel/core');
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ usage() {
|
|||
echo "$*"
|
||||
echo
|
||||
fi
|
||||
echo "Usage: ${NAME} [--listen PORT] [--vnc VNC_HOST:PORT] [--cert CERT] [--ssl-only]"
|
||||
echo "Usage: ${NAME} [--listen [HOST:]PORT] [--vnc VNC_HOST:PORT] [--cert CERT] [--ssl-only]"
|
||||
echo
|
||||
echo "Starts the WebSockets proxy and a mini-webserver and "
|
||||
echo "provides a cut-and-paste URL to go to."
|
||||
echo
|
||||
echo " --listen PORT Port for proxy/webserver to listen on"
|
||||
echo " Default: 6080"
|
||||
echo " --listen [HOST:]PORT Port for proxy/webserver to listen on"
|
||||
echo " Default: 6080 (on all interfaces)"
|
||||
echo " --vnc VNC_HOST:PORT VNC server host:port proxy target"
|
||||
echo " Default: localhost:5900"
|
||||
echo " --cert CERT Path to combined cert/key file, or just"
|
||||
|
|
@ -47,14 +47,16 @@ usage() {
|
|||
NAME="$(basename $0)"
|
||||
REAL_NAME="$(readlink -f $0)"
|
||||
HERE="$(cd "$(dirname "$REAL_NAME")" && pwd)"
|
||||
HOST=""
|
||||
PORT="6080"
|
||||
LISTEN="$PORT"
|
||||
VNC_DEST="localhost:5900"
|
||||
CERT=""
|
||||
KEY=""
|
||||
WEB=""
|
||||
proxy_pid=""
|
||||
SSLONLY=""
|
||||
RECORD_ARG=""
|
||||
RECORD=""
|
||||
SYSLOG_ARG=""
|
||||
HEARTBEAT_ARG=""
|
||||
IDLETIMEOUT_ARG=""
|
||||
|
|
@ -86,14 +88,14 @@ cleanup() {
|
|||
while [ "$*" ]; do
|
||||
param=$1; shift; OPTARG=$1
|
||||
case $param in
|
||||
--listen) PORT="${OPTARG}"; shift ;;
|
||||
--listen) LISTEN="${OPTARG}"; shift ;;
|
||||
--vnc) VNC_DEST="${OPTARG}"; shift ;;
|
||||
--cert) CERT="${OPTARG}"; shift ;;
|
||||
--key) KEY="${OPTARG}"; shift ;;
|
||||
--web) WEB="${OPTARG}"; shift ;;
|
||||
--ssl-only) SSLONLY="--ssl-only" ;;
|
||||
--file-only) FILEONLY_ARG="--file-only" ;;
|
||||
--record) RECORD_ARG="--record ${OPTARG}"; shift ;;
|
||||
--record) RECORD="${OPTARG}"; shift ;;
|
||||
--syslog) SYSLOG_ARG="--syslog ${OPTARG}"; shift ;;
|
||||
--heartbeat) HEARTBEAT_ARG="--heartbeat ${OPTARG}"; shift ;;
|
||||
--idle-timeout) IDLETIMEOUT_ARG="--idle-timeout ${OPTARG}"; shift ;;
|
||||
|
|
@ -107,14 +109,23 @@ while [ "$*" ]; do
|
|||
esac
|
||||
done
|
||||
|
||||
if [ "$LISTEN" != "$PORT" ]; then
|
||||
HOST=${LISTEN%:*}
|
||||
PORT=${LISTEN##*:}
|
||||
# if no host was given, restore
|
||||
[ "$HOST" = "$PORT" ] && HOST=""
|
||||
fi
|
||||
|
||||
# Sanity checks
|
||||
if bash -c "exec 7<>/dev/tcp/localhost/${PORT}" &> /dev/null; then
|
||||
exec 7<&-
|
||||
exec 7>&-
|
||||
die "Port ${PORT} in use. Try --listen PORT"
|
||||
else
|
||||
exec 7<&-
|
||||
exec 7>&-
|
||||
if [ -z "${HOST}" ]; then
|
||||
if bash -c "exec 7<>/dev/tcp/localhost/${PORT}" &> /dev/null; then
|
||||
exec 7<&-
|
||||
exec 7>&-
|
||||
die "Port ${PORT} in use. Try --listen PORT"
|
||||
else
|
||||
exec 7<&-
|
||||
exec 7>&-
|
||||
fi
|
||||
fi
|
||||
|
||||
trap "cleanup" TERM QUIT INT EXIT
|
||||
|
|
@ -191,9 +202,14 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
echo "Starting webserver and WebSockets proxy on port ${PORT}"
|
||||
#${HERE}/websockify --web ${WEB} ${CERT:+--cert ${CERT}} ${PORT} ${VNC_DEST} &
|
||||
${WEBSOCKIFY} ${SYSLOG_ARG} ${SSLONLY} ${FILEONLY_ARG} --web ${WEB} ${CERT:+--cert ${CERT}} ${KEY:+--key ${KEY}} ${PORT} ${VNC_DEST} ${HEARTBEAT_ARG} ${IDLETIMEOUT_ARG} ${RECORD_ARG} ${TIMEOUT_ARG} ${WEBAUTH_ARG} ${AUTHPLUGIN_ARG} ${AUTHSOURCE_ARG} &
|
||||
# Make all file paths absolute as websockify changes working directory
|
||||
WEB=`realpath "${WEB}"`
|
||||
[ -n "${CERT}" ] && CERT=`realpath "${CERT}"`
|
||||
[ -n "${KEY}" ] && KEY=`realpath "${KEY}"`
|
||||
[ -n "${RECORD}" ] && RECORD=`realpath "${RECORD}"`
|
||||
|
||||
echo "Starting webserver and WebSockets proxy on${HOST:+ host ${HOST}} port ${PORT}"
|
||||
${WEBSOCKIFY} ${SYSLOG_ARG} ${SSLONLY} ${FILEONLY_ARG} --web ${WEB} ${CERT:+--cert ${CERT}} ${KEY:+--key ${KEY}} ${LISTEN} ${VNC_DEST} ${HEARTBEAT_ARG} ${IDLETIMEOUT_ARG} ${RECORD:+--record ${RECORD}} ${TIMEOUT_ARG} ${WEBAUTH_ARG} ${AUTHPLUGIN_ARG} ${AUTHSOURCE_ARG} &
|
||||
proxy_pid="$!"
|
||||
sleep 1
|
||||
if [ -z "$proxy_pid" ] || ! ps -eo pid= | grep -w "$proxy_pid" > /dev/null; then
|
||||
|
|
@ -202,11 +218,15 @@ if [ -z "$proxy_pid" ] || ! ps -eo pid= | grep -w "$proxy_pid" > /dev/null; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$HOST" ]; then
|
||||
HOST=$(hostname)
|
||||
fi
|
||||
|
||||
echo -e "\n\nNavigate to this URL:\n"
|
||||
if [ "x$SSLONLY" == "x" ]; then
|
||||
echo -e " http://$(hostname):${PORT}/vnc.html?host=$(hostname)&port=${PORT}\n"
|
||||
echo -e " http://${HOST}:${PORT}/vnc.html?host=${HOST}&port=${PORT}\n"
|
||||
else
|
||||
echo -e " https://$(hostname):${PORT}/vnc.html?host=$(hostname)&port=${PORT}\n"
|
||||
echo -e " https://${HOST}:${PORT}/vnc.html?host=${HOST}&port=${PORT}\n"
|
||||
fi
|
||||
|
||||
echo -e "Press Ctrl-C to exit\n\n"
|
||||
|
|
|
|||
Loading…
Reference in New Issue