diff --git a/N_tigervnc_revert_fltk_1_3_3_requirements.patch b/N_tigervnc_revert_fltk_1_3_3_requirements.patch new file mode 100644 index 0000000..d5126ce --- /dev/null +++ b/N_tigervnc_revert_fltk_1_3_3_requirements.patch @@ -0,0 +1,1005 @@ +From 5c30d3e80ff682f94fdc6ba5a7e63372c2e7a471 Mon Sep 17 00:00:00 2001 +From: Michal Srb +Date: Wed, 15 Jul 2015 16:41:33 +0300 +Subject: [PATCH] Revert "Raise FLTK requirement to 1.3.3" + +This reverts commit 56610fb847eaf1fe27a5b7331ede93296ff835ff. + +Conflicts: + BUILDING.txt + config.h.in + vncviewer/DesktopWindow.cxx + vncviewer/Viewport.cxx + +diff --git a/BUILDING.txt b/BUILDING.txt +index 9987bd7..9703b1c 100644 +--- a/BUILDING.txt ++++ b/BUILDING.txt +@@ -12,6 +12,9 @@ Build Requirements (All Systems) + -- zlib + + -- FLTK 1.3.3 or later ++-- FLTK 1.3.2 ++ * Must be a patched snapshot to get full functionality ++ * See "Building FLTK" below. + + -- If building TLS support: + * GnuTLS 3.x +@@ -62,6 +65,38 @@ Build Requirements (Java) + -- See "Building Java Support" below. + + ++============= ++Building FLTK ++============= ++ ++TigerVNC requires FLTK 1.3.2 (or later). Although it will build and work ++with plain 1.3.2, to get full functionality and the best behaviour you ++need to build a patched version: ++ ++1. Check out FLTK 1.3.2 using Subversion: ++$ svn co http://svn.easysw.com/public/fltk/fltk/tags/release-1.3.2 fltk-1.3.2 ++ ++2. For full functionality, apply patches. All patches can be found in ++ the contrib/fltk/ directory. There are also some general fixes to ++ FLTK that can be found in the contrib/fltk/fixes/ directory that ++ might be useful. ++ ++3. Use CMake to build FLTK using the same procedures described below for ++ building TigerVNC. The recipes in the "Build Recipes" section also apply. ++ If you want optimized code, make sure to build with ++ -DCMAKE_BUILD_TYPE=Release. ++ ++4. (optional) Use 'make install' to install FLTK into a directory of your ++ choosing. ++ ++5. When building TigerVNC, set the FLTK_FLUID_EXECUTABLE CMake variable to the ++ location of the fluid executable that was built in Step 3 or installed in ++ Step 4. This gives CMake a hint as to where to find the FLTK library. ++ ++6. If you did not install FLTK, then set the FLTK_INCLUDE_DIR CMake variable to ++ the location of the FLTK source directory. ++ ++ + ================== + Out-of-Tree Builds + ================== +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a46679b..cd91965 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -226,6 +226,41 @@ if(UNIX AND NOT APPLE) + endif() + endif() + ++if(FLTK_FOUND) ++ set(CMAKE_REQUIRED_INCLUDES ${FLTK_INCLUDE_DIR}) ++ set(CMAKE_REQUIRED_LIBRARIES ${FLTK_LIBRARIES}) ++ ++ # FLTK STR #2636 ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { Fl::add_clipboard_notify(NULL, NULL); return 0; }" HAVE_FLTK_CLIPBOARD) ++ ++ # FLTK STR #2638 ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { return FL_Volume_Down; }" HAVE_FLTK_MEDIAKEYS) ++ ++ # FLTK STR #2641 ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { return FL_FULLSCREEN; }" HAVE_FLTK_FULLSCREEN) ++ ++ # FLTK STR #2660 ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { void (Fl_Window::*foo)(const Fl_RGB_Image*,int,int) = &Fl_Window::cursor; return 0; }" HAVE_FLTK_CURSOR) ++ ++ # FLTK STR #2697 ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { int X, Y, W, H; Fl::screen_work_area(X, Y, W, H); return 0; }" HAVE_FLTK_WORK_AREA) ++ ++ # FLTK STR #2816 ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { Fl_Window::default_icons(0, 0); return 0; }" HAVE_FLTK_ICONS) ++ ++ # FLTK STR #2860 ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { void (Fl_Window::*foo)(int,int,int,int) = &Fl_Window::fullscreen_screens; return 0; }" HAVE_FLTK_FULLSCREEN_SCREENS) ++ ++ # FLTK STR #xxxx ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { Fl::add_system_handler(NULL, NULL); return 0; }" HAVE_FLTK_XHANDLERS) ++ ++ # FLTK STR #xxxx ++ check_cxx_source_compiles("#include \nint main(int c, char** v) { Fl::disable_im(); return 0; }" HAVE_FLTK_IM) ++ ++ set(CMAKE_REQUIRED_INCLUDES) ++ set(CMAKE_REQUIRED_LIBRARIES) ++endif() ++ + # Check for GNUTLS library + option(ENABLE_GNUTLS "Enable protocol encryption and advanced authentication" ON) + if(ENABLE_GNUTLS) +diff --git a/config.h.in b/config.h.in +index 345af7d..490d7f6 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -1,6 +1,25 @@ + #define PACKAGE_NAME "@CMAKE_PROJECT_NAME@" + #define PACKAGE_VERSION "@VERSION@" + ++#cmakedefine HAVE_INET_ATON ++#cmakedefine HAVE_INET_PTON ++#cmakedefine HAVE_GETADDRINFO ++#cmakedefine HAVE_GNUTLS_SET_GLOBAL_ERRNO ++#cmakedefine HAVE_GNUTLS_SET_ERRNO ++#cmakedefine HAVE_GNUTLS_X509_CRT_PRINT ++#cmakedefine HAVE_GNUTLS_X509_CRT_T ++#cmakedefine HAVE_GNUTLS_DATUM_T ++#cmakedefine HAVE_GNUTLS_PK_ALGORITHM_T ++#cmakedefine HAVE_GNUTLS_SIGN_ALGORITHM_T ++#cmakedefine HAVE_FLTK_CLIPBOARD ++#cmakedefine HAVE_FLTK_MEDIAKEYS ++#cmakedefine HAVE_FLTK_FULLSCREEN ++#cmakedefine HAVE_FLTK_FULLSCREEN_SCREENS ++#cmakedefine HAVE_FLTK_CURSOR ++#cmakedefine HAVE_FLTK_WORK_AREA ++#cmakedefine HAVE_FLTK_ICONS ++#cmakedefine HAVE_FLTK_XHANDLERS ++#cmakedefine HAVE_FLTK_IM + #cmakedefine HAVE_ACTIVE_DESKTOP_H + #cmakedefine HAVE_ACTIVE_DESKTOP_L + #cmakedefine ENABLE_NLS 1 +diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx +index bba502b..1a6e02b 100644 +--- a/vncviewer/DesktopWindow.cxx ++++ b/vncviewer/DesktopWindow.cxx +@@ -112,8 +112,13 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, + // On OS X we can do the maximize thing properly before the + // window is showned. Other platforms handled further down... + if (maximize) { ++#ifdef HAVE_FLTK_WORK_AREA + int dummy; + Fl::screen_work_area(dummy, dummy, w, h, geom_x, geom_y); ++#else ++ w = Fl::w(); ++ h = Fl::h(); ++#endif + } + #endif + +@@ -123,6 +128,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, + size(w, h); + } + ++#ifdef HAVE_FLTK_FULLSCREEN + if (fullScreen) { + // Hack: Window managers seem to be rather crappy at respecting + // fullscreen hints on initial windows. So on X11 we'll have to +@@ -133,13 +139,16 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, + delayedFullscreen = true; + #endif + } ++#endif + + show(); + + // Full screen events are not sent out for a hidden window, + // so send a fake one here to set up things properly. ++#ifdef HAVE_FLTK_FULLSCREEN + if (fullscreen_active()) + handle(FL_FULLSCREEN); ++#endif + + // Unfortunately, current FLTK does not allow us to set the + // maximized property on Windows and X11 before showing the window. +@@ -156,6 +165,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, + if ((w != this->w()) || (h != this->h())) + scroll->size(this->w(), this->h()); + ++#ifdef HAVE_FLTK_FULLSCREEN + if (delayedFullscreen) { + // Hack: Fullscreen requests may be ignored, so we need a timeout for + // when we should stop waiting. We also really need to wait for the +@@ -163,6 +173,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, + Fl::add_timeout(0.5, handleFullscreenTimeout, this); + fullscreen_on(); + } ++#endif + } + + +@@ -234,7 +245,9 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h) + // If we're letting the viewport match the window perfectly, then + // keep things that way for the new size, otherwise just keep things + // like they are. ++#ifdef HAVE_FLTK_FULLSCREEN + if (!fullscreen_active()) { ++#endif + if ((w() == viewport->w()) && (h() == viewport->h())) + size(new_w, new_h); + else { +@@ -244,7 +257,9 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h) + if ((w() > new_w) || (h() > new_h)) + size(__rfbmin(w(), new_w), __rfbmin(h(), new_h)); + } ++#ifdef HAVE_FLTK_FULLSCREEN + } ++#endif + + viewport->size(new_w, new_h); + +@@ -273,7 +288,10 @@ void DesktopWindow::resize(int x, int y, int w, int h) + #if ! (defined(WIN32) || defined(__APPLE__)) + // X11 window managers will treat a resize to cover the entire + // monitor as a request to go full screen. Make sure we avoid this. +- if (!fullscreen_active()) { ++#ifdef HAVE_FLTK_FULLSCREEN ++ if (!fullscreen_active()) ++#endif ++ { + bool resize_req; + + // If there is no X11 window, then this must be a resize request, +@@ -349,6 +367,7 @@ void DesktopWindow::resize(int x, int y, int w, int h) + int DesktopWindow::handle(int event) + { + switch (event) { ++#ifdef HAVE_FLTK_FULLSCREEN + case FL_FULLSCREEN: + fullScreen.setParam(fullscreen_active()); + +@@ -387,6 +406,16 @@ int DesktopWindow::handle(int event) + } + // Continue processing so that the viewport also gets mouse events + break; ++#endif ++ ++ case FL_SHORTCUT: ++ // Sometimes the focus gets out of whack and we fall through to the ++ // shortcut dispatching. Try to make things sane again... ++ if (Fl::focus() == NULL) { ++ take_focus(); ++ Fl::handle(FL_KEYDOWN, this); ++ } ++ return 1; + } + + return Fl_Window::handle(event); +@@ -399,6 +428,7 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win) + + ret = Fl::handle_(event, win); + ++#ifdef HAVE_FLTK_FULLSCREEN + // This is hackish and the result of the dodgy focus handling in FLTK. + // The basic problem is that FLTK's view of focus and the system's tend + // to differ, and as a result we do not see all the FL_FOCUS events we +@@ -426,6 +456,7 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win) + break; + } + } ++#endif + + return ret; + } +@@ -433,6 +464,8 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win) + + void DesktopWindow::fullscreen_on() + { ++#ifdef HAVE_FLTK_FULLSCREEN ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS + if (not fullScreenAllMonitors) + fullscreen_screens(-1, -1, -1, -1); + else { +@@ -471,8 +504,10 @@ void DesktopWindow::fullscreen_on() + + fullscreen_screens(top, bottom, left, right); + } ++#endif // HAVE_FLTK_FULLSCREEN_SCREENS + + fullscreen(); ++#endif // HAVE_FLTK_FULLSCREEN + } + + void DesktopWindow::grabKeyboard() +@@ -492,7 +527,13 @@ void DesktopWindow::grabKeyboard() + #elif defined(__APPLE__) + int ret; + +- ret = cocoa_capture_display(this, fullScreenAllMonitors); ++ ret = cocoa_capture_display(this, ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS ++ fullScreenAllMonitors ++#else ++ false ++#endif ++ ); + if (ret != 0) + vlog.error(_("Failure grabbing keyboard")); + #else +@@ -549,12 +590,14 @@ void DesktopWindow::handleGrab(void *data) + + assert(self); + ++#ifdef HAVE_FLTK_FULLSCREEN + if (!fullscreenSystemKeys) + return; + if (!self->fullscreen_active()) + return; + + self->grabKeyboard(); ++#endif + } + + +@@ -565,22 +608,31 @@ void DesktopWindow::maximizeWindow() + // We cannot use ShowWindow() in full screen mode as it will + // resize things implicitly. Fortunately modifying the style + // directly results in a maximized state once we leave full screen. ++#ifdef HAVE_FLTK_FULLSCREEN + if (fullscreen_active()) { + WINDOWINFO wi; + wi.cbSize = sizeof(WINDOWINFO); + GetWindowInfo(fl_xid(this), &wi); + SetWindowLongPtr(fl_xid(this), GWL_STYLE, wi.dwStyle | WS_MAXIMIZE); + } else ++#endif + ShowWindow(fl_xid(this), SW_MAXIMIZE); + #elif defined(__APPLE__) + // OS X is somewhat strange and does not really have a concept of a + // maximized window, so we can simply resize the window to the workarea. + // Note that we shouldn't do this whilst in full screen as that will + // incorrectly adjust things. ++#ifdef HAVE_FLTK_FULLSCREEN + if (fullscreen_active()) + return; ++#endif + int X, Y, W, H; ++#ifdef HAVE_FLTK_WORK_AREA + Fl::screen_work_area(X, Y, W, H, this->x(), this->y()); ++#else ++ W = Fl::w(); ++ H = Fl::h(); ++#endif + size(W, H); + #else + // X11 +@@ -638,7 +690,9 @@ void DesktopWindow::remoteResize(int width, int height) + ScreenSet layout; + ScreenSet::iterator iter; + ++#ifdef HAVE_FLTK_FULLSCREEN + if (!fullscreen_active() || (width > w()) || (height > h())) { ++#endif + // In windowed mode (or the framebuffer is so large that we need + // to scroll) we just report a single virtual screen that covers + // the entire framebuffer. +@@ -669,6 +723,7 @@ void DesktopWindow::remoteResize(int width, int height) + layout.begin()->dimensions.tl.y = 0; + layout.begin()->dimensions.br.x = width; + layout.begin()->dimensions.br.y = height; ++#ifdef HAVE_FLTK_FULLSCREEN + } else { + int i; + rdr::U32 id; +@@ -735,6 +790,7 @@ void DesktopWindow::remoteResize(int width, int height) + if (layout.num_screens() == 0) + layout.add_screen(rfb::Screen(0, 0, 0, width, height, 0)); + } ++#endif + + // Do we actually change anything? + if ((width == cc->cp.width) && +@@ -810,6 +866,7 @@ void DesktopWindow::handleOptions(void *data) + { + DesktopWindow *self = (DesktopWindow*)data; + ++#ifdef HAVE_FLTK_FULLSCREEN + if (self->fullscreen_active() && fullscreenSystemKeys) + self->grabKeyboard(); + else +@@ -819,6 +876,7 @@ void DesktopWindow::handleOptions(void *data) + self->fullscreen_on(); + else if (!fullScreen && self->fullscreen_active()) + self->fullscreen_off(); ++#endif + } + + void DesktopWindow::handleFullscreenTimeout(void *data) +@@ -837,6 +895,7 @@ void DesktopWindow::handleFullscreenTimeout(void *data) + + void DesktopWindow::handleEdgeScroll(void *data) + { ++#ifdef HAVE_FLTK_FULLSCREEN + DesktopWindow *self = (DesktopWindow *)data; + + int mx, my; +@@ -893,4 +952,5 @@ void DesktopWindow::handleEdgeScroll(void *data) + self->scroll->scroll_to(self->scroll->xposition() - dx, self->scroll->yposition() - dy); + + Fl::repeat_timeout(0.1, handleEdgeScroll, data); ++#endif + } +diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx +index 3c8fcb4..d1495ef 100644 +--- a/vncviewer/OptionsDialog.cxx ++++ b/vncviewer/OptionsDialog.cxx +@@ -290,8 +290,12 @@ void OptionsDialog::loadOptions(void) + desktopHeightInput->value(buf); + } + remoteResizeCheckbox->value(remoteResize); ++#ifdef HAVE_FLTK_FULLSCREEN + fullScreenCheckbox->value(fullScreen); ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS + fullScreenAllMonitorsCheckbox->value(fullScreenAllMonitors); ++#endif // HAVE_FLTK_FULLSCREEN_SCREENS ++#endif // HAVE_FLTK_FULLSCREEN + + handleDesktopSize(desktopSizeCheckbox, this); + +@@ -394,8 +398,12 @@ void OptionsDialog::storeOptions(void) + desktopSize.setParam(""); + } + remoteResize.setParam(remoteResizeCheckbox->value()); ++#ifdef HAVE_FLTK_FULLSCREEN + fullScreen.setParam(fullScreenCheckbox->value()); ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS + fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox->value()); ++#endif // HAVE_FLTK_FULLSCREEN_SCREENS ++#endif // HAVE_FLTK_FULLSCREEN + + /* Misc. */ + shared.setParam(sharedCheckbox->value()); +@@ -750,18 +758,26 @@ void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th) + _("Resize remote session to the local window"))); + ty += CHECK_HEIGHT + TIGHT_MARGIN; + ++#ifdef HAVE_FLTK_FULLSCREEN ++ + fullScreenCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty, + CHECK_MIN_WIDTH, + CHECK_HEIGHT, + _("Full-screen mode"))); + ty += CHECK_HEIGHT + TIGHT_MARGIN; + ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS ++ + fullScreenAllMonitorsCheckbox = new Fl_Check_Button(LBLRIGHT(tx + INDENT, ty, + CHECK_MIN_WIDTH, + CHECK_HEIGHT, + _("Enable full-screen mode over all monitors"))); + ty += CHECK_HEIGHT + TIGHT_MARGIN; + ++#endif // HAVE_FLTK_FULLSCREEN_SCREENS ++ ++#endif // HAVE_FLTK_FULLSCREEN ++ + group->end(); + } + +diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx +index ca65acd..4c989f3 100644 +--- a/vncviewer/Viewport.cxx ++++ b/vncviewer/Viewport.cxx +@@ -106,10 +106,15 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_) + lastPointerPos(0, 0), lastButtonMask(0), + menuCtrlKey(false), menuAltKey(false), cursor(NULL) + { ++// FLTK STR #2636 gives us the ability to monitor clipboard changes ++#ifdef HAVE_FLTK_CLIPBOARD + Fl::add_clipboard_notify(handleClipboardChange, this); ++#endif + ++#ifdef HAVE_FLTK_XHANDLERS + // We need to intercept keyboard events early + Fl::add_system_handler(handleSystemEvent, this); ++#endif + + frameBuffer = createFramebuffer(w, h); + assert(frameBuffer); +@@ -143,9 +148,13 @@ Viewport::~Viewport() + // again later when this object is already gone. + Fl::remove_timeout(handlePointerTimeout, this); + ++#ifdef HAVE_FLTK_XHANDLERS + Fl::remove_system_handler(handleSystemEvent); ++#endif + ++#ifdef HAVE_FLTK_CLIPBOARD + Fl::remove_clipboard_notify(handleClipboardChange); ++#endif + + OptionsDialog::removeCallback(handleOptions); + +@@ -185,6 +194,7 @@ rfb::ModifiablePixelBuffer* Viewport::getFramebuffer(void) + return frameBuffer; + } + ++#ifdef HAVE_FLTK_CURSOR + static const char * dotcursor_xpm[] = { + "5 5 2 1", + ". c #000000", +@@ -194,10 +204,12 @@ static const char * dotcursor_xpm[] = { + " ... ", + " ... ", + " "}; ++#endif + + void Viewport::setCursor(int width, int height, const Point& hotspot, + void* data, void* mask) + { ++#ifdef HAVE_FLTK_CURSOR + if (cursor) { + if (!cursor->alloc_array) + delete [] cursor->array; +@@ -257,6 +269,7 @@ void Viewport::setCursor(int width, int height, const Point& hotspot, + + if (Fl::belowmouse() == this) + window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y); ++#endif + } + + +@@ -354,13 +367,17 @@ int Viewport::handle(int event) + return 1; + + case FL_ENTER: ++ // Yes, we would like some pointer events please! ++#ifdef HAVE_FLTK_CURSOR + if (cursor) + window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y); +- // Yes, we would like some pointer events please! ++#endif + return 1; + + case FL_LEAVE: ++#ifdef HAVE_FLTK_CURSOR + window()->cursor(FL_CURSOR_DEFAULT); ++#endif + // Fall through as we want a last move event to help trigger edge stuff + case FL_PUSH: + case FL_RELEASE: +@@ -396,7 +413,9 @@ int Viewport::handle(int event) + return 1; + + case FL_FOCUS: ++#ifdef HAVE_FLTK_IM + Fl::disable_im(); ++#endif + // Yes, we would like some focus please! + return 1; + +@@ -405,12 +424,17 @@ int Viewport::handle(int event) + // sense (e.g. Alt+Tab where we only see the Alt press) + while (!downKeySym.empty()) + handleKeyRelease(downKeySym.begin()->first); ++#ifdef HAVE_FLTK_IM + Fl::enable_im(); ++#endif + return 1; + + case FL_KEYDOWN: ++ handleFLTKKeyPress(); ++ return 1; ++ + case FL_KEYUP: +- // Just ignore these as keys were handled in the event handler ++ handleKeyRelease(Fl::event_original_key()); + return 1; + } + +@@ -784,6 +808,258 @@ int Viewport::handleSystemEvent(void *event, void *data) + return 0; + } + ++ ++rdr::U32 Viewport::translateKeyEvent(void) ++{ ++ unsigned ucs; ++ int keyCode, origKeyCode; ++ const char *keyText; ++ int keyTextLen; ++ ++ keyCode = Fl::event_key(); ++ origKeyCode = Fl::event_original_key(); ++ keyText = Fl::event_text(); ++ keyTextLen = Fl::event_length(); ++ ++ vlog.debug("FLTK key %d (%d) '%s'[%d]", origKeyCode, keyCode, keyText, keyTextLen); ++ ++ // First check for function keys ++ if ((keyCode > FL_F) && (keyCode <= FL_F_Last)) ++ return XK_F1 + (keyCode - FL_F - 1); ++ ++ // Numpad numbers ++ if ((keyCode >= (FL_KP + '0')) && (keyCode <= (FL_KP + '9'))) ++ return XK_KP_0 + (keyCode - (FL_KP + '0')); ++ ++ // FLTK does some special remapping of numpad keys when numlock is off ++ if ((origKeyCode >= FL_KP) && (origKeyCode <= FL_KP_Last)) { ++ switch (keyCode) { ++ case FL_F+1: ++ return XK_KP_F1; ++ case FL_F+2: ++ return XK_KP_F2; ++ case FL_F+3: ++ return XK_KP_F3; ++ case FL_F+4: ++ return XK_KP_F4; ++ case FL_Home: ++ return XK_KP_Home; ++ case FL_Left: ++ return XK_KP_Left; ++ case FL_Up: ++ return XK_KP_Up; ++ case FL_Right: ++ return XK_KP_Right; ++ case FL_Down: ++ return XK_KP_Down; ++ case FL_Page_Up: ++ return XK_KP_Page_Up; ++ case FL_Page_Down: ++ return XK_KP_Page_Down; ++ case FL_End: ++ return XK_KP_End; ++ case FL_Insert: ++ return XK_KP_Insert; ++ case FL_Delete: ++ return XK_KP_Delete; ++ } ++ } ++ ++#if defined(WIN32) || defined(__APPLE__) ++ // X11 fairly consistently uses XK_KP_Separator for comma and ++ // XK_KP_Decimal for period. Windows and OS X are a different matter ++ // though. ++ // ++ // OS X will consistently generate the same key code no matter what ++ // layout is being used. ++ // ++ // Windows is terribly inconcistent, and is not something that's ++ // likely to change: ++ // http://blogs.msdn.com/michkap/archive/2006/09/13/752377.aspx ++ // ++ // To get X11 behaviour, we instead look at the text generated by ++ // they key. ++ if ((keyCode == (FL_KP + ',')) || (keyCode == (FL_KP + '.'))) { ++ switch (keyText[0]) { ++ case ',': ++ return XK_KP_Separator; ++ case '.': ++ return XK_KP_Decimal; ++ default: ++ vlog.error(_("Unknown decimal separator: '%s'"), keyText); ++ return XK_KP_Decimal; ++ } ++ } ++#endif ++ ++ // Then other special keys ++ switch (keyCode) { ++ case FL_BackSpace: ++ return XK_BackSpace; ++ case FL_Tab: ++ return XK_Tab; ++ case FL_Enter: ++ return XK_Return; ++ case FL_Pause: ++ return XK_Pause; ++ case FL_Scroll_Lock: ++ return XK_Scroll_Lock; ++ case FL_Escape: ++ return XK_Escape; ++ case FL_Home: ++ return XK_Home; ++ case FL_Left: ++ return XK_Left; ++ case FL_Up: ++ return XK_Up; ++ case FL_Right: ++ return XK_Right; ++ case FL_Down: ++ return XK_Down; ++ case FL_Page_Up: ++ return XK_Page_Up; ++ case FL_Page_Down: ++ return XK_Page_Down; ++ case FL_End: ++ return XK_End; ++ case FL_Print: ++ return XK_Print; ++ case FL_Insert: ++ return XK_Insert; ++ case FL_Menu: ++ return XK_Menu; ++ case FL_Help: ++ return XK_Help; ++ case FL_Num_Lock: ++ return XK_Num_Lock; ++ case FL_Shift_L: ++ return XK_Shift_L; ++ case FL_Shift_R: ++ return XK_Shift_R; ++ case FL_Control_L: ++ return XK_Control_L; ++ case FL_Control_R: ++ return XK_Control_R; ++ case FL_Caps_Lock: ++ return XK_Caps_Lock; ++ case FL_Meta_L: ++ return XK_Super_L; ++ case FL_Meta_R: ++ return XK_Super_R; ++ case FL_Alt_L: ++ return XK_Alt_L; ++ case FL_Alt_R: ++ return XK_Alt_R; ++ case FL_Delete: ++ return XK_Delete; ++ case FL_KP_Enter: ++ return XK_KP_Enter; ++ case FL_KP + '=': ++ return XK_KP_Equal; ++ case FL_KP + '*': ++ return XK_KP_Multiply; ++ case FL_KP + '+': ++ return XK_KP_Add; ++ case FL_KP + ',': ++ return XK_KP_Separator; ++ case FL_KP + '-': ++ return XK_KP_Subtract; ++ case FL_KP + '.': ++ return XK_KP_Decimal; ++ case FL_KP + '/': ++ return XK_KP_Divide; ++#ifdef HAVE_FLTK_MEDIAKEYS ++ case FL_Volume_Down: ++ return XF86XK_AudioLowerVolume; ++ case FL_Volume_Mute: ++ return XF86XK_AudioMute; ++ case FL_Volume_Up: ++ return XF86XK_AudioRaiseVolume; ++ case FL_Media_Play: ++ return XF86XK_AudioPlay; ++ case FL_Media_Stop: ++ return XF86XK_AudioStop; ++ case FL_Media_Prev: ++ return XF86XK_AudioPrev; ++ case FL_Media_Next: ++ return XF86XK_AudioNext; ++ case FL_Home_Page: ++ return XF86XK_HomePage; ++ case FL_Mail: ++ return XF86XK_Mail; ++ case FL_Search: ++ return XF86XK_Search; ++ case FL_Back: ++ return XF86XK_Back; ++ case FL_Forward: ++ return XF86XK_Forward; ++ case FL_Stop: ++ return XF86XK_Stop; ++ case FL_Refresh: ++ return XF86XK_Refresh; ++ case FL_Sleep: ++ return XF86XK_Sleep; ++ case FL_Favorites: ++ return XF86XK_Favorites; ++#endif ++ case XK_ISO_Level3_Shift: ++ // FLTK tends to let this one leak through on X11... ++ return XK_ISO_Level3_Shift; ++ case XK_Multi_key: ++ // Same for this... ++ return XK_Multi_key; ++ } ++ ++ // Unknown special key? ++ if (keyTextLen == 0) { ++ vlog.error(_("Unknown FLTK key code %d (0x%04x)"), keyCode, keyCode); ++ return NoSymbol; ++ } ++ ++ // Control character? ++ if ((keyTextLen == 1) && ((keyText[0] < 0x20) | (keyText[0] == 0x7f))) { ++ if (keyText[0] == 0x00) ++ return XK_2; ++ else if (keyText[0] < 0x1b) { ++ if (!!Fl::event_state(FL_SHIFT) != !!Fl::event_state(FL_CAPS_LOCK)) ++ return keyText[0] + XK_A - 0x01; ++ else ++ return keyText[0] + XK_a - 0x01; ++ } else if (keyText[0] < 0x20) ++ return keyText[0] + XK_3 - 0x1b; ++ else ++ return XK_8; ++ } ++ ++ // Look up the symbol the key produces and translate that from Unicode ++ // to a X11 keysym. ++ if (fl_utf_nb_char((const unsigned char*)keyText, strlen(keyText)) != 1) { ++ vlog.error(_("Multiple characters given for key code %d (0x%04x): '%s'"), ++ keyCode, keyCode, keyText); ++ return NoSymbol; ++ } ++ ++ ucs = fl_utf8decode(keyText, NULL, NULL); ++ return ucs2keysym(ucs); ++} ++ ++ ++void Viewport::handleFLTKKeyPress(void) ++{ ++ rdr::U32 keySym; ++ ++#ifdef HAVE_FLTK_XHANDLERS ++ return; ++#endif ++ ++ keySym = translateKeyEvent(); ++ if (keySym == NoSymbol) ++ return; ++ ++ handleKeyPress(Fl::event_original_key(), keySym); ++} ++ ++ + void Viewport::initContextMenu() + { + contextMenu->clear(); +@@ -791,11 +1067,15 @@ void Viewport::initContextMenu() + fltk_menu_add(contextMenu, _("E&xit viewer"), 0, NULL, + (void*)ID_EXIT, FL_MENU_DIVIDER); + ++#ifdef HAVE_FLTK_FULLSCREEN + fltk_menu_add(contextMenu, _("&Full screen"), 0, NULL, (void*)ID_FULLSCREEN, + FL_MENU_TOGGLE | (window()->fullscreen_active()?FL_MENU_VALUE:0)); ++#endif + fltk_menu_add(contextMenu, _("Resize &window to session"), 0, NULL, + (void*)ID_RESIZE, ++#ifdef HAVE_FLTK_FULLSCREEN + (window()->fullscreen_active()?FL_MENU_INACTIVE:0) | ++#endif + FL_MENU_DIVIDER); + + fltk_menu_add(contextMenu, _("&Ctrl"), 0, NULL, (void*)ID_CTRL, +@@ -843,14 +1123,18 @@ void Viewport::popupContextMenu() + + // Unfortunately FLTK doesn't reliably restore the mouse pointer for + // menus, so we have to help it out. ++#ifdef HAVE_FLTK_CURSOR + if (Fl::belowmouse() == this) + window()->cursor(FL_CURSOR_DEFAULT); ++#endif + + m = contextMenu->popup(); + + // Back to our proper mouse pointer. ++#ifdef HAVE_FLTK_CURSOR + if ((Fl::belowmouse() == this) && cursor) + window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y); ++#endif + + if (m == NULL) + return; +@@ -859,15 +1143,19 @@ void Viewport::popupContextMenu() + case ID_EXIT: + exit_vncviewer(); + break; ++#ifdef HAVE_FLTK_FULLSCREEN + case ID_FULLSCREEN: + if (window()->fullscreen_active()) + window()->fullscreen_off(); + else + ((DesktopWindow*)window())->fullscreen_on(); + break; ++#endif + case ID_RESIZE: ++#ifdef HAVE_FLTK_FULLSCREEN + if (window()->fullscreen_active()) + break; ++#endif + window()->size(w(), h()); + break; + case ID_CTRL: +diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h +index 387ff03..8e60da6 100644 +--- a/vncviewer/Viewport.h ++++ b/vncviewer/Viewport.h +@@ -75,6 +75,9 @@ private: + + static int handleSystemEvent(void *event, void *data); + ++ rdr::U32 translateKeyEvent(void); ++ void handleFLTKKeyPress(void); ++ + void initContextMenu(); + void popupContextMenu(); + +diff --git a/vncviewer/cocoa.mm b/vncviewer/cocoa.mm +index 3919cb8..e51cba9 100644 +--- a/vncviewer/cocoa.mm ++++ b/vncviewer/cocoa.mm +@@ -60,7 +60,11 @@ int cocoa_capture_display(Fl_Window *win, bool all_displays) + if (count != (unsigned)Fl::screen_count()) + return 1; + ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS + index = Fl::screen_num(win->x(), win->y(), win->w(), win->h()); ++#else ++ index = 0; ++#endif + + if (CGDisplayCapture(displays[index]) != kCGErrorSuccess) + return 1; +@@ -95,9 +99,11 @@ void cocoa_release_display(Fl_Window *win) + + // FIXME: Store the previous level somewhere so we don't have to hard + // code a level here. ++#ifdef HAVE_FLTK_FULLSCREEN + if (win->fullscreen_active() && win->contains(Fl::focus())) + newlevel = NSStatusWindowLevel; + else ++#endif + newlevel = NSNormalWindowLevel; + + // Only change if different as the level change also moves the window +diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx +index 7cce1cd..3dca578 100644 +--- a/vncviewer/parameters.cxx ++++ b/vncviewer/parameters.cxx +@@ -92,10 +92,14 @@ IntParameter qualityLevel("QualityLevel", + 8); + + BoolParameter maximize("Maximize", "Maximize viewer window", false); ++#ifdef HAVE_FLTK_FULLSCREEN + BoolParameter fullScreen("FullScreen", "Full screen mode", false); ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS + BoolParameter fullScreenAllMonitors("FullScreenAllMonitors", + "Enable full screen over all monitors", + true); ++#endif // HAVE_FLTK_FULLSCREEN_SCREENS ++#endif // HAVE_FLTK_FULLSCREEN + StringParameter desktopSize("DesktopSize", + "Reconfigure desktop size on the server on " + "connect (if possible)", ""); +@@ -156,8 +160,12 @@ static VoidParameter* parameterArray[] = { + &compressLevel, + &noJpeg, + &qualityLevel, ++#ifdef HAVE_FLTK_FULLSCREEN + &fullScreen, ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS + &fullScreenAllMonitors, ++#endif // HAVE_FLTK_FULLSCREEN_SCREENS ++#endif // HAVE_FLTK_FULLSCREEN + &desktopSize, + &geometry, + &remoteResize, +diff --git a/vncviewer/parameters.h b/vncviewer/parameters.h +index 0de61d2..9827b14 100644 +--- a/vncviewer/parameters.h ++++ b/vncviewer/parameters.h +@@ -39,8 +39,12 @@ extern rfb::BoolParameter noJpeg; + extern rfb::IntParameter qualityLevel; + + extern rfb::BoolParameter maximize; ++#ifdef HAVE_FLTK_FULLSCREEN + extern rfb::BoolParameter fullScreen; ++#ifdef HAVE_FLTK_FULLSCREEN_SCREENS + extern rfb::BoolParameter fullScreenAllMonitors; ++#endif // HAVE_FLTK_FULLSCREEN_SCREENS ++#endif // HAVE_FLTK_FULLSCREEN + extern rfb::StringParameter desktopSize; + extern rfb::StringParameter geometry; + extern rfb::BoolParameter remoteResize; +diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx +index 4b989bb..598acde 100644 +--- a/vncviewer/vncviewer.cxx ++++ b/vncviewer/vncviewer.cxx +@@ -181,6 +181,7 @@ static void init_fltk() + Fl_Window::default_xclass("vncviewer"); + + // Set the default icon for all windows. ++#ifdef HAVE_FLTK_ICONS + #ifdef WIN32 + HICON lg, sm; + +@@ -240,6 +241,7 @@ static void init_fltk() + for (int i = 0;i < count;i++) + delete icons[i]; + #endif ++#endif // FLTK_HAVE_ICONS + + // This makes the "icon" in dialogs rounded, which fits better + // with the above schemes. diff --git a/tigervnc-clean-pressed-key-on-exit.patch b/tigervnc-clean-pressed-key-on-exit.patch index 1c38242..c8f76b4 100644 --- a/tigervnc-clean-pressed-key-on-exit.patch +++ b/tigervnc-clean-pressed-key-on-exit.patch @@ -1,8 +1,8 @@ -Index: tigervnc-1.4.1/vncviewer/DesktopWindow.cxx +Index: tigervnc-1.5.0/vncviewer/DesktopWindow.cxx =================================================================== ---- tigervnc-1.4.1.orig/vncviewer/DesktopWindow.cxx -+++ tigervnc-1.4.1/vncviewer/DesktopWindow.cxx -@@ -188,6 +188,8 @@ DesktopWindow::~DesktopWindow() +--- tigervnc-1.5.0.orig/vncviewer/DesktopWindow.cxx ++++ tigervnc-1.5.0/vncviewer/DesktopWindow.cxx +@@ -177,6 +177,8 @@ DesktopWindow::~DesktopWindow() OptionsDialog::removeCallback(handleOptions); @@ -11,11 +11,11 @@ Index: tigervnc-1.4.1/vncviewer/DesktopWindow.cxx // FLTK automatically deletes all child widgets, so we shouldn't touch // them ourselves here } -Index: tigervnc-1.4.1/vncviewer/Viewport.cxx +Index: tigervnc-1.5.0/vncviewer/Viewport.cxx =================================================================== ---- tigervnc-1.4.1.orig/vncviewer/Viewport.cxx -+++ tigervnc-1.4.1/vncviewer/Viewport.cxx -@@ -144,6 +144,11 @@ Viewport::Viewport(int w, int h, const r +--- tigervnc-1.5.0.orig/vncviewer/Viewport.cxx ++++ tigervnc-1.5.0/vncviewer/Viewport.cxx +@@ -139,6 +139,11 @@ Viewport::Viewport(int w, int h, const r Viewport::~Viewport() { @@ -27,23 +27,23 @@ Index: tigervnc-1.4.1/vncviewer/Viewport.cxx // Unregister all timeouts in case they get a change tro trigger // again later when this object is already gone. Fl::remove_timeout(handlePointerTimeout, this); -Index: tigervnc-1.4.1/vncviewer/vncviewer.cxx +Index: tigervnc-1.5.0/vncviewer/vncviewer.cxx =================================================================== ---- tigervnc-1.4.1.orig/vncviewer/vncviewer.cxx -+++ tigervnc-1.4.1/vncviewer/vncviewer.cxx -@@ -88,6 +88,8 @@ char vncServerName[VNCSERVERNAMELEN] = { - static bool exitMainloop = false; - static const char *exitError = NULL; +--- tigervnc-1.5.0.orig/vncviewer/vncviewer.cxx ++++ tigervnc-1.5.0/vncviewer/vncviewer.cxx +@@ -107,6 +107,8 @@ static const char *about_text() + return buffer; + } +static CConn *cc; + void exit_vncviewer(const char *error) { // Prioritise the first error we get as that is probably the most -@@ -114,6 +116,16 @@ static void CleanupSignalHandler(int sig +@@ -158,6 +160,16 @@ static void CleanupSignalHandler(int sig // CleanupSignalHandler allows C++ object cleanup to happen because it calls // exit() rather than the default which is to abort. - vlog.info(_("CleanupSignalHandler called")); + vlog.info(_("Termination signal %d has been received. TigerVNC Viewer will now exit."), sig); + delete cc; + exit(1); +} @@ -57,7 +57,7 @@ Index: tigervnc-1.4.1/vncviewer/vncviewer.cxx exit(1); } -@@ -392,11 +404,19 @@ int main(int argc, char** argv) +@@ -460,11 +472,19 @@ int main(int argc, char** argv) init_fltk(); @@ -77,7 +77,7 @@ Index: tigervnc-1.4.1/vncviewer/vncviewer.cxx Configuration::enableViewerParams(); /* Load the default parameter settings */ -@@ -497,7 +517,7 @@ int main(int argc, char** argv) +@@ -577,7 +597,7 @@ int main(int argc, char** argv) #endif } diff --git a/tigervnc-newfbsize.patch b/tigervnc-newfbsize.patch index a059b14..24e0ebe 100644 --- a/tigervnc-newfbsize.patch +++ b/tigervnc-newfbsize.patch @@ -1,8 +1,8 @@ -Index: tigervnc-1.4.1/vncviewer/CConn.cxx +Index: tigervnc-1.5.0/vncviewer/CConn.cxx =================================================================== ---- tigervnc-1.4.1.orig/vncviewer/CConn.cxx -+++ tigervnc-1.4.1/vncviewer/CConn.cxx -@@ -424,6 +424,8 @@ void CConn::dataRect(const Rect& r, int +--- tigervnc-1.5.0.orig/vncviewer/CConn.cxx ++++ tigervnc-1.5.0/vncviewer/CConn.cxx +@@ -427,6 +427,8 @@ void CConn::dataRect(const Rect& r, int if (encoding != encodingCopyRect) lastServerEncoding = encoding; @@ -10,4 +10,4 @@ Index: tigervnc-1.4.1/vncviewer/CConn.cxx + setDesktopSize( r.width(), r.height() ); if (!Decoder::supported(encoding)) { - vlog.error(_("Unknown rect encoding %d"), encoding); + // TRANSLATORS: Refers to a VNC protocol encoding type diff --git a/tigervnc-sf3495623.patch b/tigervnc-sf3495623.patch deleted file mode 100644 index c4b5d08..0000000 --- a/tigervnc-sf3495623.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff -ur tigervnc-1.3.0.orig/common/network/TcpSocket.cxx tigervnc-1.3.0/common/network/TcpSocket.cxx ---- tigervnc-1.3.0.orig/common/network/TcpSocket.cxx 2014-02-07 16:35:24.644388330 +0200 -+++ tigervnc-1.3.0/common/network/TcpSocket.cxx 2014-02-07 16:39:50.608078320 +0200 -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -450,7 +451,10 @@ - } - - void TcpListener::getMyAddresses(std::list* result) { -- const hostent* addrs = gethostbyname(0); -+ char hostname[HOST_NAME_MAX]; -+ if (gethostname(hostname, HOST_NAME_MAX) < 0) -+ throw rdr::SystemException("gethostname", errorNumber); -+ const hostent* addrs = gethostbyname(hostname); - if (addrs == 0) - throw rdr::SystemException("gethostbyname", errorNumber); - if (addrs->h_addrtype != AF_INET) diff --git a/tigervnc.changes b/tigervnc.changes index 26a2218..0eaa7f5 100644 --- a/tigervnc.changes +++ b/tigervnc.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Wed Jul 15 11:52:02 UTC 2015 - msrb@suse.com + +- Updated to tigervnc 1.5.0. +- Dropped no longer needed patches: + * tigervnc-sf3495623.patch + * u_syslog.patch + * u_tigervnc-build-with-xserver-1.17.patch +- Use encryption everywhere. (fate#318936) +- Work with fltk 1.3.2. + * N_tigervnc_revert_fltk_1_3_3_requirements.patch + ------------------------------------------------------------------- Mon Apr 20 12:10:10 UTC 2015 - msrb@suse.com diff --git a/tigervnc.spec b/tigervnc.spec index abd5a0d..bcd1ca0 100644 --- a/tigervnc.spec +++ b/tigervnc.spec @@ -16,8 +16,14 @@ # +%define vncgroup vnc +%define vncuser vnc + +%define tlskey %{_sysconfdir}/vnc/tls.key +%define tlscert %{_sysconfdir}/vnc/tls.cert + Name: tigervnc -Version: 1.4.3 +Version: 1.5.0 Release: 0 Provides: tightvnc = 1.3.9 Obsoletes: tightvnc < 1.3.9 @@ -92,7 +98,6 @@ Summary: A high-performance, platform-neutral implementation of VNC License: GPL-2.0 and MIT Group: System/X11/Servers/XF86_4 Source1: https://github.com/TigerVNC/tigervnc/archive/v%{version}.tar.gz -Source2: index.vnc Source3: vnc.xinetd Source4: 10-libvnc.conf Source5: vnc-server.firewall @@ -102,18 +107,15 @@ Source8: vnc.reg Source9: vncpasswd.arg Patch1: tigervnc-newfbsize.patch Patch2: tigervnc-clean-pressed-key-on-exit.patch -Patch3: tigervnc-sf3495623.patch -Patch4: u_tigervnc-dont-send-ascii-control-characters.patch -Patch5: u_tigervnc-ignore-epipe-on-write.patch -Patch6: n_tigervnc-date-time.patch -Patch7: U_include-vencrypt-only-if-any-subtype-present.patch -Patch8: u_tigervnc-use_preferred_mode.patch -Patch9: u_tigervnc-cve-2014-8240.patch -Patch10: u_tigervnc-build-with-xserver-1.17.patch -Patch11: u_terminate_instead_of_ignoring_restart.patch -# Require and build against gnutls 3.x -Patch12: tigervnc-gnutls-3.4-required.patch -Patch13: u_syslog.patch +Patch3: u_tigervnc-ignore-epipe-on-write.patch +Patch4: n_tigervnc-date-time.patch +Patch5: U_include-vencrypt-only-if-any-subtype-present.patch +Patch6: u_tigervnc-use_preferred_mode.patch +Patch7: u_tigervnc-cve-2014-8240.patch +Patch8: u_tigervnc-use-default-trust-manager-in-java-viewer-if-custom.patch +Patch9: u_tigervnc-display-SHA-1-fingerprint-of-untrusted-certificate.patch +Patch10: u_tigervnc-add-autoaccept-parameter.patch +Patch11: N_tigervnc_revert_fltk_1_3_3_requirements.patch %description TigerVNC is a high-performance, platform-neutral implementation of VNC (Virtual Network Computing), @@ -123,6 +125,11 @@ it attempts to maintain a common look and feel and re-use components, where poss TigerVNC also provides extensions for advanced authentication methods and TLS encryption. %package -n xorg-x11-Xvnc +# Needed to generate certificates +Requires(post): openssl +# Needed to serve java applet +Requires: python +Requires: python-pyOpenSSL Requires: xinetd Requires: xkeyboard-config Summary: TigerVNC implementation of Xvnc @@ -137,20 +144,18 @@ cp -r /usr/src/xserver/* unix/xserver/ %patch1 -p1 %patch2 -p1 -%patch3 -p1 -%patch4 -p0 +%patch3 -p0 +%patch4 -p1 %patch5 -p0 -%patch6 -p1 -%patch7 -p0 -%patch8 -p0 +%patch6 -p0 +%patch7 -p1 +%patch8 -p1 %patch9 -p1 %patch10 -p1 %patch11 -p1 -%patch12 -p1 -%patch13 -p1 pushd unix/xserver -patch -p1 < ../xserver116.patch +patch -p1 < ../xserver117.patch popd %build @@ -203,7 +208,6 @@ mkdir -p $RPM_BUILD_ROOT%{_datadir}/vnc/classes install -m755 VncViewer.jar $RPM_BUILD_ROOT%{_datadir}/vnc/classes popd -install -D -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_datadir}/vnc/classes install -D -m 644 %{SOURCE3} $RPM_BUILD_ROOT/etc/xinetd.d/vnc %ifnarch s390x install -D -m 644 %{SOURCE4} $RPM_BUILD_ROOT/etc/X11/xorg.conf.d/10-libvnc.conf @@ -218,22 +222,40 @@ ln -s -f %{_sysconfdir}/alternatives/vncviewer $RPM_BUILD_ROOT%{_bindir}/vncview ln -s -f %{_sysconfdir}/alternatives/vncviewer.1.gz $RPM_BUILD_ROOT%{_mandir}/man1/vncviewer.1.gz %endif +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/vnc + rm -rf $RPM_BUILD_ROOT/usr/share/doc/tigervnc-* %find_lang '%{name}' -%if 0%{?suse_version} >= 1315 +%pre -n xorg-x11-Xvnc +getent group %{vncgroup} > /dev/null || groupadd -r %{vncgroup} +getent passwd %{vncuser} > /dev/null || useradd -r -g %{vncgroup} -d /var/lib/empty -s /sbin/nologin -c "user for VNC" %{vncuser} + +%post -n xorg-x11-Xvnc +if ! test -e %{tlskey} ; then + (umask 077 && openssl genrsa -out %{tlskey} 2048) + chown %{vncuser}:%{vncgroup} %{tlskey} +fi +if ! test -e %{tlscert} ; then + cn="Automatically generated certificate for the VNC service" + openssl req -new -x509 -extensions usr_cert \ + -key %{tlskey} -out %{tlscert} -days 7305 -subj "/CN=$cn/" + chown %{vncuser}:%{vncgroup} %{tlscert} +fi %post +%if 0%{?suse_version} >= 1315 %_sbindir/update-alternatives \ --install %{_bindir}/vncviewer vncviewer %{_bindir}/vncviewer-tigervnc 20 \ --slave %{_mandir}/man1/vncviewer.1.gz vncviewer.1.gz %{_mandir}/man1/vncviewer-tigervnc.1.gz +%endif %postun +%if 0%{?suse_version} >= 1315 if [ "$1" = 0 ] ; then "%_sbindir/update-alternatives" --remove vncviewer /usr/bin/vncviewer-tigervnc fi - %endif %files -f %{name}.lang @@ -298,4 +320,8 @@ fi %doc java/com/tigervnc/vncviewer/README %{_datadir}/vnc +%dir %{_sysconfdir}/vnc +%ghost %attr(0600,%{vncuser},%{vncuser}) %config(noreplace) %{tlskey} +%ghost %attr(0644,%{vncuser},%{vncuser}) %config(noreplace) %{tlscert} + %changelog diff --git a/u_syslog.patch b/u_syslog.patch deleted file mode 100644 index aee0398..0000000 --- a/u_syslog.patch +++ /dev/null @@ -1,196 +0,0 @@ -Author: Michal Srb -Subject: Syslog logging -Patch-Mainline: To be upstreamed - -Index: tigervnc-1.4.1/common/rfb/CMakeLists.txt -=================================================================== ---- tigervnc-1.4.1.orig/common/rfb/CMakeLists.txt -+++ tigervnc-1.4.1/common/rfb/CMakeLists.txt -@@ -29,6 +29,7 @@ set(RFB_SOURCES - Logger.cxx - Logger_file.cxx - Logger_stdio.cxx -+ Logger_syslog.cxx - Password.cxx - PixelBuffer.cxx - PixelFormat.cxx -Index: tigervnc-1.4.1/common/rfb/LogWriter.h -=================================================================== ---- tigervnc-1.4.1.orig/common/rfb/LogWriter.h -+++ tigervnc-1.4.1/common/rfb/LogWriter.h -@@ -68,10 +68,15 @@ namespace rfb { - } - } - -- DEF_LOGFUNCTION(error, 0) -- DEF_LOGFUNCTION(status, 10) -- DEF_LOGFUNCTION(info, 30) -- DEF_LOGFUNCTION(debug, 100) -+ static const int LEVEL_ERROR = 0; -+ static const int LEVEL_STATUS = 10; -+ static const int LEVEL_INFO = 30; -+ static const int LEVEL_DEBUG = 100; -+ -+ DEF_LOGFUNCTION(error, LEVEL_ERROR) -+ DEF_LOGFUNCTION(status, LEVEL_STATUS) -+ DEF_LOGFUNCTION(info, LEVEL_INFO) -+ DEF_LOGFUNCTION(debug, LEVEL_DEBUG) - - // -=- DIAGNOSTIC & HELPER ROUTINES - -Index: tigervnc-1.4.1/common/rfb/Logger_syslog.cxx -=================================================================== ---- /dev/null -+++ tigervnc-1.4.1/common/rfb/Logger_syslog.cxx -@@ -0,0 +1,65 @@ -+/* Copyright (C) 2015 TigerVNC -+ * -+ * 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. -+ */ -+ -+// -=- Logger_syslog.cxx - Logger instance for a syslog -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+using namespace rfb; -+ -+ -+Logger_Syslog::Logger_Syslog(const char* loggerName) -+ : Logger(loggerName) -+{ -+ openlog("Xvnc", LOG_CONS | LOG_PID, LOG_USER); -+} -+ -+Logger_Syslog::~Logger_Syslog() -+{ -+ closelog(); -+} -+ -+void Logger_Syslog::write(int level, const char *logname, const char *message) -+{ -+ // Convert our priority level into syslog level -+ int priority; -+ if (level >= LogWriter::LEVEL_DEBUG) { -+ priority = LOG_DEBUG; -+ } else if (level >= LogWriter::LEVEL_INFO) { -+ priority = LOG_INFO; -+ } else if (level >= LogWriter::LEVEL_STATUS) { -+ priority = LOG_NOTICE; -+ } else { -+ priority = LOG_ERR; -+ } -+ -+ syslog(priority, "%s: %s", logname, message); -+} -+ -+static Logger_Syslog logger("syslog"); -+ -+void rfb::initSyslogLogger() { -+ logger.registerLogger(); -+} -Index: tigervnc-1.4.1/common/rfb/Logger_syslog.h -=================================================================== ---- /dev/null -+++ tigervnc-1.4.1/common/rfb/Logger_syslog.h -@@ -0,0 +1,40 @@ -+/* Copyright (C) 2015 TigerVNC -+ * -+ * 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. -+ */ -+ -+// -=- Logger_syslog - log to syslog -+ -+#ifndef __RFB_LOGGER_SYSLOG_H__ -+#define __RFB_LOGGER_SYSLOG_H__ -+ -+#include -+#include -+ -+namespace rfb { -+ -+ class Logger_Syslog : public Logger { -+ public: -+ Logger_Syslog(const char* loggerName); -+ virtual ~Logger_Syslog(); -+ -+ virtual void write(int level, const char *logname, const char *message); -+ }; -+ -+ void initSyslogLogger(); -+}; -+ -+#endif -Index: tigervnc-1.4.1/unix/xserver/hw/vnc/Xvnc.man -=================================================================== ---- tigervnc-1.4.1.orig/unix/xserver/hw/vnc/Xvnc.man -+++ tigervnc-1.4.1/unix/xserver/hw/vnc/Xvnc.man -@@ -274,11 +274,11 @@ stop non-SSH connections from any other - . - .TP - .B \-Log \fIlogname\fP:\fIdest\fP:\fIlevel\fP --Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP or --\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose --output. \fIlogname\fP is usually \fB*\fP meaning all, but you can target a --specific source file if you know the name of its "LogWriter". Default is --\fB*:stderr:30\fP. -+Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP, -+\fBstdout\fP or \fBsyslog\fP, and \fIlevel\fP is between 0 and 100, 100 meaning -+most verbose output. \fIlogname\fP is usually \fB*\fP meaning all, but you can -+target a specific source file if you know the name of its "LogWriter". Default -+is \fB*:stderr:30\fP. - . - .TP - .B \-RemapKeys \fImapping -Index: tigervnc-1.4.1/unix/xserver/hw/vnc/xvnc.cc -=================================================================== ---- tigervnc-1.4.1.orig/unix/xserver/hw/vnc/xvnc.cc -+++ tigervnc-1.4.1/unix/xserver/hw/vnc/xvnc.cc -@@ -34,6 +34,7 @@ from the X Consortium. - - #include - #include -+#include - #include - #include - #include "vncExtInit.h" -@@ -376,6 +377,7 @@ ddxProcessArgument(int argc, char *argv[ - vfbInitializePixmapDepths(); - firstTime = FALSE; - rfb::initStdIOLoggers(); -+ rfb::initSyslogLogger(); - rfb::LogWriter::setLogParams("*:stderr:30"); - rfb::Configuration::enableServerParams(); - } diff --git a/u_tigervnc-add-autoaccept-parameter.patch b/u_tigervnc-add-autoaccept-parameter.patch new file mode 100644 index 0000000..f651691 --- /dev/null +++ b/u_tigervnc-add-autoaccept-parameter.patch @@ -0,0 +1,116 @@ +diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java +index 6014502..9b886b5 100644 +--- a/java/com/tigervnc/rfb/CSecurityTLS.java ++++ b/java/com/tigervnc/rfb/CSecurityTLS.java +@@ -47,6 +47,9 @@ public class CSecurityTLS extends CSecurity { + public static StringParameter x509crl + = new StringParameter("x509crl", + "X509 CRL file", "", Configuration.ConfigurationObject.ConfViewer); ++ public static StringParameter x509autoaccept ++ = new StringParameter("x509autoaccept", ++ "X509 Certificate SHA-1 fingerprint", "", Configuration.ConfigurationObject.ConfViewer); + + private void initGlobal() + { +@@ -71,6 +74,7 @@ public class CSecurityTLS extends CSecurity { + setDefaults(); + cafile = x509ca.getData(); + crlfile = x509crl.getData(); ++ certautoaccept = x509autoaccept.getData(); + } + + public static String getDefaultCA() { +@@ -247,34 +251,46 @@ public class CSecurityTLS extends CSecurity { + try { + tm.checkServerTrusted(chain, authType); + } catch (CertificateException e) { +- Object[] answer = {"Proceed", "Exit"}; +- +- StringBuilder message = new StringBuilder(); +- message.append(e.getCause().getLocalizedMessage()); +- message.append("\nContinue connecting to this host?"); ++ String fingerprint = null; + + try { ++ StringBuilder fingerprintBuilder = new StringBuilder(); ++ + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + sha1.update(chain[0].getEncoded()); + +- message.append("\nSHA-1 fingerprint: "); +- + for(byte B : sha1.digest()) { +- message.append(Integer.toHexString(0xff & B)); +- message.append(':'); ++ fingerprintBuilder.append(String.format("%02x", /*0xff & */B)); ++ fingerprintBuilder.append(':'); + } +- message.deleteCharAt(message.length() - 1); ++ fingerprintBuilder.deleteCharAt(fingerprintBuilder.length() - 1); ++ ++ fingerprint = fingerprintBuilder.toString(); + } catch (NoSuchAlgorithmException noSuchAlgorithmException) { + // No fingerprint then... + } + +- int ret = JOptionPane.showOptionDialog(null, +- message.toString(), +- "Confirm certificate exception?", +- JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, +- null, answer, answer[0]); +- if (ret == JOptionPane.NO_OPTION) +- System.exit(1); ++ if(fingerprint == null || certautoaccept == null || !fingerprint.equalsIgnoreCase(certautoaccept)) { ++ Object[] answer = {"Proceed", "Exit"}; ++ ++ StringBuilder message = new StringBuilder(); ++ message.append(e.getCause().getLocalizedMessage()); ++ message.append("\nContinue connecting to this host?"); ++ if(fingerprint != null) { ++ message.append("\nSHA-1 fingerprint: "); ++ message.append(fingerprint); ++ message.append("\nBle: "); ++ message.append(certautoaccept); ++ } ++ ++ int ret = JOptionPane.showOptionDialog(null, ++ message.toString(), ++ "Confirm certificate exception?", ++ JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, ++ null, answer, answer[0]); ++ if (ret == JOptionPane.NO_OPTION) ++ System.exit(1); ++ } + } catch (java.lang.Exception e) { + throw new Exception(e.toString()); + } +@@ -301,7 +317,7 @@ public class CSecurityTLS extends CSecurity { + private SSLEngineManager manager; + private boolean anon; + +- private String cafile, crlfile; ++ private String cafile, crlfile, certautoaccept; + private FdInStream is; + private FdOutStream os; + +diff --git a/java/com/tigervnc/vncviewer/VncViewer.java b/java/com/tigervnc/vncviewer/VncViewer.java +index cc21c2e..6786636 100644 +--- a/java/com/tigervnc/vncviewer/VncViewer.java ++++ b/java/com/tigervnc/vncviewer/VncViewer.java +@@ -354,6 +354,8 @@ public class VncViewer extends javax.swing.JApplet + parent.setFocusTraversalKeysEnabled(false); + setLookAndFeel(); + setBackground(Color.white); ++ ++ SecurityClient.setDefaults(); + } + + private void getTimestamp() { +@@ -375,6 +377,7 @@ public class VncViewer extends javax.swing.JApplet + if (embed.getValue() && nViewers == 0) { + alwaysShowServerDialog.setParam(false); + Configuration.global().readAppletParams(this); ++ Configuration.viewer().readAppletParams(this); + fullScreen.setParam(false); + scalingFactor.setParam("100"); + String host = getCodeBase().getHost(); diff --git a/u_tigervnc-add-cadata-parameter.patch b/u_tigervnc-add-cadata-parameter.patch new file mode 100644 index 0000000..f651691 --- /dev/null +++ b/u_tigervnc-add-cadata-parameter.patch @@ -0,0 +1,116 @@ +diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java +index 6014502..9b886b5 100644 +--- a/java/com/tigervnc/rfb/CSecurityTLS.java ++++ b/java/com/tigervnc/rfb/CSecurityTLS.java +@@ -47,6 +47,9 @@ public class CSecurityTLS extends CSecurity { + public static StringParameter x509crl + = new StringParameter("x509crl", + "X509 CRL file", "", Configuration.ConfigurationObject.ConfViewer); ++ public static StringParameter x509autoaccept ++ = new StringParameter("x509autoaccept", ++ "X509 Certificate SHA-1 fingerprint", "", Configuration.ConfigurationObject.ConfViewer); + + private void initGlobal() + { +@@ -71,6 +74,7 @@ public class CSecurityTLS extends CSecurity { + setDefaults(); + cafile = x509ca.getData(); + crlfile = x509crl.getData(); ++ certautoaccept = x509autoaccept.getData(); + } + + public static String getDefaultCA() { +@@ -247,34 +251,46 @@ public class CSecurityTLS extends CSecurity { + try { + tm.checkServerTrusted(chain, authType); + } catch (CertificateException e) { +- Object[] answer = {"Proceed", "Exit"}; +- +- StringBuilder message = new StringBuilder(); +- message.append(e.getCause().getLocalizedMessage()); +- message.append("\nContinue connecting to this host?"); ++ String fingerprint = null; + + try { ++ StringBuilder fingerprintBuilder = new StringBuilder(); ++ + MessageDigest sha1 = MessageDigest.getInstance("SHA1"); + sha1.update(chain[0].getEncoded()); + +- message.append("\nSHA-1 fingerprint: "); +- + for(byte B : sha1.digest()) { +- message.append(Integer.toHexString(0xff & B)); +- message.append(':'); ++ fingerprintBuilder.append(String.format("%02x", /*0xff & */B)); ++ fingerprintBuilder.append(':'); + } +- message.deleteCharAt(message.length() - 1); ++ fingerprintBuilder.deleteCharAt(fingerprintBuilder.length() - 1); ++ ++ fingerprint = fingerprintBuilder.toString(); + } catch (NoSuchAlgorithmException noSuchAlgorithmException) { + // No fingerprint then... + } + +- int ret = JOptionPane.showOptionDialog(null, +- message.toString(), +- "Confirm certificate exception?", +- JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, +- null, answer, answer[0]); +- if (ret == JOptionPane.NO_OPTION) +- System.exit(1); ++ if(fingerprint == null || certautoaccept == null || !fingerprint.equalsIgnoreCase(certautoaccept)) { ++ Object[] answer = {"Proceed", "Exit"}; ++ ++ StringBuilder message = new StringBuilder(); ++ message.append(e.getCause().getLocalizedMessage()); ++ message.append("\nContinue connecting to this host?"); ++ if(fingerprint != null) { ++ message.append("\nSHA-1 fingerprint: "); ++ message.append(fingerprint); ++ message.append("\nBle: "); ++ message.append(certautoaccept); ++ } ++ ++ int ret = JOptionPane.showOptionDialog(null, ++ message.toString(), ++ "Confirm certificate exception?", ++ JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, ++ null, answer, answer[0]); ++ if (ret == JOptionPane.NO_OPTION) ++ System.exit(1); ++ } + } catch (java.lang.Exception e) { + throw new Exception(e.toString()); + } +@@ -301,7 +317,7 @@ public class CSecurityTLS extends CSecurity { + private SSLEngineManager manager; + private boolean anon; + +- private String cafile, crlfile; ++ private String cafile, crlfile, certautoaccept; + private FdInStream is; + private FdOutStream os; + +diff --git a/java/com/tigervnc/vncviewer/VncViewer.java b/java/com/tigervnc/vncviewer/VncViewer.java +index cc21c2e..6786636 100644 +--- a/java/com/tigervnc/vncviewer/VncViewer.java ++++ b/java/com/tigervnc/vncviewer/VncViewer.java +@@ -354,6 +354,8 @@ public class VncViewer extends javax.swing.JApplet + parent.setFocusTraversalKeysEnabled(false); + setLookAndFeel(); + setBackground(Color.white); ++ ++ SecurityClient.setDefaults(); + } + + private void getTimestamp() { +@@ -375,6 +377,7 @@ public class VncViewer extends javax.swing.JApplet + if (embed.getValue() && nViewers == 0) { + alwaysShowServerDialog.setParam(false); + Configuration.global().readAppletParams(this); ++ Configuration.viewer().readAppletParams(this); + fullScreen.setParam(false); + scalingFactor.setParam("100"); + String host = getCodeBase().getHost(); diff --git a/u_tigervnc-build-with-xserver-1.17.patch b/u_tigervnc-build-with-xserver-1.17.patch deleted file mode 100644 index ef5c8c6..0000000 --- a/u_tigervnc-build-with-xserver-1.17.patch +++ /dev/null @@ -1,52 +0,0 @@ -Author: Michal Srb -Subject: Build with xserver 1.17.x. - -Do not use removed xalloc&xfree. -Add 1.17.x to supported list. - -Index: tigervnc-1.4.1/unix/xserver/hw/vnc/xorg-version.h -=================================================================== ---- tigervnc-1.4.1.orig/unix/xserver/hw/vnc/xorg-version.h -+++ tigervnc-1.4.1/unix/xserver/hw/vnc/xorg-version.h -@@ -48,8 +48,10 @@ - #define XORG 115 - #elif XORG_VERSION_CURRENT < ((1 * 10000000) + (16 * 100000) + (99 * 1000)) - #define XORG 116 -+#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (17 * 100000) + (99 * 1000)) -+#define XORG 117 - #else --#error "X.Org newer than 1.16 is not supported" -+#error "X.Org newer than 1.17 is not supported" - #endif - - #endif -Index: tigervnc-1.4.1/unix/xserver/hw/vnc/xvnc.cc -=================================================================== ---- tigervnc-1.4.1.orig/unix/xserver/hw/vnc/xvnc.cc -+++ tigervnc-1.4.1/unix/xserver/hw/vnc/xvnc.cc -@@ -717,9 +717,9 @@ vfbInstallColormap(ColormapPtr pmap) - entries = pmap->pVisual->ColormapEntries; - pVisual = pmap->pVisual; - -- ppix = (Pixel *)xalloc(entries * sizeof(Pixel)); -- prgb = (xrgb *)xalloc(entries * sizeof(xrgb)); -- defs = (xColorItem *)xalloc(entries * sizeof(xColorItem)); -+ ppix = (Pixel *)malloc(entries * sizeof(Pixel)); -+ prgb = (xrgb *)malloc(entries * sizeof(xrgb)); -+ defs = (xColorItem *)malloc(entries * sizeof(xColorItem)); - - for (i = 0; i < entries; i++) ppix[i] = i; - /* XXX truecolor */ -@@ -738,9 +738,9 @@ vfbInstallColormap(ColormapPtr pmap) - } - (*pmap->pScreen->StoreColors)(pmap, entries, defs); - -- xfree(ppix); -- xfree(prgb); -- xfree(defs); -+ free(ppix); -+ free(prgb); -+ free(defs); - } - } - diff --git a/u_tigervnc-display-SHA-1-fingerprint-of-untrusted-certificate.patch b/u_tigervnc-display-SHA-1-fingerprint-of-untrusted-certificate.patch new file mode 100644 index 0000000..d510b2f --- /dev/null +++ b/u_tigervnc-display-SHA-1-fingerprint-of-untrusted-certificate.patch @@ -0,0 +1,48 @@ +From af09e89d54b57649cf60363d03f84d129baecd27 Mon Sep 17 00:00:00 2001 +From: Michal Srb +Date: Tue, 7 Jul 2015 02:38:18 +0300 +Subject: [PATCH 2/2] Display SHA-1 fingerprint of untrusted certificate in + java client. + +--- + java/com/tigervnc/rfb/CSecurityTLS.java | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java +index 7633f08..6014502 100644 +--- a/java/com/tigervnc/rfb/CSecurityTLS.java ++++ b/java/com/tigervnc/rfb/CSecurityTLS.java +@@ -248,9 +248,28 @@ public class CSecurityTLS extends CSecurity { + tm.checkServerTrusted(chain, authType); + } catch (CertificateException e) { + Object[] answer = {"Proceed", "Exit"}; ++ ++ StringBuilder message = new StringBuilder(); ++ message.append(e.getCause().getLocalizedMessage()); ++ message.append("\nContinue connecting to this host?"); ++ ++ try { ++ MessageDigest sha1 = MessageDigest.getInstance("SHA1"); ++ sha1.update(chain[0].getEncoded()); ++ ++ message.append("\nSHA-1 fingerprint: "); ++ ++ for(byte B : sha1.digest()) { ++ message.append(Integer.toHexString(0xff & B)); ++ message.append(':'); ++ } ++ message.deleteCharAt(message.length() - 1); ++ } catch (NoSuchAlgorithmException noSuchAlgorithmException) { ++ // No fingerprint then... ++ } ++ + int ret = JOptionPane.showOptionDialog(null, +- e.getCause().getLocalizedMessage()+"\n"+ +- "Continue connecting to this host?", ++ message.toString(), + "Confirm certificate exception?", + JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, answer, answer[0]); +-- +2.1.4 + diff --git a/u_tigervnc-use-default-trust-manager-in-java-viewer-if-custom.patch b/u_tigervnc-use-default-trust-manager-in-java-viewer-if-custom.patch new file mode 100644 index 0000000..8169243 --- /dev/null +++ b/u_tigervnc-use-default-trust-manager-in-java-viewer-if-custom.patch @@ -0,0 +1,60 @@ +From d6d847633660abb99764192f73da7be5adf3da9c Mon Sep 17 00:00:00 2001 +From: Michal Srb +Date: Tue, 7 Jul 2015 02:09:21 +0300 +Subject: [PATCH 1/2] Use default trust manager in java viewer if custom CA is + not specified. + +--- + java/com/tigervnc/rfb/CSecurityTLS.java | 34 +++++++++++++++++---------------- + 1 file changed, 18 insertions(+), 16 deletions(-) + +diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java +index 6f799bb..7633f08 100644 +--- a/java/com/tigervnc/rfb/CSecurityTLS.java ++++ b/java/com/tigervnc/rfb/CSecurityTLS.java +@@ -207,24 +207,26 @@ public class CSecurityTLS extends CSecurity { + try { + ks.load(null, null); + File cacert = new File(cafile); +- if (!cacert.exists() || !cacert.canRead()) +- return; +- InputStream caStream = new FileInputStream(cafile); +- X509Certificate ca = (X509Certificate)cf.generateCertificate(caStream); +- ks.setCertificateEntry("CA", ca); +- PKIXBuilderParameters params = new PKIXBuilderParameters(ks, new X509CertSelector()); +- File crlcert = new File(crlfile); +- if (!crlcert.exists() || !crlcert.canRead()) { +- params.setRevocationEnabled(false); ++ if (!cacert.exists() || !cacert.canRead()) { ++ tmf.init((KeyStore)null); // Use default trust manager + } else { +- InputStream crlStream = new FileInputStream(crlfile); +- Collection crls = cf.generateCRLs(crlStream); +- CertStoreParameters csp = new CollectionCertStoreParameters(crls); +- CertStore store = CertStore.getInstance("Collection", csp); +- params.addCertStore(store); +- params.setRevocationEnabled(true); ++ InputStream caStream = new FileInputStream(cafile); ++ X509Certificate ca = (X509Certificate)cf.generateCertificate(caStream); ++ ks.setCertificateEntry("CA", ca); ++ PKIXBuilderParameters params = new PKIXBuilderParameters(ks, new X509CertSelector()); ++ File crlcert = new File(crlfile); ++ if (!crlcert.exists() || !crlcert.canRead()) { ++ params.setRevocationEnabled(false); ++ } else { ++ InputStream crlStream = new FileInputStream(crlfile); ++ Collection crls = cf.generateCRLs(crlStream); ++ CertStoreParameters csp = new CollectionCertStoreParameters(crls); ++ CertStore store = CertStore.getInstance("Collection", csp); ++ params.addCertStore(store); ++ params.setRevocationEnabled(true); ++ } ++ tmf.init(new CertPathTrustManagerParameters(params)); + } +- tmf.init(new CertPathTrustManagerParameters(params)); + } catch (java.io.FileNotFoundException e) { + vlog.error(e.toString()); + } catch (java.io.IOException e) { +-- +2.1.4 + diff --git a/u_tigervnc-use_preferred_mode.patch b/u_tigervnc-use_preferred_mode.patch index 64453f7..273d049 100644 --- a/u_tigervnc-use_preferred_mode.patch +++ b/u_tigervnc-use_preferred_mode.patch @@ -6,22 +6,21 @@ References: bnc#896540 If there is any resolution specified with -geometry or -screen parameters, report this resolution as preferred one. That way desktop environments won't change it immediately after start. -Index: unix/xserver/hw/vnc/xvnc.cc +Index: unix/xserver/hw/vnc/xvnc.c =================================================================== ---- unix/xserver/hw/vnc/xvnc.cc (revision 5186) -+++ unix/xserver/hw/vnc/xvnc.cc (working copy) -@@ -1319,12 +1319,22 @@ - /* Make sure the CRTC has this output set */ +--- unix/xserver/hw/vnc/xvnc.c.orig ++++ unix/xserver/hw/vnc/xvnc.c +@@ -1296,12 +1296,24 @@ static RRCrtcPtr vncRandRCrtcCreate(Scre vncRandRCrtcSet(pScreen, crtc, NULL, 0, 0, RR_Rotate_0, 1, &output); -- /* Populate a list of default modes */ -- RRModePtr modes[sizeof(vncRandRWidths)/sizeof(*vncRandRWidths)]; -- int num_modes; -+ /* Populate a list of modes */ -+ RRModePtr modes[sizeof(vncRandRWidths)/sizeof(*vncRandRWidths) + 1]; -+ int num_modes = 0; + /* Populate a list of default modes */ +- modes = malloc(sizeof(RRModePtr)*sizeof(vncRandRWidths)/sizeof(*vncRandRWidths)); ++ modes = malloc(sizeof(RRModePtr)*sizeof(vncRandRWidths)/sizeof(*vncRandRWidths) + 1); + if (modes == NULL) + return NULL; -- num_modes = 0; + num_modes = 0; ++ + /* Start with requested mode */ + mode = vncRandRModeGet(pScreen->width, pScreen->height); + if(mode != NULL) { @@ -30,19 +29,19 @@ Index: unix/xserver/hw/vnc/xvnc.cc + } + + /* Add default modes */ - for (int i = 0;i < sizeof(vncRandRWidths)/sizeof(*vncRandRWidths);i++) { + for (i = 0;i < sizeof(vncRandRWidths)/sizeof(*vncRandRWidths);i++) { + if (vncRandRWidths[i] == pScreen->width && vncRandRHeights[i] == pScreen->height) + continue; + mode = vncRandRModeGet(vncRandRWidths[i], vncRandRHeights[i]); if (mode != NULL) { modes[num_modes] = mode; -@@ -1332,7 +1342,7 @@ +@@ -1309,7 +1321,7 @@ static RRCrtcPtr vncRandRCrtcCreate(Scre } } - RROutputSetModes(output, modes, num_modes, 0); + RROutputSetModes(output, modes, num_modes, 1); - return crtc; - } + free(modes); + diff --git a/v1.4.3.tar.gz b/v1.4.3.tar.gz deleted file mode 100644 index 938fa9b..0000000 --- a/v1.4.3.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0b2603db2b32dfd6e48f6f59618bd9819d187bfbb0c16218637d074a69756824 -size 1372873 diff --git a/v1.5.0.tar.gz b/v1.5.0.tar.gz new file mode 100644 index 0000000..3e5edd1 --- /dev/null +++ b/v1.5.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b0ec1a85d708f72fee17326bd1f894b9132df089226561306f4c2ef19d7df25 +size 1268682 diff --git a/vnc.xinetd b/vnc.xinetd index 8adea29..d683da5 100644 --- a/vnc.xinetd +++ b/vnc.xinetd @@ -8,9 +8,9 @@ service vnc1 socket_type = stream protocol = tcp wait = no - user = nobody + user = vnc server = /usr/bin/Xvnc - server_args = -noreset -inetd -once -query localhost -geometry 1024x768 -securitytypes none -log *:syslog:30 + server_args = -noreset -inetd -once -query localhost -geometry 1024x768 -securitytypes X509None,None -X509Key /etc/vnc/tls.key -X509Cert /etc/vnc/tls.cert -log *:syslog:30 disable = yes } # default: off @@ -23,9 +23,9 @@ service vnc2 socket_type = stream protocol = tcp wait = no - user = nobody + user = vnc server = /usr/bin/Xvnc - server_args = -noreset -inetd -once -query localhost -geometry 1280x1024 -securitytypes none -log *:syslog:30 + server_args = -noreset -inetd -once -query localhost -geometry 1280x1024 -securitytypes X509None,None -X509Key /etc/vnc/tls.key -X509Cert /etc/vnc/tls.cert -log *:syslog:30 disable = yes } # default: off @@ -38,9 +38,9 @@ service vnc3 socket_type = stream protocol = tcp wait = no - user = nobody + user = vnc server = /usr/bin/Xvnc - server_args = -noreset -inetd -once -query localhost -geometry 1600x1200 -securitytypes none -log *:syslog:30 + server_args = -noreset -inetd -once -query localhost -geometry 1600x1200 -securitytypes X509None,None -X509Key /etc/vnc/tls.key -X509Cert /etc/vnc/tls.cert -log *:syslog:30 disable = yes } # default: off @@ -53,7 +53,7 @@ service vnchttpd1 socket_type = stream protocol = tcp wait = no - user = nobody + user = vnc server = /usr/bin/vnc_inetd_httpd server_args = 1024 768 5901 disable = yes @@ -68,7 +68,7 @@ service vnchttpd2 socket_type = stream protocol = tcp wait = no - user = nobody + user = vnc server = /usr/bin/vnc_inetd_httpd server_args = 1280 1024 5902 disable = yes @@ -83,7 +83,7 @@ service vnchttpd3 socket_type = stream protocol = tcp wait = no - user = nobody + user = vnc server = /usr/bin/vnc_inetd_httpd server_args = 1600 1200 5903 disable = yes diff --git a/vnc_inetd_httpd b/vnc_inetd_httpd index bc54c81..13d8777 100644 --- a/vnc_inetd_httpd +++ b/vnc_inetd_httpd @@ -1,62 +1,114 @@ -#!/bin/bash -read request url httptype || exit 0 -url="${url/ /}" -httptype="${httptype/ /}" +#!/usr/bin/env python -width=$1 -height=$2 -port=$3 +# This is simple stupid WWW server intended to serve VNC java applet. +# It is made to be called by xinetd. +# It handles both HTTP and HTTPS on the same port. If HTTPS is allowed, any HTTP requests is responded with redirect to HTTPS. -if [ "x$httptype" != "x" ]; then - line="x" - while [ -n "$line" ]; do - read line || exit 0 - line="${line/ /}" - done -fi -case "$url" in -/) - # We need the size of the display for the current applet. - # The VNC menubar is 20 pixels high ... - height=$((height+20)) - ctype="text/html" - content=" -Remote Desktop - - - - - - -" - ;; -*.jar|*.class) - # Use basename to make sure we have just a filename, not ../../... - url=${url/.*\/} - ctype="application/octet-stream" - cfile="/usr/share/vnc/classes/$url" - content="FILE" - ;; -esac +import re +import sys +import socket +import time -if [ "x$httptype" != "x" ]; then - echo "HTTP/1.0 200 OK" - echo "Content-Type: $ctype" - if [ "$content" == "FILE" ]; then - clen=`wc -c "$cfile"` - else - clen=`echo "$content"|wc -c` - fi - echo "Content-Length: $clen" - echo "Connection: close" - echo -fi +from OpenSSL import SSL, crypto -if [ "$request" == "GET" ]; then - if [ "$content" == "FILE" ]; then - cat "$cfile" - else - echo "$content" - fi -fi -exit 0 +TLS_KEY = "/etc/vnc/tls.key" +TLS_CERT = "/etc/vnc/tls.cert" +JAR_FILE = "/usr/share/vnc/classes/VncViewer.jar" +TIMEOUT = 10 + +WIDTH = int(sys.argv[1]) +HEIGHT = int(sys.argv[2]) +VNC_PORT = int(sys.argv[3]) +USE_HTTPS = not (len(sys.argv) >= 5 and sys.argv[4] == "NoHTTPS") + + +# Take the stdin as our input socket (given from xinetd) +conn = sock = socket.fromfd(sys.stdin.fileno(), socket.AF_INET, socket.SOCK_STREAM) + +# If we are supposed to use HTTPS, load certificate and replace conn with SSL connection. +if USE_HTTPS: + cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(TLS_CERT, 'r').read()) + + context = SSL.Context(SSL.SSLv23_METHOD) + context.use_privatekey_file(TLS_KEY) + context.use_certificate(cert) + + conn = SSL.Connection(context, sock) + conn.set_accept_state() + +# Send normal response +def send_response(connection, ctype, response): + connection.sendall( + "HTTP/1.0 200 OK\n" + + "Content-Type: " + ctype + "\n" + + "Content-Length: " + str(len(response)) + "\n" + + "Connection: close\n" + + "\n" + + response + ) + +# Send redirect +def send_redirect(connection, ctype, response, location): + connection.sendall( + "HTTP/1.0 301 Moved Permanently\n" + + "Location: " + location + "\n" + + "Content-Type: " + ctype + "\n" + + "Content-Length: " + str(len(response)) + "\n" + + "Connection: close\n" + + "\n" + + response + ) + + +# Try to read and parse HTTP request +try: + start_time = time.time() + buffer = '' + while True: + buffer += conn.recv(1024) + + if buffer.endswith("\r\n\r\n") or start_time + TIMEOUT < time.time(): + break + + method, url = buffer.split(" ", 2)[0:2] + + if url == '/VncViewer.jar': + with open(JAR_FILE, 'r') as file: + send_response(conn, "application/octet-stream", file.read()) + else: + response = \ + """ + + Remote Desktop + + + + + + """%(WIDTH, HEIGHT, VNC_PORT, 'X509None' if USE_HTTPS else 'TLSNone', cert.digest('SHA1') if USE_HTTPS else '') + + send_response(conn, "text/html", response) + +except SSL.Error: + # If SSL failed, it is most probably because the browser is actually trying to do normal HTTP request. + + # We have now a partially consumed HTTP request in sock, let's try if we can get Host header out of it + partial_request = sock.recv(8000) # Arbitrary big number, if the request is longer than this, we will just skip the rest. + + host = None + match = re.search(r"\r\nHost: ([^\r]+)\r\n", partial_request) + if match: + host = match.group(1) + + if host: + # If we got host header, we can redirect nicely with HTTP 301. + send_redirect(sock, "text.html", "Use https.", "https://" + host) + else: + # If we don't know the host header, redirect using javascript. + send_response(sock, "text.html", "Use https.")