Compare commits

..

218 Commits

Author SHA1 Message Date
Justin
617210e063 Synced submodule 2021-05-11 19:19:55 -04:00
Justin
aaef2012bd Switched to upstream toggle-game-mode branch 2021-05-11 19:09:30 -04:00
matt
551164b425 update noVNC submodule 2021-05-07 05:29:19 -04:00
matt
1518575982 Update NoVNC commit 2021-05-06 05:21:46 -04:00
matt
fda877dd72 WIP: update novnc commit 2021-05-04 15:46:26 -04:00
Lauri Kasanen
c0f107a83e Add server-side support for relative mouse motion, kasm-only hack 2021-05-03 13:52:58 +03:00
matt
aefdb1392f KASM-1511 istouch bugfix 2021-04-26 05:58:04 -04:00
Lauri Kasanen
14e08a2067 Add trailing slash in dir listing 2021-04-22 11:33:05 +03:00
matt
f64bd4f1a4 Correct spelling of License file 2021-04-20 15:41:38 -04:00
Kasm
0b6334369c Merge pull request #36 from kasmtech/upstreamsync_sans_novnc
Upstream Syncs
2021-04-20 14:51:25 -04:00
matt
b8c69a7560 update noVNC submodule commit 2021-04-20 09:46:01 -04:00
matt
e84a37fb3d switched submodule commit id 2021-04-20 08:11:20 -04:00
matt
23935145a8 update submodule branch 2021-04-18 06:55:26 -04:00
matt
7f7b177b1a Update noVNC to latest master 2021-04-18 06:45:32 -04:00
Lauri Kasanen
95d34f7e58 Fix some local->remote clipboard merge misses 2021-04-13 13:49:43 +03:00
Lauri Kasanen
a1cf454f06 Sync utf8 clipboard support 2021-04-12 12:38:24 +03:00
matt
04461b9d4c fixes 2021-04-11 21:35:13 +00:00
matt
0d482f9a9b Update noVNC commit 2021-04-01 08:18:59 -04:00
matt
a7773bee6b Updated submodule ref 2021-03-31 15:06:27 -04:00
matt
75cef8b726 [skip CI] build fixes 2021-03-31 07:54:59 -04:00
matt
380bc0e7f8 merged master in 2021-03-31 05:21:35 -04:00
matt
999cfbb806 Added kasm novnc as submod 2021-03-30 15:32:18 -04:00
matt
12a0c0d8af removed novnc 2021-03-30 15:25:35 -04:00
Lauri Kasanen
7bfcb19ee1 Fixups 2021-03-29 13:25:16 +03:00
Quentin Dreyer
df9ca2e0ce chore: sync with W3C documentation
https://www.w3.org/TR/uievents-key/
2021-03-29 12:50:39 +03:00
Pierre Ossman
4fda2526f4 Send combination keysyms for some Japanese keys
Windows doesn't give us stable symbols for a bunch of Japanese IM keys,
instead alternating between two symbols. This state is not synchronised
with the IM running on the remote server so to have stable behaviour we
have to collapse these multiple symbols in to a single keysym.
2021-03-29 12:50:22 +03:00
Pierre Ossman
102257cb32 Fix typo for ZenkakuHankaku key 2021-03-29 12:50:16 +03:00
Pierre Ossman
77509c1e56 Use toggle keysym for Eisu key
This matches how the key behaves on a Linux system.
2021-03-29 12:50:12 +03:00
Pierre Ossman
9e0a5d26af Update keycode mappings to latest version
This update fixes Korean layouts.
2021-03-29 12:48:56 +03:00
Pierre Ossman
c6c2661121 Add workaround for Firefox PNG rounding bug 2021-03-29 12:48:06 +03:00
Pierre Ossman
8b8201fd73 Remove Firefox Alt workaround
The bug got fixed way back in Firefox 63, and it is also misbehaving
with modern Firefox as they no longer consider AltGr an Alt-key.
2021-03-29 12:48:02 +03:00
Pierre Ossman
33a113a475 Handle empty rects in RAW decoder as well
It was overlooked in the previous commit because we couldn't feed
empty data messages through the test framework.
2021-03-29 12:47:49 +03:00
Samuel Mannehed
6d1cebc24a Ignore recording variables in our linter 2021-03-29 12:47:43 +03:00
Pierre Ossman
fcd7836a83 Approximate comparison of JPEG result
The browsers have various rounding errors so we need to compare the
output data only approximately and not exactly.
2021-03-29 12:47:38 +03:00
Pierre Ossman
073737c8ac Handle empty rects from the server
These are very pointless for the server to send, but not a violation of
the protocol so we need to be able to handle them. We've seen this
happen in real world scenarios a few times.
2021-03-29 12:47:30 +03:00
Samuel Mannehed
16c72ba0a7 Fix call to _recvMessage()
Missed to rename this one in commit ea858bfa275d85541ac26d035967959714e8e255
2021-03-29 12:45:49 +03:00
Samuel Mannehed
d3c9ff8b12 Fix names of recording variables
The name of these variables must match how they were set when the
recording was created.

Reverts part of 95632e413d75030c49577c0e5cf1003208a5ba09
2021-03-29 12:45:41 +03:00
Pierre Ossman
4bc4c1d7f6 noVNC 1.2.0 2021-03-29 12:45:36 +03:00
Pierre Ossman
d8ba9a61e2 Update generated JS files for translations 2021-03-29 12:45:31 +03:00
Samuel Mannehed
0e2a25476f Update Swedish translation 2021-03-29 12:45:28 +03:00
Pierre Ossman
b3b4acaaa3 noVNC 1.2.0 beta 2021-03-29 12:45:08 +03:00
Pierre Ossman
201f2517f7 Remove note about clipboard ISO 8859-1 restriction
We now support full Unicode, provided the server also supports the
proper extension.
2021-03-29 12:44:59 +03:00
Pierre Ossman
f51167a2ce Update translation template file 2021-03-29 12:44:54 +03:00
Pierre Ossman
87b3a630cf Remove redundant VERSION file
We want to avoid having this in multiple places.
2021-03-29 12:44:42 +03:00
Pierre Ossman
7412dde8ee Handle quick Cursor detach after mouse up
This timer might fire after the Cursor object has detached from a DOM
element, causing crashes. This will likely not happen in real scenarios,
but the tests are quick enough to trigger this.
2021-03-29 12:44:25 +03:00
Pierre Ossman
3ef6e1333b Remove default Karma options
No need to mention things where we already use the default value.
2021-03-29 12:43:59 +03:00
Samuel Mannehed
b84220f319 Add lint rule for function declaration indentation 2021-03-29 12:41:44 +03:00
Pierre Ossman
42d437ad25 Start fake test clock at real clock time
Some code relies on the clock having a somewhat sane value, so let's not
start at 0.
2021-03-29 12:41:15 +03:00
Pierre Ossman
d5b84d9185 Avoid fractional pixel sizes from Display 2021-03-29 12:41:06 +03:00
Pierre Ossman
6db1c2bf0d Avoid printing the Websock buffer in tests
It takes forever and just messes up the output.
2021-03-29 12:40:09 +03:00
Pierre Ossman
ae1bc396bf Standardise on a single blit function
Keep everything simpler by always blitting in the same pixel format.
It's up to the decoders to convert if they need to.
2021-03-29 12:39:31 +03:00
Pierre Ossman
c7a7ce70be Fix bad BasicCompression check in Tight decoder 2021-03-29 12:37:29 +03:00
Pierre Ossman
55178c76b8 Test correct handling of alpha
The forth byte of a pixel is undefined in most encodings, so make sure
the decoders don't leak that through as an alpha channel.
2021-03-29 12:36:47 +03:00
Pierre Ossman
5752bf8ab7 Add tests for the Tight decoders 2021-03-29 12:36:42 +03:00
Pierre Ossman
6fd1035fb1 Split decoder tests to separate files 2021-03-29 12:36:35 +03:00
Pierre Ossman
212e0f1a10 Move tile handling to Hextile decoder
It is only used there so no need for it to be in the general
Display class.
2021-03-29 12:36:23 +03:00
Samuel Mannehed
69b945fc87 Standardize on camelCase in Display 2021-03-29 12:35:23 +03:00
Samuel Mannehed
b837bd6f59 Add camelCase rule to eslint 2021-03-29 12:34:42 +03:00
Samuel Mannehed
670eefbc97 Standardize on camelCase in Base64 2021-03-29 12:34:31 +03:00
Samuel Mannehed
b2d8db3f7b Standardize on camelCase in Decoders 2021-03-29 12:34:29 +03:00
Samuel Mannehed
a3e2b1e46e Standardize on camelCase in Logging 2021-03-29 12:34:25 +03:00
Samuel Mannehed
472ede66ea Standardize on camelCase in Websock 2021-03-29 12:34:23 +03:00
Samuel Mannehed
da228af778 Standardize on camelCase in tests 2021-03-29 12:34:13 +03:00
Samuel Mannehed
59f5648592 Remove unused properties and variables
The code that used these were removed in the following commits:

* 9ff86fb718477515ede2d6457f06643935d76bcd (RFB._mouse_arr)
* bb6965f2e60c2301dd638383bdc792d1f10af942 (old_requestAnimationFrame)
* 490d471c53b1791398d6c30f0efce54925939f33 (Display._c_forceCanvas)
2021-03-29 12:27:54 +03:00
Samuel Mannehed
19c473f792 Properly limit mouse moves to once every 17 ms
Previous attempt in c958269 had a number of issues, this is a full
rewrite, complete with improved unit tests.

Fixes github issue #1402
2021-03-29 12:26:12 +03:00
Samuel Mannehed
8a8fa1d906 Stop send mouse clicks while dragging in view only 2021-03-29 12:23:20 +03:00
Samuel Mannehed
5a81223d96 Standardize on camelCase for functions in RFB 2021-03-29 12:23:12 +03:00
Samuel Mannehed
eff38d47f9 Standardize on camelCase for variables in RFB 2021-03-29 12:21:50 +03:00
Samuel Mannehed
1de3769fd3 Remove unused mouse_arr variable 2021-03-29 12:16:38 +03:00
Samuel Mannehed
749ddce5b9 Add unit tests for mouse move limit 2021-03-29 12:16:01 +03:00
Samuel Mannehed
d420aa6413 Shorten rows to max 80 chars in mouse.js 2021-03-29 12:15:56 +03:00
Samuel Mannehed
93e42772bc Fix wording in comment 2021-03-29 12:15:49 +03:00
Uwe Klatt
9098478faf Limit mouse move events to one every 17 ms 2021-03-29 12:15:39 +03:00
Samuel Mannehed
4710ec1822 Fix indentation for focus check 2021-03-29 12:15:34 +03:00
Samuel Mannehed
02b9b268ff Don't fade the control bar if it has focus
Fixes github issue #1369
2021-03-29 12:15:29 +03:00
Samuel Mannehed
a015e33111 Hide the clipboard when not connected
Fixes github issue #1367.
2021-03-29 12:15:25 +03:00
Ingo Blechschmidt
950d871b0e Document default setting of focusOnClick 2021-03-29 12:15:19 +03:00
Filip Stedronsky
02e7b006de rfb: VeNCrypt Plain SecurityType support
This allows using TigerVNC server with PAM authentication (e.g. agains
LDAP or other extensible authentication mechanisms)

Tested with TigerVNC server (Xvnc -SecurityTypes Plain -PlainUsers '*')

Should not break anything else, this method is tried last when all
other fail.

Tested in Firefox 74 and Chromium 80
2021-03-29 12:14:55 +03:00
Alex Tanskanen
95af51e28d Fix focus problem after closing the toolbar
Closing the toolbar would make the focus remain on the toolbar and
not in the session. The only way to switch focus was to click in the
session. This commit will automatically switch back focus to the session
after closing the toolbar.
2021-03-29 12:14:49 +03:00
Niko Lehto
64dfb8d1d6 Hide clipboard side bar button when view only mode
The clipboard side bar button serves no purpose if user uses 'View Only'
mode, this commit hides this button in those instances.
2021-03-29 12:14:25 +03:00
Alex Tanskanen
b173c8854a Fix crash with too large clipboard data
If too much text is copied in the session, String.fromCharCode.apply()
would crash in Safari on macOS and Chrome on Linux. This commit fixes
this issue by avoiding apply() altogether. Also added test to cover this
issue.
2021-03-29 12:14:19 +03:00
Pierre Ossman
888f24e7af Style all input types for consistent UI
At least all that the browsers will let us.
2021-03-29 12:14:14 +03:00
Niko Lehto
8be81165bd Add extended clipboard Pseudo-Encoding
Add extended clipboard pseudo-encoding to allow the use of unicode
characters in the clipboard.
2021-03-29 12:13:59 +03:00
Niko Lehto
509b5795a0 Export constants in inflate.js for easier usage 2021-03-29 12:09:49 +03:00
Niko Lehto
581fe511ad Fix bug where inflate would read too much data 2021-03-29 12:09:44 +03:00
Niko Lehto
9ca647667b Split api of inflate
Added ability to read data chunk wise.
2021-03-29 12:09:40 +03:00
Niko Lehto
dbe2930758 Handle errors from zlib/pako 2021-03-29 12:09:36 +03:00
Niko Lehto
b690ae4c2d Move error handling to Inflate class
Every call wants this check so this should be done inside the class.
2021-03-29 12:09:32 +03:00
Niko Lehto
5e4544d5fc Add missing copyright header for Inflator.js 2021-03-29 12:09:27 +03:00
Niko Lehto
0b19961b06 Remove unused inflate argument
The value true was an invalid flush argument so it was in practice
unused.
2021-03-29 12:09:21 +03:00
Niko Lehto
286694869b Add util for unsigned and signed int. conversion
Will be used in later commit in extended clipboard handling.
2021-03-29 12:09:10 +03:00
Niko Lehto
fdeefcfab4 Add deflator helper class for deflating data
Wraps pako's deflate for easier usage.
2021-03-29 12:09:05 +03:00
Niko Lehto
24cf1f0f9a Make clipBoardPasteFrom() test more specific
Don't rely on clientCutText() to test clipboardPasteFrom().
2021-03-29 12:08:58 +03:00
Alvin Townsend
d01f6e6d27 Correcting path to package.json for running at a path other than root. 2021-03-29 12:08:52 +03:00
Samuel Mannehed
c1160d1468 Fix color channels for VMware alpha cursors
The red and blue channels were incorrectly swapped.
2021-03-29 12:08:36 +03:00
Juanjo Diaz
1c38b6f120 Remove generated HTML by Cursor when it detaches 2021-03-29 12:08:01 +03:00
Samuel Mannehed
70dd0058ac Simplify encodeUTF8/decodeUTF8 unittests 2021-03-29 12:07:57 +03:00
Samuel Mannehed
a4c5c38b53 Add unit tests for encodeUTF8 and decodeUTF8 2021-03-29 12:07:52 +03:00
Samuel Mannehed
789308212b Remove unused python scripts 2021-03-29 12:07:48 +03:00
Samuel Mannehed
ce5fe304cb Fix chinese translation for "Disconnect"
Thanks for @wavezhang, @litongjava, and @bhzhu203 for helping out.
2021-03-29 12:07:41 +03:00
Samuel Mannehed
781075c841 Update chinese translation strings
Thanks to @QQ2017 and @wavezhang for helping out with correcting these.
2021-03-29 12:07:36 +03:00
Samuel Mannehed
2f43cead79 Add comment for browser and platform detection 2021-03-29 12:07:32 +03:00
Samuel Mannehed
e7a5aa271e Add short description at the top of browser.js 2021-03-29 12:07:23 +03:00
Samuel Mannehed
ad206180d2 Properly detect scrollbar gutter
As a rule, instead of hard-coding a behavior on specific platforms we
should do dynamic detection.

This commit moves away from always hiding scrollbars on Android and iOS
and instead detects the rendered width of scrollbars in the browser.
2021-03-29 12:07:09 +03:00
Pierre Ossman
89dd199317 Allow cursor to be updated while connecting
We haven't got a server provided cursor at this point, but we might
have done something local, e.g. enabled the dot cursor.
2021-03-29 12:06:42 +03:00
Pierre Ossman
8be70e5ae0 Handle slow loading of images
Internet Explorer seems to flag images as loaded prematurely, which
can result in rendering bugs. We can detect this by looking at the
dimensions though.
2021-03-29 12:06:28 +03:00
Samuel Mannehed
ce94d92e18 Build in the behavior to ignore decodeUTF8 errors
Makes the code clearer and more explicit in intent.
2021-03-29 12:03:54 +03:00
Samuel Mannehed
c3ef9ff557 Peter is no longer part of the noVNC team 2021-03-29 12:02:16 +03:00
Chris \"Koying\" Browet
c0276776e9 Add support for Unix Tight auth 2021-03-29 12:02:05 +03:00
VanyM
10f4aa9e7b Add try catch in every place that uses decodeUTF8 2021-03-29 12:02:00 +03:00
Samuel Mannehed
b2dc76ee18 Add encodeUTF8 function to core/util/strings.js 2021-03-29 12:01:15 +03:00
Pierre Ossman
12cdad066e Make Cursor.detach() safe to call when not attached
Avoids having checks in higher layers.
2021-03-29 12:01:10 +03:00
Samuel Mannehed
a850be4afa Fix chinese translation errors
Thanks to @QQ2017 for providing the translation strings
2021-03-29 12:01:07 +03:00
Samuel Mannehed
354d544843 Simplify logic for status hierarchy
Removes unnecessary variable
2021-03-29 12:01:02 +03:00
Samuel Mannehed
0bf9403a36 Ensure warning status timeouts are honored
When showing a new status popup we want to set a timer for how long to
show it. In cases where we show many statuses in a fast succession we
need to remove any running timeouts when showing a new one.

There are exceptions when new statuses won't be shown, and thats if a
more severe status is already showing, i.e and error or a warning.

Warnings can still have timeouts. There was a bug that occured when we
tried to show a normal status while a warning was showing. The bug
caused the warning status timeout to be removed even if the normal
status was never shown. We should only remove running timeouts if we're
actually going to show a new status.
2021-03-29 12:00:47 +03:00
Pierre Ossman
29db8997ec Don't use arrow functions in legacy loader
The browsers that need the legacy code do not support such fancy
modern things.
2021-03-29 12:00:38 +03:00
Pierre Ossman
46f15667f7 Load support scripts first
E.g. SystemJS requires the Promise polyfill, so make sure all our
support files are loaded first.
2021-03-29 11:59:59 +03:00
Pierre Ossman
edb5fee88b Upgrade to latest babel
There has been a lot of renaming and restructuring in babel, so we need
to modify our code to handle the latest version. We also need to adjust
the way we build our babel worker as babel itself no longer runs in older
browsers such as Internet Explorer.
2021-03-29 11:59:50 +03:00
Pierre Ossman
23871b42d1 Always include Promise polyfill for legacy browsers
It is now used by our general code and not just by the conversion
routines, so we need to make sure it is always included for the
old browsers.
2021-03-29 11:58:26 +03:00
Pierre Ossman
d6d875ef3b Clean up handling of untransformed files
This control flow is difficult enough as it is to follow. Move the
handling of the untransformed files to a separate block to make it
slightly easier to understand.
2021-03-29 11:58:20 +03:00
Pierre Ossman
6c84631bbc Remove redundant "no copy" check
We also check this list as a filter to walkDir(), so no need for the
extra check here.
2021-03-29 11:58:13 +03:00
wavezhang
6bb87ee2b2 Update zh_CN.po
fix spell errors, improve translations
2021-03-29 11:57:31 +03:00
Alex Tanskanen
15c74e7dc9 Fix missing caps lock events on iOS
Caps Lock on iOS only trigged key release or key press events.
When it's clicked it would only send keydown, and next time
it would only send keyup and so on. It should send both a key press
and a key release.

Also added the unit tests for macOS since those were missing.

Co-Authored-By: Alex Tanskanen <aleta@cendio.se>
2021-03-29 11:57:26 +03:00
Samuel Mannehed
f1be4be653 Add README to app/locale warning not to modify 2021-03-29 11:57:09 +03:00
Alex Tanskanen
b5f1a00282 Add "macOS shuffle" to iOS as well
Since iOS functions like macOS with regards to Alt behaving like AltGr,
we need the same workaround on iOS as well.
2021-03-29 11:57:05 +03:00
Pierre Ossman
740a8217ab Handle missing Shift events on Windows
This is a bug in the OS that leaks through to the browsers. We need
to fake a Shift release here to avoid Shift getting stuck in the remote
session.
2021-03-29 11:57:00 +03:00
Pierre Ossman
796de9653f Send NumLock on macOS, even though the key is Clear
There is no obvious choice what works best here, but this is what
TigerVNC has been doing for years without complaints. Let's follow
them until we get reports that this doesn't work well.
2021-03-29 11:56:55 +03:00
Pierre Ossman
6916c83b48 Fix typo for MailSend key 2021-03-29 11:56:49 +03:00
Pierre Ossman
d10d7167f6 Update to latest UI Events key specification 2021-03-29 11:56:45 +03:00
Pierre Ossman
a8dc933701 Fix AltGr for a few more keys in IE and Edge
Some keys apparently send 'Unidentified' rather than an unshifted value.
Make sure those are also handled. Examples are \ and | on a Swedish
keyboard.
2021-03-29 11:56:40 +03:00
Samuel Mannehed
d61bf69c33 Keep the virtual keyboard after using extra keys
If using the extra keys always gives focus to the screen then an
on-screen keyboard would be closed. When using on-screen keyboards we
instead want to give focus to our virtual keyboard input element.
2021-03-29 11:56:34 +03:00
Pierre Ossman
62fca18cb9 Revert iOS keyup workaround
It seems Apple has fixed their buggy keyup events, so remove the
workaround and allow keys to be kept pressed again.

This is a revert of 9e99ce126ca8f6f350fa015c0e58d35103c62f7e.
2021-03-29 11:56:31 +03:00
Pierre Ossman
dc3ddc8efc Handle broken numpad delete key in Chrome 2021-03-29 11:56:24 +03:00
Pierre Ossman
e497b53d09 Explain why Clear maps to KP_Begin 2021-03-29 11:56:11 +03:00
Pierre Ossman
7dc51fa7a5 Try to handle Meta key properly
The standards have unfortunatly caused some confusion between the Windows
key and the original Meta key. Try to handle the common case sanely at least.
2021-03-29 11:56:08 +03:00
Samuel Mannehed
443858cf83 Move focus to the screen when using extra keys
A regression from 2afda54 and friends was that you couldn't use the
extra keys and then directly use the keyboard, you would have to click
in the session first.

This commit restores the correct behavior and also adds a visual queue
to the fact that the screen got the focus by fading the controlbar.
2021-03-29 11:56:01 +03:00
Samuel Mannehed
6b39933658 Add missing scancode for sendTab 2021-03-29 11:55:55 +03:00
Samuel Mannehed
6067290169 Rename document.capturedElem to captureElement
To better fit most naming.
2021-03-29 11:55:52 +03:00
Pierre Ossman
a8699ab8cb Improve Windows key image
The previous one didn't have sharp lines, or follow pixel boundaries
properly.
2021-03-29 11:55:45 +03:00
Samuel Mannehed
996895268e Hide the emulated cursor when target is null
Makes it easier to understand what happens when a real element isn't
passed as a target to updateVisibility(). Also makes the code more
robust to future changes.

Co-authored-by: Alex Tanskanen <aleta@cendio.se>
Co-authored-by: Niko Lehto <nikle@cendio.se>
2021-03-29 11:55:38 +03:00
Samuel Mannehed
fb14c2dec9 Fix disappearing cursor after click
In the cursor emulation when deciding if the cursor should be hidden -
Instead of checking what's under the cursor, we check the element that
has capture.

This introduced another bug in the cursor emulation. The cursor did not
always disappear properly when using our cursor emulation together with
our setCapture polyfill. More specifically, we saw a problem when a
capture ended on an element without cursor emulation.

We solved this by introducing another visibility check on a timer in
the cursor emulation. However this led to yet another problem where
this timer conflicted with the timer in the setCapture polyfill.

We removed the timeout in the setCapture polyfill and created a
variable to make sure that all the events remaining in the queue can be
completed.

Co-authored-by: Alex Tanskanen <aleta@cendio.se>
Co-authored-by: Niko Lehto <nikle@cendio.se>
2021-03-29 11:55:28 +03:00
Samuel Mannehed
83d5e5bffd Check next elem at mouseleave in cursor emulation
It's not obvious that we want to hide the cursor when we get a leave,
it depends on the element that we're leaving to. This makes the code
more robust.

Co-authored-by: Alex Tanskanen <aleta@cendio.se>
Co-authored-by: Niko Lehto <nikle@cendio.se>
2021-03-29 11:55:20 +03:00
Samuel Mannehed
19dfb7901c Rename variables in setCapture proxy
The names of many variables were too similar. To make the code easier
to follow we renamed:

* _captureElem to _capturedElem
* _captureElemChanged() to _capturedElemChanged()
* captureElem to proxyElem
* elem to target

Co-authored-by: Alex Tanskanen <aleta@cendio.se>
Co-authored-by: Niko Lehto <nikle@cendio.se>
2021-03-29 11:55:13 +03:00
Pierre Ossman
6acf3c9e62 Never show drag icon if clipping is disabled
Toggling the enabled state is a remnant from an earlier version
of the code where we could determine if the the session is actually
clipped, and not just that the setting is enabled.

Right now we only change things based on the setting, so let's
completely hide the button when clipping is disabled.
2021-03-29 11:54:51 +03:00
Samuel Mannehed
0dcb896920 Update copyright to 2019 for modified files 2021-03-29 11:54:44 +03:00
Samuel Mannehed
d88aefba4e Code comments for how the receieve queue works 2021-03-29 11:54:33 +03:00
Samuel Mannehed
b0c54f6b24 Clarify why we ENABLE_COPYWITHIN is false 2021-03-29 11:54:26 +03:00
Samuel Mannehed
6342a117ff Clarify comments for broken alt in FF on Windows 2021-03-29 11:54:18 +03:00
Niko Lehto
766fc43855 Add support for VMware cursor encoding
Supports both classic cursor type and alpha cursor type. In classic
mode the server can send 'inverted' pixels for the cursor, our code
does not support this but handles these pixels as opaque black.

Co-authored-by: Samuel Mannehed <samuel@cendio.se>
2021-03-29 11:53:24 +03:00
Niko Lehto
19f0803636 Fix url cursor detection on Edge
_supportCursorURIs was set to true even when Edge didn't support
URIs because the fallback value "default" was used.
2021-03-29 11:51:50 +03:00
Niko Lehto
3c3ac34eb8 Test unicode desktop names 2021-03-29 11:51:18 +03:00
Niko Lehto
8c43287afb Add support for DesktopName extension
This extension allows session name to be changed during runtime.
2021-03-29 11:50:44 +03:00
Pierre Ossman
c16cc6e2b9 Set viewport size for autoscale tests
We were incorrectly relying on the viewport being indirectly set
for us. Make sure we are explicit in what we want for these tests.
2021-03-29 11:49:41 +03:00
Pierre Ossman
c211f31113 Remove pointless Display.clear()
It served no meaningful purpose and it had bugs. So let's remove it
rather than try to fix it.
2021-03-29 11:49:36 +03:00
Pierre Ossman
4cc536636a Remove unused Display.logo attribute 2021-03-29 11:49:21 +03:00
Pierre Ossman
734bdd3746 Deprecate showDotCursor option for RFB constructor
It is not relevant for the connection stage so it should not have
been a constructor argument to begin with. Ship with a warning for
a release before we remove it.
2021-03-29 11:47:35 +03:00
Pierre Ossman
8218a0cb2a Make sure showDotCursor can be modified before connecting
The cursor object is only attached to our canvas whilst connecting,
so we need to make sure we don't try to update anything when were
not connected or we'll get a crash.
2021-03-29 11:46:22 +03:00
Pierre Ossman
2525174260 Regenerate module loader after tool upgrades 2021-03-29 11:46:12 +03:00
Jesper Alf Dam
b0896c8859 When compacting the receive buffer don't copy unused buffer space
When compacting the receive buffer, we should only copy the bytes
between _rQi and _rQlen (the index of the first unread byte, and the
next write position).

Previously, we copied everything for _rQi up untill the end of the
buffer.
2021-03-29 11:45:23 +03:00
Jesper Alf Dam
09de4b8349 Don't compact the receive buffer unless we've actually run out of space
Previously, we would compact the buffer (moving unread data to the
start of the buffer) as follows:

- after processing a message, if there are zero unread bytes, just reset
  the indices for first and last unread byte to zero
- else, if at least 1/8th of the buffer is used, copy remaining data to the beginning of the buffer

The second option is never actually necessary, as before inserting new data
into the array, we already check if there's enough free space, and
compact the buffer first if necessary. So we've been doing a lot of
copies that weren't actually needed. Let's not do that any more.
2021-03-29 11:45:00 +03:00
Jesper Alf Dam
d4747a8c80 Avoid recursion in Alt check on Firefox
The Firefox workaround which checks for missing Alt key events may
synthesise new KeyboardEvents. On these events, checkAlt should not be
recursively triggered. Otherwise, we get "too much recursion" errors
whenever the Alt key is pressed.
2021-03-29 11:44:49 +03:00
Pierre Ossman
5b73c1ca23 Fix trivial lint issues in translation tools
Indentation, missing semicolon, etc.
2021-03-29 11:44:42 +03:00
Pierre Ossman
f21fb95bb9 Remove unused import from module loader 2021-03-29 11:44:23 +03:00
Pierre Ossman
7b02f3d8b8 Avoid deprecated called.once from sinon-chai
It's been removed in newer versions and will break eventually.
2021-03-29 11:44:04 +03:00
Samuel Mannehed
03a333fb18 Add missing parentheses for arrow func arg
Our lint tests expect this when an arrow functino has a body with
curly braces.
2021-03-29 11:43:15 +03:00
Samuel Mannehed
54253efaa0 Add documentation for the option showDotCursor
This is not only a property, it's also a parameter to the constructor.
2021-03-29 11:43:09 +03:00
Samuel Mannehed
8b859f4598 Remove the default value of wsProtocols
Using the 'binary' protocol by default is very non-standard.
2021-03-29 11:42:58 +03:00
Shira Maximov
8c5b5f17eb Add support in websocket sub-protocols 2021-03-29 11:42:28 +03:00
Juanjo Diaz
71fa476514 Add version number to UI 2021-03-29 11:40:55 +03:00
Samuel Mannehed
4fd1f19f3b Update link to websock.js API 2021-03-29 11:40:48 +03:00
Lee Yarwood
257aabecb0 launch.sh: Check for a local websockify directory
Previously launch.sh would check both for the existence of a local
websockify file and /websockify/run file.

This initial check should really be for a local websockify directory
as in packaged environments a file could very well be the actual
executable leading to launch.sh incorrectly attempting to use a local
version of websockify.
2021-03-29 11:40:40 +03:00
Pierre Ossman
74161066af Add support for separate key file in launch script 2021-03-29 11:40:25 +03:00
Samuel Mannehed
e2d86788ba Revert "Fullscreen from iframe (#1236)" (#1247)
This reverts commit 19cdc15aa314760446866a1bcc2db99a80479683.
2021-03-29 11:39:56 +03:00
Pierre Ossman
4c635f65d3 Remove server pixel format warnings
These are harmless and really only for debugging. So remove them
as they tend to trick people in to thinking something is wrong.
We already print the entire server pixel format earlier anyway in
case we need the details.
2021-03-29 11:39:47 +03:00
Ján Jockusch
1d4ada6815 Fullscreen from iframe (#1236)
* First attempt to make the fullscreen button work inside an iframe.

* Cleaner distinction between document element and document.

* Scoping corrections. Auto-detect correct iframe.

* Added comments to the relevant sections.

* IE issue fixed.

* Same source issue solved. fullscreenToggle now checks if it is permitted to inspect other iframes.
2021-03-29 11:39:32 +03:00
Samuel Mannehed
d3ec2aa4d1 noVNC 1.1.0 2021-03-29 11:39:20 +03:00
Samuel Mannehed
10c334303a Update generated JS files for translations 2021-03-29 11:39:13 +03:00
Samuel Mannehed
c4987024ef Update Dutch translations
Co-authored-by: Arend Lapere <arend.lapere@gmail.com>
2021-03-29 11:39:04 +03:00
Samuel Mannehed
04d7bef2ae Update Swedish translations 2021-03-29 11:38:58 +03:00
Samuel Mannehed
12565dc4ac Allow autoscale() with zero height or width
Commit 6e7e6f9 stopped the function from running if width or height was
zero, this commit reverts that change. This commit also makes the
resulting canvas 0x0 if autoscale is called with zero. By adding this
special case we can avoid division by zero in the calculations.
2021-03-29 11:38:52 +03:00
Pierre Ossman
46b7d1db95 Fix up errors and warnings in vnc_playback.html
Remove the styling, as it isn't really needed, and fix some minor
things that the w3c validator complains about.
2021-03-29 11:38:25 +03:00
Samuel Mannehed
0045f07965 Remove invalid HTML attributes from textarea 2021-03-29 11:37:52 +03:00
Samuel Mannehed
d1fdb877ef Fix invalid input type 'input' 2021-03-29 11:37:36 +03:00
Samuel Mannehed
e62e12fbfe Input type image is not allowed to have values 2021-03-29 11:37:18 +03:00
Samuel Mannehed
50183c7caa Add default language 2021-03-29 11:36:20 +03:00
Samuel Mannehed
79ab05192b Add check for bad values for Display.autoscale() 2021-03-29 11:36:08 +03:00
Juanjo Diaz
c6c278f9d5 Replace unnecessary function supportsCursorURIs by a constant variable 2021-03-29 11:35:44 +03:00
Juanjo Diaz
37c17ddbf9 Move support check from display to browser 2021-03-29 11:35:38 +03:00
Dmitriy Shweew
c755008d15 Add Russian translation (#1211)
By Dmitriy Shweew (shweew)
2021-03-29 11:35:31 +03:00
Juanjo Diaz
075eed5cbb Convert DES into a class 2021-03-29 11:35:23 +03:00
Juanjo Diaz
7b7295fd4e Use default argument for base64 2021-03-29 11:35:16 +03:00
Juanjo Diaz
5964156a6f Remove unnecessary context from eventtarget 2021-03-29 11:35:11 +03:00
Juanjo Diaz
1ff792cf4b Remove unnecessary constructor parameter from Cursor 2021-03-29 11:35:06 +03:00
Juanjo Diaz
3043216b63 Remove intermediate variable from mouse 2021-03-29 11:34:56 +03:00
Pierre Ossman
499b251716 Remove error handling in clientCutText()
It is not necessary as Websock.flush() is guaranteed to succeed and
give us some space. It also remove the call to _fail(), which was
invalid at this place as clientCutText() is not a method on RFB.
2021-03-29 11:34:50 +03:00
Pierre Ossman
d20f751441 Throw correct Error object
We've already defined the name Error as a logging function, so we
need to be more explicit when we want to refer to the exception
class.
2021-03-29 11:34:45 +03:00
Pierre Ossman
915901848d Send data one byte at a time in tests
This makes sure we don't have code assuming that everything is
neatly packaged in a single WebSocket message.
2021-03-29 11:34:38 +03:00
Pierre Ossman
ee2423ed2b Clean up RFB._rfb_auth_schema assignment 2021-03-29 11:34:29 +03:00
Pierre Ossman
ce6d66f030 Fix security failure reason handling of slow data
Things would break if the security result and security reason did
not arrive in the same WebSocket message.
2021-03-29 11:34:21 +03:00
Pierre Ossman
41e6fedba6 Fix version handshake to handle slow data 2021-03-29 11:34:08 +03:00
Pierre Ossman
642a67f76f Use arrow function to avoid bind 2021-03-29 11:34:00 +03:00
Pierre Ossman
d7198cbe5d Consume data properly in Hextile decoder
We accidentally removed the code updating the data index in 8a189a6,
resulting in the decoder newer consuming any data. So the data would
be parsed as the next rect, causing weird errors.
2021-03-29 11:33:25 +03:00
lhchavez
25b8e64adb Add support for notifying clients about pointer movements
This change adds support for the VMware Mouse Position
pseudo-encoding[1], which is used to notify VNC clients when X11 clients
call `XWarpPointer()`[2]. This function is called by SDL (and other
similar libraries)  when they detect that the server does not support
native relative motion, like some RFB clients.

With this, RFB clients can choose to adjust the local cursor position
under certain circumstances to match what the server has set. For
instance, if pointer lock has been enabled on the client's machine and
the cursor is not being drawn locally, the local position of the cursor
is irrelevant, so the RFB client can use what the server sends as the
canonical absolute position of the cursor. This ultimately enables the
possibility of games (especially FPS games) to behave how users expect
(if the clients implement the corresponding change).

Part of: #619

1: https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#vmware-cursor-position-pseudo-encoding
2: https://tronche.com/gui/x/xlib/input/XWarpPointer.html
3: https://hg.libsdl.org/SDL/file/28e3b60e2131/src/events/SDL_mouse.c#l804
2021-03-29 11:27:54 +03:00
Pierre Ossman
d8caab699d Add missing headers for TCP_CORK
We didn't include the proper headers to get the correct define, so
corking was never enabled.
2021-03-29 11:04:00 +03:00
Pierre Ossman
da83ecf86a Drop other selection on ownership change
Otherwise we might end up owners of something we cannot deliver data on,
which can hang applications.
2021-03-29 11:03:38 +03:00
Pierre Ossman
189f503b98 Fix handling of bad update requests
We computed a safe area if a client gave us a bogus one, but we didn't
actually use it. Fix this properly and make sure we don't pass on bad
coordinates further.
2021-03-29 11:00:41 +03:00
Pierre Ossman
f54dc7829a Update keycode maps to latest version
Mainly fixes for Japanese and Korean keyboard layouts.
2021-03-29 10:57:41 +03:00
Pierre Ossman
fde088ce65 Improved bandwidth monitoring
Now measures over an entire update, which should hopefully give us more
stable values. They are still small values for fast networks though so
increase precision in the values we keep.
2021-03-29 10:52:51 +03:00
Pierre Ossman
a55f142c98 Don't shuffle input buffer unless actually needed 2021-03-29 10:50:16 +03:00
Pierre Ossman
25995e2490 Remove unused bufSize argument from streams 2021-03-29 10:49:25 +03:00
Pierre Ossman
281d65292a Remove special functions from JPEG compressor
We can do what we want with the standard methods.
2021-03-29 10:48:55 +03:00
Pierre Ossman
57a3c3bba8 Simplify stream availability handling
Just have a simply number of bytes argument to avoid a lot of
complexity.
2021-03-29 10:48:26 +03:00
Pierre Ossman
92c7695981 Create common base classes for buffered streams
Most streams are backed by a memory buffer. Create common base classes
for this functionality to avoid code duplication.
2021-03-29 10:11:16 +03:00
Pierre Ossman
7f90205cf2 Add stream avail() methods
Makes it more readable to write code that needs to know how much
data/space is available in a stream.
2021-03-29 10:08:40 +03:00
Pierre Ossman
910fd8fa3e Remove unused stream methods
They were accidentally left unused in fbad8a9 so they haven't been used
in some time.
2021-03-29 10:04:04 +03:00
Pierre Ossman
c97828471c Use proper constants for socket shutdown()
For readability.
2021-03-29 10:03:05 +03:00
Pierre Ossman
c5b7137f2b Flush data on close
There might be some final handshake data that is still stuck in the
buffers, so make a best effort attempt at getting it to the client.
2021-03-29 10:02:31 +03:00
Pierre Ossman
a3c0ce55c9 Support calling methods from timers
We can't safely use the normal timers in base classes as we cannot
guarantee that subclasses will call the base class' handleTimeout()
properly if the subclass overrides it.
2021-03-29 09:58:18 +03:00
293 changed files with 2598 additions and 91949 deletions

View File

@@ -4,6 +4,7 @@ services:
variables:
GITLAB_SHARED_DIND_DIR: /builds/$CI_PROJECT_PATH/shared
GIT_SUBMODULE_STRATEGY: normal
GIT_FETCH_EXTRA_FLAGS: --tags
stages:

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "kasmweb"]
path = kasmweb
url = https://github.com/kasmtech/noVNC.git
branch = toggle-game-mode

View File

@@ -20,7 +20,7 @@ Incomplete and generally out of date copyright list::
All Rights Reserved.
This software is distributed under the GNU General Public Licence as published
by the Free Software Foundation. See the file LICENCE.TXT for the conditions
by the Free Software Foundation. See the file LICENSE.TXT for the conditions
under which this software is made available. KasmVNC also contains code from
other sources. See the Acknowledgements section below, and the individual
source files, for details of the conditions under which they are made
@@ -105,4 +105,4 @@ This distribution contains software from the X Window System. This is:
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
SOFTWARE.

View File

@@ -101,4 +101,4 @@ We also need help with Windows, which is not currently supported. While KasmVNC
See the [builder/README.md](https://github.com/kasmtech/KasmVNC/blob/master/builder/README.md). We containerize our build systems to ensure highly repeatable builds.
### License and Acknowledgements
See the [LICENSE.TXT](https://github.com/kasmtech/KasmVNC/blob/master/LICENCE.TXT) and [ACKNOWLEDGEMENTS.MD](https://github.com/kasmtech/KasmVNC/blob/master/LICENSE.TXT)
See the [LICENSE.TXT](https://github.com/kasmtech/KasmVNC/blob/master/LICENSE.TXT) and [ACKNOWLEDGEMENTS.MD](https://github.com/kasmtech/KasmVNC/blob/master/LICENSE.TXT)

View File

@@ -14,6 +14,5 @@ cp -R ./* /build/
cd /build
rm *.md
rm AUTHORS
rm *.yml
rm vnc.html
rm vnc_lite.html

View File

@@ -69,7 +69,7 @@ cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
/usr/share/man/man1/*
/usr/share/kasmvnc/www
%license /usr/share/doc/kasmvncserver/LICENCE.TXT
%license /usr/share/doc/kasmvncserver/LICENSE.TXT
%doc /usr/share/doc/kasmvncserver/README.md
%changelog

View File

@@ -76,5 +76,5 @@ endif() #UNIX
# Common
#
install(FILES ${CMAKE_SOURCE_DIR}/LICENCE.TXT DESTINATION ${DOC_DIR})
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE.TXT DESTINATION ${DOC_DIR})
install(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION ${DOC_DIR})

View File

@@ -25,6 +25,9 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#define errorNumber WSAGetLastError()
#define SHUT_RD SD_RECEIVE
#define SHUT_WR SD_SEND
#define SHUT_RDWR SD_BOTH
#else
#define errorNumber errno
#define closesocket close
@@ -94,7 +97,7 @@ Socket::~Socket()
void Socket::shutdown()
{
isShutdown_ = true;
::shutdown(getFd(), 2);
::shutdown(getFd(), SHUT_RDWR);
}
bool Socket::isShutdown() const
@@ -149,7 +152,7 @@ void SocketListener::shutdown()
closesocket(fd);
fd = -1;
#else
::shutdown(fd, 2);
::shutdown(fd, SHUT_RDWR);
#endif
}

View File

@@ -779,7 +779,13 @@ static void dirlisting(ws_ctx_t *ws_ctx, const char fullpath[], const char path[
if (!strcmp(names[i]->d_name, ".") || !strcmp(names[i]->d_name, ".."))
continue;
sprintf(buf, "<li><a href=\"%s\">%s</a></li>", names[i]->d_name, names[i]->d_name);
if (names[i]->d_type == DT_DIR)
sprintf(buf, "<li><a href=\"%s/\">%s/</a></li>", names[i]->d_name,
names[i]->d_name);
else
sprintf(buf, "<li><a href=\"%s\">%s</a></li>", names[i]->d_name,
names[i]->d_name);
ws_send(ws_ctx, buf, strlen(buf));
}

View File

@@ -0,0 +1,69 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2020 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <rdr/BufferedInStream.h>
#include <rdr/Exception.h>
using namespace rdr;
static const size_t DEFAULT_BUF_SIZE = 8192;
BufferedInStream::BufferedInStream()
: bufSize(DEFAULT_BUF_SIZE), offset(0)
{
ptr = end = start = new U8[bufSize];
}
BufferedInStream::~BufferedInStream()
{
delete [] start;
}
size_t BufferedInStream::pos()
{
return offset + ptr - start;
}
bool BufferedInStream::overrun(size_t needed, bool wait)
{
if (needed > bufSize)
throw Exception("BufferedInStream overrun: "
"requested size of %lu bytes exceeds maximum of %lu bytes",
(long unsigned)needed, (long unsigned)bufSize);
// Do we need to shuffle things around?
if ((bufSize - (ptr - start)) < needed) {
memmove(start, ptr, end - ptr);
offset += ptr - start;
end -= ptr - start;
ptr = start;
}
while (avail() < needed) {
if (!fillBuffer(start + bufSize - end, wait))
return false;
}
return true;
}

View File

@@ -0,0 +1,54 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2020 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
//
// Base class for input streams with a buffer
//
#ifndef __RDR_BUFFEREDINSTREAM_H__
#define __RDR_BUFFEREDINSTREAM_H__
#include <rdr/InStream.h>
namespace rdr {
class BufferedInStream : public InStream {
public:
virtual ~BufferedInStream();
virtual size_t pos();
private:
virtual bool fillBuffer(size_t maxSize, bool wait) = 0;
virtual bool overrun(size_t needed, bool wait);
private:
size_t bufSize;
size_t offset;
U8* start;
protected:
BufferedInStream();
};
} // end of namespace rdr
#endif

View File

@@ -0,0 +1,108 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2020 Pierre Ossman for Cendio AB
* Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <rdr/BufferedOutStream.h>
#include <rdr/Exception.h>
using namespace rdr;
static const size_t DEFAULT_BUF_SIZE = 16384;
BufferedOutStream::BufferedOutStream()
: bufSize(DEFAULT_BUF_SIZE), offset(0)
{
ptr = start = sentUpTo = new U8[bufSize];
end = start + bufSize;
}
BufferedOutStream::~BufferedOutStream()
{
// FIXME: Complain about non-flushed buffer?
delete [] start;
}
size_t BufferedOutStream::length()
{
return offset + ptr - sentUpTo;
}
size_t BufferedOutStream::bufferUsage()
{
return ptr - sentUpTo;
}
void BufferedOutStream::flush()
{
while (sentUpTo < ptr) {
size_t len;
len = bufferUsage();
if (!flushBuffer(false))
break;
offset += len - bufferUsage();
}
// Managed to flush everything?
if (sentUpTo == ptr)
ptr = sentUpTo = start;
}
void BufferedOutStream::overrun(size_t needed)
{
if (needed > bufSize)
throw Exception("BufferedOutStream overrun: "
"requested size of %lu bytes exceeds maximum of %lu bytes",
(long unsigned)needed, (long unsigned)bufSize);
// First try to get rid of the data we have
flush();
// Still not enough space?
while (needed > avail()) {
// Can we shuffle things around?
// (don't do this if it gains us less than 25%)
if (((size_t)(sentUpTo - start) > bufSize / 4) &&
(needed < bufSize - (ptr - sentUpTo))) {
memmove(start, sentUpTo, ptr - sentUpTo);
ptr = start + (ptr - sentUpTo);
sentUpTo = start;
} else {
size_t len;
len = bufferUsage();
// Have to get rid of more data, so allow the flush to wait...
flushBuffer(true);
offset += len - bufferUsage();
// Managed to flush everything?
if (sentUpTo == ptr)
ptr = sentUpTo = start;
}
}
}

View File

@@ -0,0 +1,65 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2020 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
//
// Base class for output streams with a buffer
//
#ifndef __RDR_BUFFEREDOUTSTREAM_H__
#define __RDR_BUFFEREDOUTSTREAM_H__
#include <rdr/OutStream.h>
namespace rdr {
class BufferedOutStream : public OutStream {
public:
virtual ~BufferedOutStream();
virtual size_t length();
virtual void flush();
size_t bufferUsage();
private:
// flushBuffer() requests that the stream be flushed. Returns true if it is
// able to progress the output (which might still not mean any bytes
// actually moved) and can be called again. If wait is true then it will
// block until all data has been written.
virtual bool flushBuffer(bool wait) = 0;
virtual void overrun(size_t needed);
private:
size_t bufSize;
size_t offset;
U8* start;
protected:
U8* sentUpTo;
protected:
BufferedOutStream();
};
}
#endif

View File

@@ -1,6 +1,8 @@
include_directories(${CMAKE_SOURCE_DIR}/common ${ZLIB_INCLUDE_DIRS})
add_library(rdr STATIC
BufferedInStream.cxx
BufferedOutStream.cxx
Exception.cxx
FdInStream.cxx
FdOutStream.cxx

View File

@@ -36,13 +36,6 @@
#include <unistd.h>
#endif
#ifndef vncmin
#define vncmin(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef vncmax
#define vncmax(a,b) (((a) > (b)) ? (a) : (b))
#endif
/* Old systems have select() in sys/time.h */
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
@@ -53,31 +46,22 @@
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 8192,
MIN_BULK_SIZE = 1024 };
enum { DEFAULT_BUF_SIZE = 8192 };
FdInStream::FdInStream(int fd_, int timeoutms_, size_t bufSize_,
FdInStream::FdInStream(int fd_, int timeoutms_,
bool closeWhenDone_)
: fd(fd_), closeWhenDone(closeWhenDone_),
timeoutms(timeoutms_), blockCallback(0),
timing(false), timeWaitedIn100us(5), timedKbits(0),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
timeoutms(timeoutms_), blockCallback(0)
{
ptr = end = start = new U8[bufSize];
}
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_,
size_t bufSize_)
: fd(fd_), timeoutms(0), blockCallback(blockCallback_),
timing(false), timeWaitedIn100us(5), timedKbits(0),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_)
: fd(fd_), timeoutms(0), blockCallback(blockCallback_)
{
ptr = end = start = new U8[bufSize];
}
FdInStream::~FdInStream()
{
delete [] start;
if (closeWhenDone) close(fd);
}
@@ -92,72 +76,15 @@ void FdInStream::setBlockCallback(FdInStreamBlockCallback* blockCallback_)
timeoutms = 0;
}
size_t FdInStream::pos()
bool FdInStream::fillBuffer(size_t maxSize, bool wait)
{
return offset + ptr - start;
}
size_t n = readWithTimeoutOrCallback((U8*)end, maxSize, wait);
if (n == 0)
return false;
end += n;
void FdInStream::readBytes(void* data, size_t length)
{
if (length < MIN_BULK_SIZE) {
InStream::readBytes(data, length);
return;
}
U8* dataPtr = (U8*)data;
size_t n = end - ptr;
if (n > length) n = length;
memcpy(dataPtr, ptr, n);
dataPtr += n;
length -= n;
ptr += n;
while (length > 0) {
n = readWithTimeoutOrCallback(dataPtr, length);
dataPtr += n;
length -= n;
offset += n;
}
}
size_t FdInStream::overrun(size_t itemSize, size_t nItems, bool wait)
{
if (itemSize > bufSize)
throw Exception("FdInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
offset += ptr - start;
end -= ptr - start;
ptr = start;
size_t bytes_to_read;
while ((size_t)(end - start) < itemSize) {
bytes_to_read = start + bufSize - end;
if (!timing) {
// When not timing, we must be careful not to read too much
// extra data into the buffer. Otherwise, the line speed
// estimation might stay at zero for a long time: All reads
// during timing=1 can be satisfied without calling
// readWithTimeoutOrCallback. However, reading only 1 or 2 bytes
// bytes is ineffecient.
bytes_to_read = vncmin(bytes_to_read, vncmax(itemSize*nItems, 8));
}
size_t n = readWithTimeoutOrCallback((U8*)end, bytes_to_read, wait);
if (n == 0) return 0;
end += n;
}
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
return true;
}
//
@@ -175,10 +102,6 @@ size_t FdInStream::overrun(size_t itemSize, size_t nItems, bool wait)
size_t FdInStream::readWithTimeoutOrCallback(void* buf, size_t len, bool wait)
{
struct timeval before, after;
if (timing)
gettimeofday(&before, 0);
int n;
while (true) {
do {
@@ -215,48 +138,5 @@ size_t FdInStream::readWithTimeoutOrCallback(void* buf, size_t len, bool wait)
if (n < 0) throw SystemException("read",errno);
if (n == 0) throw EndOfStream();
if (timing) {
gettimeofday(&after, 0);
int newTimeWaited = ((after.tv_sec - before.tv_sec) * 10000 +
(after.tv_usec - before.tv_usec) / 100);
int newKbits = n * 8 / 1000;
// limit rate to between 10kbit/s and 40Mbit/s
if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4;
timeWaitedIn100us += newTimeWaited;
timedKbits += newKbits;
}
return n;
}
void FdInStream::startTiming()
{
timing = true;
// Carry over up to 1s worth of previous rate for smoothing.
if (timeWaitedIn100us > 10000) {
timedKbits = timedKbits * 10000 / timeWaitedIn100us;
timeWaitedIn100us = 10000;
}
}
void FdInStream::stopTiming()
{
timing = false;
if (timeWaitedIn100us < timedKbits/2)
timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
}
unsigned int FdInStream::kbitsPerSecond()
{
// The following calculation will overflow 32-bit arithmetic if we have
// received more than about 50Mbytes (400Mbits) since we started timing, so
// it should be OK for a single RFB update.
return timedKbits * 10000 / timeWaitedIn100us;
}

View File

@@ -23,7 +23,7 @@
#ifndef __RDR_FDINSTREAM_H__
#define __RDR_FDINSTREAM_H__
#include <rdr/InStream.h>
#include <rdr/BufferedInStream.h>
namespace rdr {
@@ -33,31 +33,21 @@ namespace rdr {
virtual ~FdInStreamBlockCallback() {}
};
class FdInStream : public InStream {
class FdInStream : public BufferedInStream {
public:
FdInStream(int fd, int timeoutms=-1, size_t bufSize=0,
bool closeWhenDone_=false);
FdInStream(int fd, FdInStreamBlockCallback* blockCallback,
size_t bufSize=0);
FdInStream(int fd, int timeoutms=-1, bool closeWhenDone_=false);
FdInStream(int fd, FdInStreamBlockCallback* blockCallback);
virtual ~FdInStream();
void setTimeout(int timeoutms);
void setBlockCallback(FdInStreamBlockCallback* blockCallback);
int getFd() { return fd; }
size_t pos();
void readBytes(void* data, size_t length);
void startTiming();
void stopTiming();
unsigned int kbitsPerSecond();
unsigned int timeWaited() { return timeWaitedIn100us; }
protected:
size_t overrun(size_t itemSize, size_t nItems, bool wait);
private:
virtual bool fillBuffer(size_t maxSize, bool wait);
size_t readWithTimeoutOrCallback(void* buf, size_t len, bool wait=true);
int fd;
@@ -65,11 +55,6 @@ namespace rdr {
int timeoutms;
FdInStreamBlockCallback* blockCallback;
bool timing;
unsigned int timeWaitedIn100us;
unsigned int timedKbits;
size_t bufSize;
size_t offset;
U8* start;
};

View File

@@ -35,6 +35,8 @@
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif
/* Old systems have select() in sys/time.h */
@@ -49,26 +51,19 @@
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_, size_t bufSize_)
: fd(fd_), blocking(blocking_), timeoutms(timeoutms_),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_)
: fd(fd_), blocking(blocking_), timeoutms(timeoutms_)
{
ptr = start = sentUpTo = new U8[bufSize];
end = start + bufSize;
gettimeofday(&lastWrite, NULL);
}
FdOutStream::~FdOutStream()
{
try {
blocking = true;
flush();
while (sentUpTo != ptr)
flushBuffer(true);
} catch (Exception&) {
}
delete [] start;
}
void FdOutStream::setTimeout(int timeoutms_) {
@@ -79,82 +74,29 @@ void FdOutStream::setBlocking(bool blocking_) {
blocking = blocking_;
}
size_t FdOutStream::length()
{
return offset + ptr - sentUpTo;
}
int FdOutStream::bufferUsage()
{
return ptr - sentUpTo;
}
unsigned FdOutStream::getIdleTime()
{
return rfb::msSince(&lastWrite);
}
void FdOutStream::flush()
bool FdOutStream::flushBuffer(bool wait)
{
while (sentUpTo < ptr) {
size_t n = writeWithTimeout((const void*) sentUpTo,
ptr - sentUpTo,
blocking? timeoutms : 0);
size_t n = writeWithTimeout((const void*) sentUpTo,
ptr - sentUpTo,
(blocking || wait)? timeoutms : 0);
// Timeout?
if (n == 0) {
// If non-blocking then we're done here
if (!blocking)
break;
// Timeout?
if (n == 0) {
// If non-blocking then we're done here
if (!blocking && !wait)
return false;
throw TimedOut();
}
sentUpTo += n;
offset += n;
throw TimedOut();
}
// Managed to flush everything?
if (sentUpTo == ptr)
ptr = sentUpTo = start;
}
sentUpTo += n;
size_t FdOutStream::overrun(size_t itemSize, size_t nItems)
{
if (itemSize > bufSize)
throw Exception("FdOutStream overrun: max itemSize exceeded");
// First try to get rid of the data we have
flush();
// Still not enough space?
if (itemSize > (size_t)(end - ptr)) {
// Can we shuffle things around?
// (don't do this if it gains us less than 25%)
if (((size_t)(sentUpTo - start) > bufSize / 4) &&
(itemSize < bufSize - (ptr - sentUpTo))) {
memmove(start, sentUpTo, ptr - sentUpTo);
ptr = start + (ptr - sentUpTo);
sentUpTo = start;
} else {
// Have to get rid of more data, so turn off non-blocking
// for a bit...
bool realBlocking;
realBlocking = blocking;
blocking = true;
flush();
blocking = realBlocking;
}
}
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
return true;
}
//

View File

@@ -26,38 +26,29 @@
#include <sys/time.h>
#include <rdr/OutStream.h>
#include <rdr/BufferedOutStream.h>
namespace rdr {
class FdOutStream : public OutStream {
class FdOutStream : public BufferedOutStream {
public:
FdOutStream(int fd, bool blocking=true, int timeoutms=-1, size_t bufSize=0);
FdOutStream(int fd, bool blocking=true, int timeoutms=-1);
virtual ~FdOutStream();
void setTimeout(int timeoutms);
void setBlocking(bool blocking);
int getFd() { return fd; }
void flush();
size_t length();
int bufferUsage();
unsigned getIdleTime();
private:
size_t overrun(size_t itemSize, size_t nItems);
virtual bool flushBuffer(bool wait);
size_t writeWithTimeout(const void* data, size_t length, int timeoutms);
int fd;
bool blocking;
int timeoutms;
size_t bufSize;
size_t offset;
U8* start;
U8* sentUpTo;
struct timeval lastWrite;
};

View File

@@ -30,7 +30,6 @@ FileInStream::FileInStream(const char *fileName)
file = fopen(fileName, "rb");
if (!file)
throw SystemException("fopen", errno);
ptr = end = b;
}
FileInStream::~FileInStream(void) {
@@ -40,50 +39,17 @@ FileInStream::~FileInStream(void) {
}
}
void FileInStream::reset(void) {
if (!file)
throw Exception("File is not open");
if (fseek(file, 0, SEEK_SET) != 0)
throw SystemException("fseek", errno);
ptr = end = b;
}
size_t FileInStream::pos()
bool FileInStream::fillBuffer(size_t maxSize, bool wait)
{
if (!file)
throw Exception("File is not open");
return ftell(file) + ptr - b;
}
size_t FileInStream::overrun(size_t itemSize, size_t nItems, bool wait)
{
if (itemSize > sizeof(b))
throw Exception("FileInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(b, ptr, end - ptr);
end -= ptr - b;
ptr = b;
while ((size_t)(end - b) < itemSize) {
size_t n = fread((U8 *)end, b + sizeof(b) - end, 1, file);
if (n == 0) {
if (ferror(file))
throw SystemException("fread", errno);
if (feof(file))
throw EndOfStream();
return 0;
}
end += b + sizeof(b) - end;
size_t n = fread((U8 *)end, 1, maxSize, file);
if (n == 0) {
if (ferror(file))
throw SystemException("fread", errno);
if (feof(file))
throw EndOfStream();
return false;
}
end += n;
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
return true;
}

View File

@@ -22,26 +22,21 @@
#include <stdio.h>
#include <rdr/InStream.h>
#include <rdr/BufferedInStream.h>
namespace rdr {
class FileInStream : public InStream {
class FileInStream : public BufferedInStream {
public:
FileInStream(const char *fileName);
~FileInStream(void);
void reset(void);
size_t pos();
protected:
size_t overrun(size_t itemSize, size_t nItems, bool wait = true);
private:
virtual bool fillBuffer(size_t maxSize, bool wait);
private:
U8 b[131072];
FILE *file;
};

View File

@@ -24,18 +24,14 @@
using namespace rdr;
const int DEFAULT_BUF_LEN = 16384;
static inline int min(int a, int b) {return a<b ? a : b;}
HexInStream::HexInStream(InStream& is, size_t bufSize_)
: bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_LEN), offset(0), in_stream(is)
HexInStream::HexInStream(InStream& is)
: in_stream(is)
{
ptr = end = start = new U8[bufSize];
}
HexInStream::~HexInStream() {
delete [] start;
}
@@ -76,44 +72,24 @@ decodeError:
}
size_t HexInStream::pos() {
return offset + ptr - start;
}
bool HexInStream::fillBuffer(size_t maxSize, bool wait) {
if (!in_stream.check(2, wait))
return false;
size_t HexInStream::overrun(size_t itemSize, size_t nItems, bool wait) {
if (itemSize > bufSize)
throw Exception("HexInStream overrun: max itemSize exceeded");
const U8* iptr = in_stream.getptr();
const U8* eptr = in_stream.getend();
size_t length = min((eptr - iptr)/2, maxSize);
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
end -= ptr - start;
offset += ptr - start;
ptr = start;
while ((size_t)(end - ptr) < itemSize) {
size_t n = in_stream.check(2, 1, wait);
if (n == 0) return 0;
const U8* iptr = in_stream.getptr();
const U8* eptr = in_stream.getend();
size_t length = min((eptr - iptr)/2, start + bufSize - end);
U8* optr = (U8*) end;
for (size_t i=0; i<length; i++) {
int v = 0;
readHexAndShift(iptr[i*2], &v);
readHexAndShift(iptr[i*2+1], &v);
optr[i] = v;
}
in_stream.setptr(iptr + length*2);
end += length;
U8* optr = (U8*) end;
for (size_t i=0; i<length; i++) {
int v = 0;
readHexAndShift(iptr[i*2], &v);
readHexAndShift(iptr[i*2+1], &v);
optr[i] = v;
}
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
in_stream.setptr(iptr + length*2);
end += length;
return nItems;
return true;
}

View File

@@ -19,29 +19,23 @@
#ifndef __RDR_HEX_INSTREAM_H__
#define __RDR_HEX_INSTREAM_H__
#include <rdr/InStream.h>
#include <rdr/BufferedInStream.h>
namespace rdr {
class HexInStream : public InStream {
class HexInStream : public BufferedInStream {
public:
HexInStream(InStream& is, size_t bufSize=0);
HexInStream(InStream& is);
virtual ~HexInStream();
size_t pos();
static bool readHexAndShift(char c, int* v);
static bool hexStrToBin(const char* s, char** data, size_t* length);
protected:
size_t overrun(size_t itemSize, size_t nItems, bool wait);
private:
virtual bool fillBuffer(size_t maxSize, bool wait);
private:
size_t bufSize;
U8* start;
size_t offset;
InStream& in_stream;
};

View File

@@ -25,8 +25,8 @@ const int DEFAULT_BUF_LEN = 16384;
static inline size_t min(size_t a, size_t b) {return a<b ? a : b;}
HexOutStream::HexOutStream(OutStream& os, size_t buflen)
: out_stream(os), offset(0), bufSize(buflen ? buflen : DEFAULT_BUF_LEN)
HexOutStream::HexOutStream(OutStream& os)
: out_stream(os), offset(0), bufSize(DEFAULT_BUF_LEN)
{
if (bufSize % 2)
bufSize--;
@@ -95,18 +95,10 @@ HexOutStream::flush() {
out_stream.flush();
}
size_t
HexOutStream::overrun(size_t itemSize, size_t nItems) {
if (itemSize > bufSize)
throw Exception("HexOutStream overrun: max itemSize exceeded");
void HexOutStream::overrun(size_t needed) {
if (needed > bufSize)
throw Exception("HexOutStream overrun: buffer size exceeded");
writeBuffer();
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
}

View File

@@ -26,7 +26,7 @@ namespace rdr {
class HexOutStream : public OutStream {
public:
HexOutStream(OutStream& os, size_t buflen=0);
HexOutStream(OutStream& os);
virtual ~HexOutStream();
void flush();
@@ -37,7 +37,7 @@ namespace rdr {
private:
void writeBuffer();
size_t overrun(size_t itemSize, size_t nItems);
virtual void overrun(size_t needed);
OutStream& out_stream;

View File

@@ -35,28 +35,25 @@ namespace rdr {
virtual ~InStream() {}
// check() ensures there is buffer data for at least one item of size
// itemSize bytes. Returns the number of items in the buffer (up to a
// maximum of nItems). If wait is false, then instead of blocking to wait
// for the bytes, zero is returned if the bytes are not immediately
// available. If itemSize or nItems is zero, check() will return zero.
// avail() returns the number of bytes that are currenctly directly
// available from the stream.
inline size_t check(size_t itemSize, size_t nItems=1, bool wait=true)
inline size_t avail()
{
size_t nAvail;
return end - ptr;
}
if (itemSize == 0 || nItems == 0)
return 0;
// check() ensures there is buffer data for at least needed bytes. Returns
// true once the data is available. If wait is false, then instead of
// blocking to wait for the bytes, false is returned if the bytes are not
// immediately available.
if (itemSize > (size_t)(end - ptr))
return overrun(itemSize, nItems, wait);
inline size_t check(size_t needed, bool wait=true)
{
if (needed > avail())
return overrun(needed, wait);
// itemSize cannot be zero at this point
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
return true;
}
// checkNoWait() tries to make sure that the given number of bytes can
@@ -64,10 +61,7 @@ namespace rdr {
// otherwise. The length must be "small" (less than the buffer size).
// If length is zero, checkNoWait() will return true.
inline bool checkNoWait(size_t length)
{
return length == 0 || check(length, 1, false) > 0;
}
inline bool checkNoWait(size_t length) { return check(length, false); }
// readU/SN() methods read unsigned and signed N-bit integers.
@@ -138,13 +132,12 @@ namespace rdr {
private:
// overrun() is implemented by a derived class to cope with buffer overrun.
// It ensures there are at least itemSize bytes of buffer data. Returns
// the number of items in the buffer (up to a maximum of nItems). itemSize
// is supposed to be "small" (a few bytes). If wait is false, then
// instead of blocking to wait for the bytes, zero is returned if the bytes
// are not immediately available.
// It ensures there are at least needed bytes of buffer data. Returns true
// once the data is available. If wait is false, then instead of blocking
// to wait for the bytes, false is returned if the bytes are not
// immediately available.
virtual size_t overrun(size_t itemSize, size_t nItems, bool wait=true) = 0;
virtual bool overrun(size_t needed, bool wait=true) = 0;
protected:

View File

@@ -53,7 +53,7 @@ namespace rdr {
private:
size_t overrun(size_t itemSize, size_t nItems, bool wait) { throw EndOfStream(); }
bool overrun(size_t needed, bool wait) { throw EndOfStream(); }
const U8* start;
bool deleteWhenDone;
};

View File

@@ -41,12 +41,6 @@ namespace rdr {
delete [] start;
}
void writeBytes(const void* data, size_t length) {
check(length);
memcpy(ptr, data, length);
ptr += length;
}
size_t length() { return ptr - start; }
void clear() { ptr = start; };
void clearAndZero() { memset(start, 0, ptr-start); clear(); }
@@ -58,11 +52,11 @@ namespace rdr {
protected:
// overrun() either doubles the buffer or adds enough space for nItems of
// size itemSize bytes.
// overrun() either doubles the buffer or adds enough space for
// needed bytes.
size_t overrun(size_t itemSize, size_t nItems) {
size_t len = ptr - start + itemSize * nItems;
virtual void overrun(size_t needed) {
size_t len = ptr - start + needed;
if (len < (size_t)(end - start) * 2)
len = (end - start) * 2;
@@ -75,8 +69,6 @@ namespace rdr {
delete [] start;
start = newStart;
end = newStart + len;
return nItems;
}
U8* start;

View File

@@ -40,22 +40,20 @@ namespace rdr {
virtual ~OutStream() {}
// check() ensures there is buffer space for at least one item of size
// itemSize bytes. Returns the number of items which fit (up to a maximum
// of nItems).
// avail() returns the number of bytes that currently be written to the
// stream without any risk of blocking.
inline size_t check(size_t itemSize, size_t nItems=1)
inline size_t avail()
{
size_t nAvail;
return end - ptr;
}
if (itemSize > (size_t)(end - ptr))
return overrun(itemSize, nItems);
// check() ensures there is buffer space for at least needed bytes.
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
inline void check(size_t needed)
{
if (needed > avail())
overrun(needed);
}
// writeU/SN() methods write unsigned and signed N-bit integers.
@@ -83,19 +81,14 @@ namespace rdr {
while (bytes-- > 0) writeU8(0);
}
inline void skip(size_t bytes) {
while (bytes > 0) {
size_t n = check(1, bytes);
ptr += n;
bytes -= n;
}
}
// writeBytes() writes an exact number of bytes.
void writeBytes(const void* data, size_t length) {
while (length > 0) {
size_t n = check(1, length);
check(1);
size_t n = length;
if (length > avail())
n = avail();
memcpy(ptr, data, n);
ptr += n;
data = (U8*)data + n;
@@ -107,7 +100,10 @@ namespace rdr {
void copyBytes(InStream* is, size_t length) {
while (length > 0) {
size_t n = check(1, length);
check(1);
size_t n = length;
if (length > avail())
n = avail();
is->readBytes(ptr, n);
ptr += n;
length -= n;
@@ -143,11 +139,9 @@ namespace rdr {
private:
// overrun() is implemented by a derived class to cope with buffer overrun.
// It ensures there are at least itemSize bytes of buffer space. Returns
// the number of items which fit (up to a maximum of nItems). itemSize is
// supposed to be "small" (a few bytes).
// It ensures there are at least needed bytes of buffer space.
virtual size_t overrun(size_t itemSize, size_t nItems) = 0;
virtual void overrun(size_t needed) = 0;
protected:

View File

@@ -32,15 +32,10 @@
using namespace rdr;
const size_t DEFAULT_BUF_LEN = 256;
unsigned int RandomStream::seed;
RandomStream::RandomStream()
: offset(0)
{
ptr = end = start = new U8[DEFAULT_BUF_LEN];
#ifdef RFB_HAVE_WINCRYPT
provider = 0;
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) {
@@ -72,8 +67,6 @@ RandomStream::RandomStream()
}
RandomStream::~RandomStream() {
delete [] start;
#ifdef RFB_HAVE_WINCRYPT
if (provider)
CryptReleaseContext(provider, 0);
@@ -83,50 +76,29 @@ RandomStream::~RandomStream() {
#endif
}
size_t RandomStream::pos() {
return offset + ptr - start;
}
size_t RandomStream::overrun(size_t itemSize, size_t nItems, bool wait) {
if (itemSize > DEFAULT_BUF_LEN)
throw Exception("RandomStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
end -= ptr - start;
offset += ptr - start;
ptr = start;
size_t length = start + DEFAULT_BUF_LEN - end;
bool RandomStream::fillBuffer(size_t maxSize, bool wait) {
#ifdef RFB_HAVE_WINCRYPT
if (provider) {
if (!CryptGenRandom(provider, length, (U8*)end))
if (!CryptGenRandom(provider, maxSize, (U8*)end))
throw rdr::SystemException("unable to CryptGenRandom", GetLastError());
end += length;
end += maxSize;
} else {
#else
#ifndef WIN32
if (fp) {
size_t n = fread((U8*)end, length, 1, fp);
if (n != 1)
size_t n = fread((U8*)end, 1, maxSize, fp);
if (n <= 0)
throw rdr::SystemException("reading /dev/urandom or /dev/random failed",
errno);
end += length;
end += n;
} else {
#else
{
#endif
#endif
for (size_t i=0; i<length; i++)
for (size_t i=0; i<maxSize; i++)
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
}
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
return true;
}

View File

@@ -20,7 +20,7 @@
#define __RDR_RANDOMSTREAM_H__
#include <stdio.h>
#include <rdr/InStream.h>
#include <rdr/BufferedInStream.h>
#ifdef WIN32
#include <windows.h>
@@ -32,22 +32,17 @@
namespace rdr {
class RandomStream : public InStream {
class RandomStream : public BufferedInStream {
public:
RandomStream();
virtual ~RandomStream();
size_t pos();
protected:
size_t overrun(size_t itemSize, size_t nItems, bool wait);
private:
virtual bool fillBuffer(size_t maxSize, bool wait);
private:
U8* start;
size_t offset;
static unsigned int seed;
#ifdef RFB_HAVE_WINCRYPT
HCRYPTPROV provider;

View File

@@ -30,21 +30,19 @@
#ifdef HAVE_GNUTLS
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
{
TLSInStream* self= (TLSInStream*) str;
InStream *in = self->in;
try {
if (!in->check(1, 1, false)) {
if (!in->check(1, false)) {
gnutls_transport_set_errno(self->session, EAGAIN);
return -1;
}
if ((size_t)(in->getend() - in->getptr()) < size)
size = in->getend() - in->getptr();
if (in->avail() < size)
size = in->avail();
in->readBytes(data, size);
@@ -57,12 +55,10 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
}
TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
: session(_session), in(_in), bufSize(DEFAULT_BUF_SIZE), offset(0)
: session(_session), in(_in)
{
gnutls_transport_ptr_t recv, send;
ptr = end = start = new U8[bufSize];
gnutls_transport_set_pull_function(session, pull);
gnutls_transport_get_ptr2(session, &recv, &send);
gnutls_transport_set_ptr2(session, this, send);
@@ -71,40 +67,16 @@ TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
TLSInStream::~TLSInStream()
{
gnutls_transport_set_pull_function(session, NULL);
delete[] start;
}
size_t TLSInStream::pos()
bool TLSInStream::fillBuffer(size_t maxSize, bool wait)
{
return offset + ptr - start;
}
size_t n = readTLS((U8*) end, maxSize, wait);
if (!wait && n == 0)
return false;
end += n;
size_t TLSInStream::overrun(size_t itemSize, size_t nItems, bool wait)
{
if (itemSize > bufSize)
throw Exception("TLSInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
offset += ptr - start;
end -= ptr - start;
ptr = start;
while ((size_t)(end - start) < itemSize) {
size_t n = readTLS((U8*) end, start + bufSize - end, wait);
if (!wait && n == 0)
return 0;
end += n;
}
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
return true;
}
size_t TLSInStream::readTLS(U8* buf, size_t len, bool wait)
@@ -112,7 +84,7 @@ size_t TLSInStream::readTLS(U8* buf, size_t len, bool wait)
int n;
if (gnutls_record_check_pending(session) == 0) {
n = in->check(1, 1, wait);
n = in->check(1, wait);
if (n == 0)
return 0;
}

View File

@@ -27,27 +27,22 @@
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#include <rdr/InStream.h>
#include <rdr/BufferedInStream.h>
namespace rdr {
class TLSInStream : public InStream {
class TLSInStream : public BufferedInStream {
public:
TLSInStream(InStream* in, gnutls_session_t session);
virtual ~TLSInStream();
size_t pos();
private:
size_t overrun(size_t itemSize, size_t nItems, bool wait);
virtual bool fillBuffer(size_t maxSize, bool wait);
size_t readTLS(U8* buf, size_t len, bool wait);
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);
gnutls_session_t session;
InStream* in;
size_t bufSize;
size_t offset;
U8* start;
};
};

View File

@@ -93,19 +93,12 @@ void TLSOutStream::flush()
out->flush();
}
size_t TLSOutStream::overrun(size_t itemSize, size_t nItems)
void TLSOutStream::overrun(size_t needed)
{
if (itemSize > bufSize)
throw Exception("TLSOutStream overrun: max itemSize exceeded");
if (needed > bufSize)
throw Exception("TLSOutStream overrun: buffer size exceeded");
flush();
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
}
size_t TLSOutStream::writeTLS(const U8* data, size_t length)

View File

@@ -39,7 +39,7 @@ namespace rdr {
size_t length();
protected:
size_t overrun(size_t itemSize, size_t nItems);
virtual void overrun(size_t needed);
private:
size_t writeTLS(const U8* data, size_t length);

View File

@@ -24,41 +24,30 @@
using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
ZlibInStream::ZlibInStream(size_t bufSize_)
: underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0),
zs(NULL), bytesIn(0)
ZlibInStream::ZlibInStream()
: underlying(0), zs(NULL), bytesIn(0)
{
ptr = end = start = new U8[bufSize];
init();
}
ZlibInStream::~ZlibInStream()
{
deinit();
delete [] start;
}
void ZlibInStream::setUnderlying(InStream* is, size_t bytesIn_)
{
underlying = is;
bytesIn = bytesIn_;
ptr = end = start;
}
size_t ZlibInStream::pos()
{
return offset + ptr - start;
skip(avail());
}
void ZlibInStream::flushUnderlying()
{
ptr = end = start;
while (bytesIn > 0) {
decompress(true);
end = start; // throw away any data
if (!check(1))
throw Exception("ZlibInStream: failed to flush remaining stream data");
skip(avail());
}
setUnderlying(NULL, 0);
@@ -96,47 +85,18 @@ void ZlibInStream::deinit()
zs = NULL;
}
size_t ZlibInStream::overrun(size_t itemSize, size_t nItems, bool wait)
{
if (itemSize > bufSize)
throw Exception("ZlibInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
offset += ptr - start;
end -= ptr - start;
ptr = start;
while ((size_t)(end - ptr) < itemSize) {
if (!decompress(wait))
return 0;
}
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
}
// decompress() calls the decompressor once. Note that this won't necessarily
// generate any output data - it may just consume some input data. Returns
// false if wait is false and we would block on the underlying stream.
bool ZlibInStream::decompress(bool wait)
bool ZlibInStream::fillBuffer(size_t maxSize, bool wait)
{
if (!underlying)
throw Exception("ZlibInStream overrun: no underlying stream");
zs->next_out = (U8*)end;
zs->avail_out = start + bufSize - end;
zs->avail_out = maxSize;
size_t n = underlying->check(1, 1, wait);
size_t n = underlying->check(1, wait);
if (n == 0) return false;
zs->next_in = (U8*)underlying->getptr();
zs->avail_in = underlying->getend() - underlying->getptr();
zs->avail_in = underlying->avail();
if (zs->avail_in > bytesIn)
zs->avail_in = bytesIn;

View File

@@ -24,38 +24,32 @@
#ifndef __RDR_ZLIBINSTREAM_H__
#define __RDR_ZLIBINSTREAM_H__
#include <rdr/InStream.h>
#include <rdr/BufferedInStream.h>
struct z_stream_s;
namespace rdr {
class ZlibInStream : public InStream {
class ZlibInStream : public BufferedInStream {
public:
ZlibInStream(size_t bufSize=0);
ZlibInStream();
virtual ~ZlibInStream();
void setUnderlying(InStream* is, size_t bytesIn);
void flushUnderlying();
size_t pos();
void reset();
private:
void init();
void deinit();
size_t overrun(size_t itemSize, size_t nItems, bool wait);
bool decompress(bool wait);
virtual bool fillBuffer(size_t maxSize, bool wait);
private:
InStream* underlying;
size_t bufSize;
size_t offset;
z_stream_s* zs;
size_t bytesIn;
U8* start;
};
} // end of namespace rdr

View File

@@ -30,9 +30,9 @@ using namespace rdr;
enum { DEFAULT_BUF_SIZE = 16384 };
ZlibOutStream::ZlibOutStream(OutStream* os, size_t bufSize_, int compressLevel)
ZlibOutStream::ZlibOutStream(OutStream* os, int compressLevel)
: underlying(os), compressionLevel(compressLevel), newLevel(compressLevel),
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
bufSize(DEFAULT_BUF_SIZE), offset(0)
{
zs = new z_stream;
zs->zalloc = Z_NULL;
@@ -95,18 +95,18 @@ void ZlibOutStream::flush()
ptr = start;
}
size_t ZlibOutStream::overrun(size_t itemSize, size_t nItems)
void ZlibOutStream::overrun(size_t needed)
{
#ifdef ZLIBOUT_DEBUG
fprintf(stderr,"zos overrun\n");
#endif
if (itemSize > bufSize)
throw Exception("ZlibOutStream overrun: max itemSize exceeded");
if (needed > bufSize)
throw Exception("ZlibOutStream overrun: buffer size exceeded");
checkCompressionLevel();
while ((size_t)(end - ptr) < itemSize) {
while (avail() < needed) {
zs->next_in = start;
zs->avail_in = ptr - start;
@@ -126,13 +126,6 @@ size_t ZlibOutStream::overrun(size_t itemSize, size_t nItems)
ptr -= zs->next_in - start;
}
}
size_t nAvail;
nAvail = (end - ptr) / itemSize;
if (nAvail < nItems)
return nAvail;
return nItems;
}
void ZlibOutStream::deflate(int flush)
@@ -148,7 +141,7 @@ void ZlibOutStream::deflate(int flush)
do {
underlying->check(1);
zs->next_out = underlying->getptr();
zs->avail_out = underlying->getend() - underlying->getptr();
zs->avail_out = underlying->avail();
#ifdef ZLIBOUT_DEBUG
fprintf(stderr,"zos: calling deflate, avail_in %d, avail_out %d\n",

View File

@@ -35,7 +35,7 @@ namespace rdr {
public:
ZlibOutStream(OutStream* os=0, size_t bufSize=0, int compressionLevel=-1);
ZlibOutStream(OutStream* os=0, int compressionLevel=-1);
virtual ~ZlibOutStream();
void setUnderlying(OutStream* os);
@@ -45,7 +45,7 @@ namespace rdr {
private:
size_t overrun(size_t itemSize, size_t nItems);
virtual void overrun(size_t needed);
void deflate(int flush);
void checkCompressionLevel();

View File

@@ -20,6 +20,7 @@
#include <string.h>
#include <rfb/Exception.h>
#include <rfb/clipboardTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/CMsgReader.h>
#include <rfb/CMsgWriter.h>
@@ -42,7 +43,8 @@ CConnection::CConnection()
: csecurity(0), is(0), os(0), reader_(0), writer_(0),
shared(false),
state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
framebuffer(NULL), decoder(this)
framebuffer(NULL), decoder(this),
serverClipboard(NULL), hasLocalClipboard(false)
{
}
@@ -54,6 +56,7 @@ CConnection::~CConnection()
reader_ = 0;
delete writer_;
writer_ = 0;
strFree(serverClipboard);
}
void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
@@ -342,6 +345,79 @@ void CConnection::dataRect(const Rect& r, int encoding)
decoder.decodeRect(r, encoding, framebuffer);
}
void CConnection::serverCutText(const char* str)
{
hasLocalClipboard = false;
strFree(serverClipboard);
serverClipboard = NULL;
serverClipboard = latin1ToUTF8(str);
handleClipboardAnnounce(true);
}
void CConnection::handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths)
{
rdr::U32 sizes[] = { 0 };
CMsgHandler::handleClipboardCaps(flags, lengths);
writer()->writeClipboardCaps(rfb::clipboardUTF8 |
rfb::clipboardRequest |
rfb::clipboardPeek |
rfb::clipboardNotify |
rfb::clipboardProvide,
sizes);
}
void CConnection::handleClipboardRequest(rdr::U32 flags)
{
if (!(flags & rfb::clipboardUTF8))
return;
if (!hasLocalClipboard)
return;
handleClipboardRequest();
}
void CConnection::handleClipboardPeek(rdr::U32 flags)
{
if (!hasLocalClipboard)
return;
if (cp.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(rfb::clipboardUTF8);
}
void CConnection::handleClipboardNotify(rdr::U32 flags)
{
strFree(serverClipboard);
serverClipboard = NULL;
if (flags & rfb::clipboardUTF8) {
hasLocalClipboard = false;
handleClipboardAnnounce(true);
} else {
handleClipboardAnnounce(false);
}
}
void CConnection::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
if (!(flags & rfb::clipboardUTF8))
return;
strFree(serverClipboard);
serverClipboard = NULL;
serverClipboard = convertLF((const char*)data[0], lengths[0]);
// FIXME: Should probably verify that this data was actually requested
handleClipboardData(serverClipboard);
}
void CConnection::authSuccess()
{
}
@@ -364,3 +440,53 @@ void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
writer()->writeFence(flags, len, data);
}
void CConnection::handleClipboardRequest()
{
}
void CConnection::handleClipboardAnnounce(bool available)
{
}
void CConnection::handleClipboardData(const char* data)
{
}
void CConnection::requestClipboard()
{
if (serverClipboard != NULL) {
handleClipboardData(serverClipboard);
return;
}
if (cp.clipboardFlags() & rfb::clipboardRequest)
writer()->writeClipboardRequest(rfb::clipboardUTF8);
}
void CConnection::announceClipboard(bool available)
{
hasLocalClipboard = available;
if (cp.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
else {
if (available)
handleClipboardRequest();
}
}
void CConnection::sendClipboardData(const char* data)
{
if (cp.clipboardFlags() & rfb::clipboardProvide) {
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));
writer()->writeClientCutText(latin1.buf, strlen(latin1.buf));
}
}

View File

@@ -107,6 +107,17 @@ namespace rfb {
virtual void framebufferUpdateEnd();
virtual void dataRect(const Rect& r, int encoding);
virtual void serverCutText(const char* str);
virtual void handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);
// Methods to be overridden in a derived class
@@ -121,9 +132,43 @@ namespace rfb {
// derived class must call on to CConnection::serverInit().
virtual void serverInit();
// handleClipboardRequest() is called whenever the server requests
// the client to send over its clipboard data. It will only be
// called after the client has first announced a clipboard change
// via announceClipboard().
virtual void handleClipboardRequest();
// handleClipboardAnnounce() is called to indicate a change in the
// clipboard on the server. Call requestClipboard() to access the
// actual data.
virtual void handleClipboardAnnounce(bool available);
// handleClipboardData() is called when the server has sent over
// the clipboard data as a result of a previous call to
// requestClipboard(). Note that this function might never be
// called if the clipboard data was no longer available when the
// server received the request.
virtual void handleClipboardData(const char* data);
// Other methods
// requestClipboard() will result in a request to the server to
// transfer its clipboard data. A call to handleClipboardData()
// will be made once the data is available.
virtual void requestClipboard();
// announceClipboard() informs the server of changes to the
// clipboard on the client. The server may later request the
// clipboard data via handleClipboardRequest().
virtual void announceClipboard(bool available);
// sendClipboardData() transfers the clipboard data to the server
// and should be called whenever the server has requested the
// clipboard via handleClipboardRequest().
virtual void sendClipboardData(const char* data);
CMsgReader* reader() { return reader_; }
CMsgWriter* writer() { return writer_; }
@@ -190,6 +235,9 @@ namespace rfb {
ModifiablePixelBuffer* framebuffer;
DecodeManager decoder;
char* serverClipboard;
bool hasLocalClipboard;
};
}
#endif

View File

@@ -92,3 +92,26 @@ void CMsgHandler::setLEDState(unsigned int state)
{
cp.setLEDState(state);
}
void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
cp.setClipboardCaps(flags, lengths);
}
void CMsgHandler::handleClipboardRequest(rdr::U32 flags)
{
}
void CMsgHandler::handleClipboardPeek(rdr::U32 flags)
{
}
void CMsgHandler::handleClipboardNotify(rdr::U32 flags)
{
}
void CMsgHandler::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
}

View File

@@ -72,6 +72,15 @@ namespace rfb {
virtual void setLEDState(unsigned int state);
virtual void handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);
ConnParams cp;
};
}

View File

@@ -18,10 +18,14 @@
*/
#include <stdio.h>
#include <rdr/OutStream.h>
#include <rdr/MemOutStream.h>
#include <rdr/ZlibOutStream.h>
#include <rfb/msgTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/encodings.h>
#include <rfb/qemuTypes.h>
#include <rfb/clipboardTypes.h>
#include <rfb/Exception.h>
#include <rfb/PixelFormat.h>
#include <rfb/Rect.h>
@@ -57,7 +61,7 @@ void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
{
startMsg(msgTypeSetEncodings);
os->skip(1);
os->pad(1);
os->writeU16(nEncodings);
for (int i = 0; i < nEncodings; i++)
os->writeU32(encodings[i]);
@@ -265,6 +269,104 @@ void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len)
endMsg();
}
void CMsgWriter::writeClipboardCaps(rdr::U32 caps,
const rdr::U32* lengths)
{
size_t i, count;
if (!(cp->clipboardFlags() & clipboardCaps))
throw Exception("Server does not support clipboard \"caps\" action");
count = 0;
for (i = 0;i < 16;i++) {
if (caps & (1 << i))
count++;
}
startMsg(msgTypeClientCutText);
os->pad(3);
os->writeS32(-(4 + 4 * count));
os->writeU32(caps | clipboardCaps);
count = 0;
for (i = 0;i < 16;i++) {
if (caps & (1 << i))
os->writeU32(lengths[count++]);
}
endMsg();
}
void CMsgWriter::writeClipboardRequest(rdr::U32 flags)
{
if (!(cp->clipboardFlags() & clipboardRequest))
throw Exception("Server does not support clipboard \"request\" action");
startMsg(msgTypeClientCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardRequest);
endMsg();
}
void CMsgWriter::writeClipboardPeek(rdr::U32 flags)
{
if (!(cp->clipboardFlags() & clipboardPeek))
throw Exception("Server does not support clipboard \"peek\" action");
startMsg(msgTypeClientCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardPeek);
endMsg();
}
void CMsgWriter::writeClipboardNotify(rdr::U32 flags)
{
if (!(cp->clipboardFlags() & clipboardNotify))
throw Exception("Server does not support clipboard \"notify\" action");
startMsg(msgTypeClientCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardNotify);
endMsg();
}
void CMsgWriter::writeClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
rdr::MemOutStream mos;
rdr::ZlibOutStream zos;
int i, count;
if (!(cp->clipboardFlags() & clipboardProvide))
throw Exception("Server does not support clipboard \"provide\" action");
zos.setUnderlying(&mos);
count = 0;
for (i = 0;i < 16;i++) {
if (!(flags & (1 << i)))
continue;
zos.writeU32(lengths[count]);
zos.writeBytes(data[count], lengths[count]);
count++;
}
zos.flush();
startMsg(msgTypeClientCutText);
os->pad(3);
os->writeS32(-(4 + mos.length()));
os->writeU32(flags | clipboardProvide);
os->writeBytes(mos.data(), mos.length());
endMsg();
}
void CMsgWriter::startMsg(int type)
{
os->writeU8(type);

View File

@@ -56,6 +56,13 @@ namespace rfb {
void writePointerEvent(const Point& pos, int buttonMask);
void writeClientCutText(const char* str, rdr::U32 len);
void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths);
void writeClipboardRequest(rdr::U32 flags);
void writeClipboardPeek(rdr::U32 flags);
void writeClipboardNotify(rdr::U32 flags);
void writeClipboardProvide(rdr::U32 flags, const size_t* lengths,
const rdr::U8* const* data);
protected:
void startMsg(int type);
void endMsg();

View File

@@ -24,6 +24,7 @@
#include <rfb/Exception.h>
#include <rfb/encodings.h>
#include <rfb/ledStates.h>
#include <rfb/clipboardTypes.h>
#include <rfb/ConnParams.h>
#include <rfb/ServerCore.h>
#include <rfb/SMsgHandler.h>
@@ -36,19 +37,25 @@ ConnParams::ConnParams()
width(0), height(0), useCopyRect(false),
supportsLocalCursor(false), supportsLocalXCursor(false),
supportsLocalCursorWithAlpha(false),
supportsCursorPosition(false),
supportsDesktopResize(false), supportsExtendedDesktopSize(false),
supportsDesktopRename(false), supportsLastRect(false),
supportsLEDState(false), supportsQEMUKeyEvent(false),
supportsWEBP(false),
supportsSetDesktopSize(false), supportsFence(false),
supportsContinuousUpdates(false),
supportsContinuousUpdates(false), supportsExtendedClipboard(false),
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
subsampling(subsampleUndefined), name_(0), verStrPos(0),
subsampling(subsampleUndefined), name_(0), cursorPos_(0, 0), verStrPos(0),
ledState_(ledUnknown), shandler(NULL)
{
memset(kasmPassed, 0, KASM_NUM_SETTINGS);
setName("");
cursor_ = new Cursor(0, 0, Point(), NULL);
clipFlags = clipboardUTF8 | clipboardRTF | clipboardHTML |
clipboardRequest | clipboardNotify | clipboardProvide;
memset(clipSizes, 0, sizeof(clipSizes));
clipSizes[0] = 20 * 1024 * 1024;
}
ConnParams::~ConnParams()
@@ -101,6 +108,11 @@ void ConnParams::setCursor(const Cursor& other)
cursor_ = new Cursor(other);
}
void ConnParams::setCursorPos(const Point& pos)
{
cursorPos_ = pos;
}
bool ConnParams::supportsEncoding(rdr::S32 encoding) const
{
return encodings_.count(encoding) != 0;
@@ -147,6 +159,9 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
case pseudoEncodingExtendedDesktopSize:
supportsExtendedDesktopSize = true;
break;
case pseudoEncodingVMwareCursorPosition:
supportsCursorPosition = true;
break;
case pseudoEncodingDesktopName:
supportsDesktopRename = true;
break;
@@ -168,6 +183,9 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
case pseudoEncodingContinuousUpdates:
supportsContinuousUpdates = true;
break;
case pseudoEncodingExtendedClipboard:
supportsExtendedClipboard = true;
break;
case pseudoEncodingSubsamp1X:
subsampling = subsampleNone;
break;
@@ -259,3 +277,17 @@ void ConnParams::setLEDState(unsigned int state)
{
ledState_ = state;
}
void ConnParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
int i, num;
clipFlags = flags;
num = 0;
for (i = 0;i < 16;i++) {
if (!(flags & (1 << i)))
continue;
clipSizes[i] = lengths[num++];
}
}

View File

@@ -84,6 +84,9 @@ namespace rfb {
const Cursor& cursor() const { return *cursor_; }
void setCursor(const Cursor& cursor);
const Point& cursorPos() const { return cursorPos_; }
void setCursorPos(const Point& pos);
bool supportsEncoding(rdr::S32 encoding) const;
void setEncodings(int nEncodings, const rdr::S32* encodings);
@@ -91,11 +94,15 @@ namespace rfb {
unsigned int ledState() { return ledState_; }
void setLEDState(unsigned int state);
rdr::U32 clipboardFlags() const { return clipFlags; }
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);
bool useCopyRect;
bool supportsLocalCursor;
bool supportsLocalXCursor;
bool supportsLocalCursorWithAlpha;
bool supportsCursorPosition;
bool supportsDesktopResize;
bool supportsExtendedDesktopSize;
bool supportsDesktopRename;
@@ -107,6 +114,7 @@ namespace rfb {
bool supportsSetDesktopSize;
bool supportsFence;
bool supportsContinuousUpdates;
bool supportsExtendedClipboard;
int compressLevel;
int qualityLevel;
@@ -136,11 +144,14 @@ namespace rfb {
PixelFormat pf_;
char* name_;
Cursor* cursor_;
Point cursorPos_;
std::set<rdr::S32> encodings_;
char verStr[13];
int verStrPos;
unsigned int ledState_;
SMsgHandler *shandler;
rdr::U32 clipFlags;
rdr::U32 clipSizes[16];
};
}
#endif

View File

@@ -36,6 +36,7 @@ namespace rfb {
rdr::U32 __unused_attr keycode,
bool __unused_attr down) { }
virtual void pointerEvent(const Point& __unused_attr pos,
const Point& __unused_attr abspos,
int __unused_attr buttonMask,
const bool __unused_attr skipClick,
const bool __unused_attr skipRelease) { }

View File

@@ -85,7 +85,7 @@ JpegInitDestination(j_compress_ptr cinfo)
jc->clear();
dest->pub.next_output_byte = jc->getptr();
dest->pub.free_in_buffer = jc->getend() - jc->getptr();
dest->pub.free_in_buffer = jc->avail();
}
static boolean
@@ -95,9 +95,9 @@ JpegEmptyOutputBuffer(j_compress_ptr cinfo)
JpegCompressor *jc = dest->instance;
jc->setptr(jc->getend());
jc->overrun(jc->getend() - jc->getstart(), 1);
jc->check(jc->length());
dest->pub.next_output_byte = jc->getptr();
dest->pub.free_in_buffer = jc->getend() - jc->getptr();
dest->pub.free_in_buffer = jc->avail();
return TRUE;
}

View File

@@ -47,12 +47,6 @@ namespace rfb {
void writeBytes(const void*, int);
inline rdr::U8* getstart() { return start; }
virtual inline size_t overrun(size_t itemSize, size_t nItems) {
return MemOutStream::overrun(itemSize, nItems);
}
private:
struct jpeg_compress_struct *cinfo;

View File

@@ -20,6 +20,7 @@
#include <string.h>
#include <rfb/Exception.h>
#include <rfb/Security.h>
#include <rfb/clipboardTypes.h>
#include <rfb/msgTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/SMsgReader.h>
@@ -52,7 +53,8 @@ SConnection::SConnection()
: readyForSetColourMapEntries(false),
is(0), os(0), reader_(0), writer_(0),
ssecurity(0), state_(RFBSTATE_UNINITIALISED),
preferredEncoding(encodingRaw)
preferredEncoding(encodingRaw),
clientClipboard(NULL), hasLocalClipboard(false)
{
defaultMajorVersion = 3;
defaultMinorVersion = 8;
@@ -69,6 +71,7 @@ SConnection::~SConnection()
reader_ = 0;
delete writer_;
writer_ = 0;
strFree(clientClipboard);
}
void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
@@ -281,6 +284,73 @@ void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings)
}
SMsgHandler::setEncodings(nEncodings, encodings);
if (cp.supportsExtendedClipboard) {
rdr::U32 sizes[] = { 0 };
writer()->writeClipboardCaps(rfb::clipboardUTF8 |
rfb::clipboardRequest |
rfb::clipboardPeek |
rfb::clipboardNotify |
rfb::clipboardProvide,
sizes);
}
}
void SConnection::clientCutText(const char* str, int len)
{
hasLocalClipboard = false;
strFree(clientClipboard);
clientClipboard = NULL;
clientClipboard = latin1ToUTF8(str);
handleClipboardAnnounce(true);
}
void SConnection::handleClipboardRequest(rdr::U32 flags)
{
if (!(flags & rfb::clipboardUTF8))
return;
if (!hasLocalClipboard)
return;
handleClipboardRequest();
}
void SConnection::handleClipboardPeek(rdr::U32 flags)
{
if (!hasLocalClipboard)
return;
if (cp.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(rfb::clipboardUTF8);
}
void SConnection::handleClipboardNotify(rdr::U32 flags)
{
strFree(clientClipboard);
clientClipboard = NULL;
if (flags & rfb::clipboardUTF8) {
handleClipboardAnnounce(true);
hasLocalClipboard = false;
} else {
handleClipboardAnnounce(false);
}
}
void SConnection::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
if (!(flags & rfb::clipboardUTF8))
return;
strFree(clientClipboard);
clientClipboard = NULL;
clientClipboard = convertLF((const char*)data[0], lengths[0]);
handleClipboardData(clientClipboard, strlen(clientClipboard));
}
void SConnection::supportsQEMUKeyEvent()
@@ -375,6 +445,58 @@ void SConnection::enableContinuousUpdates(bool enable,
{
}
void SConnection::handleClipboardRequest()
{
}
void SConnection::handleClipboardAnnounce(bool available)
{
}
void SConnection::handleClipboardData(const char* data, int len)
{
}
void SConnection::requestClipboard()
{
if (clientClipboard != NULL) {
handleClipboardData(clientClipboard, strlen(clientClipboard));
return;
}
if (cp.supportsExtendedClipboard &&
(cp.clipboardFlags() & rfb::clipboardRequest))
writer()->writeClipboardRequest(rfb::clipboardUTF8);
}
void SConnection::announceClipboard(bool available)
{
hasLocalClipboard = available;
if (cp.supportsExtendedClipboard &&
(cp.clipboardFlags() & rfb::clipboardNotify))
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
else {
if (available)
handleClipboardRequest();
}
}
void SConnection::sendClipboardData(const char* data, int len)
{
if (cp.supportsExtendedClipboard &&
(cp.clipboardFlags() & rfb::clipboardProvide)) {
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));
writer()->writeServerCutText(latin1.buf, strlen(latin1.buf));
}
}
void SConnection::writeFakeColourMap(void)
{
int i;

View File

@@ -73,6 +73,15 @@ namespace rfb {
virtual void setEncodings(int nEncodings, const rdr::S32* encodings);
virtual void clientCutText(const char* str, int len);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);
virtual void supportsQEMUKeyEvent();
// Methods to be overridden in a derived class
@@ -118,6 +127,25 @@ namespace rfb {
virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h);
// handleClipboardRequest() is called whenever the client requests
// the server to send over its clipboard data. It will only be
// called after the server has first announced a clipboard change
// via announceClipboard().
virtual void handleClipboardRequest();
// handleClipboardAnnounce() is called to indicate a change in the
// clipboard on the client. Call requestClipboard() to access the
// actual data.
virtual void handleClipboardAnnounce(bool available);
// handleClipboardData() is called when the client has sent over
// the clipboard data as a result of a previous call to
// requestClipboard(). Note that this function might never be
// called if the clipboard data was no longer available when the
// client received the request.
virtual void handleClipboardData(const char* data, int len);
virtual void add_changed_all() {}
// setAccessRights() allows a security package to limit the access rights
@@ -138,6 +166,22 @@ namespace rfb {
// Other methods
// requestClipboard() will result in a request to the client to
// transfer its clipboard data. A call to handleClipboardData()
// will be made once the data is available.
virtual void requestClipboard();
// announceClipboard() informs the client of changes to the
// clipboard on the server. The client may later request the
// clipboard data via handleClipboardRequest().
virtual void announceClipboard(bool available);
// sendClipboardData() transfers the clipboard data to the client
// and should be called whenever the client has requested the
// clipboard via handleClipboardRequest().
virtual void sendClipboardData(const char* data, int len);
// authenticated() returns true if the client has authenticated
// successfully.
bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
@@ -203,6 +247,9 @@ namespace rfb {
SSecurity* ssecurity;
stateEnum state_;
rdr::S32 preferredEncoding;
char* clientClipboard;
bool hasLocalClipboard;
};
}
#endif

View File

@@ -77,6 +77,25 @@ namespace rfb {
// pointerEvent(), keyEvent() and clientCutText() are called in response to
// the relevant RFB protocol messages from clients.
// See InputHandler for method signatures.
// handleClipboardRequest() is called whenever a client requests
// the server to send over its clipboard data. It will only be
// called after the server has first announced a clipboard change
// via VNCServer::announceClipboard().
virtual void handleClipboardRequest() {}
// handleClipboardAnnounce() is called to indicate a change in the
// clipboard on a client. Call VNCServer::requestClipboard() to
// access the actual data.
virtual void handleClipboardAnnounce(bool __unused_attr available) {}
// handleClipboardData() is called when a client has sent over
// the clipboard data as a result of a previous call to
// VNCServer::requestClipboard(). Note that this function might
// never be called if the clipboard data was no longer available
// when the client received the request.
virtual void handleClipboardData(const char* __unused_attr data, int len __unused_attr) {}
protected:
virtual ~SDesktop() {}
};

View File

@@ -64,6 +64,29 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
supportsQEMUKeyEvent();
}
void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
cp.setClipboardCaps(flags, lengths);
}
void SMsgHandler::handleClipboardRequest(rdr::U32 flags)
{
}
void SMsgHandler::handleClipboardPeek(rdr::U32 flags)
{
}
void SMsgHandler::handleClipboardNotify(rdr::U32 flags)
{
}
void SMsgHandler::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
}
void SMsgHandler::supportsLocalCursor()
{
}

View File

@@ -54,6 +54,15 @@ namespace rfb {
virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h) = 0;
virtual void handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);
virtual void sendStats() = 0;
virtual bool canChangeKasmSettings() const = 0;

View File

@@ -18,8 +18,11 @@
*/
#include <stdio.h>
#include <rdr/InStream.h>
#include <rdr/ZlibInStream.h>
#include <rfb/msgTypes.h>
#include <rfb/qemuTypes.h>
#include <rfb/clipboardTypes.h>
#include <rfb/Exception.h>
#include <rfb/util.h>
#include <rfb/SMsgHandler.h>
@@ -217,18 +220,22 @@ void SMsgReader::readPointerEvent()
int mask = is->readU8();
int x = is->readU16();
int y = is->readU16();
handler->pointerEvent(Point(x, y), mask, false, false);
handler->pointerEvent(Point(x, y), Point(0, 0), mask, false, false);
}
void SMsgReader::readClientCutText()
{
is->skip(3);
int len = is->readU32();
if (len < 0) {
throw Exception("Cut text too long.");
rdr::U32 len = is->readU32();
if (len & 0x80000000) {
rdr::S32 slen = len;
slen = -slen;
readExtendedClipboard(slen);
return;
}
if (len > maxCutText) {
if (len > (size_t)maxCutText) {
is->skip(len);
vlog.error("Cut text too long (%d bytes) - ignoring", len);
return;
@@ -239,6 +246,100 @@ void SMsgReader::readClientCutText()
handler->clientCutText(ca.buf, len);
}
void SMsgReader::readExtendedClipboard(rdr::S32 len)
{
rdr::U32 flags;
rdr::U32 action;
if (len < 4)
throw Exception("Invalid extended clipboard message");
if (len > maxCutText) {
vlog.error("Extended clipboard message too long (%d bytes) - ignoring", len);
is->skip(len);
return;
}
flags = is->readU32();
action = flags & clipboardActionMask;
if (action & clipboardCaps) {
int i;
size_t num;
rdr::U32 lengths[16];
num = 0;
for (i = 0;i < 16;i++) {
if (flags & (1 << i))
num++;
}
if (len < (rdr::S32)(4 + 4*num))
throw Exception("Invalid extended clipboard message");
num = 0;
for (i = 0;i < 16;i++) {
if (flags & (1 << i))
lengths[num++] = is->readU32();
}
handler->handleClipboardCaps(flags, lengths);
} else if (action == clipboardProvide) {
rdr::ZlibInStream zis;
int i;
size_t num;
size_t lengths[16];
rdr::U8* buffers[16];
zis.setUnderlying(is, len - 4);
num = 0;
for (i = 0;i < 16;i++) {
if (!(flags & 1 << i))
continue;
lengths[num] = zis.readU32();
if (lengths[num] > (size_t)maxCutText) {
vlog.error("Extended clipboard data too long (%d bytes) - ignoring",
(unsigned)lengths[num]);
zis.skip(lengths[num]);
flags &= ~(1 << i);
continue;
}
buffers[num] = new rdr::U8[lengths[num]];
zis.readBytes(buffers[num], lengths[num]);
num++;
}
zis.flushUnderlying();
zis.setUnderlying(NULL, 0);
handler->handleClipboardProvide(flags, lengths, buffers);
num = 0;
for (i = 0;i < 16;i++) {
if (!(flags & 1 << i))
continue;
delete [] buffers[num++];
}
} else {
switch (action) {
case clipboardRequest:
handler->handleClipboardRequest(flags);
break;
case clipboardPeek:
handler->handleClipboardPeek(flags);
break;
case clipboardNotify:
handler->handleClipboardNotify(flags);
break;
default:
throw Exception("Invalid extended clipboard action");
}
}
}
void SMsgReader::readRequestStats()
{
is->skip(3);

View File

@@ -55,6 +55,7 @@ namespace rfb {
void readKeyEvent();
void readPointerEvent();
void readClientCutText();
void readExtendedClipboard(rdr::S32 len);
void readRequestStats();
void readQEMUMessage();

View File

@@ -19,8 +19,12 @@
*/
#include <stdio.h>
#include <rdr/OutStream.h>
#include <rdr/MemOutStream.h>
#include <rdr/ZlibOutStream.h>
#include <rfb/msgTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/clipboardTypes.h>
#include <rfb/Exception.h>
#include <rfb/ConnParams.h>
#include <rfb/UpdateTracker.h>
@@ -39,6 +43,7 @@ SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
needSetDesktopSize(false), needExtendedDesktopSize(false),
needSetDesktopName(false), needSetCursor(false),
needSetXCursor(false), needSetCursorWithAlpha(false),
needCursorPos(false),
needLEDState(false), needQEMUKeyEvent(false)
{
}
@@ -88,6 +93,112 @@ void SMsgWriter::writeServerCutText(const char* str, int len)
endMsg();
}
void SMsgWriter::writeClipboardCaps(rdr::U32 caps,
const rdr::U32* lengths)
{
size_t i, count;
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
count = 0;
for (i = 0;i < 16;i++) {
if (caps & (1 << i))
count++;
}
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-(4 + 4 * count));
os->writeU32(caps | clipboardCaps);
count = 0;
for (i = 0;i < 16;i++) {
if (caps & (1 << i))
os->writeU32(lengths[count++]);
}
endMsg();
}
void SMsgWriter::writeClipboardRequest(rdr::U32 flags)
{
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardRequest))
throw Exception("Client does not support clipboard \"request\" action");
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardRequest);
endMsg();
}
void SMsgWriter::writeClipboardPeek(rdr::U32 flags)
{
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardPeek))
throw Exception("Client does not support clipboard \"peek\" action");
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardPeek);
endMsg();
}
void SMsgWriter::writeClipboardNotify(rdr::U32 flags)
{
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardNotify))
throw Exception("Client does not support clipboard \"notify\" action");
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-4);
os->writeU32(flags | clipboardNotify);
endMsg();
}
void SMsgWriter::writeClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
rdr::MemOutStream mos;
rdr::ZlibOutStream zos;
int i, count;
if (!cp->supportsExtendedClipboard)
throw Exception("Client does not support extended clipboard");
if (!(cp->clipboardFlags() & clipboardProvide))
throw Exception("Client does not support clipboard \"provide\" action");
zos.setUnderlying(&mos);
count = 0;
for (i = 0;i < 16;i++) {
if (!(flags & (1 << i)))
continue;
zos.writeU32(lengths[count]);
zos.writeBytes(data[count], lengths[count]);
count++;
}
zos.flush();
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeS32(-(4 + mos.length()));
os->writeU32(flags | clipboardProvide);
os->writeBytes(mos.data(), mos.length());
endMsg();
}
void SMsgWriter::writeStats(const char* str, int len)
{
startMsg(msgTypeStats);
@@ -204,6 +315,14 @@ bool SMsgWriter::writeSetCursorWithAlpha()
return true;
}
void SMsgWriter::writeCursorPos()
{
if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition))
throw Exception("Client does not support cursor position");
needCursorPos = true;
}
bool SMsgWriter::writeLEDState()
{
if (!cp->supportsLEDState)
@@ -232,6 +351,8 @@ bool SMsgWriter::needFakeUpdate()
return true;
if (needSetCursor || needSetXCursor || needSetCursorWithAlpha)
return true;
if (needCursorPos)
return true;
if (needLEDState)
return true;
if (needQEMUKeyEvent)
@@ -284,6 +405,8 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
nRects++;
if (needSetCursorWithAlpha)
nRects++;
if (needCursorPos)
nRects++;
if (needLEDState)
nRects++;
if (needQEMUKeyEvent)
@@ -399,6 +522,18 @@ void SMsgWriter::writePseudoRects()
needSetCursorWithAlpha = false;
}
if (needCursorPos) {
const Point& cursorPos = cp->cursorPos();
if (cp->supportsEncoding(pseudoEncodingVMwareCursorPosition)) {
writeSetVMwareCursorPositionRect(cursorPos.x, cursorPos.y);
} else {
throw Exception("Client does not support cursor position");
}
needCursorPos = false;
}
if (needSetDesktopName) {
writeSetDesktopNameRect(cp->name());
needSetDesktopName = false;
@@ -577,6 +712,20 @@ void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height,
}
}
void SMsgWriter::writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY)
{
if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition))
throw Exception("Client does not support cursor position");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeSetVMwareCursorRect: nRects out of sync");
os->writeS16(hotspotX);
os->writeS16(hotspotY);
os->writeU16(0);
os->writeU16(0);
os->writeU32(pseudoEncodingVMwareCursorPosition);
}
void SMsgWriter::writeLEDStateRect(rdr::U8 state)
{
if (!cp->supportsLEDState)

View File

@@ -55,6 +55,14 @@ namespace rfb {
// writeBell() and writeServerCutText() do the obvious thing.
void writeBell();
void writeServerCutText(const char* str, int len);
void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths);
void writeClipboardRequest(rdr::U32 flags);
void writeClipboardPeek(rdr::U32 flags);
void writeClipboardNotify(rdr::U32 flags);
void writeClipboardProvide(rdr::U32 flags, const size_t* lengths,
const rdr::U8* const* data);
void writeStats(const char* str, int len);
// writeFence() sends a new fence request or response to the client.
@@ -83,6 +91,9 @@ namespace rfb {
bool writeSetXCursor();
bool writeSetCursorWithAlpha();
// Notifies the client that the cursor pointer was moved by the server.
void writeCursorPos();
// Same for LED state message
bool writeLEDState();
@@ -138,6 +149,7 @@ namespace rfb {
void writeSetCursorWithAlphaRect(int width, int height,
int hotspotX, int hotspotY,
const rdr::U8* data);
void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY);
void writeLEDStateRect(rdr::U8 state);
void writeQEMUKeyEventRect();
@@ -153,6 +165,7 @@ namespace rfb {
bool needSetCursor;
bool needSetXCursor;
bool needSetCursorWithAlpha;
bool needCursorPos;
bool needLEDState;
bool needQEMUKeyEvent;

View File

@@ -35,6 +35,8 @@ namespace rfb {
dispatch elapsed Timer callbacks and to determine how long to wait in select() for
the next timeout to occur.
For classes that can be derived it's best to use MethodTimer which can call a specific
method on the class, thus avoiding conflicts when subclassing.
*/
struct Timer {
@@ -101,6 +103,19 @@ namespace rfb {
static std::list<Timer*> pending;
};
template<class T> class MethodTimer
: public Timer, public Timer::Callback {
public:
MethodTimer(T* obj_, bool (T::*cb_)(Timer*))
: Timer(this), obj(obj_), cb(cb_) {}
virtual bool handleTimeout(Timer* t) { return (obj->*cb)(t); }
private:
T* obj;
bool (T::*cb)(Timer*);
};
};
#endif

View File

@@ -155,6 +155,17 @@ void VNCSConnectionST::close(const char* reason)
server->lastDisconnectTime = time(0);
}
try {
if (sock->outStream().bufferUsage() > 0) {
sock->cork(false);
sock->outStream().flush();
if (sock->outStream().bufferUsage() > 0)
vlog.error("Failed to flush remaining socket data on close");
}
} catch (rdr::Exception& e) {
vlog.error("Failed to flush remaining socket data on close: %s", e.str());
}
// Just shutdown the socket and mark our state as closing. Eventually the
// calling code will call VNCServerST's removeSocket() method causing us to
// be deleted.
@@ -392,7 +403,31 @@ static void keylog(unsigned keysym, const char *client) {
flushKeylog(client);
}
void VNCSConnectionST::serverCutTextOrClose(const char *str, int len)
void VNCSConnectionST::requestClipboardOrClose()
{
try {
if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::acceptCutText) return;
if (state() != RFBSTATE_NORMAL) return;
requestClipboard();
} catch(rdr::Exception& e) {
close(e.str());
}
}
void VNCSConnectionST::announceClipboardOrClose(bool available)
{
try {
if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::sendCutText) return;
if (state() != RFBSTATE_NORMAL) return;
announceClipboard(available);
} catch(rdr::Exception& e) {
close(e.str());
}
}
void VNCSConnectionST::sendClipboardDataOrClose(const char* data)
{
try {
if (!(accessRights & AccessCutText)) return;
@@ -402,19 +437,19 @@ void VNCSConnectionST::serverCutTextOrClose(const char *str, int len)
sock->getPeerAddress());
return;
}
int len = strlen(data);
const int origlen = len;
if (rfb::Server::DLP_ClipSendMax && len > rfb::Server::DLP_ClipSendMax)
len = rfb::Server::DLP_ClipSendMax;
cliplog(str, len, origlen, "sent", sock->getPeerAddress());
if (state() == RFBSTATE_NORMAL)
writer()->writeServerCutText(str, len);
cliplog(data, len, origlen, "sent", sock->getPeerAddress());
if (state() != RFBSTATE_NORMAL) return;
sendClipboardData(data, len);
gettimeofday(&lastClipboardOp, NULL);
} catch(rdr::Exception& e) {
close(e.str());
}
}
void VNCSConnectionST::setDesktopNameOrClose(const char *name)
{
try {
@@ -506,6 +541,15 @@ void VNCSConnectionST::renderedCursorChange()
}
}
// cursorPositionChange() is called whenever the cursor has changed position by
// the server. If the client supports being informed about these changes then
// it will arrange for the new cursor position to be sent to the client.
void VNCSConnectionST::cursorPositionChange()
{
setCursorPos();
}
// needRenderedCursor() returns true if this client needs the server-side
// rendered cursor. This may be because it does not support local cursor or
// because the current cursor position has not been set by this client.
@@ -637,14 +681,52 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf)
setCursor();
}
void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease)
void VNCSConnectionST::pointerEvent(const Point& pos, const Point& abspos, int buttonMask, const bool skipClick, const bool skipRelease)
{
pointerEventTime = lastEventTime = time(0);
server->lastUserInputTime = lastEventTime;
if (!(accessRights & AccessPtrEvents)) return;
if (!rfb::Server::acceptPointerEvents) return;
if (!server->pointerClient || server->pointerClient == this) {
pointerEventPos = pos;
Point newpos = pos;
if (pos.x & 0x4000) {
newpos.x &= ~0x4000;
newpos.y &= ~0x4000;
if (newpos.x & 0x8000) {
newpos.x &= ~0x8000;
newpos.x = -newpos.x;
}
if (newpos.y & 0x8000) {
newpos.y &= ~0x8000;
newpos.y = -newpos.y;
}
if (newpos.x < 0) {
if (pointerEventPos.x + newpos.x >= 0)
pointerEventPos.x += newpos.x;
else
pointerEventPos.x = 0;
} else {
pointerEventPos.x += newpos.x;
if (pointerEventPos.x >= cp.width)
pointerEventPos.x = cp.width;
}
if (newpos.y < 0) {
if (pointerEventPos.y + newpos.y >= 0)
pointerEventPos.y += newpos.y;
else
pointerEventPos.y = 0;
} else {
pointerEventPos.y += newpos.y;
if (pointerEventPos.y >= cp.height)
pointerEventPos.y = cp.height;
}
} else {
pointerEventPos = pos;
}
if (buttonMask)
server->pointerClient = this;
else
@@ -665,7 +747,7 @@ void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask, const bool
}
}
server->desktop->pointerEvent(pointerEventPos, buttonMask, skipclick, skiprelease);
server->desktop->pointerEvent(newpos, pointerEventPos, buttonMask, skipclick, skiprelease);
}
}
@@ -826,24 +908,6 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
server->desktop->keyEvent(keysym, keycode, down);
}
void VNCSConnectionST::clientCutText(const char* str, int len)
{
if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::acceptCutText) return;
if (msSince(&lastClipboardOp) < (unsigned) rfb::Server::DLP_ClipDelay) {
vlog.info("DLP: client %s: refused to receive clipboard, too soon",
sock->getPeerAddress());
return;
}
const int origlen = len;
if (rfb::Server::DLP_ClipAcceptMax && len > rfb::Server::DLP_ClipAcceptMax)
len = rfb::Server::DLP_ClipAcceptMax;
cliplog(str, len, origlen, "received", sock->getPeerAddress());
gettimeofday(&lastClipboardOp, NULL);
server->desktop->clientCutText(str, len);
}
void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
{
Rect safeRect;
@@ -863,7 +927,7 @@ void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
// Just update the requested region.
// Framebuffer update will be sent a bit later, see processMessages().
Region reqRgn(r);
Region reqRgn(safeRect);
if (!incremental || !continuousUpdates)
requested.assign_union(reqRgn);
@@ -977,6 +1041,38 @@ void VNCSConnectionST::enableContinuousUpdates(bool enable,
}
}
void VNCSConnectionST::handleClipboardRequest()
{
if (!(accessRights & AccessCutText)) return;
server->handleClipboardRequest(this);
}
void VNCSConnectionST::handleClipboardAnnounce(bool available)
{
if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::acceptCutText) return;
server->handleClipboardAnnounce(this, available);
}
void VNCSConnectionST::handleClipboardData(const char* data, int len)
{
if (!(accessRights & AccessCutText)) return;
if (!rfb::Server::acceptCutText) return;
if (msSince(&lastClipboardOp) < (unsigned) rfb::Server::DLP_ClipDelay) {
vlog.info("DLP: client %s: refused to receive clipboard, too soon",
sock->getPeerAddress());
return;
}
const int origlen = len;
if (rfb::Server::DLP_ClipAcceptMax && len > rfb::Server::DLP_ClipAcceptMax)
len = rfb::Server::DLP_ClipAcceptMax;
cliplog(data, len, origlen, "received", sock->getPeerAddress());
gettimeofday(&lastClipboardOp, NULL);
server->handleClipboardData(this, data, len);
}
// supportsLocalCursor() is called whenever the status of
// cp.supportsLocalCursor has changed. If the client does now support local
// cursor, we make sure that the old server-side rendered cursor is cleaned up
@@ -1471,6 +1567,21 @@ void VNCSConnectionST::setCursor()
}
}
// setCursorPos() is called whenever the cursor has changed position by the
// server. If the client supports being informed about these changes then it
// will arrange for the new cursor position to be sent to the client.
void VNCSConnectionST::setCursorPos()
{
if (state() != RFBSTATE_NORMAL)
return;
if (cp.supportsCursorPosition) {
cp.setCursorPos(server->cursorPos);
writer()->writeCursorPos();
}
}
void VNCSConnectionST::setDesktopName(const char *name)
{
cp.setName(name);

View File

@@ -75,9 +75,11 @@ namespace rfb {
void screenLayoutChangeOrClose(rdr::U16 reason);
void setCursorOrClose();
void bellOrClose();
void serverCutTextOrClose(const char *str, int len);
void setDesktopNameOrClose(const char *name);
void setLEDStateOrClose(unsigned int state);
void requestClipboardOrClose();
void announceClipboardOrClose(bool available);
void sendClipboardDataOrClose(const char* data);
// checkIdleTimeout() returns the number of milliseconds left until the
// idle timeout expires. If it has expired, the connection is closed and
@@ -97,6 +99,11 @@ namespace rfb {
// cursor.
void renderedCursorChange();
// cursorPositionChange() is called whenever the cursor has changed position by
// the server. If the client supports being informed about these changes then
// it will arrange for the new cursor position to be sent to the client.
void cursorPositionChange();
// needRenderedCursor() returns true if this client needs the server-side
// rendered cursor. This may be because it does not support local cursor
// or because the current cursor position has not been set by this client.
@@ -168,15 +175,17 @@ namespace rfb {
virtual void queryConnection(const char* userName);
virtual void clientInit(bool shared);
virtual void setPixelFormat(const PixelFormat& pf);
virtual void pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease);
virtual void pointerEvent(const Point& pos, const Point& abspos, int buttonMask, const bool skipClick, const bool skipRelease);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
virtual void clientCutText(const char* str, int len);
virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
virtual void setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout);
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h);
virtual void handleClipboardRequest();
virtual void handleClipboardAnnounce(bool available);
virtual void handleClipboardData(const char* data, int len);
virtual void supportsLocalCursor();
virtual void supportsFence();
virtual void supportsContinuousUpdates();
@@ -223,6 +232,7 @@ namespace rfb {
void screenLayoutChange(rdr::U16 reason);
void setCursor();
void setCursorPos();
void setDesktopName(const char *name);
void setLEDState(unsigned int state);
void setSocketTimeouts();

View File

@@ -52,9 +52,21 @@ namespace rfb {
// getPixelBuffer() returns a pointer to the PixelBuffer object.
virtual PixelBuffer* getPixelBuffer() const = 0;
// serverCutText() tells the server that the cut text has changed. This
// will normally be sent to all clients.
virtual void serverCutText(const char* str, int len) = 0;
// requestClipboard() will result in a request to a client to
// transfer its clipboard data. A call to
// SDesktop::handleClipboardData() will be made once the data is
// available.
virtual void requestClipboard() = 0;
// announceClipboard() informs all clients of changes to the
// clipboard on the server. A client may later request the
// clipboard data via SDesktop::handleClipboardRequest().
virtual void announceClipboard(bool available) = 0;
// sendClipboardData() transfers the clipboard data to a client
// and should be called whenever a client has requested the
// clipboard via SDesktop::handleClipboardRequest().
virtual void sendClipboardData(const char* data) = 0;
// bell() tells the server that it should make all clients make a bell sound.
virtual void bell() = 0;
@@ -69,8 +81,10 @@ namespace rfb {
virtual void setCursor(int width, int height, const Point& hotspot,
const rdr::U8* cursorData) = 0;
// setCursorPos() tells the server the current position of the cursor.
virtual void setCursorPos(const Point& p) = 0;
// setCursorPos() tells the server the current position of the cursor, and
// whether the server initiated that change (e.g. through another X11
// client calling XWarpPointer()).
virtual void setCursorPos(const Point& p, bool warped) = 0;
// setName() tells the server what desktop title to supply to clients
virtual void setName(const char* name) = 0;

View File

@@ -123,8 +123,8 @@ static void parseRegionPart(const bool percents, rdr::U16 &pcdest, int &dest,
VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
: blHosts(&blacklist), desktop(desktop_), desktopStarted(false),
blockCounter(0), pb(0), blackedpb(0), ledState(ledUnknown),
name(strDup(name_)), pointerClient(0), comparer(0),
cursor(new Cursor(0, 0, Point(), NULL)),
name(strDup(name_)), pointerClient(0), clipboardClient(0),
comparer(0), cursor(new Cursor(0, 0, Point(), NULL)),
renderedCursorInvalid(false),
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
lastConnectionTime(0), disableclients(false),
@@ -502,6 +502,45 @@ void VNCServerST::setScreenLayout(const ScreenSet& layout)
}
}
void VNCServerST::requestClipboard()
{
if (clipboardClient == NULL)
return;
clipboardClient->requestClipboard();
}
void VNCServerST::announceClipboard(bool available)
{
std::list<VNCSConnectionST*>::iterator ci, ci_next;
if (available)
clipboardClient = NULL;
clipboardRequestors.clear();
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
ci_next = ci; ci_next++;
(*ci)->announceClipboard(available);
}
}
void VNCServerST::sendClipboardData(const char* data)
{
std::list<VNCSConnectionST*>::iterator ci, ci_next;
if (strchr(data, '\r') != NULL)
throw Exception("Invalid carriage return in clipboard data");
for (ci = clipboardRequestors.begin();
ci != clipboardRequestors.end(); ci = ci_next) {
ci_next = ci; ci_next++;
(*ci)->sendClipboardDataOrClose(data);
}
clipboardRequestors.clear();
}
void VNCServerST::bell()
{
std::list<VNCSConnectionST*>::iterator ci, ci_next;
@@ -511,15 +550,6 @@ void VNCServerST::bell()
}
}
void VNCServerST::serverCutText(const char* str, int len)
{
std::list<VNCSConnectionST*>::iterator ci, ci_next;
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
ci_next = ci; ci_next++;
(*ci)->serverCutTextOrClose(str, len);
}
}
void VNCServerST::setName(const char* name_)
{
name.replaceBuf(strDup(name_));
@@ -565,14 +595,17 @@ void VNCServerST::setCursor(int width, int height, const Point& newHotspot,
}
}
void VNCServerST::setCursorPos(const Point& pos)
void VNCServerST::setCursorPos(const Point& pos, bool warped)
{
if (!cursorPos.equals(pos)) {
cursorPos = pos;
renderedCursorInvalid = true;
std::list<VNCSConnectionST*>::iterator ci;
for (ci = clients.begin(); ci != clients.end(); ci++)
for (ci = clients.begin(); ci != clients.end(); ci++) {
(*ci)->renderedCursorChange();
if (warped)
(*ci)->cursorPositionChange();
}
}
}
@@ -1049,3 +1082,32 @@ bool VNCServerST::getComparerState()
}
return false;
}
void VNCServerST::handleClipboardRequest(VNCSConnectionST* client)
{
clipboardRequestors.push_back(client);
if (clipboardRequestors.size() == 1)
desktop->handleClipboardRequest();
}
void VNCServerST::handleClipboardAnnounce(VNCSConnectionST* client,
bool available)
{
if (available)
clipboardClient = client;
else {
if (client != clipboardClient)
return;
clipboardClient = NULL;
}
desktop->handleClipboardAnnounce(available);
}
void VNCServerST::handleClipboardData(VNCSConnectionST* client,
const char* data, int len)
{
if (client != clipboardClient)
return;
desktop->handleClipboardData(data, len);
}

View File

@@ -96,12 +96,14 @@ namespace rfb {
virtual void setPixelBuffer(PixelBuffer* pb);
virtual void setScreenLayout(const ScreenSet& layout);
virtual PixelBuffer* getPixelBuffer() const { if (DLPRegion.enabled && blackedpb) return blackedpb; else return pb; }
virtual void serverCutText(const char* str, int len);
virtual void requestClipboard();
virtual void announceClipboard(bool available);
virtual void sendClipboardData(const char* data);
virtual void add_changed(const Region &region);
virtual void add_copied(const Region &dest, const Point &delta);
virtual void setCursor(int width, int height, const Point& hotspot,
const rdr::U8* data);
virtual void setCursorPos(const Point& p);
virtual void setCursorPos(const Point& p, bool warped);
virtual void setLEDState(unsigned state);
virtual void bell();
@@ -189,6 +191,10 @@ namespace rfb {
void setAPIMessager(network::GetAPIMessager *msgr) { apimessager = msgr; }
void handleClipboardRequest(VNCSConnectionST* client);
void handleClipboardAnnounce(VNCSConnectionST* client, bool available);
void handleClipboardData(VNCSConnectionST* client, const char* data, int len);
protected:
friend class VNCSConnectionST;
@@ -217,6 +223,8 @@ namespace rfb {
std::list<VNCSConnectionST*> clients;
VNCSConnectionST* pointerClient;
VNCSConnectionST* clipboardClient;
std::list<VNCSConnectionST*> clipboardRequestors;
std::list<network::Socket*> closingSockets;
static EncCache encCache;

View File

@@ -31,7 +31,7 @@ IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1);
ZRLEEncoder::ZRLEEncoder(SConnection* conn)
: Encoder(conn, encodingZRLE, EncoderPlain, 127),
zos(0,0,zlibLevel), mos(129*1024)
zos(0,zlibLevel), mos(129*1024)
{
zos.setUnderlying(&mos);
}

View File

@@ -0,0 +1,41 @@
/* Copyright 2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef __RFB_CLIPBOARDTYPES_H__
#define __RFB_CLIPBOARDTYPES_H__
namespace rfb {
// Formats
const unsigned int clipboardUTF8 = 1 << 0;
const unsigned int clipboardRTF = 1 << 1;
const unsigned int clipboardHTML = 1 << 2;
const unsigned int clipboardDIB = 1 << 3;
const unsigned int clipboardFiles = 1 << 4;
const unsigned int clipboardFormatMask = 0x0000ffff;
// Actions
const unsigned int clipboardCaps = 1 << 24;
const unsigned int clipboardRequest = 1 << 25;
const unsigned int clipboardPeek = 1 << 26;
const unsigned int clipboardNotify = 1 << 27;
const unsigned int clipboardProvide = 1 << 28;
const unsigned int clipboardActionMask = 0xff000000;
}
#endif

View File

@@ -85,6 +85,12 @@ namespace rfb {
const int pseudoEncodingVideoOutTimeLevel1 = -1986;
const int pseudoEncodingVideoOutTimeLevel100 = -1887;
// VMware-specific
const int pseudoEncodingVMwareCursorPosition = 0x574d5666;
// UltraVNC-specific
const int pseudoEncodingExtendedClipboard = 0xC0A1E5CE;
int encodingNum(const char* name);
const char* encodingName(int num);
}

View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -63,6 +64,10 @@ namespace rfb {
delete [] s;
}
void strFree(wchar_t* s) {
delete [] s;
}
bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) {
CharArray out1old, out2old;
@@ -107,6 +112,444 @@ namespace rfb {
dest[src ? destlen-1 : 0] = 0;
}
char* convertLF(const char* src, size_t bytes)
{
char* buffer;
size_t sz;
char* out;
const char* in;
size_t in_len;
// Always include space for a NULL
sz = 1;
// Compute output size
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
if (*in != '\r') {
sz++;
in++;
in_len--;
continue;
}
if ((in_len < 2) || (*(in+1) != '\n'))
sz++;
in++;
in_len--;
}
// Alloc
buffer = new char[sz];
memset(buffer, 0, sz);
// And convert
out = buffer;
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
if (*in != '\r') {
*out++ = *in++;
in_len--;
continue;
}
if ((in_len < 2) || (*(in+1) != '\n'))
*out++ = '\n';
in++;
in_len--;
}
return buffer;
}
char* convertCRLF(const char* src, size_t bytes)
{
char* buffer;
size_t sz;
char* out;
const char* in;
size_t in_len;
// Always include space for a NULL
sz = 1;
// Compute output size
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
sz++;
if (*in == '\r') {
if ((in_len < 2) || (*(in+1) != '\n'))
sz++;
} else if (*in == '\n') {
if ((in == src) || (*(in-1) != '\r'))
sz++;
}
in++;
in_len--;
}
// Alloc
buffer = new char[sz];
memset(buffer, 0, sz);
// And convert
out = buffer;
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
if (*in == '\n') {
if ((in == src) || (*(in-1) != '\r'))
*out++ = '\r';
}
*out = *in;
if (*in == '\r') {
if ((in_len < 2) || (*(in+1) != '\n')) {
out++;
*out = '\n';
}
}
out++;
in++;
in_len--;
}
return buffer;
}
size_t ucs4ToUTF8(unsigned src, char* dst) {
if (src < 0x80) {
*dst++ = src;
*dst++ = '\0';
return 1;
} else if (src < 0x800) {
*dst++ = 0xc0 | (src >> 6);
*dst++ = 0x80 | (src & 0x3f);
*dst++ = '\0';
return 2;
} else if (src < 0x10000) {
*dst++ = 0xe0 | (src >> 12);
*dst++ = 0x80 | ((src >> 6) & 0x3f);
*dst++ = 0x80 | (src & 0x3f);
*dst++ = '\0';
return 3;
} else if (src < 0x110000) {
*dst++ = 0xf0 | (src >> 18);
*dst++ = 0x80 | ((src >> 12) & 0x3f);
*dst++ = 0x80 | ((src >> 6) & 0x3f);
*dst++ = 0x80 | (src & 0x3f);
*dst++ = '\0';
return 4;
} else {
return ucs4ToUTF8(0xfffd, dst);
}
}
size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst) {
size_t count, consumed;
*dst = 0xfffd;
if (max == 0)
return 0;
consumed = 1;
if ((*src & 0x80) == 0) {
*dst = *src;
count = 0;
} else if ((*src & 0xe0) == 0xc0) {
*dst = *src & 0x1f;
count = 1;
} else if ((*src & 0xf0) == 0xe0) {
*dst = *src & 0x0f;
count = 2;
} else if ((*src & 0xf8) == 0xf0) {
*dst = *src & 0x07;
count = 3;
} else {
// Invalid sequence, consume all continuation characters
src++;
max--;
while ((max-- > 0) && ((*src++ & 0xc0) == 0x80))
consumed++;
return consumed;
}
src++;
max--;
while (count--) {
consumed++;
// Invalid or truncated sequence?
if ((max == 0) || ((*src & 0xc0) != 0x80)) {
*dst = 0xfffd;
return consumed;
}
*dst <<= 6;
*dst |= *src & 0x3f;
src++;
max--;
}
return consumed;
}
size_t ucs4ToUTF16(unsigned src, wchar_t* dst) {
if ((src < 0xd800) || ((src >= 0xe000) && (src < 0x10000))) {
*dst++ = src;
*dst++ = L'\0';
return 1;
} else if ((src >= 0x10000) && (src < 0x110000)) {
src -= 0x10000;
*dst++ = 0xd800 | ((src >> 10) & 0x03ff);
*dst++ = 0xdc00 | (src & 0x03ff);
*dst++ = L'\0';
return 2;
} else {
return ucs4ToUTF16(0xfffd, dst);
}
}
size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst) {
*dst = 0xfffd;
if (max == 0)
return 0;
if ((*src < 0xd800) || (*src >= 0xe000)) {
*dst = *src;
return 1;
}
if (*src & 0x0400) {
size_t consumed;
// Invalid sequence, consume all continuation characters
consumed = 0;
while ((max > 0) && (*src & 0x0400)) {
src++;
max--;
consumed++;
}
return consumed;
}
*dst = *src++;
max--;
// Invalid or truncated sequence?
if ((max == 0) || ((*src & 0xfc00) != 0xdc00)) {
*dst = 0xfffd;
return 1;
}
*dst = 0x10000 + ((*dst & 0x03ff) << 10);
*dst |= *src & 0x3ff;
return 2;
}
char* latin1ToUTF8(const char* src, size_t bytes) {
char* buffer;
size_t sz;
char* out;
const char* in;
size_t in_len;
// Always include space for a NULL
sz = 1;
// Compute output size
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
char buf[5];
sz += ucs4ToUTF8(*(const unsigned char*)in, buf);
in++;
in_len--;
}
// Alloc
buffer = new char[sz];
memset(buffer, 0, sz);
// And convert
out = buffer;
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
out += ucs4ToUTF8(*(const unsigned char*)in, out);
in++;
in_len--;
}
return buffer;
}
char* utf8ToLatin1(const char* src, size_t bytes) {
char* buffer;
size_t sz;
char* out;
const char* in;
size_t in_len;
// Always include space for a NULL
sz = 1;
// Compute output size
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
len = utf8ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
sz++;
}
// Alloc
buffer = new char[sz];
memset(buffer, 0, sz);
// And convert
out = buffer;
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
len = utf8ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
if (ucs > 0xff)
*out++ = '?';
else
*out++ = (unsigned char)ucs;
}
return buffer;
}
char* utf16ToUTF8(const wchar_t* src, size_t units)
{
char* buffer;
size_t sz;
char* out;
const wchar_t* in;
size_t in_len;
// Always include space for a NULL
sz = 1;
// Compute output size
in = src;
in_len = units;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
char buf[5];
len = utf16ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
sz += ucs4ToUTF8(ucs, buf);
}
// Alloc
buffer = new char[sz];
memset(buffer, 0, sz);
// And convert
out = buffer;
in = src;
in_len = units;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
len = utf16ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
out += ucs4ToUTF8(ucs, out);
}
return buffer;
}
wchar_t* utf8ToUTF16(const char* src, size_t bytes)
{
wchar_t* buffer;
size_t sz;
wchar_t* out;
const char* in;
size_t in_len;
// Always include space for a NULL
sz = 1;
// Compute output size
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
wchar_t buf[3];
len = utf8ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
sz += ucs4ToUTF16(ucs, buf);
}
// Alloc
buffer = new wchar_t[sz];
memset(buffer, 0, sz * sizeof(wchar_t));
// And convert
out = buffer;
in = src;
in_len = bytes;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
len = utf8ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
out += ucs4ToUTF16(ucs, out);
}
return buffer;
}
unsigned msBetween(const struct timeval *first,
const struct timeval *second)
{

View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -67,6 +68,7 @@ namespace rfb {
char* strDup(const char* s);
void strFree(char* s);
void strFree(wchar_t* s);
// Returns true if split successful. Returns false otherwise.
// ALWAYS *copies* first part of string to out1 buffer.
@@ -83,6 +85,25 @@ namespace rfb {
// Copies src to dest, up to specified length-1, and guarantees termination
void strCopy(char* dest, const char* src, int destlen);
// Makes sure line endings are in a certain format
char* convertLF(const char* src, size_t bytes = (size_t)-1);
char* convertCRLF(const char* src, size_t bytes = (size_t)-1);
// Convertions between various Unicode formats. The returned strings are
// always null terminated and must be freed using strFree().
size_t ucs4ToUTF8(unsigned src, char* dst);
size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst);
size_t ucs4ToUTF16(unsigned src, wchar_t* dst);
size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst);
char* latin1ToUTF8(const char* src, size_t bytes = (size_t)-1);
char* utf8ToLatin1(const char* src, size_t bytes = (size_t)-1);
char* utf16ToUTF8(const wchar_t* src, size_t units = (size_t)-1);
wchar_t* utf8ToUTF16(const char* src, size_t bytes = (size_t)-1);
// HELPER functions for timeout handling

View File

@@ -26,7 +26,7 @@ TigerVNC is
All Rights Reserved.
This software is distributed under the GNU General Public Licence as published
by the Free Software Foundation. See the file LICENCE.TXT for the conditions
by the Free Software Foundation. See the file LICENSE.TXT for the conditions
under which this software is made available. TigerVNC also contains code from
other sources. See the Acknowledgements section below, and the individual
source files, for details of the conditions under which they are made

View File

@@ -26,7 +26,7 @@ TigerVNC is
All Rights Reserved.
This software is distributed under the GNU General Public Licence as published
by the Free Software Foundation. See the file LICENCE.TXT for the conditions
by the Free Software Foundation. See the file LICENSE.TXT for the conditions
under which this software is made available. TigerVNC also contains code from
other sources. See the Acknowledgements section below, and the individual
source files, for details of the conditions under which they are made

View File

@@ -26,7 +26,7 @@ TigerVNC is
All Rights Reserved.
This software is distributed under the GNU General Public Licence as published
by the Free Software Foundation. See the file LICENCE.TXT for the conditions
by the Free Software Foundation. See the file LICENSE.TXT for the conditions
under which this software is made available. TigerVNC also contains code from
other sources. See the Acknowledgements section below, and the individual
source files, for details of the conditions under which they are made

View File

@@ -1031,7 +1031,7 @@ fi
%files license
%defattr(-,root,root,-)
%doc LICENCE.TXT
%doc LICENSE.TXT
%files icons
%defattr(-,root,root,-)

View File

@@ -444,7 +444,7 @@ fi
%files license
%defattr(-,root,root,-)
%doc LICENCE.TXT
%doc LICENSE.TXT
%files icons
%defattr(-,root,root,-)

View File

@@ -376,7 +376,7 @@ fi
%{_datadir}/vnc/classes/*
%files license
%doc %{_docdir}/%{name}-%{version}/LICENCE.TXT
%doc %{_docdir}/%{name}-%{version}/LICENSE.TXT
%files icons
%defattr(-,root,root,-)

1
kasmweb Submodule

Submodule kasmweb added at 33066b89b3

View File

@@ -1 +0,0 @@
**/xtscancodes.js

View File

@@ -1,48 +0,0 @@
{
"env": {
"browser": true,
"es6": true
},
"parserOptions": {
"sourceType": "module"
},
"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,
"CallExpression": { "arguments": "first" },
"ArrayExpression": "first",
"ObjectExpression": "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"],
}
}

14
kasmweb/.gitignore vendored
View File

@@ -1,14 +0,0 @@
*.pyc
*.o
tests/data_*.js
utils/rebind.so
utils/websockify
/node_modules
/build
/lib
recordings
*.swp
*~
noVNC-*.tgz
/dist
index.html

0
kasmweb/.gitmodules vendored
View File

View File

@@ -1,53 +0,0 @@
language: node_js
sudo: false
cache:
directories:
- node_modules
node_js:
- 6
env:
matrix:
- TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='Windows 10'
# FIXME Skip tests in Linux since Sauce Labs browser versions are ancient.
# - TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='Linux'
- TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='OS X 10.11'
- TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='Windows 10'
# - TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='Linux'
- TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='OS X 10.11'
- TEST_BROWSER_NAME='internet explorer' TEST_BROWSER_OS='Windows 10'
- TEST_BROWSER_NAME='internet explorer' TEST_BROWSER_OS='Windows 7'
- TEST_BROWSER_NAME=microsoftedge TEST_BROWSER_OS='Windows 10'
- TEST_BROWSER_NAME=safari TEST_BROWSER_OS='OS X 10.13'
before_script: npm install -g karma-cli
addons:
sauce_connect:
username: "directxman12"
jwt:
secure: "d3ekMYslpn6R4f0ajtRMt9SUFmNGDiItHpqaXC5T4KI0KMEsxgvEOfJot5PiFFJWg1DSpJZH6oaW2UxGZ3duJLZrXIEd/JePY8a6NtT35BNgiDPgcp+eu2Bu3rhrSNg7/HEsD1ma+JeUTnv18Ai5oMFfCCQJx2J6osIxyl/ZVxA="
stages:
- lint
- test
- name: deploy
if: tag is PRESENT
jobs:
include:
- stage: lint
env:
addons:
before_script:
script: npm run lint
- stage: deploy
env:
addons:
script: skip
before_script: skip
deploy:
provider: npm
email: ossman@cendio.se
api_key:
secure: "Qq2Mi9xQawO2zlAigzshzMu2QMHvu1IaN9l0ZIivE99wHJj7eS5f4miJ9wB+/mWRRgb3E8uj9ZRV24+Oc36drlBTU9sz+lHhH0uFMfAIseceK64wZV9sLAZm472fmPp2xdUeTCCqPaRy7g1XBqiJ0LyZvEFLsRijqcLjPBF+b8w="
on:
tags: true
repo: novnc/noVNC

View File

@@ -1,13 +0,0 @@
maintainers:
- Joel Martin (@kanaka)
- Solly Ross (@directxman12)
- Samuel Mannehed for Cendio AB (@samhed)
- Pierre Ossman for Cendio AB (@CendioOssman)
maintainersEmeritus:
- @astrand
contributors:
# There are a bunch of people that should be here.
# If you want to be on this list, feel free send a PR
# to add yourself.
- jalf <git@jalf.dk>
- NTT corp.

View File

@@ -1,68 +0,0 @@
noVNC is Copyright (C) 2018 The noVNC Authors
(./AUTHORS)
The noVNC core library files are licensed under the MPL 2.0 (Mozilla
Public License 2.0). The noVNC core library is composed of the
Javascript code necessary for full noVNC operation. This includes (but
is not limited to):
core/**/*.js
app/*.js
test/playback.js
The HTML, CSS, font and images files that included with the noVNC
source distibution (or repository) are not considered part of the
noVNC core library and are licensed under more permissive licenses.
The intent is to allow easy integration of noVNC into existing web
sites and web applications.
The HTML, CSS, font and image files are licensed as follows:
*.html : 2-Clause BSD license
app/styles/*.css : 2-Clause BSD license
app/styles/Orbitron* : SIL Open Font License 1.1
(Copyright 2009 Matt McInerney)
app/images/ : Creative Commons Attribution-ShareAlike
http://creativecommons.org/licenses/by-sa/3.0/
Some portions of noVNC are copyright to their individual authors.
Please refer to the individual source files and/or to the noVNC commit
history: https://github.com/novnc/noVNC/commits/master
The are several files and projects that have been incorporated into
the noVNC core library. Here is a list of those files and the original
licenses (all MPL 2.0 compatible):
core/base64.js : MPL 2.0
core/des.js : Various BSD style licenses
vendor/pako/ : MIT
vendor/browser-es-module-loader/src/ : MIT
vendor/browser-es-module-loader/dist/ : Various BSD style licenses
vendor/promise.js : MIT
Any other files not mentioned above are typically marked with
a copyright/license header at the top of the file. The default noVNC
license is MPL-2.0.
The following license texts are included:
docs/LICENSE.MPL-2.0
docs/LICENSE.OFL-1.1
docs/LICENSE.BSD-3-Clause (New BSD)
docs/LICENSE.BSD-2-Clause (Simplified BSD / FreeBSD)
vendor/pako/LICENSE (MIT)
Or alternatively the license texts may be found here:
http://www.mozilla.org/MPL/2.0/
http://scripts.sil.org/OFL
http://en.wikipedia.org/wiki/BSD_licenses
https://opensource.org/licenses/MIT

View File

@@ -1,151 +0,0 @@
## noVNC: HTML VNC Client Library and Application
[![Build Status](https://travis-ci.org/novnc/noVNC.svg?branch=master)](https://travis-ci.org/novnc/noVNC)
### Description
noVNC is both a HTML VNC client JavaScript library and an application built on
top of that library. noVNC runs well in any modern browser including mobile
browsers (iOS and Android).
Many companies, projects and products have integrated noVNC including
[OpenStack](http://www.openstack.org),
[OpenNebula](http://opennebula.org/),
[LibVNCServer](http://libvncserver.sourceforge.net), and
[ThinLinc](https://cendio.com/thinlinc). See
[the Projects and Companies wiki page](https://github.com/novnc/noVNC/wiki/Projects-and-companies-using-noVNC)
for a more complete list with additional info and links.
### Table of Contents
- [News/help/contact](#newshelpcontact)
- [Features](#features)
- [Screenshots](#screenshots)
- [Browser Requirements](#browser-requirements)
- [Server Requirements](#server-requirements)
- [Quick Start](#quick-start)
- [Integration and Deployment](#integration-and-deployment)
- [Authors/Contributors](#authorscontributors)
### 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).
Bugs and feature requests can be submitted via
[github issues](https://github.com/novnc/noVNC/issues). If you have questions
about using noVNC then please first use the
[discussion group](https://groups.google.com/forum/?fromgroups#!forum/novnc).
We also have a [wiki](https://github.com/novnc/noVNC/wiki/) with lots of
helpful information.
If you are looking for a place to start contributing to noVNC, a good place to
start would be the issues that are marked as
["patchwelcome"](https://github.com/novnc/noVNC/issues?labels=patchwelcome).
Please check our
[contribution guide](https://github.com/novnc/noVNC/wiki/Contributing) though.
If you want to show appreciation for noVNC you could donate to a great non-
profits such as:
[Compassion International](http://www.compassion.com/),
[SIL](http://www.sil.org),
[Habitat for Humanity](http://www.habitat.org),
[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
* Supports all modern browsers including mobile (iOS, Android)
* Supported VNC encodings: raw, copyrect, rre, hextile, tight, tightPNG
* Supports scaling, clipping and resizing the desktop
* Local cursor rendering
* Clipboard copy/paste
* Licensed mainly under the [MPL 2.0](http://www.mozilla.org/MPL/2.0/), see
[the license document](LICENSE.txt) for details
### Screenshots
Running in Firefox before and after connecting:
<img src="http://novnc.com/img/noVNC-1-login.png" width=400>&nbsp;
<img src="http://novnc.com/img/noVNC-3-connected.png" width=400>
See more screenshots
[here](http://novnc.com/screenshots.html).
### Browser Requirements
noVNC uses many modern web technologies so a formal requirement list is
not available. However these are the minimum versions we are currently
aware of:
* Chrome 49, Firefox 44, Safari 10, Opera 36, IE 11, Edge 12
### Server Requirements
noVNC follows the standard VNC protocol, but unlike other VNC clients it does
require WebSockets support. Many servers include support (e.g.
[x11vnc/libvncserver](http://libvncserver.sourceforge.net/),
[QEMU](http://www.qemu.org/), and
[MobileVNC](http://www.smartlab.at/mobilevnc/)), but for the others you need to
use a WebSockets to TCP socket proxy. noVNC has a sister project
[websockify](https://github.com/novnc/websockify) that provides a simple such
proxy.
### Quick Start
* Use the launch script to automatically download and start websockify, which
includes a mini-webserver and the WebSockets proxy. The `--vnc` option is
used to specify the location of a running VNC server:
`./utils/launch.sh --vnc localhost:5901`
* Point your browser to the cut-and-paste URL that is output by the launch
script. Hit the Connect button, enter a password if the VNC server has one
configured, and enjoy!
### Integration and Deployment
Please see our other documents for how to integrate noVNC in your own software,
or deploying the noVNC application in production environments:
* [Embedding](docs/EMBEDDING.md) - For the noVNC application
* [Library](docs/LIBRARY.md) - For the noVNC JavaScript library
### Authors/Contributors
See [AUTHORS](AUTHORS) for a (full-ish) list of authors. If you're not on
that list and you think you should be, feel free to send a PR to fix that.
* Core team:
* [Joel Martin](https://github.com/kanaka)
* [Samuel Mannehed](https://github.com/samhed) (Cendio)
* [Peter Åstrand](https://github.com/astrand) (Cendio)
* [Solly Ross](https://github.com/DirectXMan12) (Red Hat / OpenStack)
* [Pierre Ossman](https://github.com/CendioOssman) (Cendio)
* Notable contributions:
* UI and Icons : Pierre Ossman, Chris Gordon
* Original Logo : Michael Sersen
* tight encoding : Michael Tinglof (Mercuri.ca)
* Included libraries:
* base64 : Martijn Pieters (Digital Creations 2), Samuel Sieb (sieb.net)
* DES : Dave Zimmerman (Widget Workshop), Jef Poskanzer (ACME Labs)
* Pako : Vitaly Puzrin (https://github.com/nodeca/pako)
Do you want to be on this list? Check out our
[contribution guide](https://github.com/novnc/noVNC/wiki/Contributing) and
start hacking!

View File

@@ -1 +0,0 @@
1.0.0

View File

@@ -1,58 +0,0 @@
// NB: this should *not* be included as a module until we have
// native support in the browsers, so that our error handler
// can catch script-loading errors.
// No ES6 can be used in this file since it's used for the translation
/* eslint-disable prefer-arrow-callback */
(function _scope() {
"use strict";
// Fallback for all uncaught errors
function handleError(event, err) {
try {
const msg = document.getElementById('noVNC_fallback_errormsg');
// Only show the initial error
if (msg.hasChildNodes()) {
return false;
}
let div = document.createElement("div");
div.classList.add('noVNC_message');
div.appendChild(document.createTextNode(event.message));
msg.appendChild(div);
if (event.filename) {
div = document.createElement("div");
div.className = 'noVNC_location';
let text = event.filename;
if (event.lineno !== undefined) {
text += ":" + event.lineno;
if (event.colno !== undefined) {
text += ":" + event.colno;
}
}
div.appendChild(document.createTextNode(text));
msg.appendChild(div);
}
if (err && err.stack) {
div = document.createElement("div");
div.className = 'noVNC_stack';
div.appendChild(document.createTextNode(err.stack));
msg.appendChild(div);
}
document.getElementById('noVNC_fallback_error')
.classList.add("noVNC_open");
} catch (exc) {
document.write("Kasm has encountered an error.");
}
// Don't return true since this would prevent the error
// from being printed to the browser console.
return false;
}
window.addEventListener('error', function onerror(evt) { handleError(evt, evt.error); });
window.addEventListener('unhandledrejection', function onreject(evt) { handleError(evt.reason, evt.reason); });
})();

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="alt.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="18.205425"
inkscape:cy="17.531398"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text5290">
<path
d="m 9.9560547,1042.3329 -2.9394531,0 -0.4638672,1.3281 -1.8896485,0 2.7001953,-7.29 2.241211,0 2.7001958,7.29 -1.889649,0 -0.4589843,-1.3281 z m -2.4707031,-1.3526 1.9970703,0 -0.9960938,-2.9003 -1.0009765,2.9003 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5340" />
<path
d="m 13.188477,1036.0634 1.748046,0 0,7.5976 -1.748046,0 0,-7.5976 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5342" />
<path
d="m 18.535156,1036.6395 0,1.5528 1.801758,0 0,1.25 -1.801758,0 0,2.3193 q 0,0.3809 0.151367,0.5176 0.151368,0.1318 0.600586,0.1318 l 0.898438,0 0,1.25 -1.499024,0 q -1.035156,0 -1.469726,-0.4297 -0.429688,-0.4345 -0.429688,-1.4697 l 0,-2.3193 -0.86914,0 0,-1.25 0.86914,0 0,-1.5528 1.748047,0 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5344" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1,106 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="clipboard.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="15.366606"
inkscape:cy="16.42981"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 9,6 6,6 C 5.4459889,6 5,6.4459889 5,7 l 0,13 c 0,0.554011 0.4459889,1 1,1 l 13,0 c 0.554011,0 1,-0.445989 1,-1 L 20,7 C 20,6.4459889 19.554011,6 19,6 l -3,0"
transform="translate(0,1027.3622)"
id="rect6083"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssssssssc" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect6085"
width="7"
height="4"
x="9"
y="1031.3622"
ry="1.00002" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
d="m 8.5071212,1038.8622 7.9999998,0"
id="path6087"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
d="m 8.5071212,1041.8622 3.9999998,0"
id="path6089"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
d="m 8.5071212,1044.8622 5.9999998,0"
id="path6091"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,96 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="connect.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="37.14834"
inkscape:cy="1.9525926"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
id="g5103"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-729.15757,315.8823)">
<path
sodipodi:nodetypes="cssssc"
inkscape:connector-curvature="0"
id="rect5096"
d="m 11,1040.3622 -5,0 c -1.108,0 -2,-0.892 -2,-2 l 0,-4 c 0,-1.108 0.892,-2 2,-2 l 5,0"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 14,1032.3622 5,0 c 1.108,0 2,0.892 2,2 l 0,4 c 0,1.108 -0.892,2 -2,2 l -5,0"
id="path5099"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssssc" />
<path
inkscape:connector-curvature="0"
id="path5101"
d="m 9,1036.3622 7,0"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -1,96 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="ctrl.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="18.205425"
inkscape:cy="17.531398"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text5290">
<path
d="m 9.1210938,1043.1898 q -0.5175782,0.2686 -1.0791016,0.4053 -0.5615235,0.1367 -1.171875,0.1367 -1.8212891,0 -2.8857422,-1.0156 -1.0644531,-1.0205 -1.0644531,-2.7637 0,-1.748 1.0644531,-2.7637 1.0644531,-1.0205 2.8857422,-1.0205 0.6103515,0 1.171875,0.1368 0.5615234,0.1367 1.0791016,0.4052 l 0,1.5088 q -0.522461,-0.3564 -1.0302735,-0.5224 -0.5078125,-0.1661 -1.0693359,-0.1661 -1.0058594,0 -1.5820313,0.6446 -0.5761719,0.6445 -0.5761719,1.7773 0,1.1279 0.5761719,1.7725 0.5761719,0.6445 1.5820313,0.6445 0.5615234,0 1.0693359,-0.166 0.5078125,-0.166 1.0302735,-0.5225 l 0,1.5088 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5370" />
<path
d="m 12.514648,1036.5687 0,1.5528 1.801758,0 0,1.25 -1.801758,0 0,2.3193 q 0,0.3809 0.151368,0.5176 0.151367,0.1318 0.600586,0.1318 l 0.898437,0 0,1.25 -1.499023,0 q -1.035157,0 -1.469727,-0.4297 -0.429687,-0.4345 -0.429687,-1.4697 l 0,-2.3193 -0.8691411,0 0,-1.25 0.8691411,0 0,-1.5528 1.748046,0 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5372" />
<path
d="m 19.453125,1039.6107 q -0.229492,-0.1074 -0.458984,-0.1562 -0.22461,-0.054 -0.454102,-0.054 -0.673828,0 -1.040039,0.4345 -0.361328,0.4297 -0.361328,1.2354 l 0,2.5195 -1.748047,0 0,-5.4687 1.748047,0 0,0.8984 q 0.336914,-0.5371 0.771484,-0.7813 0.439453,-0.249 1.049805,-0.249 0.08789,0 0.19043,0.01 0.102539,0 0.297851,0.029 l 0.0049,1.582 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5374" />
<path
d="m 20.332031,1035.9926 1.748047,0 0,7.5976 -1.748047,0 0,-7.5976 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5376" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,100 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="ctrlaltdel.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="11.135667"
inkscape:cy="16.407428"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5253"
width="5"
height="5.0000172"
x="16"
y="1031.3622"
ry="1.0000174" />
<rect
y="1043.3622"
x="4"
height="5.0000172"
width="5"
id="rect5255"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
ry="1.0000174" />
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5257"
width="5"
height="5.0000172"
x="13"
y="1043.3622"
ry="1.0000174" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,94 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="disconnect.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="25.05707"
inkscape:cy="11.594858"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
id="g5171"
transform="translate(-24.062499,-6.15775e-4)">
<path
id="path5110"
transform="translate(0,1027.3622)"
d="m 39.744141,3.4960938 c -0.769923,0 -1.539607,0.2915468 -2.121094,0.8730468 l -2.566406,2.5664063 1.414062,1.4140625 2.566406,-2.5664063 c 0.403974,-0.404 1.010089,-0.404 1.414063,0 l 2.828125,2.828125 c 0.40398,0.4039 0.403907,1.0101621 0,1.4140629 l -2.566406,2.566406 1.414062,1.414062 2.566406,-2.566406 c 1.163041,-1.1629 1.162968,-3.0791874 0,-4.2421874 L 41.865234,4.3691406 C 41.283747,3.7876406 40.514063,3.4960937 39.744141,3.4960938 Z M 39.017578,9.015625 a 1.0001,1.0001 0 0 0 -0.6875,0.3027344 l -0.445312,0.4453125 1.414062,1.4140621 0.445313,-0.445312 A 1.0001,1.0001 0 0 0 39.017578,9.015625 Z m -6.363281,0.7070312 a 1.0001,1.0001 0 0 0 -0.6875,0.3027348 L 28.431641,13.5625 c -1.163042,1.163 -1.16297,3.079187 0,4.242188 l 2.828125,2.828124 c 1.162974,1.163101 3.079213,1.163101 4.242187,0 l 3.535156,-3.535156 a 1.0001,1.0001 0 1 0 -1.414062,-1.414062 l -3.535156,3.535156 c -0.403974,0.404 -1.010089,0.404 -1.414063,0 l -2.828125,-2.828125 c -0.403981,-0.404 -0.403908,-1.010162 0,-1.414063 l 3.535156,-3.537109 A 1.0001,1.0001 0 0 0 32.654297,9.7226562 Z m 3.109375,2.1621098 -2.382813,2.384765 a 1.0001,1.0001 0 1 0 1.414063,1.414063 l 2.382812,-2.384766 -1.414062,-1.414062 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:connector-curvature="0" />
<rect
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)"
y="752.29541"
x="-712.31262"
height="18.000017"
width="3"
id="rect5116"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

View File

@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="drag.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="9.8789407"
inkscape:cy="9.5008608"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 7.039733,1049.3037 c -0.4309106,-0.1233 -0.7932634,-0.4631 -0.9705434,-0.9103 -0.04922,-0.1241 -0.057118,-0.2988 -0.071321,-1.5771 l -0.015972,-1.4375 -0.328125,-0.082 c -0.7668138,-0.1927 -1.1897046,-0.4275 -1.7031253,-0.9457 -0.4586773,-0.4629 -0.6804297,-0.8433 -0.867034,-1.4875 -0.067215,-0.232 -0.068001,-0.2642 -0.078682,-3.2188 -0.012078,-3.341 -0.020337,-3.2012 0.2099452,-3.5555 0.2246623,-0.3458 0.5798271,-0.5892 0.9667343,-0.6626 0.092506,-0.017 0.531898,-0.032 0.9764271,-0.032 l 0.8082347,0 1.157e-4,1.336 c 1.125e-4,1.2779 0.00281,1.3403 0.062214,1.4378 0.091785,0.1505 0.2357707,0.226 0.4314082,0.2261 0.285389,2e-4 0.454884,-0.1352 0.5058962,-0.4042 0.019355,-0.102 0.031616,-0.982 0.031616,-2.269 0,-1.9756 0.00357,-2.1138 0.059205,-2.2926 0.1645475,-0.5287 0.6307616,-0.9246 1.19078,-1.0113 0.8000572,-0.1238 1.5711277,0.4446 1.6860387,1.2429 0.01732,0.1203 0.03177,0.8248 0.03211,1.5657 6.19e-4,1.3449 7.22e-4,1.347 0.07093,1.4499 0.108355,0.1587 0.255268,0.2248 0.46917,0.2108 0.204069,-0.013 0.316116,-0.08 0.413642,-0.2453 0.06028,-0.1024 0.06307,-0.1778 0.07862,-2.1218 0.01462,-1.8283 0.02124,-2.0285 0.07121,-2.1549 0.260673,-0.659 0.934894,-1.0527 1.621129,-0.9465 0.640523,0.099 1.152269,0.6104 1.243187,1.2421 0.01827,0.1269 0.03175,0.9943 0.03211,2.0657 l 6.19e-4,1.8469 0.07031,0.103 c 0.108355,0.1587 0.255267,0.2248 0.46917,0.2108 0.204069,-0.013 0.316115,-0.08 0.413642,-0.2453 0.05951,-0.1011 0.06329,-0.1786 0.07907,-1.6218 0.01469,-1.3438 0.02277,-1.5314 0.07121,-1.6549 0.257975,-0.6576 0.934425,-1.0527 1.620676,-0.9465 0.640522,0.099 1.152269,0.6104 1.243186,1.2421 0.0186,0.1292 0.03179,1.0759 0.03222,2.3125 7.15e-4,2.0335 0.0025,2.0966 0.06283,2.1956 0.09178,0.1505 0.235771,0.226 0.431409,0.2261 0.285388,2e-4 0.454884,-0.1352 0.505897,-0.4042 0.01874,-0.099 0.03161,-0.8192 0.03161,-1.769 0,-1.4848 0.0043,-1.6163 0.0592,-1.7926 0.164548,-0.5287 0.630762,-0.9246 1.19078,-1.0113 0.800057,-0.1238 1.571128,0.4446 1.686039,1.2429 0.04318,0.2999 0.04372,9.1764 5.78e-4,9.4531 -0.04431,0.2841 -0.217814,0.6241 -0.420069,0.8232 -0.320102,0.315 -0.63307,0.4268 -1.194973,0.4268 l -0.35281,0 -2.51e-4,1.2734 c -1.25e-4,0.7046 -0.01439,1.3642 -0.03191,1.4766 -0.06665,0.4274 -0.372966,0.8704 -0.740031,1.0702 -0.349999,0.1905 0.01748,0.18 -6.242199,0.1776 -5.3622439,0 -5.7320152,-0.01 -5.9121592,-0.057 l 1.4e-5,0 z"
id="path4379"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -1,81 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="error.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="14.00357"
inkscape:cy="12.443398"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 7 3 C 4.7839905 3 3 4.7839905 3 7 L 3 18 C 3 20.21601 4.7839905 22 7 22 L 18 22 C 20.21601 22 22 20.21601 22 18 L 22 7 C 22 4.7839905 20.21601 3 18 3 L 7 3 z M 7.6992188 6 A 1.6916875 1.6924297 0 0 1 8.9121094 6.5117188 L 12.5 10.101562 L 16.087891 6.5117188 A 1.6916875 1.6924297 0 0 1 17.251953 6 A 1.6916875 1.6924297 0 0 1 18.480469 8.90625 L 14.892578 12.496094 L 18.480469 16.085938 A 1.6916875 1.6924297 0 1 1 16.087891 18.478516 L 12.5 14.888672 L 8.9121094 18.478516 A 1.6916875 1.6924297 0 1 1 6.5214844 16.085938 L 10.109375 12.496094 L 6.5214844 8.90625 A 1.6916875 1.6924297 0 0 1 7.6992188 6 z "
transform="translate(0,1027.3622)"
id="rect4135" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="esc.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="18.205425"
inkscape:cy="17.531398"
inkscape:document-units="px"
inkscape:current-layer="text5290"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text5290">
<path
d="m 3.9331055,1036.1464 5.0732422,0 0,1.4209 -3.1933594,0 0,1.3574 3.0029297,0 0,1.4209 -3.0029297,0 0,1.6699 3.3007812,0 0,1.4209 -5.180664,0 0,-7.29 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5314" />
<path
d="m 14.963379,1038.1385 0,1.3282 q -0.561524,-0.2344 -1.083984,-0.3516 -0.522461,-0.1172 -0.986329,-0.1172 -0.498046,0 -0.742187,0.127 -0.239258,0.122 -0.239258,0.3808 0,0.21 0.180664,0.3223 0.185547,0.1123 0.65918,0.166 l 0.307617,0.044 q 1.342773,0.1709 1.806641,0.5615 0.463867,0.3906 0.463867,1.2256 0,0.874 -0.644531,1.3134 -0.644532,0.4395 -1.923829,0.4395 -0.541992,0 -1.123046,-0.088 -0.576172,-0.083 -1.186524,-0.2539 l 0,-1.3281 q 0.522461,0.2539 1.069336,0.3808 0.551758,0.127 1.118164,0.127 0.512695,0 0.771485,-0.1416 0.258789,-0.1416 0.258789,-0.4199 0,-0.2344 -0.180664,-0.3467 -0.175782,-0.1172 -0.708008,-0.1807 l -0.307617,-0.039 q -1.166993,-0.1465 -1.635743,-0.542 -0.46875,-0.3955 -0.46875,-1.2012 0,-0.8691 0.595703,-1.2891 0.595704,-0.4199 1.826172,-0.4199 0.483399,0 1.015625,0.073 0.532227,0.073 1.157227,0.2294 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5316" />
<path
d="m 21.066895,1038.1385 0,1.4258 q -0.356446,-0.2441 -0.717774,-0.3613 -0.356445,-0.1172 -0.742187,-0.1172 -0.732422,0 -1.142579,0.4297 -0.405273,0.4248 -0.405273,1.1914 0,0.7666 0.405273,1.1963 0.410157,0.4248 1.142579,0.4248 0.410156,0 0.776367,-0.1221 0.371094,-0.122 0.683594,-0.3613 l 0,1.4307 q -0.410157,0.1513 -0.834961,0.2246 -0.419922,0.078 -0.844727,0.078 -1.479492,0 -2.314453,-0.7568 -0.834961,-0.7618 -0.834961,-2.1143 0,-1.3525 0.834961,-2.1094 0.834961,-0.7617 2.314453,-0.7617 0.429688,0 0.844727,0.078 0.419921,0.073 0.834961,0.2246 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5318" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="9"
height="10"
viewBox="0 0 9 10"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="expander.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="45.254834"
inkscape:cx="9.8737281"
inkscape:cy="6.4583132"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-object-midpoints="false"
inkscape:object-nodes="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1042.3622)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 2.0800781,1042.3633 A 2.0002,2.0002 0 0 0 0,1044.3613 l 0,6 a 2.0002,2.0002 0 0 0 3.0292969,1.7168 l 5,-3 a 2.0002,2.0002 0 0 0 0,-3.4316 l -5,-3 a 2.0002,2.0002 0 0 0 -0.9492188,-0.2832 z"
id="path4138"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,93 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="fullscreen.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="16.400723"
inkscape:cy="15.083758"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="false">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5006"
width="17"
height="17.000017"
x="4"
y="1031.3622"
ry="3.0000174" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 7.5,1044.8622 4,0 -1.5,-1.5 1.5,-1.5 -1,-1 -1.5,1.5 -1.5,-1.5 0,4 z"
id="path5017"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path5025"
d="m 17.5,1034.8622 -4,0 1.5,1.5 -1.5,1.5 1,1 1.5,-1.5 1.5,1.5 0,-4 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5"
height="6"
viewBox="0 0 5 6"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="handle.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="1.3551778"
inkscape:cy="8.7800329"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1046.3622)">
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.0000803,1049.3622 -3,-2 0,4 z"
id="path4247"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,172 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="15"
height="50"
viewBox="0 0 15 50"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="handle_bg.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="-10.001409"
inkscape:cy="24.512566"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1002.3622)">
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4249"
width="1"
height="1.0000174"
x="9.5"
y="1008.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1013.8622"
x="9.5"
height="1.0000174"
width="1"
id="rect4255"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
ry="1.7382812e-05"
y="1008.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4261"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4263"
width="1"
height="1.0000174"
x="4.5"
y="1013.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1039.8622"
x="9.5"
height="1.0000174"
width="1"
id="rect4265"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4267"
width="1"
height="1.0000174"
x="9.5"
y="1044.8622"
ry="1.7382812e-05" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4269"
width="1"
height="1.0000174"
x="4.5"
y="1039.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1044.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4271"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4273"
width="1"
height="1.0000174"
x="9.5"
y="1018.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1018.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4275"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4277"
width="1"
height="1.0000174"
x="9.5"
y="1034.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1034.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4279"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.2 KiB

Some files were not shown because too many files have changed in this diff Show More