mirror of
https://github.com/KDE/krfb
synced 2026-07-01 15:51:18 -07:00
Compare commits
117 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da7bea30c2 | ||
|
|
e353929815 | ||
|
|
12a77faf02 | ||
|
|
4c420434ea | ||
|
|
16decb9103 | ||
|
|
0772af984d | ||
|
|
1f1aa58026 | ||
|
|
daaa7b45a6 | ||
|
|
8bcbb2de9a | ||
|
|
08f5308e7e | ||
|
|
a5eed055d8 | ||
|
|
3e9b02243f | ||
|
|
067dc983e1 | ||
|
|
9f1da938ae | ||
|
|
3faf49f1d0 | ||
|
|
3b7b7950af | ||
|
|
6d52dc072e | ||
|
|
b6f30a98fa | ||
|
|
4bd481ad54 | ||
|
|
e72807e225 | ||
|
|
51c54d7dd8 | ||
|
|
e270fb9186 | ||
|
|
f13c451752 | ||
|
|
e00ee00314 | ||
|
|
e45bad0e33 | ||
|
|
bdb22dca4d | ||
|
|
bfa0444be7 | ||
|
|
8a82a27da8 | ||
|
|
5097a44442 | ||
|
|
b24786205f | ||
|
|
9f56633c0b | ||
|
|
7c061ccbf1 | ||
|
|
e69fc2b61f | ||
|
|
dda89a146f | ||
|
|
ff967c23c1 | ||
|
|
672311ccea | ||
|
|
2b938c712e | ||
|
|
5fd621abc9 | ||
|
|
59183f3c69 | ||
|
|
33cc068753 | ||
|
|
f6d4256f5d | ||
|
|
324f029f10 | ||
|
|
c2c6d43299 | ||
|
|
1c9189bf50 | ||
|
|
705ddc2c07 | ||
|
|
5c9a3528b6 | ||
|
|
ba554fe831 | ||
|
|
cb5f243262 | ||
|
|
f947f69bfb | ||
|
|
0eb7e1c502 | ||
|
|
86c5ea3905 | ||
|
|
78ec1e53c8 | ||
|
|
e8da15b195 | ||
|
|
423c87c382 | ||
|
|
60e66e16a0 | ||
|
|
d93b3faf39 | ||
|
|
8a2549b757 | ||
|
|
6e0024e7b3 | ||
|
|
d55fe89023 | ||
|
|
527910e277 | ||
|
|
b116adb5d9 | ||
|
|
edac882b43 | ||
|
|
aa9cf0bdb8 | ||
|
|
eee9c34020 | ||
|
|
14525564ac | ||
|
|
19699557db | ||
|
|
28506ebe7d | ||
|
|
1af586747d | ||
|
|
8825c4cddc | ||
|
|
7bd681fd44 | ||
|
|
bed6c11c35 | ||
|
|
7e94d6349c | ||
|
|
301fd72d19 | ||
|
|
2a533c7140 | ||
|
|
1f408749b7 | ||
|
|
0ea0b3418c | ||
|
|
76de39285b | ||
|
|
25f4383a51 | ||
|
|
cda3a0b972 | ||
|
|
62e5eacbe7 | ||
|
|
a615da21f9 | ||
|
|
10d6dd4717 | ||
|
|
486b16c357 | ||
|
|
8126d36f15 | ||
|
|
78b649f39f | ||
|
|
cf0548f348 | ||
|
|
fac983d5a4 | ||
|
|
8ffe4d2ded | ||
|
|
5dd01e87b6 | ||
|
|
f19f108a4e | ||
|
|
4742556c51 | ||
|
|
bed6086fe7 | ||
|
|
2c5cbc755e | ||
|
|
fb4b28b250 | ||
|
|
cbb9102445 | ||
|
|
897734b4d6 | ||
|
|
83ac8619ed | ||
|
|
0230d66584 | ||
|
|
c74886dfe7 | ||
|
|
ff019b99cd | ||
|
|
4f78b51022 | ||
|
|
29d9b92b06 | ||
|
|
87f1f85913 | ||
|
|
cc1f23f23e | ||
|
|
a8da333e3b | ||
|
|
47e2db27de | ||
|
|
893afe07eb | ||
|
|
b0c10700e8 | ||
|
|
410567156d | ||
|
|
739c655ec7 | ||
|
|
7fa12d44dd | ||
|
|
62df847d4f | ||
|
|
e16b1c0007 | ||
|
|
51ffeee4ce | ||
|
|
ebbaa32be7 | ||
|
|
f4e9a6446a | ||
|
|
c6a6483e08 |
129
CMakeLists.txt
129
CMakeLists.txt
@@ -1,15 +1,23 @@
|
||||
project(krfb)
|
||||
|
||||
if(NOT INSIDE_KDENETWORK)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/../cmake/modules ${CMAKE_MODULE_PATH})
|
||||
message("Not building inside KDENetwork, loading KDE CMake Macros.")
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
|
||||
|
||||
find_package(KDE4 REQUIRED)
|
||||
|
||||
include(KDE4Defaults)
|
||||
include(MacroLibrary)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
find_package(LibVNCServer)
|
||||
macro_optional_find_package(LibVNCServer)
|
||||
|
||||
if (BUILD_EXPERIMENTAL_TUBES_SUPPORT)
|
||||
message(WARNING "You enabled experimental Tubes support. Expect breakage!!")
|
||||
|
||||
macro_optional_find_package(TelepathyQt4)
|
||||
macro_log_feature(TELEPATHY_QT4_FOUND "telepathy-qt4" "Telepathy Qt Bindings" "http://telepathy.freedesktop.org" FALSE "0.18" "Needed to build Telepathy Tubes support.")
|
||||
endif (BUILD_EXPERIMENTAL_TUBES_SUPPORT)
|
||||
|
||||
set(CMAKE_REQUIRED_DEFINITIONS ${_KDE_PLATFORM_DEFINITIONS})
|
||||
|
||||
@@ -17,115 +25,26 @@ if(NOT INSIDE_KDENETWORK)
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
|
||||
endif(NOT INSIDE_KDENETWORK)
|
||||
|
||||
check_symbol_exists(rfbInitServer "rfb/rfb.h" HAVE_LIBVNCSERVER)
|
||||
macro_bool_to_01(X11_Xdamage_FOUND HAVE_XDAMAGE)
|
||||
macro_bool_to_01(X11_XShm_FOUND HAVE_XSHM)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-krfb.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-krfb.h )
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}) # for config-krfb.h
|
||||
|
||||
include_directories ("${CMAKE_CURRENT_BINARY_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb/ui"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/libvncserver/"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libvncserver/"
|
||||
)
|
||||
|
||||
if(Q_WS_X11)
|
||||
if(NOT X11_XTest_FOUND)
|
||||
macro_log_feature(X11_XTest_FOUND "libXtst" "X11 Testing Resource extension library" "http://xorg.freedesktop.org" FALSE "" "useful for automated testing of X clients.")
|
||||
message(FATAL_ERROR "krfb requires the libXtst (http://xorg.freedesktop.org) to be built")
|
||||
endif(NOT X11_XTest_FOUND)
|
||||
endif(Q_WS_X11)
|
||||
|
||||
#add_subdirectory(kinetd)
|
||||
#add_subdirectory(kcm_krfb)
|
||||
if (HAVE_LIBVNCSERVER)
|
||||
|
||||
#####################################
|
||||
# First target: libkrfb - a library
|
||||
# for linking plugins against.
|
||||
|
||||
set (krfbprivate_SRCS
|
||||
framebuffer.cpp
|
||||
framebufferplugin.cpp
|
||||
)
|
||||
|
||||
kde4_add_library (krfbprivate
|
||||
SHARED
|
||||
${krfbprivate_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfbprivate
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${X11_X11_LIB}
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
)
|
||||
|
||||
set_target_properties (krfbprivate PROPERTIES
|
||||
VERSION ${GENERIC_LIB_VERSION}
|
||||
SOVERSION ${GENERIC_LIB_VERSION}
|
||||
)
|
||||
|
||||
install (TARGETS krfbprivate
|
||||
${INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
)
|
||||
|
||||
install (FILES
|
||||
krfb-framebuffer.desktop
|
||||
DESTINATION ${SERVICETYPES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
#####################################
|
||||
# Build the plugins
|
||||
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_subdirectory(libvncserver)
|
||||
add_subdirectory(krfb)
|
||||
add_subdirectory (framebuffers)
|
||||
|
||||
#####################################
|
||||
# Second target: krfb - the app
|
||||
# itself.
|
||||
|
||||
set(krfb_SRCS
|
||||
main.cpp
|
||||
trayicon.cpp
|
||||
krfbserver.cpp
|
||||
manageinvitationsdialog.cpp
|
||||
invitationmanager.cpp
|
||||
invitedialog.cpp
|
||||
invitation.cpp
|
||||
connectiondialog.cpp
|
||||
personalinvitedialog.cpp
|
||||
connectioncontroller.cpp
|
||||
events.cpp
|
||||
framebuffermanager.cpp
|
||||
)
|
||||
|
||||
kde4_add_kcfg_files(krfb_SRCS krfbconfig.kcfgc)
|
||||
|
||||
kde4_add_ui_files(krfb_SRCS connectionwidget.ui
|
||||
manageinvitations.ui
|
||||
personalinvitewidget.ui
|
||||
invitewidget.ui
|
||||
configtcp.ui
|
||||
configsecurity.ui
|
||||
)
|
||||
|
||||
kde4_add_executable(krfb ${krfb_SRCS})
|
||||
|
||||
target_link_libraries(krfb
|
||||
krfbprivate
|
||||
${JPEG_LIBRARIES}
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
${X11_Xext_LIB}
|
||||
${X11_X11_LIB}
|
||||
${X11_Xdamage_LIB}
|
||||
${QT_QTNETWORK_LIBRARY}
|
||||
${KDE4_KDNSSD_LIBS}
|
||||
${KDE4_KDEUI_LIBS}
|
||||
)
|
||||
|
||||
if(X11_XTest_FOUND)
|
||||
target_link_libraries(krfb ${X11_XTest_LIB})
|
||||
endif(X11_XTest_FOUND)
|
||||
|
||||
install(TARGETS krfb ${INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install(FILES krfb.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
|
||||
install(FILES krfb.notifyrc DESTINATION ${DATA_INSTALL_DIR}/krfb)
|
||||
|
||||
endif (HAVE_LIBVNCSERVER)
|
||||
if (NOT INSIDE_KDENETWORK)
|
||||
macro_display_feature_log()
|
||||
endif ()
|
||||
|
||||
22
cmake/modules/COPYING-CMAKE-SCRIPTS
Normal file
22
cmake/modules/COPYING-CMAKE-SCRIPTS
Normal file
@@ -0,0 +1,22 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
39
cmake/modules/FindTelepathyQt4.cmake
Normal file
39
cmake/modules/FindTelepathyQt4.cmake
Normal file
@@ -0,0 +1,39 @@
|
||||
# Try to find the Qt4 binding of the Telepathy library
|
||||
# TELEPATHY_QT4_FOUND - system has TelepathyQt4
|
||||
# TELEPATHY_QT4_INCLUDE_DIR - the TelepathyQt4 include directory
|
||||
# TELEPATHY_QT4_LIBRARIES - Link these to use TelepathyQt4
|
||||
|
||||
# Copyright (c) 2008, Allen Winter <winter@kde.org>
|
||||
# Copyright (c) 2009, Andre Moreira Magalhaes <andrunko@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
set(TELEPATHY_QT4_FIND_REQUIRED ${TelepathyQt4_FIND_REQUIRED})
|
||||
if(TELEPATHY_QT4_INCLUDE_DIR AND TELEPATHY_QT4_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
set(TELEPATHY_QT4_FIND_QUIETLY TRUE)
|
||||
endif(TELEPATHY_QT4_INCLUDE_DIR AND TELEPATHY_QT4_LIBRARIES)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_TELEPATHY_QT4 QUIET TelepathyQt4>=0.1.8)
|
||||
endif(PKG_CONFIG_FOUND)
|
||||
|
||||
find_path(TELEPATHY_QT4_INCLUDE_DIR
|
||||
NAMES TelepathyQt4/Types
|
||||
HINTS
|
||||
${PC_TELEPATHY_QT4_INCLUDEDIR}
|
||||
${PC_TELEPATHY_QT4_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(TELEPATHY_QT4_LIBRARIES
|
||||
NAMES telepathy-qt4
|
||||
HINTS
|
||||
${PC_TELEPATHY_QT4_LIBDIR}
|
||||
${PC_TELEPATHY_QT4_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(TELEPATHY_QT4 DEFAULT_MSG
|
||||
TELEPATHY_QT4_LIBRARIES TELEPATHY_QT4_INCLUDE_DIR)
|
||||
@@ -1,253 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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.
|
||||
*/
|
||||
#include "connectioncontroller.h"
|
||||
#include "connectioncontroller.moc"
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QHostInfo>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
|
||||
#include <KConfig>
|
||||
#include <KGlobal>
|
||||
#include <KUser>
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
#include <KDebug>
|
||||
|
||||
|
||||
#include "invitationmanager.h"
|
||||
#include "connectiondialog.h"
|
||||
#include "events.h"
|
||||
#include "krfbserver.h"
|
||||
|
||||
#include "krfbconfig.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
static QString peerAddress(int sock) {
|
||||
|
||||
const int ADDR_SIZE = 50;
|
||||
struct sockaddr sa;
|
||||
socklen_t salen = sizeof(struct sockaddr);
|
||||
if (getpeername(sock, &sa, &salen) == 0) {
|
||||
if (sa.sa_family == AF_INET) {
|
||||
struct sockaddr_in *si = (struct sockaddr_in *)&sa;
|
||||
return QString(inet_ntoa(si->sin_addr));
|
||||
}
|
||||
if (sa.sa_family == AF_INET6) {
|
||||
char inetbuf[ADDR_SIZE];
|
||||
inet_ntop(sa.sa_family, &sa, inetbuf, ADDR_SIZE);
|
||||
return QString(inetbuf);
|
||||
}
|
||||
return QString("not a network address");
|
||||
}
|
||||
return QString("unable to determine...");
|
||||
}
|
||||
|
||||
static void clientGoneHook(rfbClientPtr cl)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->handleClientGone();
|
||||
}
|
||||
|
||||
|
||||
static bool checkPassword(const QString &p, unsigned char *ochallenge, const char *response, int len)
|
||||
{
|
||||
|
||||
if ((len == 0) && (p.length() == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char passwd[MAXPWLEN];
|
||||
unsigned char challenge[CHALLENGESIZE];
|
||||
|
||||
memcpy(challenge, ochallenge, CHALLENGESIZE);
|
||||
bzero(passwd, MAXPWLEN);
|
||||
if (!p.isNull()) {
|
||||
strncpy(passwd, p.toLatin1(),
|
||||
(MAXPWLEN <= p.length()) ? MAXPWLEN : p.length());
|
||||
}
|
||||
|
||||
rfbEncryptBytes(challenge, passwd);
|
||||
return memcmp(challenge, response, len) == 0;
|
||||
}
|
||||
|
||||
|
||||
ConnectionController::ConnectionController(struct _rfbClientRec *_cl, KrfbServer * parent)
|
||||
: QObject(parent), cl(_cl)
|
||||
{
|
||||
cl->clientData = (void*)this;
|
||||
}
|
||||
|
||||
ConnectionController::~ConnectionController()
|
||||
{
|
||||
}
|
||||
|
||||
enum rfbNewClientAction ConnectionController::handleNewClient()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
bool askOnConnect = KrfbConfig::askOnConnect();
|
||||
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
|
||||
|
||||
remoteIp = peerAddress(cl->sock);
|
||||
|
||||
if (!allowUninvited && InvitationManager::self()->activeInvitations() == 0) {
|
||||
KNotification::event("UnexpectedConnection",
|
||||
i18n("Refused uninvited connection attempt from %1",
|
||||
remoteIp));
|
||||
return RFB_CLIENT_REFUSE;
|
||||
}
|
||||
|
||||
// In the remaining cases, the connection will be at least partially established, so we need
|
||||
// the clientGoneHook to be called when the connection ends.
|
||||
cl->clientGoneHook = clientGoneHook;
|
||||
|
||||
if (!askOnConnect) {
|
||||
KNotification::event("NewConnectionAutoAccepted",
|
||||
i18n("Accepted uninvited connection from %1",
|
||||
remoteIp));
|
||||
|
||||
emit sessionEstablished(remoteIp);
|
||||
return RFB_CLIENT_ACCEPT;
|
||||
}
|
||||
|
||||
KNotification::event("NewConnectionOnHold",
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
remoteIp));
|
||||
|
||||
ConnectionDialog *dialog = new ConnectionDialog(0);
|
||||
dialog->setRemoteHost(remoteIp);
|
||||
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
|
||||
connect(dialog, SIGNAL(cancelClicked()), SLOT(dialogRejected()));
|
||||
|
||||
dialog->show();
|
||||
|
||||
return RFB_CLIENT_ON_HOLD;
|
||||
}
|
||||
|
||||
bool ConnectionController::handleCheckPassword(rfbClientPtr cl, const char *response, int len)
|
||||
{
|
||||
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
|
||||
QString password = KrfbConfig::uninvitedConnectionPassword();
|
||||
|
||||
bool authd = false;
|
||||
kDebug() << "about to start autentication";
|
||||
|
||||
if (allowUninvited) {
|
||||
authd = checkPassword(password, cl->authChallenge, response, len);
|
||||
}
|
||||
|
||||
if (!authd) {
|
||||
QList<Invitation> invlist = InvitationManager::self()->invitations();
|
||||
|
||||
foreach(const Invitation &it, invlist) {
|
||||
kDebug() << "checking password";
|
||||
if (checkPassword(it.password(), cl->authChallenge, response, len) && it.isValid()) {
|
||||
authd = true;
|
||||
InvitationManager::self()->removeInvitation(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!authd) {
|
||||
if (InvitationManager::self()->invitations().size() > 0) {
|
||||
KNotification::event("InvalidPasswordInvitations",
|
||||
i18n("Failed login attempt from %1: wrong password",
|
||||
remoteIp));
|
||||
} else {
|
||||
KNotification::event("InvalidPassword",
|
||||
i18n("Failed login attempt from %1: wrong password",
|
||||
remoteIp));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ConnectionController::handleKeyEvent(bool down, rfbKeySym keySym)
|
||||
{
|
||||
if (controlEnabled) {
|
||||
KeyboardEvent ev(down, keySym);
|
||||
ev.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionController::handlePointerEvent(int bm, int x, int y)
|
||||
{
|
||||
if (controlEnabled) {
|
||||
PointerEvent ev(bm, x, y);
|
||||
ev.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionController::handleClientGone()
|
||||
{
|
||||
emit clientDisconnected(this);
|
||||
kDebug() << "client gone";
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void ConnectionController::clipboardToServer(const QString &s)
|
||||
{
|
||||
ClipboardEvent ev(this, s);
|
||||
ev.exec();
|
||||
}
|
||||
|
||||
void ConnectionController::dialogAccepted()
|
||||
{
|
||||
ConnectionDialog *dialog = qobject_cast<ConnectionDialog*>(sender());
|
||||
|
||||
if (!dialog) {
|
||||
kWarning() << "Wrong type of sender.";
|
||||
return;
|
||||
}
|
||||
// rfbStartOnHoldClient(cl);
|
||||
cl->onHold = false;
|
||||
setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
|
||||
setControlCanBeEnabled(dialog->cbAllowRemoteControl->isChecked());
|
||||
emit sessionEstablished(remoteIp);
|
||||
}
|
||||
|
||||
void ConnectionController::dialogRejected()
|
||||
{
|
||||
kDebug() << "refused connection";
|
||||
rfbRefuseOnHoldClient(cl);
|
||||
}
|
||||
|
||||
void ConnectionController::setControlEnabled(bool enable)
|
||||
{
|
||||
controlEnabled = enable;
|
||||
}
|
||||
|
||||
void ConnectionController::setControlCanBeEnabled(bool canBeEnabled)
|
||||
{
|
||||
m_controlCanBeEnabled = canBeEnabled;
|
||||
}
|
||||
|
||||
bool ConnectionController::controlCanBeEnabled() const
|
||||
{
|
||||
return m_controlCanBeEnabled;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTIONCONTROLLER_H
|
||||
#define CONNECTIONCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
class KrfbServer;
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class ConnectionController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConnectionController(struct _rfbClientRec *_cl, KrfbServer *parent);
|
||||
|
||||
~ConnectionController();
|
||||
|
||||
bool handleCheckPassword(rfbClientPtr cl, const char *response, int len);
|
||||
void handleNegotiationFinished(struct _rfbClientRec *cl);
|
||||
|
||||
void handleKeyEvent(bool down , rfbKeySym keySym );
|
||||
void handlePointerEvent( int bm, int x, int y);
|
||||
void handleClientGone();
|
||||
void clipboardToServer(const QString &);
|
||||
|
||||
enum rfbNewClientAction handleNewClient();
|
||||
|
||||
void setControlEnabled(bool enable);
|
||||
|
||||
void setControlCanBeEnabled(bool canBeEnabled);
|
||||
bool controlCanBeEnabled() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void sessionEstablished(QString);
|
||||
void notification(QString, QString);
|
||||
void clientDisconnected(ConnectionController *);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void dialogAccepted();
|
||||
void dialogRejected();
|
||||
|
||||
private:
|
||||
QString remoteIp;
|
||||
struct _rfbClientRec *cl;
|
||||
bool controlEnabled;
|
||||
bool m_controlCanBeEnabled;
|
||||
/*
|
||||
int fd;
|
||||
KrfbServer *server;
|
||||
rfbScreenInfoPtr screen;
|
||||
rfbClientPtr client;
|
||||
QTcpSocket *tcpConn;
|
||||
*/
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,71 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "connectiondialog.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QLabel>
|
||||
|
||||
#include <KIconLoader>
|
||||
#include <KLocale>
|
||||
#include <KStandardGuiItem>
|
||||
|
||||
ConnectionDialog::ConnectionDialog( QWidget *parent )
|
||||
: KDialog( parent )
|
||||
{
|
||||
setCaption(i18n("New Connection"));
|
||||
setButtons(Ok|Cancel);
|
||||
setDefaultButton(Cancel);
|
||||
setModal(true);
|
||||
|
||||
setMinimumSize(500, 200);
|
||||
|
||||
m_connectWidget = new QWidget( this );
|
||||
setupUi(m_connectWidget);
|
||||
|
||||
pixmapLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
|
||||
KGuiItem accept = KStandardGuiItem::ok();
|
||||
accept.setText( i18n( "Accept Connection" ) );
|
||||
setButtonGuiItem(Ok, accept);
|
||||
|
||||
KGuiItem refuse = KStandardGuiItem::cancel();
|
||||
refuse.setText( i18n( "Refuse Connection" ) );
|
||||
setButtonGuiItem(Cancel, refuse);
|
||||
|
||||
setMainWidget( m_connectWidget );
|
||||
}
|
||||
|
||||
void ConnectionDialog::setRemoteHost( const QString &host )
|
||||
{
|
||||
remoteHost->setText( host );
|
||||
}
|
||||
|
||||
void ConnectionDialog::setAllowRemoteControl( bool b )
|
||||
{
|
||||
cbAllowRemoteControl->setChecked( b );
|
||||
cbAllowRemoteControl->setVisible(b);
|
||||
}
|
||||
|
||||
bool ConnectionDialog::allowRemoteControl()
|
||||
{
|
||||
return cbAllowRemoteControl->isChecked();
|
||||
}
|
||||
|
||||
#include "connectiondialog.moc"
|
||||
197
events.cpp
197
events.cpp
@@ -1,197 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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.
|
||||
*/
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QX11Info>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
|
||||
Display *KeyboardEvent::dpy;
|
||||
signed char KeyboardEvent::modifiers[0x100];
|
||||
KeyCode KeyboardEvent::keycodes[0x100];
|
||||
KeyCode KeyboardEvent::leftShiftCode;
|
||||
KeyCode KeyboardEvent::rightShiftCode;
|
||||
KeyCode KeyboardEvent::altGrCode;
|
||||
const int KeyboardEvent::LEFTSHIFT = 1;
|
||||
const int KeyboardEvent::RIGHTSHIFT = 2;
|
||||
const int KeyboardEvent::ALTGR = 4;
|
||||
char KeyboardEvent::ModifierState;
|
||||
bool KeyboardEvent::initDone = false;
|
||||
|
||||
|
||||
KeyboardEvent::KeyboardEvent(bool d, KeySym k)
|
||||
: down(d), keySym(k)
|
||||
{
|
||||
initKeycodes();
|
||||
}
|
||||
|
||||
void KeyboardEvent::initKeycodes()
|
||||
{
|
||||
if (initDone) return;
|
||||
initDone = true;
|
||||
KeySym key,*keymap;
|
||||
int i,j,minkey,maxkey,syms_per_keycode;
|
||||
|
||||
dpy = QX11Info::display();
|
||||
|
||||
memset(modifiers,-1,sizeof(modifiers));
|
||||
|
||||
XDisplayKeycodes(dpy,&minkey,&maxkey);
|
||||
Q_ASSERT(minkey >= 8);
|
||||
Q_ASSERT(maxkey < 256);
|
||||
keymap = (KeySym*) XGetKeyboardMapping(dpy, minkey,
|
||||
(maxkey - minkey + 1),
|
||||
&syms_per_keycode);
|
||||
Q_ASSERT(keymap);
|
||||
|
||||
for (i = minkey; i <= maxkey; i++) {
|
||||
for (j=0; j<syms_per_keycode; j++) {
|
||||
key = keymap[(i-minkey)*syms_per_keycode+j];
|
||||
if (key>=' ' && key<0x100 && i==XKeysymToKeycode(dpy,key)) {
|
||||
keycodes[key]=i;
|
||||
modifiers[key]=j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
|
||||
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
|
||||
|
||||
XFree ((char *)keymap);
|
||||
}
|
||||
|
||||
/* this function adjusts the modifiers according to mod (as from modifiers) and ModifierState */
|
||||
void KeyboardEvent::tweakModifiers(signed char mod, bool down)
|
||||
{
|
||||
|
||||
bool isShift = ModifierState & (LEFTSHIFT|RIGHTSHIFT);
|
||||
if(mod < 0)
|
||||
return;
|
||||
|
||||
if(isShift && mod != 1) {
|
||||
if(ModifierState & LEFTSHIFT) {
|
||||
XTestFakeKeyEvent(dpy, leftShiftCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
if(ModifierState & RIGHTSHIFT) {
|
||||
XTestFakeKeyEvent(dpy, rightShiftCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
if(!isShift && mod==1) {
|
||||
XTestFakeKeyEvent(dpy, leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if((ModifierState&ALTGR) && mod != 2) {
|
||||
XTestFakeKeyEvent(dpy, altGrCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
|
||||
if(!(ModifierState&ALTGR) && mod==2) {
|
||||
XTestFakeKeyEvent(dpy, altGrCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardEvent::exec() {
|
||||
#define ADJUSTMOD(sym,state) \
|
||||
if(keySym==sym) { if(down) ModifierState|=state; else ModifierState&=~state; }
|
||||
|
||||
ADJUSTMOD(XK_Shift_L,LEFTSHIFT);
|
||||
ADJUSTMOD(XK_Shift_R,RIGHTSHIFT);
|
||||
ADJUSTMOD(XK_Mode_switch,ALTGR);
|
||||
|
||||
if(keySym>=' ' && keySym<0x100) {
|
||||
KeyCode k;
|
||||
if (down) {
|
||||
tweakModifiers(modifiers[keySym],True);
|
||||
}
|
||||
k = keycodes[keySym];
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(dpy, k, down, CurrentTime);
|
||||
}
|
||||
if (down) {
|
||||
tweakModifiers(modifiers[keySym],False);
|
||||
}
|
||||
} else {
|
||||
KeyCode k = XKeysymToKeycode(dpy, keySym );
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(dpy, k, down, CurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PointerEvent::initialized = false;
|
||||
Display *PointerEvent::dpy;
|
||||
int PointerEvent::buttonMask = 0;
|
||||
|
||||
PointerEvent::PointerEvent(int b, int _x, int _y)
|
||||
: button_mask(b),x(_x),y(_y)
|
||||
{
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
dpy = QX11Info::display();
|
||||
buttonMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PointerEvent::exec() {
|
||||
QDesktopWidget *desktopWidget = QApplication::desktop();
|
||||
|
||||
int screen = desktopWidget->screenNumber();
|
||||
if (screen < 0)
|
||||
screen = 0;
|
||||
XTestFakeMotionEvent(dpy, screen, x, y, CurrentTime);
|
||||
|
||||
for(int i = 0; i < 5; i++) {
|
||||
if ((buttonMask&(1<<i))!=(button_mask&(1<<i))) {
|
||||
XTestFakeButtonEvent(dpy,
|
||||
i+1,
|
||||
(button_mask&(1<<i))?True:False,
|
||||
CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
buttonMask = button_mask;
|
||||
}
|
||||
|
||||
|
||||
ClipboardEvent::ClipboardEvent(ConnectionController *c, const QString &ctext)
|
||||
:controller(c),text(ctext)
|
||||
{
|
||||
}
|
||||
|
||||
void ClipboardEvent::exec()
|
||||
{
|
||||
#if 0
|
||||
if ((controller->lastClipboardDirection == ConnectionController::LAST_SYNC_TO_CLIENT) &&
|
||||
(controller->lastClipboardText == text)) {
|
||||
return;
|
||||
}
|
||||
controller->lastClipboardDirection = ConnectionController::LAST_SYNC_TO_SERVER;
|
||||
controller->lastClipboardText = text;
|
||||
|
||||
controller->clipboard->setText(text, QClipboard::Clipboard);
|
||||
controller->clipboard->setText(text, QClipboard::Selection);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
VNCEvent::~ VNCEvent()
|
||||
{
|
||||
}
|
||||
70
events.h
70
events.h
@@ -1,70 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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.
|
||||
*/
|
||||
|
||||
#ifndef EVENTS_H
|
||||
#define EVENTS_H
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QEvent>
|
||||
#include <QString>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
class ConnectionController;
|
||||
|
||||
class QCursor;
|
||||
|
||||
class VNCEvent {
|
||||
public:
|
||||
virtual void exec() = 0;
|
||||
virtual ~VNCEvent();
|
||||
};
|
||||
|
||||
class KeyboardEvent : public VNCEvent {
|
||||
bool down;
|
||||
KeySym keySym;
|
||||
|
||||
static Display *dpy;
|
||||
static signed char modifiers[0x100];
|
||||
static KeyCode keycodes[0x100], leftShiftCode, rightShiftCode, altGrCode;
|
||||
static const int LEFTSHIFT;
|
||||
static const int RIGHTSHIFT;
|
||||
static const int ALTGR;
|
||||
static char ModifierState;
|
||||
static bool initDone;
|
||||
|
||||
static void tweakModifiers(signed char mod, bool down);
|
||||
public:
|
||||
static void initKeycodes();
|
||||
|
||||
KeyboardEvent(bool d, KeySym k);
|
||||
virtual void exec();
|
||||
};
|
||||
|
||||
class PointerEvent : public VNCEvent {
|
||||
int button_mask, x, y;
|
||||
|
||||
static bool initialized;
|
||||
static Display *dpy;
|
||||
static int buttonMask;
|
||||
public:
|
||||
PointerEvent(int b, int _x, int _y);
|
||||
virtual void exec();
|
||||
};
|
||||
|
||||
class ClipboardEvent : public VNCEvent {
|
||||
ConnectionController *controller;
|
||||
QString text;
|
||||
public:
|
||||
ClipboardEvent(ConnectionController *c, const QString &text);
|
||||
virtual void exec();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,29 +2,38 @@
|
||||
Encoding=UTF-8
|
||||
Comment=Qt based Framebuffer for KRfb.
|
||||
Comment[ast]=Esquema Qt de buffer pa KRfb
|
||||
Comment[bs]=Kadrobafer za KRfb na osnovu Qt
|
||||
Comment[ca]=«Framebuffer» basat en Qt per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en Qt per al KRfb.
|
||||
Comment[cs]=Framebuffer založený na Qt pro KRfb.
|
||||
Comment[da]=Qt-baseret framebuffer til KRfb.
|
||||
Comment[de]=Qt-basierter Framebuffer für KRfb
|
||||
Comment[el]=Μνήμη εξόδου βίντεο καρέ με βάση το Qt για το KRfb.
|
||||
Comment[en_GB]=Qt based Framebuffer for KRfb.
|
||||
Comment[es]=Esquema Qt de buffer para KRfb
|
||||
Comment[es]=Memoria intermedia de vídeo basada en Qt para KRfb.
|
||||
Comment[et]=KRfb Qt põhine kaadripuhver
|
||||
Comment[eu]=Qt-n oinarritutako KRfb-ren irteerako bideoa
|
||||
Comment[fi]=QT-perustainen Kehyspuskuri KRfb:lle
|
||||
Comment[fr]=Sortie vidéo basée sur Qt pour KRfb.
|
||||
Comment[fr]=Sortie vidéo fondée sur Qt pour KRfb.
|
||||
Comment[ga]=Maolán fráma le haghaidh KRfb, bunaithe ar Qt.
|
||||
Comment[gl]=Framebuffer baseado en Qt para KRfb.
|
||||
Comment[hr]=Međuspremnik okvira baziran na Qt-u za KRfb.
|
||||
Comment[hu]=Qt-alapú framebuffer a Krfb-hez.
|
||||
Comment[ia]=Framebuffer basate sur Qt per KRfb
|
||||
Comment[it]=Framebuffer basato su Qt per KRfb.
|
||||
Comment[kk]=Qt негіздеген KRfb-нің кадр буфері.
|
||||
Comment[km]=Framebuffer មានមូលដ្ឋានលើ Qt សម្រាប់ KRfb ។
|
||||
Comment[ko]=KRfb를 위한 Qt 기반 프레임버퍼.
|
||||
Comment[lt]=Qt pagrindu veikiantis Framebuffer skirtas KRfb.
|
||||
Comment[lv]=Qt balstīts kadrbuferis priekš KRfb.
|
||||
Comment[nb]=Qt-basert rammebuffer for KRfb.
|
||||
Comment[nds]=Op Qt opbuut Bildpuffer för KRfb
|
||||
Comment[nl]=Op Qt gebaseerd framebuffer voor KRfb.
|
||||
Comment[nn]=Qt basert framebuffer for KRfb.
|
||||
Comment[pl]=Bufor ramki na podstawie Qt dla KRfb.
|
||||
Comment[pt]='Framebuffer' baseado no Qt para o KRfb.
|
||||
Comment[pt_BR]=Framebuffer baseado no Qt para o KRfb.
|
||||
Comment[si]=KRfb සඳහා Qt මත පදනම් වූ රාමු බෆරය
|
||||
Comment[sk]=Framebuffer založený na Qt pre KRfb.
|
||||
Comment[sl]=Slikovni medpomnilnik za KRFB, ki temelji na Qt
|
||||
Comment[sr]=Кадробафер за КРФБ на основу КуТ‑у
|
||||
@@ -39,29 +48,38 @@ Comment[zh_CN]=基于 Qt 的 KRfb 帧缓冲机制
|
||||
Comment[zh_TW]=KRfb 的 Qt-based Framebuffer
|
||||
Name=Qt Framebuffer for KRfb
|
||||
Name[ast]=Esquema Qt de buffer pa KRfb
|
||||
Name[bs]=Qt-ov kadrobafer za KRFB
|
||||
Name[ca]=«Framebuffer» Qt per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» Qt per al KRfb.
|
||||
Name[cs]=Qt Framebuffer pro KRfb
|
||||
Name[da]=Qt-framebuffer til KRfb
|
||||
Name[de]=Qt-Framebuffer für KRfb
|
||||
Name[el]=Qt Framebuffer for KRfb
|
||||
Name[en_GB]=Qt Framebuffer for KRfb
|
||||
Name[es]=Esquema Qt de buffer para KRfb
|
||||
Name[es]=Memoria intermedia de vídeo Qt para KRfb
|
||||
Name[et]=KRfb Qt kaadripuhver
|
||||
Name[eu]=KRfb-ren Qt-ko irteerako bideoa
|
||||
Name[fi]=QT-kehyspuskuri KRfb:lle
|
||||
Name[fr]=Sortie vidéo Qt pour KRfb
|
||||
Name[ga]=Maolán fráma Qt le haghaidh KRfb
|
||||
Name[gl]=Framebuffer de Qt para KRfb
|
||||
Name[hr]=Qt Framebuffer za KRfb
|
||||
Name[hu]=Qt framebuffer a Krfb-hez
|
||||
Name[ia]=Framebuffer Qt per KRfb
|
||||
Name[it]=Framebuffer Qt per KRfb
|
||||
Name[kk]=Qt KRfb кадр буфері
|
||||
Name[km]=Qt Framebuffer សម្រាប់for KRfb
|
||||
Name[ko]=KRfb를 위한 Qt 프레임버퍼
|
||||
Name[lt]=Qt Framebufferis skirtas KRfb
|
||||
Name[lv]=Qt kadrbuferis priekš KRfb.
|
||||
Name[nb]=Qt rammebuffer for KRfb
|
||||
Name[nds]=Qt-Bildpuffer för KRfb
|
||||
Name[nl]=Qt-framebuffer voor KRfb
|
||||
Name[nn]=Qt-framebuffer for KRfb
|
||||
Name[pl]=Bufor ramki Qt dla KRfb
|
||||
Name[pt]='Framebuffer' do Qt para o KRfb
|
||||
Name[pt_BR]=Framebuffer do Qt para o KRfb
|
||||
Name[si]=KRfb සඳහා වන Qt රාමුබෆරය
|
||||
Name[sk]=Qt Framebuffer pre KRfb
|
||||
Name[sl]=Slikovni medpomnilnik Qt za KRFB
|
||||
Name[sr]=КуТ‑ов кадробафер за КРФБ
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
const int UPDATE_TIME = 500;
|
||||
|
||||
QtFrameBuffer::QtFrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent)
|
||||
: FrameBuffer(id, parent)
|
||||
{
|
||||
fbImage = QPixmap::grabWindow(win).toImage();
|
||||
fb = new char[fbImage.numBytes()];
|
||||
@@ -49,7 +49,7 @@ int QtFrameBuffer::width()
|
||||
return fbImage.width();
|
||||
}
|
||||
|
||||
void QtFrameBuffer::getServerFormat(rfbPixelFormat& format)
|
||||
void QtFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
{
|
||||
format.bitsPerPixel = 32;
|
||||
format.depth = 32;
|
||||
@@ -80,12 +80,12 @@ void QtFrameBuffer::updateFrameBuffer()
|
||||
map.fill(0);
|
||||
|
||||
for (int x = 0; x < imgSize.width(); x++) {
|
||||
for (int y = 0; y < imgSize.height(); y++) {
|
||||
if (img.pixel(x,y) != fbImage.pixel(x,y)) {
|
||||
map.setPixel(x,y,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < imgSize.height(); y++) {
|
||||
if (img.pixel(x, y) != fbImage.pixel(x, y)) {
|
||||
map.setPixel(x, y, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QRegion r(QBitmap::fromImage(map));
|
||||
tiles = tiles + r.rects();
|
||||
@@ -94,7 +94,7 @@ void QtFrameBuffer::updateFrameBuffer()
|
||||
tiles.append(img.rect());
|
||||
#endif
|
||||
|
||||
memcpy(fb, (const char*)img.bits(), img.numBytes());
|
||||
memcpy(fb, (const char *)img.bits(), img.numBytes());
|
||||
fbImage = img;
|
||||
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
|
||||
class QTimer;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class QtFrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QtFrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
virtual int height();
|
||||
virtual int width();
|
||||
virtual int paddedWidth();
|
||||
virtual void getServerFormat(rfbPixelFormat& format);
|
||||
virtual void getServerFormat(rfbPixelFormat &format);
|
||||
virtual void startMonitor();
|
||||
virtual void stopMonitor();
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
|
||||
QtFrameBufferPlugin::QtFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -2,29 +2,38 @@
|
||||
Encoding=UTF-8
|
||||
Comment=X11 XDamage/XShm based Framebuffer for KRfb.
|
||||
Comment[ast]=Esquema de buffer pa KRfb basáu en XDamage/XShm
|
||||
Comment[bs]=X11 XDamage/XShm baziran framebafer za KRfb.
|
||||
Comment[ca]=«Framebuffer» basat en XDamage/XShmQt de l'X11 per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en XDamage/XShmQt de l'X11 per al KRfb.
|
||||
Comment[cs]=Framebuffer založený na X11 XDamage/XShm pro KRfb.
|
||||
Comment[da]=X11 XDamage/XShm-baseret framebuffer til KRfb.
|
||||
Comment[de]=X11 XDamage/XShm-basierter Framebuffer für KRfb.
|
||||
Comment[el]=Μνήμη εξόδου βίντεο καρέ με βάση το X11 XDamage/XShm για το KRfb.
|
||||
Comment[en_GB]=X11 XDamage/XShm based Framebuffer for KRfb.
|
||||
Comment[es]=Esquema de buffer para KRfb basado en XDamage/XShm
|
||||
Comment[es]=Memoria intermedia de vídeo basada en X11 Damage/XShm para KRfb.
|
||||
Comment[et]=KRfb X11 XDamage/XShm põhine kaadripuhver
|
||||
Comment[eu]=X11 XDamage/XShm oinarritutako KRfb-ren irteerako bideoa.
|
||||
Comment[fi]=X11 XDamage/XShm-perustainen kehyspuskui KRfb:lle.
|
||||
Comment[fr]=Sortie vidéo basée sur X11 XDamage / XShm pour KRfb.
|
||||
Comment[fr]=Sortie vidéo fondée sur X11 XDamage / XShm pour KRfb.
|
||||
Comment[ga]=Maolán fráma le haghaidh KRfb, bunaithe ar X11 XDamage/XShm
|
||||
Comment[gl]=Framebuffer baseado en Xll XDamage/Xshm para XRfb.
|
||||
Comment[hr]=Međuspreminik okvira baziran na X11 XDamage/XShm za KRfb.
|
||||
Comment[hu]=X11 XDamage/XShm-alapú framebuffer a Krfb-hez.
|
||||
Comment[ia]=Framebuffer basate sur X11 XDamage/XShm per KRfb.
|
||||
Comment[it]=Framebuffer basato su XDamage/XShm di X11 per KRfb.
|
||||
Comment[kk]=X11 XDamage/XShm негіздеген KRfb кадр буфері.
|
||||
Comment[km]=X11 XDamage/XShm based Framebuffer សម្រាប់ KRfb ។
|
||||
Comment[ko]=KRfb를 위한 X11 XDamage/XShm 기반 프레임버퍼.
|
||||
Comment[lt]=X11 XDamage/XShm paremtas Framebuffer skirtas KRfb.
|
||||
Comment[lv]=X11 XDamage/XShm balstīts kadrbuferis priekš KRfb.
|
||||
Comment[nb]=Rammebuffer for KRfb basert på X11 XDamage/XShm.
|
||||
Comment[nds]=Op X11-XDamage/-XShm opbuut Bildpuffer för KRfb
|
||||
Comment[nl]=Op X11 XDamage/XShm gebaseerd framebuffer voor KRfb.
|
||||
Comment[nn]=X11 XDamage/XShm basert framebuffer for KRfb.
|
||||
Comment[pl]=Bufor ramki na podstawie X11 XDamage/XShm dla KRfb.
|
||||
Comment[pt]='Framebuffer' baseado no XDamage/XShm do X11 para o KRfb.
|
||||
Comment[pt_BR]=Framebuffer baseado no XDamage/XShm do X11 para o KRfb.
|
||||
Comment[si]=KRfb සඳහා වන රාමු බෆරය මත පදනම් වූ X11 XDamage/XShm.
|
||||
Comment[sk]=Framebuffer založený na X11 XDamage/XShm pre KRfb.
|
||||
Comment[sl]=Slikovni medpomnilnik za KRFB, ki temelji na X11 XDamage/XShm
|
||||
Comment[sr]=Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.
|
||||
@@ -39,29 +48,38 @@ Comment[zh_CN]=基于 X11 XDamage/XShm 扩展的 KRfb 帧缓冲机制。
|
||||
Comment[zh_TW]=KRfb 的 X11 XDamage/XShm based Framebuffer
|
||||
Name=X11 Framebuffer for KRfb
|
||||
Name[ast]=Buffer de X11 pa KRfb
|
||||
Name[bs]=X11 frame bafer za KRfb
|
||||
Name[ca]=«Framebuffer» de l'X11 per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» de l'X11 per al KRfb.
|
||||
Name[cs]=X11 Framebuffer pro KRfb
|
||||
Name[da]=X11-framebuffer til KRfb
|
||||
Name[de]=X11-Framebuffer für KRfb
|
||||
Name[el]=X11 Framebuffer for KRfb
|
||||
Name[en_GB]=X11 Framebuffer for KRfb
|
||||
Name[es]=Buffer de X11 para KRfb
|
||||
Name[es]=Memoria intermedia de vídeo X11 para KRfb
|
||||
Name[et]=KRfb X11 kaadripuhver
|
||||
Name[eu]=KRfb-ren X11-ko irteerako bideoa
|
||||
Name[fi]=X11-kehyspuskuri KRfb:lle
|
||||
Name[fr]=Sortie vidéo X11 pour KRfb
|
||||
Name[ga]=Maolán fráma X11 le haghaidh KRfb
|
||||
Name[gl]=Framebuffer de X11 para KRfb
|
||||
Name[hr]=Međuspremnik okvira X11 za KRfb
|
||||
Name[hu]=X11 framebuffer a Krfb-hez
|
||||
Name[ia]=Framebuffer X11 per KRfb
|
||||
Name[it]=Framebuffer X11 per KRfb
|
||||
Name[kk]=X11 KRfb кадр буфері
|
||||
Name[km]=X11 Framebuffer សម្រាប់ KRfb
|
||||
Name[ko]=KRfb를 위한 X11 프레임버퍼
|
||||
Name[lt]=X11 Framebuffer skirtas KRfb
|
||||
Name[lv]=X11 kadrbuferis priekš KRfb
|
||||
Name[nb]=X11 rammebuffer for KRfb
|
||||
Name[nds]=X11-Bildpuffer för KRfb
|
||||
Name[nl]=X11 framebuffer voor KRfb
|
||||
Name[nn]=X11-framebuffer for KRfb
|
||||
Name[pl]=Bufor ramki X11 dla KRfb
|
||||
Name[pt]='Framebuffer' do X11 para o KRfb
|
||||
Name[pt_BR]=Framebuffer do X11 para o KRfb
|
||||
Name[si]=KRfb සඳහා X11 රාමු බෆරය
|
||||
Name[sk]=X11 Framebuffer pre KRfb
|
||||
Name[sl]=Slikovni medpomnilnik X11 za KRFB
|
||||
Name[sr]=Икс11 кадробафер за КРФБ.
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
#include <X11/extensions/XShm.h>
|
||||
#endif
|
||||
|
||||
class X11FrameBuffer::P {
|
||||
class X11FrameBuffer::P
|
||||
{
|
||||
|
||||
public:
|
||||
#ifdef HAVE_XDAMAGE
|
||||
@@ -50,8 +51,8 @@ public:
|
||||
bool running;
|
||||
};
|
||||
|
||||
X11FrameBuffer::X11FrameBuffer(WId id, QObject* parent)
|
||||
:FrameBuffer(id, parent), d(new X11FrameBuffer::P)
|
||||
X11FrameBuffer::X11FrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent), d(new X11FrameBuffer::P)
|
||||
{
|
||||
#ifdef HAVE_XSHM
|
||||
d->useShm = XShmQueryExtension(QX11Info::display());
|
||||
@@ -68,10 +69,11 @@ X11FrameBuffer::X11FrameBuffer(WId id, QObject* parent)
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
|
||||
if (d->useShm) {
|
||||
#ifdef HAVE_XSHM
|
||||
d->updateTile = XShmCreateImage(QX11Info::display(),
|
||||
DefaultVisual( QX11Info::display(), 0 ),
|
||||
DefaultVisual(QX11Info::display(), 0),
|
||||
d->framebufferImage->bits_per_pixel,
|
||||
ZPixmap,
|
||||
NULL,
|
||||
@@ -83,7 +85,7 @@ X11FrameBuffer::X11FrameBuffer(WId id, QObject* parent)
|
||||
IPC_CREAT | 0777);
|
||||
|
||||
d->shminfo.shmaddr = d->updateTile->data = (char *)
|
||||
shmat(d->shminfo.shmid, 0, 0);
|
||||
shmat(d->shminfo.shmid, 0, 0);
|
||||
d->shminfo.readOnly = False;
|
||||
|
||||
XShmAttach(QX11Info::display(), &d->shminfo);
|
||||
@@ -91,11 +93,12 @@ X11FrameBuffer::X11FrameBuffer(WId id, QObject* parent)
|
||||
} else {
|
||||
;
|
||||
}
|
||||
|
||||
kDebug() << "Got image. bpp: " << d->framebufferImage->bits_per_pixel
|
||||
<< ", depth: " << d->framebufferImage->depth
|
||||
<< ", padded width: " << d->framebufferImage->bytes_per_line
|
||||
<< " (sent: " << d->framebufferImage->width * 4 << ")"
|
||||
<< endl;
|
||||
<< ", depth: " << d->framebufferImage->depth
|
||||
<< ", padded width: " << d->framebufferImage->bytes_per_line
|
||||
<< " (sent: " << d->framebufferImage->width * 4 << ")"
|
||||
<< endl;
|
||||
|
||||
fb = d->framebufferImage->data;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
@@ -142,14 +145,14 @@ int X11FrameBuffer::paddedWidth()
|
||||
return d->framebufferImage->bytes_per_line;
|
||||
}
|
||||
|
||||
void X11FrameBuffer::getServerFormat(rfbPixelFormat& format)
|
||||
void X11FrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
{
|
||||
format.bitsPerPixel = d->framebufferImage->bits_per_pixel;
|
||||
format.depth = d->framebufferImage->depth;
|
||||
format.trueColour = true;
|
||||
format.bigEndian = ((d->framebufferImage->bitmap_bit_order == MSBFirst) ? true : false);
|
||||
|
||||
if ( format.bitsPerPixel == 8 ) {
|
||||
if (format.bitsPerPixel == 8) {
|
||||
format.redShift = 0;
|
||||
format.greenShift = 3;
|
||||
format.blueShift = 6;
|
||||
@@ -158,24 +161,33 @@ void X11FrameBuffer::getServerFormat(rfbPixelFormat& format)
|
||||
format.blueMax = 3;
|
||||
} else {
|
||||
format.redShift = 0;
|
||||
if ( d->framebufferImage->red_mask )
|
||||
while ( ! ( d->framebufferImage->red_mask & (1 << format.redShift) ) )
|
||||
|
||||
if (d->framebufferImage->red_mask)
|
||||
while (!(d->framebufferImage->red_mask & (1 << format.redShift))) {
|
||||
format.redShift++;
|
||||
}
|
||||
|
||||
format.greenShift = 0;
|
||||
if ( d->framebufferImage->green_mask )
|
||||
while ( ! ( d->framebufferImage->green_mask & (1 << format.greenShift) ) )
|
||||
|
||||
if (d->framebufferImage->green_mask)
|
||||
while (!(d->framebufferImage->green_mask & (1 << format.greenShift))) {
|
||||
format.greenShift++;
|
||||
}
|
||||
|
||||
format.blueShift = 0;
|
||||
if ( d->framebufferImage->blue_mask )
|
||||
while ( ! ( d->framebufferImage->blue_mask & (1 << format.blueShift) ) )
|
||||
|
||||
if (d->framebufferImage->blue_mask)
|
||||
while (!(d->framebufferImage->blue_mask & (1 << format.blueShift))) {
|
||||
format.blueShift++;
|
||||
}
|
||||
|
||||
format.redMax = d->framebufferImage->red_mask >> format.redShift;
|
||||
format.greenMax = d->framebufferImage->green_mask >> format.greenShift;
|
||||
format.blueMax = d->framebufferImage->blue_mask >> format.blueShift;
|
||||
}
|
||||
}
|
||||
|
||||
void X11FrameBuffer::handleXDamage(XEvent * event)
|
||||
void X11FrameBuffer::handleXDamage(XEvent *event)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
XDamageNotifyEvent *dev = (XDamageNotifyEvent *)event;
|
||||
@@ -189,118 +201,141 @@ void X11FrameBuffer::handleXDamage(XEvent * event)
|
||||
}
|
||||
|
||||
|
||||
void X11FrameBuffer::cleanupRects() {
|
||||
void X11FrameBuffer::cleanupRects()
|
||||
{
|
||||
|
||||
QList<QRect> cpy = tiles;
|
||||
bool inserted = false;
|
||||
tiles.clear();
|
||||
// kDebug() << "before cleanup: " << cpy.size();
|
||||
foreach (const QRect &r, cpy) {
|
||||
foreach(const QRect & r, cpy) {
|
||||
if (tiles.size() > 0) {
|
||||
for(int i = 0; i < tiles.size(); i++) {
|
||||
// kDebug() << r << tiles[i];
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
// kDebug() << r << tiles[i];
|
||||
if (r.intersects(tiles[i])) {
|
||||
tiles[i] |= r;
|
||||
inserted = true;
|
||||
break;
|
||||
// kDebug() << "merged into " << tiles[i];
|
||||
// kDebug() << "merged into " << tiles[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted) {
|
||||
tiles.append(r);
|
||||
// kDebug() << "appended " << r;
|
||||
// kDebug() << "appended " << r;
|
||||
}
|
||||
} else {
|
||||
// kDebug() << "appended " << r;
|
||||
// kDebug() << "appended " << r;
|
||||
tiles.append(r);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < tiles.size(); i++) {
|
||||
tiles[i].adjust(-30,-30,30,30);
|
||||
if (tiles[i].top() < 0){
|
||||
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
tiles[i].adjust(-30, -30, 30, 30);
|
||||
|
||||
if (tiles[i].top() < 0) {
|
||||
tiles[i].setTop(0);
|
||||
}
|
||||
if (tiles[i].left() < 0){
|
||||
|
||||
if (tiles[i].left() < 0) {
|
||||
tiles[i].setLeft(0);
|
||||
}
|
||||
|
||||
if (tiles[i].bottom() > d->framebufferImage->height) {
|
||||
tiles[i].setBottom(d->framebufferImage->height);
|
||||
}
|
||||
|
||||
if (tiles[i].right() > d->framebufferImage->width) {
|
||||
tiles[i].setRight(d->framebufferImage->width);
|
||||
}
|
||||
}
|
||||
|
||||
// kDebug() << "after cleanup: " << tiles.size();
|
||||
}
|
||||
|
||||
void X11FrameBuffer::acquireEvents() {
|
||||
void X11FrameBuffer::acquireEvents()
|
||||
{
|
||||
|
||||
XEvent ev;
|
||||
while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent+XDamageNotify, &ev)) {
|
||||
|
||||
while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent + XDamageNotify, &ev)) {
|
||||
handleXDamage(&ev);
|
||||
}
|
||||
XDamageSubtract(QX11Info::display(),d->damage, None, None);
|
||||
|
||||
XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
}
|
||||
|
||||
QList< QRect > X11FrameBuffer::modifiedTiles()
|
||||
{
|
||||
QList<QRect> ret;
|
||||
if (!d->running) return ret;
|
||||
|
||||
if (!d->running) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
kapp->processEvents(); // try to make sure every damage event goes trough;
|
||||
cleanupRects();
|
||||
QRect gl;
|
||||
|
||||
//d->useShm = false;
|
||||
if (tiles.size() > 0) {
|
||||
if (d->useShm) {
|
||||
#ifdef HAVE_XSHM
|
||||
|
||||
foreach(const QRect &r, tiles) {
|
||||
foreach(const QRect & r, tiles) {
|
||||
// kDebug() << r;
|
||||
gl |= r;
|
||||
int y = r.y();
|
||||
int x = r.x();
|
||||
while (x < r.right() ) {
|
||||
while (y < r.bottom() ) {
|
||||
if (y+d->updateTile->height > d->framebufferImage->height) {
|
||||
|
||||
while (x < r.right()) {
|
||||
while (y < r.bottom()) {
|
||||
if (y + d->updateTile->height > d->framebufferImage->height) {
|
||||
y = d->framebufferImage->height - d->updateTile->height;
|
||||
}
|
||||
if (x+d->updateTile->width > d->framebufferImage->width) {
|
||||
|
||||
if (x + d->updateTile->width > d->framebufferImage->width) {
|
||||
x = d->framebufferImage->width - d->updateTile->width;
|
||||
}
|
||||
|
||||
// kDebug() << "x: " << x << " (" << r.x() << ") y: " << y << " (" << r.y() << ") " << r;
|
||||
XShmGetImage(QX11Info::display(), win, d->updateTile, x, y, AllPlanes);
|
||||
int pxsize = d->framebufferImage->bits_per_pixel / 8;
|
||||
char *dest = fb + ((d->framebufferImage->bytes_per_line * y) + (x*pxsize));
|
||||
char *dest = fb + ((d->framebufferImage->bytes_per_line * y) + (x * pxsize));
|
||||
char *src = d->updateTile->data;
|
||||
|
||||
for (int i = 0; i < d->updateTile->height; i++) {
|
||||
memcpy(dest, src, d->updateTile->bytes_per_line);
|
||||
dest += d->framebufferImage->bytes_per_line;
|
||||
src += d->updateTile->bytes_per_line;
|
||||
}
|
||||
|
||||
y += d->updateTile->height;
|
||||
}
|
||||
|
||||
x += d->updateTile->width;
|
||||
y = r.y();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
foreach(const QRect &r, tiles) {
|
||||
foreach(const QRect & r, tiles) {
|
||||
XGetSubImage(QX11Info::display(),
|
||||
win,
|
||||
r.left(),
|
||||
r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
AllPlanes,
|
||||
ZPixmap,
|
||||
d->framebufferImage,
|
||||
r.left(),
|
||||
r.top()
|
||||
);
|
||||
win,
|
||||
r.left(),
|
||||
r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
AllPlanes,
|
||||
ZPixmap,
|
||||
d->framebufferImage,
|
||||
r.left(),
|
||||
r.top()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// kDebug() << "tot: " << gl;
|
||||
// kDebug() << tiles.size();
|
||||
ret = tiles;
|
||||
@@ -313,7 +348,7 @@ void X11FrameBuffer::startMonitor()
|
||||
d->running = true;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
d->damage = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles);
|
||||
XDamageSubtract(QX11Info::display(),d->damage, None, None);
|
||||
XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -321,14 +356,14 @@ void X11FrameBuffer::stopMonitor()
|
||||
{
|
||||
d->running = false;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
XDamageDestroy(QX11Info::display(),d->damage);
|
||||
XDamageDestroy(QX11Info::display(), d->damage);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
EvWidget::EvWidget(X11FrameBuffer * x11fb)
|
||||
:QWidget(0), fb(x11fb)
|
||||
EvWidget::EvWidget(X11FrameBuffer *x11fb)
|
||||
: QWidget(0), fb(x11fb)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
int er;
|
||||
@@ -336,13 +371,15 @@ EvWidget::EvWidget(X11FrameBuffer * x11fb)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool EvWidget::x11Event(XEvent * event)
|
||||
bool EvWidget::x11Event(XEvent *event)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
if (event->type == xdamageBaseEvent+XDamageNotify) {
|
||||
|
||||
if (event->type == xdamageBaseEvent + XDamageNotify) {
|
||||
fb->handleXDamage(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -14,14 +14,15 @@
|
||||
|
||||
class X11FrameBuffer;
|
||||
|
||||
class EvWidget: public QWidget {
|
||||
class EvWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EvWidget(X11FrameBuffer *x11fb);
|
||||
|
||||
protected:
|
||||
bool x11Event ( XEvent * event );
|
||||
bool x11Event(XEvent *event);
|
||||
|
||||
private:
|
||||
X11FrameBuffer *fb;
|
||||
@@ -29,13 +30,13 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class X11FrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
X11FrameBuffer(WId id, QObject* parent = 0);
|
||||
X11FrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
~X11FrameBuffer();
|
||||
|
||||
@@ -44,18 +45,18 @@ public:
|
||||
virtual int height();
|
||||
virtual int width();
|
||||
virtual int paddedWidth();
|
||||
virtual void getServerFormat(rfbPixelFormat& format);
|
||||
virtual void getServerFormat(rfbPixelFormat &format);
|
||||
virtual void startMonitor();
|
||||
virtual void stopMonitor();
|
||||
|
||||
|
||||
void handleXDamage( XEvent *event);
|
||||
void handleXDamage(XEvent *event);
|
||||
private:
|
||||
void cleanupRects();
|
||||
void acquireEvents();
|
||||
|
||||
class P;
|
||||
P * const d;
|
||||
P *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
|
||||
X11FrameBufferPlugin::X11FrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "invitedialog.h"
|
||||
|
||||
#include <kiconloader.h>
|
||||
#include <klocale.h>
|
||||
#include <KStandardGuiItem>
|
||||
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QToolTip>
|
||||
#include <QtGui/QCursor>
|
||||
|
||||
InviteDialog::InviteDialog( QWidget *parent )
|
||||
: KDialog( parent )
|
||||
{
|
||||
setCaption(i18n("Invitation"));
|
||||
setButtons(User1|Close|Help);
|
||||
setHelp(QString(), "krfb");
|
||||
setDefaultButton(NoDefault);
|
||||
|
||||
setMinimumSize(500, 300);
|
||||
|
||||
m_inviteWidget = new QWidget( this );
|
||||
setupUi(m_inviteWidget);
|
||||
|
||||
pixmapLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
setMainWidget( m_inviteWidget );
|
||||
|
||||
setButtonGuiItem( User1, KStandardGuiItem::configure() );
|
||||
|
||||
connect( btnCreateInvite, SIGNAL( clicked() ),
|
||||
SIGNAL( createInviteClicked() ) );
|
||||
connect( btnEmailInvite, SIGNAL( clicked() ),
|
||||
SIGNAL( emailInviteClicked() ) );
|
||||
connect( btnManageInvite, SIGNAL( clicked() ),
|
||||
SIGNAL( manageInviteClicked() ) );
|
||||
connect( helpLabel, SIGNAL( linkActivated ( QString ) ),
|
||||
SLOT( showWhatsthis() ));
|
||||
}
|
||||
|
||||
void InviteDialog::slotUser1()
|
||||
{
|
||||
emit configureClicked();
|
||||
}
|
||||
|
||||
void InviteDialog::enableInviteButton( bool enable )
|
||||
{
|
||||
btnCreateInvite->setEnabled( enable );
|
||||
}
|
||||
|
||||
void InviteDialog::setInviteCount( int count )
|
||||
{
|
||||
btnManageInvite->setText(
|
||||
i18n( "&Manage Invitations (%1)...", count ) );
|
||||
}
|
||||
|
||||
void InviteDialog::showWhatsthis()
|
||||
{
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
i18n("An invitation creates a one-time password that allows the receiver to connect to your desktop.\n"
|
||||
"It is valid for only one successful connection and will expire after an hour if it has not been used. \n"
|
||||
"When somebody connects to your computer a dialog will appear and ask you for permission.\n "
|
||||
"The connection will not be established before you accept it. In this dialog you can also\n restrict "
|
||||
"the other person to view your desktop only, without the ability to move your\n mouse pointer or press "
|
||||
"keys.\nIf you want to create a permanent password for Desktop Sharing, allow 'Uninvited Connections' \n"
|
||||
"in the configuration."));
|
||||
}
|
||||
|
||||
#include "invitedialog.moc"
|
||||
@@ -1,6 +1,6 @@
|
||||
include_directories(${CMAKE_BINARY_DIR}/krfb/krfb/ ${CMAKE_SOURCE_DIR}/krfb/srvloc/)
|
||||
include_directories(${CMAKE_BINARY_DIR}/krfb/krfb)
|
||||
|
||||
set(kcm_krfb_PART_SRCS kcm_krfb.cpp ${srvloc_SRCS} ${krfbconfig_SRCS})
|
||||
set(kcm_krfb_PART_SRCS kcm_krfb.cpp ${krfbconfig_SRCS})
|
||||
|
||||
kde4_add_ui3_files(kcm_krfb_PART_SRCS configurationwidget.ui)
|
||||
kde4_add_ui3_files(kcm_krfb_PART_SRCS
|
||||
@@ -10,7 +10,7 @@ kde4_add_ui3_files(kcm_krfb_PART_SRCS
|
||||
|
||||
kde4_add_plugin(kcm_krfb ${kcm_krfb_PART_SRCS})
|
||||
|
||||
target_link_libraries(kcm_krfb ${KDE4_KDECORE_LIBS} ${KDE4_KDE3SUPPORT_LIBS} ${SLP_LIBRARIES})
|
||||
target_link_libraries(kcm_krfb ${KDE4_KDECORE_LIBS} ${KDE4_KDE3SUPPORT_LIBS})
|
||||
|
||||
install(TARGETS kcm_krfb DESTINATION ${PLUGIN_INSTALL_DIR})
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
#! /bin/sh
|
||||
$EXTRACTRC *.ui >> rc.cpp
|
||||
$XGETTEXT *.cpp -o $podir/kcm_krfb.pot
|
||||
|
||||
@@ -39,128 +39,142 @@
|
||||
|
||||
|
||||
typedef KGenericFactory<KcmKRfb, QWidget> KcmKRfbFactory;
|
||||
K_EXPORT_COMPONENT_FACTORY( krfb, KcmKRfbFactory( "kcm_krfb" ) )
|
||||
K_EXPORT_COMPONENT_FACTORY(krfb, KcmKRfbFactory("kcm_krfb"))
|
||||
|
||||
|
||||
|
||||
KcmKRfb::KcmKRfb(QWidget *p, const QStringList &) :
|
||||
KCModule(KcmKRfbFactory::componentData(), p),
|
||||
m_configuration(KRFB_CONFIGURATION_MODE) {
|
||||
KCModule(KcmKRfbFactory::componentData(), p),
|
||||
m_configuration(KRFB_CONFIGURATION_MODE)
|
||||
{
|
||||
|
||||
KGlobal::locale()->insertCatalog("krfb");
|
||||
m_confWidget = new ConfigurationWidget(this);
|
||||
KGlobal::locale()->insertCatalog("krfb");
|
||||
m_confWidget = new ConfigurationWidget(this);
|
||||
|
||||
QVBoxLayout *l = new QVBoxLayout(this);
|
||||
l->setSpacing(KDialog::spacingHint());
|
||||
l->setMargin(0);
|
||||
l->add(m_confWidget);
|
||||
QVBoxLayout *l = new QVBoxLayout(this);
|
||||
l->setSpacing(KDialog::spacingHint());
|
||||
l->setMargin(0);
|
||||
l->add(m_confWidget);
|
||||
|
||||
setButtons(Default|Apply|Default);
|
||||
setButtons(Default | Apply | Default);
|
||||
|
||||
KAboutData* about = new KAboutData( "kcm_krfb", 0, ki18n("Desktop Sharing Control Module"),
|
||||
VERSION,
|
||||
ki18n("Configure desktop sharing"), KAboutData::License_GPL,
|
||||
ki18n("(c) 2002, Tim Jansen\n"),
|
||||
KLocalizedString(), "http://www.tjansen.de/krfb", "tim@tjansen.de");
|
||||
about->addAuthor(ki18n("Tim Jansen"), KLocalizedString(), "tim@tjansen.de");
|
||||
setAboutData( about );
|
||||
KAboutData *about = new KAboutData("kcm_krfb", 0, ki18n("Desktop Sharing Control Module"),
|
||||
VERSION,
|
||||
ki18n("Configure desktop sharing"), KAboutData::License_GPL,
|
||||
ki18n("(c) 2002, Tim Jansen\n"),
|
||||
KLocalizedString(), "http://www.tjansen.de/krfb", "tim@tjansen.de");
|
||||
about->addAuthor(ki18n("Tim Jansen"), KLocalizedString(), "tim@tjansen.de");
|
||||
setAboutData(about);
|
||||
|
||||
load();
|
||||
load();
|
||||
|
||||
connect(m_confWidget->passwordInput, SIGNAL(textChanged(const QString&)), SLOT(configChanged()) );
|
||||
connect(m_confWidget->allowUninvitedCB, SIGNAL(clicked()), SLOT(configChanged()) );
|
||||
connect(m_confWidget->enableSLPCB, SIGNAL(clicked()), SLOT(configChanged()) );
|
||||
connect(m_confWidget->confirmConnectionsCB, SIGNAL(clicked()), SLOT(configChanged()) );
|
||||
connect(m_confWidget->allowDesktopControlCB, SIGNAL(clicked()), SLOT(configChanged()) );
|
||||
connect(m_confWidget->autoPortCB, SIGNAL(clicked()), SLOT(configChanged()) );
|
||||
connect(m_confWidget->portInput, SIGNAL(valueChanged(int)), SLOT(configChanged()) );
|
||||
connect((QObject*)m_confWidget->manageInvitations, SIGNAL(clicked()),
|
||||
&m_configuration, SLOT(showManageInvitationsDialog()) );
|
||||
connect(&m_configuration, SIGNAL(invitationNumChanged(int)),
|
||||
this, SLOT(setInvitationNum(int)));
|
||||
setInvitationNum(m_configuration.invitations().size());
|
||||
connect(m_confWidget->disableBackgroundCB, SIGNAL(clicked()), SLOT(configChanged()) );
|
||||
connect(m_confWidget->passwordInput, SIGNAL(textChanged(QString)), SLOT(configChanged()));
|
||||
connect(m_confWidget->allowUninvitedCB, SIGNAL(clicked()), SLOT(configChanged()));
|
||||
connect(m_confWidget->enableSLPCB, SIGNAL(clicked()), SLOT(configChanged()));
|
||||
connect(m_confWidget->confirmConnectionsCB, SIGNAL(clicked()), SLOT(configChanged()));
|
||||
connect(m_confWidget->allowDesktopControlCB, SIGNAL(clicked()), SLOT(configChanged()));
|
||||
connect(m_confWidget->autoPortCB, SIGNAL(clicked()), SLOT(configChanged()));
|
||||
connect(m_confWidget->portInput, SIGNAL(valueChanged(int)), SLOT(configChanged()));
|
||||
connect((QObject *)m_confWidget->manageInvitations, SIGNAL(clicked()),
|
||||
&m_configuration, SLOT(showManageInvitationsDialog()));
|
||||
connect(&m_configuration, SIGNAL(invitationNumChanged(int)),
|
||||
this, SLOT(setInvitationNum(int)));
|
||||
setInvitationNum(m_configuration.invitations().size());
|
||||
connect(m_confWidget->disableBackgroundCB, SIGNAL(clicked()), SLOT(configChanged()));
|
||||
}
|
||||
|
||||
void KcmKRfb::configChanged() {
|
||||
emit changed(true);
|
||||
void KcmKRfb::configChanged()
|
||||
{
|
||||
emit changed(true);
|
||||
}
|
||||
|
||||
void KcmKRfb::setInvitationNum(int num) {
|
||||
if (num == 0)
|
||||
m_confWidget->invitationNumLabel->setText(i18n("You have no open invitation."));
|
||||
else
|
||||
m_confWidget->invitationNumLabel->setText(i18n("Open invitations: %1", num));
|
||||
void KcmKRfb::setInvitationNum(int num)
|
||||
{
|
||||
if (num == 0) {
|
||||
m_confWidget->invitationNumLabel->setText(i18n("You have no open invitation."));
|
||||
} else {
|
||||
m_confWidget->invitationNumLabel->setText(i18n("Open invitations: %1", num));
|
||||
}
|
||||
}
|
||||
|
||||
void KcmKRfb::checkKInetd(bool &kinetdAvailable, bool &krfbAvailable) {
|
||||
kinetdAvailable = false;
|
||||
krfbAvailable = false;
|
||||
//TODO verify it when kinetd will port
|
||||
QDBusInterface kinetd("org.kde.kded", "/modules/kinetd", "org.kde.kinetd");
|
||||
QDBusReply<bool> reply = kinetd.call("isInstalled","krfb");
|
||||
if(!reply.isValid())
|
||||
return;
|
||||
krfbAvailable = reply;
|
||||
kinetdAvailable=true;
|
||||
void KcmKRfb::checkKInetd(bool &kinetdAvailable, bool &krfbAvailable)
|
||||
{
|
||||
kinetdAvailable = false;
|
||||
krfbAvailable = false;
|
||||
//TODO verify it when kinetd will port
|
||||
QDBusInterface kinetd("org.kde.kded", "/modules/kinetd", "org.kde.kinetd");
|
||||
QDBusReply<bool> reply = kinetd.call("isInstalled", "krfb");
|
||||
|
||||
if (!reply.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
krfbAvailable = reply;
|
||||
kinetdAvailable = true;
|
||||
}
|
||||
|
||||
void KcmKRfb::load() {
|
||||
bool kinetdAvailable, krfbAvailable;
|
||||
checkKInetd(kinetdAvailable, krfbAvailable);
|
||||
void KcmKRfb::load()
|
||||
{
|
||||
bool kinetdAvailable, krfbAvailable;
|
||||
checkKInetd(kinetdAvailable, krfbAvailable);
|
||||
|
||||
m_confWidget->allowUninvitedCB->setChecked(m_configuration.allowUninvitedConnections());
|
||||
m_confWidget->enableSLPCB->setChecked(m_configuration.enableSLP());
|
||||
m_confWidget->confirmConnectionsCB->setChecked(m_configuration.askOnConnect());
|
||||
m_confWidget->allowDesktopControlCB->setChecked(m_configuration.allowDesktopControl());
|
||||
m_confWidget->passwordInput->setText(m_configuration.password());
|
||||
m_confWidget->autoPortCB->setChecked(m_configuration.preferredPort()<0);
|
||||
m_confWidget->portInput->setValue(m_configuration.preferredPort()> 0 ?
|
||||
m_configuration.preferredPort() : 5900);
|
||||
m_confWidget->disableBackgroundCB->setChecked(m_configuration.disableBackground());
|
||||
emit changed(false);
|
||||
m_confWidget->allowUninvitedCB->setChecked(m_configuration.allowUninvitedConnections());
|
||||
m_confWidget->enableSLPCB->setChecked(m_configuration.enableSLP());
|
||||
m_confWidget->confirmConnectionsCB->setChecked(m_configuration.askOnConnect());
|
||||
m_confWidget->allowDesktopControlCB->setChecked(m_configuration.allowDesktopControl());
|
||||
m_confWidget->passwordInput->setText(m_configuration.password());
|
||||
m_confWidget->autoPortCB->setChecked(m_configuration.preferredPort() < 0);
|
||||
m_confWidget->portInput->setValue(m_configuration.preferredPort() > 0 ?
|
||||
m_configuration.preferredPort() : 5900);
|
||||
m_confWidget->disableBackgroundCB->setChecked(m_configuration.disableBackground());
|
||||
emit changed(false);
|
||||
}
|
||||
|
||||
void KcmKRfb::save() {
|
||||
void KcmKRfb::save()
|
||||
{
|
||||
|
||||
m_configuration.update();
|
||||
bool allowUninvited = m_confWidget->allowUninvitedCB->isChecked();
|
||||
m_configuration.setAllowUninvited(allowUninvited);
|
||||
m_configuration.setEnableSLP(m_confWidget->enableSLPCB->isChecked());
|
||||
m_configuration.setAskOnConnect(m_confWidget->confirmConnectionsCB->isChecked());
|
||||
m_configuration.setAllowDesktopControl(m_confWidget->allowDesktopControlCB->isChecked());
|
||||
m_configuration.setPassword(m_confWidget->passwordInput->text());
|
||||
if (m_confWidget->autoPortCB->isChecked())
|
||||
m_configuration.setPreferredPort(-1);
|
||||
else
|
||||
m_configuration.setPreferredPort(m_confWidget->portInput->value());
|
||||
m_configuration.setDisableBackground(m_confWidget->disableBackgroundCB->isChecked());
|
||||
m_configuration.save();
|
||||
m_configuration.update();
|
||||
bool allowUninvited = m_confWidget->allowUninvitedCB->isChecked();
|
||||
m_configuration.setAllowUninvited(allowUninvited);
|
||||
m_configuration.setEnableSLP(m_confWidget->enableSLPCB->isChecked());
|
||||
m_configuration.setAskOnConnect(m_confWidget->confirmConnectionsCB->isChecked());
|
||||
m_configuration.setAllowDesktopControl(m_confWidget->allowDesktopControlCB->isChecked());
|
||||
m_configuration.setPassword(m_confWidget->passwordInput->text());
|
||||
|
||||
if (m_confWidget->autoPortCB->isChecked()) {
|
||||
m_configuration.setPreferredPort(-1);
|
||||
} else {
|
||||
m_configuration.setPreferredPort(m_confWidget->portInput->value());
|
||||
}
|
||||
|
||||
m_configuration.setDisableBackground(m_confWidget->disableBackgroundCB->isChecked());
|
||||
m_configuration.save();
|
||||
#if 0
|
||||
kapp->dcopClient()->emitDCOPSignal("KRFB::ConfigChanged", "KRFB_ConfigChanged()", QByteArray());
|
||||
kapp->dcopClient()->emitDCOPSignal("KRFB::ConfigChanged", "KRFB_ConfigChanged()", QByteArray());
|
||||
#endif
|
||||
emit changed(false);
|
||||
emit changed(false);
|
||||
}
|
||||
|
||||
void KcmKRfb::defaults() {
|
||||
bool kinetdAvailable, krfbAvailable;
|
||||
checkKInetd(kinetdAvailable, krfbAvailable);
|
||||
void KcmKRfb::defaults()
|
||||
{
|
||||
bool kinetdAvailable, krfbAvailable;
|
||||
checkKInetd(kinetdAvailable, krfbAvailable);
|
||||
|
||||
m_confWidget->allowUninvitedCB->setChecked(false);
|
||||
m_confWidget->enableSLPCB->setChecked(true);
|
||||
m_confWidget->confirmConnectionsCB->setChecked(false);
|
||||
m_confWidget->allowDesktopControlCB->setChecked(false);
|
||||
m_confWidget->passwordInput->setText("");
|
||||
m_confWidget->autoPortCB->setChecked(true);
|
||||
m_confWidget->portInput->setValue(5900);
|
||||
m_confWidget->disableBackgroundCB->setChecked(false);
|
||||
emit changed(true);
|
||||
m_confWidget->allowUninvitedCB->setChecked(false);
|
||||
m_confWidget->enableSLPCB->setChecked(true);
|
||||
m_confWidget->confirmConnectionsCB->setChecked(false);
|
||||
m_confWidget->allowDesktopControlCB->setChecked(false);
|
||||
m_confWidget->passwordInput->setText("");
|
||||
m_confWidget->autoPortCB->setChecked(true);
|
||||
m_confWidget->portInput->setValue(5900);
|
||||
m_confWidget->disableBackgroundCB->setChecked(false);
|
||||
emit changed(true);
|
||||
}
|
||||
|
||||
QString KcmKRfb::quickHelp() const
|
||||
{
|
||||
return i18n("<h1>Desktop Sharing</h1> This module allows you to configure"
|
||||
" the KDE desktop sharing.");
|
||||
return i18n("<h1>Desktop Sharing</h1> This module allows you to configure"
|
||||
" the KDE desktop sharing.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,22 +27,23 @@
|
||||
#include "configurationwidget.h"
|
||||
#include "../krfb/configuration.h"
|
||||
|
||||
class KcmKRfb : public KCModule {
|
||||
Q_OBJECT
|
||||
class KcmKRfb : public KCModule
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
Configuration m_configuration;
|
||||
ConfigurationWidget *m_confWidget;
|
||||
void checkKInetd(bool&, bool&);
|
||||
Configuration m_configuration;
|
||||
ConfigurationWidget *m_confWidget;
|
||||
void checkKInetd(bool &, bool &);
|
||||
public:
|
||||
KcmKRfb(QWidget *p, const QStringList &);
|
||||
KcmKRfb(QWidget *p, const QStringList &);
|
||||
|
||||
void load();
|
||||
void save();
|
||||
void defaults();
|
||||
QString quickHelp() const;
|
||||
void load();
|
||||
void save();
|
||||
void defaults();
|
||||
QString quickHelp() const;
|
||||
private slots:
|
||||
void setInvitationNum(int num);
|
||||
void configChanged();
|
||||
void setInvitationNum(int num);
|
||||
void configChanged();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -14,9 +14,10 @@ Name=Desktop Sharing
|
||||
Name[af]=Werkskerm Deeling
|
||||
Name[ar]=مشاركة سطح المكتب
|
||||
Name[ast]=Escritoriu compartiu
|
||||
Name[bg]=Споделяне на работното място
|
||||
Name[bg]=Споделяне на работния плот
|
||||
Name[bn]=ডেস্কটপ ভাগাভাগি
|
||||
Name[br]=Rannañ ar vurev
|
||||
Name[bs]=Dijeljenje radne površine
|
||||
Name[ca]=Compartició de l'escriptori
|
||||
Name[ca@valencia]=Compartició de l'escriptori
|
||||
Name[cs]=Sdílení pracovní plochy
|
||||
@@ -39,6 +40,7 @@ Name[hi]=डेस्कटॉप साझेदारी
|
||||
Name[hne]=डेस्कटाप साझेदारी
|
||||
Name[hr]=Dijeljenje radne površine
|
||||
Name[hu]=Munkaasztal-megosztás
|
||||
Name[ia]=Compartir de scriptorio
|
||||
Name[is]=Skjáborðamiðlun
|
||||
Name[it]=Condivisione del desktop
|
||||
Name[ja]=デスクトップ共有
|
||||
@@ -58,10 +60,11 @@ Name[nn]=Skrivebordsdeling
|
||||
Name[pa]=ਡੈਸਕਟਾਪ ਸ਼ੇਅਰਿੰਗ
|
||||
Name[pl]=Współdzielenie pulpitu
|
||||
Name[pt]=Partilha do Ecrã
|
||||
Name[pt_BR]=Compartilhamento do Desktop
|
||||
Name[pt_BR]=Compartilhamento do área de trabalho
|
||||
Name[ro]=Partajare birou
|
||||
Name[ru]=Общий рабочий стол
|
||||
Name[se]=Čállinbeavdejuohkkin
|
||||
Name[si]=වැඩතල හවුල්
|
||||
Name[sk]=Zdieľanie pracovnej plochy
|
||||
Name[sl]=Deljenje namizja
|
||||
Name[sr]=Дељење површи
|
||||
@@ -73,6 +76,7 @@ Name[ta]=பணிமேடை பகிர்வு
|
||||
Name[tg]=Истифодабарии муштараки Мизи корӣ
|
||||
Name[th]=ใช้งานพื้นที่ทำงานร่วมกัน
|
||||
Name[tr]=Masaüstü Paylaşımı
|
||||
Name[ug]=ئۈستەلئۈستىنى ھەمبەھىرلەش
|
||||
Name[uk]=Спільні стільниці
|
||||
Name[vi]=Chia sẻ màn hình nền
|
||||
Name[xh]=Ukwehlulelana kwe Desktop
|
||||
@@ -85,9 +89,10 @@ Comment=Configure Desktop Sharing
|
||||
Comment[af]=Konfigureer Werkskerm Deeling
|
||||
Comment[ar]=تعديل مشاركة سطح المكتب
|
||||
Comment[ast]=Configura'l to escritoriu compartíu
|
||||
Comment[bg]=Настройване споделянето на работното място
|
||||
Comment[bg]=Настройки на споделянето на работния плот
|
||||
Comment[bn]=ডেস্কটপ ভাগাভাগি কনফিগার করুন
|
||||
Comment[br]=Kefluniañ rannañ ar vurev
|
||||
Comment[bs]=Podešavanje dijeljenja površine
|
||||
Comment[ca]=Lupa de l'escriptori
|
||||
Comment[ca@valencia]=Lupa de l'escriptori
|
||||
Comment[cs]=Nastavit sdílení pracovní plochy
|
||||
@@ -110,6 +115,7 @@ Comment[hi]=डेस्कटॉप साझेदारी कॉन्फ़
|
||||
Comment[hne]=डेस्कटाप साझेदारी कान्फिगर करव
|
||||
Comment[hr]=Podešavanje dijeljenja radne površine
|
||||
Comment[hu]=A munkaasztal-megosztás beállításai
|
||||
Comment[ia]=Configura le compartir de scriptorio
|
||||
Comment[is]=Stilla skjáborðsmiðlun
|
||||
Comment[it]=Configura condivisione del desktop
|
||||
Comment[ja]=デスクトップ共有の設定
|
||||
@@ -129,10 +135,11 @@ Comment[nn]=Set opp skrivebordsdeling
|
||||
Comment[pa]=ਡੈਸਕਟਾਪ ਸ਼ੇਅਰਿੰਗ ਸੰਰਚਨਾ
|
||||
Comment[pl]=Konfiguracja współdzielenia pulpitu
|
||||
Comment[pt]=Configurar a Partilha do Ecrã
|
||||
Comment[pt_BR]=Configurar compartilhamento da área de trabalho
|
||||
Comment[pt_BR]=Configura o compartilhamento da área de trabalho
|
||||
Comment[ro]=Configurează partajarea biroului
|
||||
Comment[ru]=Параметры общего рабочего стола
|
||||
Comment[se]=Heivet čállinbeavdejuohkkima
|
||||
Comment[si]=වැඩතල හවුල් සකසන්න
|
||||
Comment[sk]=Nastavenie zdieľania pracovnej plochy
|
||||
Comment[sl]=Nastavi deljenje namizja
|
||||
Comment[sr]=Подешавање дељења површи
|
||||
@@ -152,47 +159,38 @@ Comment[zh_CN]=配置桌面共享
|
||||
Comment[zh_HK]=設定桌面分享
|
||||
Comment[zh_TW]=設定桌面分享
|
||||
X-KDE-Keywords=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited
|
||||
X-KDE-Keywords[bg]=Keywords=споделяне, работно, място, десктоп, покана, връзка, desktop sharing, krfb, vnc, sharing, krdc, remote desktop connection, invitation, port, slp, uninvited
|
||||
X-KDE-Keywords[ca]=compartició de l'escriptori,krfb,vnc,compartir,krdc,connexió a l'escriptori remot,invitació,port,slp,no invitat
|
||||
X-KDE-Keywords[cs]=sdílení plochy,krfb,vnc,sdílení,rdp,krdc,připojení vzdálené plochy,pozvánka,port,slp
|
||||
X-KDE-Keywords[cy]=rhannu penbwrdd,krfb,vnc,rhannu,rdp,krdc,cysylltiad penbwrdd pell,gwahoddiad,porth,slp,heb wahoddiad
|
||||
X-KDE-Keywords[da]=desktopdeling,krfb,vnc,deling,krdc,ekstern desktopforbindelse,invitation,port,slp,ikke inviteret
|
||||
X-KDE-Keywords[de]=Arbeitsfläche freigeben,krfb,VNC,freigeben,krdc,Entfernte Arbeitsfläche,Einladung,Port,slp,uneingeladen,rdp,remote desktop
|
||||
X-KDE-Keywords[el]=κοινή χρήση επιφάνειας εργασίας,krfb,vnc,κοινή χρήση,krdc,σύνδεση σε απομακρυσμένη επιφάνεια εργασίας,πρόσκληση,θύρα,slp,απρόσκλητο
|
||||
X-KDE-Keywords[es]=escritorio compartido,krfb,vnc,compartir,rdp,krdc, conexión escritorio remoto,invitación,puerto,slp,no invitado
|
||||
X-KDE-Keywords[ca]=compartició d'escriptori,krfb,vnc,compartició,krdc,connexió d'escriptori remot,invitació,port,slp,no invitat
|
||||
X-KDE-Keywords[ca@valencia]=compartició d'escriptori,krfb,vnc,compartició,krdc,connexió d'escriptori remot,invitació,port,slp,no invitat
|
||||
X-KDE-Keywords[da]=skrivebordsdeling,krfb,vnc,deling,krdc,remote desktop,fjernskrivebord,invitation,port,slp,uinviteret
|
||||
X-KDE-Keywords[de]=freigabe der arbeitsfläche,krfb,vnc,freigabe,krdc,fernwartung,einladung,port,slp
|
||||
X-KDE-Keywords[el]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited
|
||||
X-KDE-Keywords[es]=compartición de escritorio,krfb,vnc,compartición,krdc,conexión de escritorio en remoto,invitación,puerto,slp,no invitado
|
||||
X-KDE-Keywords[et]=töölaua jagamine,krfb,vnc,jagamine,rdp,krdc,kaugtöölaua ühendus,rdp,kutse,port,slp,kutsumata
|
||||
X-KDE-Keywords[eu]=mahaigain partekatzea,krfb,vnc,partekatzea,krdc,urruneko mahaigain konexioa,gonbidapena,ataka,slp,gonbidapen gabea
|
||||
X-KDE-Keywords[fa]=اشتراک رومیزی، krfb، vnc، اتصال رومیزی راه دور، دعوت، درگاه، slp، دعوتنشده
|
||||
X-KDE-Keywords[fi]=työpöydän jakaminen,krfb,vnc,jakaminen,krdc,etätyöpöytäyhteys, kutsu,portti,slp,kutsumaton, työpöytä
|
||||
X-KDE-Keywords[fr]=partage de bureau,krfb,vnc,partage,rdp,krdc,connexion à un bureau distant,invitation,port,slp,non invité
|
||||
X-KDE-Keywords[gl]=compartilla de escritorio, vnc, compartir, krdc, conexón ao escritorio remoto, invitación, porto, slt, convidado, compartillar
|
||||
X-KDE-Keywords[he]=שיתוף שולחן עבודה,שיתוף,חיבור לשולחן עבודה מרוחק,desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection, invitation, port, slp, uninvited
|
||||
X-KDE-Keywords[hu]=munkaasztal-megosztás,krfb,vnc,megosztás,krdc,csatlakozás távoli munkaasztalhoz,meghívás,port,slp,meghívás nélkül
|
||||
X-KDE-Keywords[is]=skjáborðsmiðlun,miðlun,krfb,vnc,rdp,krdc,fjarvinnsla,remote desktop connection,rdp
|
||||
X-KDE-Keywords[fi]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,työpöydän jakaminen,jakaminen,etätyöpöytä,etäyhteys,kutsu,portti
|
||||
X-KDE-Keywords[fr]=partage de bureau,krfb,vnc,partage,krdc,connexion à un bureau distant,invitation,port,slp,non-invité
|
||||
X-KDE-Keywords[hu]=asztalmegosztás,krfb,vnc,megosztás,krdc,távoliasztal-kapcsolat,meghívás,port,slp,meghívatlan
|
||||
X-KDE-Keywords[ia]=compartir de scriptorio,krfb.vnc,compartir,krdc,connexion de scriptorio remote,invitation,porto,slp,non invitate
|
||||
X-KDE-Keywords[it]=condivisione desktop,krfb,vnc,condivisione,krdc,connessione desktop remoto,invito,porta,slp,non invitato
|
||||
X-KDE-Keywords[ja]=デスクトップ共有,krfb,vnc,共有,rdp,krdc,リモートデスクトップ接続,招待,ポート,slp,uninvited
|
||||
X-KDE-Keywords[km]=ការចែករំលែកផ្ទៃតុ,krfb,vnc,ការចែករំលែក,krdc,ការតភ្ជាប់ផ្ទៃតុពីចម្ងាយ,អញ្ជើញ,ច្រក,slp,មិនបានអញ្ជើញ
|
||||
X-KDE-Keywords[lt]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,dalinimasis darbastaliu,nutolusio darbastalio prijungimas,kvietimas,ryšys,nekviestas,jungtis,prievadas,dalintis,pasidalinti,jungimasis,prisijungti,kviesti
|
||||
X-KDE-Keywords[mk]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,делење на површината,krfb,vnc,делење,krdc,поврзување со оддалечена површина,покана,порта,slp,непоканет
|
||||
X-KDE-Keywords[ms]= perkongsian ruang kerja, sambungan, liang, desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited
|
||||
X-KDE-Keywords[nb]=skrivebordsdeling,krfb,vnc,deling,krdc,tilkobling til fjernt skrivebord,invitasjon,port,slp,ikke invitert
|
||||
X-KDE-Keywords[nds]=schriefdisch,freegeven,freegaav,krfb,vnc,delen,krdc,feern Schriefdisch,verbinnen,inladen,port,slp,nich inlaadt
|
||||
X-KDE-Keywords[ne]=डेस्कटप साझेदारी,krfb,vnc,साझेदारी,krdc, टाढाको डेस्कटप जडान,निमन्त्रणा,पोर्ट,slp,निमन्त्रणा नगरिएको
|
||||
X-KDE-Keywords[nl]=desktop sharing,krfb,vnc,sharing,rdp,krdc,remote desktop connection,uitnodiging,slp,rdp,verbinding, bureaublad delen,bureaublad op afstand
|
||||
X-KDE-Keywords[nn]=skrivebordsdeling,krfb,vnc,deling,krdc,nettverksskrivebord,invitasjon,port,slp,ikkje invitert
|
||||
X-KDE-Keywords[pl]=współdzielenie pulpitu,krfb,vnc,współdzielenie,rdp,krdc,zdalne połączenie, zdalne biurko, zdalny pulpit, zaproszenie,port,slp
|
||||
X-KDE-Keywords[pt]=partilha do ecrã,krfb,vnc,partilha,krdc,ligação a um ecrã remoto,convite,porto,slp,sem convite
|
||||
X-KDE-Keywords[pt_BR]=compartilhamento de desktop,krfb,vnc,compartilhamento,krdc,conexão a desktop remoto,convite,porta,slp,não convidado
|
||||
X-KDE-Keywords[sl]=namizje,souporaba,krfb,vnc,krdc,povezava oddaljenega namizja, povabilo,port,slp,nepovabljen
|
||||
X-KDE-Keywords[sr]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,радна површина,дељење,позив,порт,непозван,удаљено
|
||||
X-KDE-Keywords[sr@latin]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,radna površina,deljenje,poziv,port,nepozvan,udaljeno
|
||||
X-KDE-Keywords[sv]=dela skrivbord,krfb,vnc,dela,krdc,fjärrskrivbordsanslutning,inbjudan,port,slp
|
||||
X-KDE-Keywords[ta]=பணிமேடை பகிர்வு,krfb,vnc,பகிர்வு,krdc,தொலை பணிமேடை இணைப்பு,அழைப்பிதழ், துறை, slp, uninvited
|
||||
X-KDE-Keywords[tr]=masaüstü paylaşımı,krfb,vnc,paylaşım,krdc,uzak masaüstü bağlantısı,davet,port,slp
|
||||
X-KDE-Keywords[uk]=спільні стільниці,krfb,vnc,спільний,rdp,krdc,з'єднання віддаленої стільниці,запрошення,rdp,slp,без запрошення
|
||||
X-KDE-Keywords[vi]=chia sẻ màn hình,krfb,vnc,chia sẻ,krdc,màn hình ở xa kết nối,mời kết nối,cổng,slp,không được mời
|
||||
X-KDE-Keywords[kk]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited
|
||||
X-KDE-Keywords[km]=ការចែករំលែកផ្ទៃតុ,krfb,vnc,ការចែករំលែក,krdc,ការតភ្ជាប់ផ្ទៃតុពីចម្ងាយ,ការអញ្ជើញ,ច្រក,slp,មិនត្រូវបានអញ្ជើញ
|
||||
X-KDE-Keywords[ko]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,데스크톱,공유,원격 데스크톱,포트
|
||||
X-KDE-Keywords[nb]=skrivebordsdeling,krfb,vnc,deling,krdc,tilkoblng til annet skrivebord,invitasjon,port,slp,ikke invitert
|
||||
X-KDE-Keywords[nds]=Schriefdischfreegaav,krfb,vnc,Freegaav,Verbinnen na feern Schriefdisch,Inladen,Port,Koppelsteed,slp,nich inlaadt
|
||||
X-KDE-Keywords[nl]=delen van bureaublad,krfb,vnc,delen,krdc,verbinding naar bureaublad op afstand,invitatie,poort,slp,ongenodigd
|
||||
X-KDE-Keywords[pl]=współdzielenie pulpitu,krfb,vnc,współdzielenie,krdc,podłączenie zdalnego pulpitu,zaproszenie,port,slp,niezaproszony
|
||||
X-KDE-Keywords[pt]=partilha do ecrã,krfb,vnc,partilha,krdc,ligação ecrã remoto,convite,porto,slp,sem convite
|
||||
X-KDE-Keywords[pt_BR]=compartilhamento da área de trabalho,krfb,vnc,compartilhar,krdc,conexão à área de trabalho remota,convite,porta,desconvidar
|
||||
X-KDE-Keywords[sk]=zdieľanie plochy,krfb,vnc,zdieľanie,krdc,vzdialené pripojenie plochy,pozvanie,port,slp,nepozvaný
|
||||
X-KDE-Keywords[sl]=namizje,deljenje,souporaba,krfb,vnc,krdc,povezava oddaljenega namizja, povabilo,port,slp,nepovabljen
|
||||
X-KDE-Keywords[sr]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,дељење површи,КРФБ,ВНЦ,дељење,КРДЦ,удаљена површ,позивница,порт,СЛП,непозван
|
||||
X-KDE-Keywords[sr@ijekavian]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,дељење површи,КРФБ,ВНЦ,дељење,КРДЦ,удаљена површ,позивница,порт,СЛП,непозван
|
||||
X-KDE-Keywords[sr@ijekavianlatin]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,deljenje površi,KRFB,VNC,deljenje,KRDC,udaljena površ,pozivnica,port,SLP,nepozvan
|
||||
X-KDE-Keywords[sr@latin]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,deljenje površi,KRFB,VNC,deljenje,KRDC,udaljena površ,pozivnica,port,SLP,nepozvan
|
||||
X-KDE-Keywords[sv]=dela skrivbord,krfb,vnc,dela,krdc,fjärrskrivbordsanslutning,inbjudan,port,slp,oinbjuden
|
||||
X-KDE-Keywords[tr]=masaüstü paylaşımı,krfb,vnc,paylaşım,krdc,uzak masaüstü bağlantısı,davet,port,slp,davet edilmemiş
|
||||
X-KDE-Keywords[uk]=krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,спільне використання,керування,оприлюднення,віддалене з’єднання,запрошення,порт,небажане
|
||||
X-KDE-Keywords[x-test]=xxdesktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvitedxx
|
||||
X-KDE-Keywords[zh_CN]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,桌面共享,共享,远程桌面连接,邀请,端口,未邀请
|
||||
X-KDE-Keywords[zh_TW]=desktop sharing,krfb,vnc,sharing,rdp,krdc,remote desktop connection,rdp,桌面分享,分享,遠端桌面連線,invitation,port,slp,uninvited
|
||||
X-KDE-Keywords[zh_CN]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited,桌面共享,共享,远程桌面,远程桌面连接,邀请,端口,取消邀请
|
||||
X-KDE-Keywords[zh_TW]=desktop sharing,krfb,vnc,sharing,krdc,remote desktop connection,invitation,port,slp,uninvited
|
||||
|
||||
Categories=Qt;KDE;X-KDE-settings-network;Settings;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
|
||||
include_directories( ${CMAKE_SOURCE_DIR}/krfb/srvloc )
|
||||
|
||||
|
||||
########### next target ###############
|
||||
|
||||
set(kded_kinetd_PART_SRCS kinetd.cpp ${srvloc_SRCS})
|
||||
set(kded_kinetd_PART_SRCS kinetd.cpp)
|
||||
|
||||
message(STATUS "Port to krfb DBUS")
|
||||
# kde4_add_dcop_skels(kded_kinetd_PART_SRCS kinetd.h )
|
||||
@@ -12,7 +8,7 @@ message(STATUS "Port to krfb DBUS")
|
||||
kde4_add_plugin(kded_kinetd ${kded_kinetd_PART_SRCS})
|
||||
|
||||
|
||||
target_link_libraries(kded_kinetd ${KDE4_KIO_LIBS} ${KDE4_KDNSSD_LIBS} ${SLP_LIBRARIES})
|
||||
target_link_libraries(kded_kinetd ${KDE4_KIO_LIBS} ${KDE4_KDNSSD_LIBS})
|
||||
|
||||
install(TARGETS kded_kinetd DESTINATION ${PLUGIN_INSTALL_DIR})
|
||||
|
||||
@@ -22,7 +18,3 @@ install(TARGETS kded_kinetd DESTINATION ${PLUGIN_INSTALL_DIR})
|
||||
install(FILES kinetd.notifyrc DESTINATION ${DATA_INSTALL_DIR}/krfb)
|
||||
install(FILES kinetdmodule.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR})
|
||||
install(FILES kinetd.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1182
kinetd/kinetd.cpp
1182
kinetd/kinetd.cpp
File diff suppressed because it is too large
Load Diff
@@ -10,9 +10,10 @@ Name=KDE Internet Daemon
|
||||
Name[af]=Kde Internet Bediener
|
||||
Name[ar]=كيدي إنترنت مراقب
|
||||
Name[ast]=Degorriu d'Internet de KDE
|
||||
Name[bg]=Интернет демон
|
||||
Name[bg]=Интернет демон (KDE)
|
||||
Name[bn]=কে-ডি-ই ইন্টারনেট ডিমন
|
||||
Name[br]=Diaoul kenrouedad KDE
|
||||
Name[bs]=KDE-ov Internet Demon
|
||||
Name[ca]=Dimoni d'Internet per al KDE
|
||||
Name[ca@valencia]=Dimoni d'Internet per al KDE
|
||||
Name[cs]=KDE Internet démon
|
||||
@@ -24,7 +25,7 @@ Name[en_GB]=KDE Internet Dæmon
|
||||
Name[eo]=KDE interreta demono
|
||||
Name[es]=Demonio de Internet de KDE
|
||||
Name[et]=KDE internetideemon
|
||||
Name[eu]=KDE interneteko daemona
|
||||
Name[eu]=KDEren interneteko daemona
|
||||
Name[fa]=شبح اینترنتی KDE
|
||||
Name[fi]=KDE:n Internet-palvelin
|
||||
Name[fr]=Démon Internet de KDE
|
||||
@@ -35,6 +36,7 @@ Name[hi]=केडीई इंटरनेट डेमन
|
||||
Name[hne]=केडीई इंटरनेट डेमन
|
||||
Name[hr]=KDE Internet Daemon
|
||||
Name[hu]=KDE internetes szolgáltatás
|
||||
Name[ia]=Demone Internet de KDE
|
||||
Name[is]=KDE Internetþjónn
|
||||
Name[it]=Demone Internet di KDE
|
||||
Name[ja]=KDE インターネットデーモン
|
||||
@@ -52,14 +54,16 @@ Name[ne]=केडीई इन्टरनेट डेइमोन
|
||||
Name[nl]=KDE Internet Daemon
|
||||
Name[nn]=KDE-Internett-teneste
|
||||
Name[pa]=KDE ਇੰਟਰਨੈੱਟ ਡੈਮਨ
|
||||
Name[pl]=Internet/sieć
|
||||
Name[pl]=Demon internetowy dla KDE
|
||||
Name[pt]=Servidor de Internet do KDE
|
||||
Name[pt_BR]=Servidor de Internet do KDE
|
||||
Name[ro]=Demon de Internet KDE
|
||||
Name[ru]=Доступ к Интернету
|
||||
Name[se]=KDE-Interneahtta-duogášprográmma
|
||||
Name[si]=KDE ජාල ඩීමනය
|
||||
Name[sk]=KDE Internet démon
|
||||
Name[sl]=Internetni strežnik za KDE
|
||||
Name[sq]=KDE Internet Daemon
|
||||
Name[sr]=КДЕ‑ов интернет демон
|
||||
Name[sr@ijekavian]=КДЕ‑ов интернет демон
|
||||
Name[sr@ijekavianlatin]=KDE‑ov internet demon
|
||||
@@ -81,8 +85,9 @@ Name[zh_TW]=KDE Internet 伺服程式
|
||||
Comment=An Internet daemon that starts network services on demand
|
||||
Comment[ar]=رقيب الإنترنت بدأ خدمة الشبكة على الرقيب
|
||||
Comment[ast]=Un degorriu d'Internet qu'entama los servicios de rede baxo demanda
|
||||
Comment[bg]=Интернет демон, който служи за стартиране на мрежови услуги при поискване
|
||||
Comment[bg]=Интернет демон, който зарежда мрежови услуги при поискване
|
||||
Comment[bn]=একটি ইন্টারনেট ডিমন যে চাহিদা ভিত্তিক নেটওয়ার্ক সার্ভিস আরম্ভ করে
|
||||
Comment[bs]=Internet daemon koji pokreće mrežne servise po zahtijevu
|
||||
Comment[ca]=Un dimoni d'Internet que arrenca els serveis de xarxa sota demanda
|
||||
Comment[ca@valencia]=Un dimoni d'Internet que arrenca els serveis de xarxa sota demanda
|
||||
Comment[cs]=Internetový démon spouštějící síťové služby na požádání
|
||||
@@ -94,7 +99,7 @@ Comment[en_GB]=An Internet dæmon that starts network services on demand
|
||||
Comment[eo]=Interreta demono kiu lanĉas retajn servojn laŭ bezono
|
||||
Comment[es]=Un demonio de Internet que inicia los servicios de red a demanda
|
||||
Comment[et]=Internetideemon, mis käivitab nõudmisel võrguteenused
|
||||
Comment[eu]=Sare zerbitzuak eskatzean abiarazten dituen Interneteko daemona
|
||||
Comment[eu]=Sareko zerbitzuak eskatzean abiarazten dituen Interneteko daemona
|
||||
Comment[fa]=یک شبح اینترنتی که خدمات شبکه را بر اساس تقاضا آغاز میکند
|
||||
Comment[fi]=Internet-palvelin, joka käynnistää verkkopalveluita
|
||||
Comment[fr]=Un démon Internet qui démarre le service réseau à la demande
|
||||
@@ -105,6 +110,7 @@ Comment[hi]=एक इंटरनेट डेमन जो मांग पर
|
||||
Comment[hne]=एक इंटरनेट डेमन जऊन मांग मं नेटवर्क सेवा चालू करथे
|
||||
Comment[hr]=Internet daemon koji pokreće mrežne usluge kada su zatražene
|
||||
Comment[hu]=A hálózati szolgáltatások vezérlését biztosító program
|
||||
Comment[ia]=Un demone internet que starta servicios de rete sur requesta
|
||||
Comment[is]=Internetþjónn sem ræsir tengingar við Internetið eftir þörfum
|
||||
Comment[it]=Un demone Internet che avvia i servizi di rete a richiesta
|
||||
Comment[ja]=要求時にネットワークサービスを起動するインターネットデーモン
|
||||
@@ -122,23 +128,24 @@ Comment[ne]=एउटा इन्टरनेट डेइमोन जसल
|
||||
Comment[nl]=Een internetdaemon die netwerkdiensten op afroep start
|
||||
Comment[nn]=Internett-teneste som startar nettverkstenester når dei trengst
|
||||
Comment[pa]=ਇੱਕ ਇੰਟਰਨੈੱਟ ਡੈਮਨ, ਜੋ ਕਿ ਲੋੜ ਪੈਣ ਉੱਤੇ ਨੈੱਟਵਰਕ ਸਰਵਿਸਾਂ ਸ਼ੁਰੂ ਕਰਦੀ ਹੈ।
|
||||
Comment[pl]=Uruchamianie usług na żądanie
|
||||
Comment[pl]=Demon internetowy, który uruchamia usługi sieciowe na żądanie
|
||||
Comment[pt]=Um servidor da Internet que inicia os serviços de rede a pedido
|
||||
Comment[pt_BR]=Um servidor Internet que inicia os serviços de rede por demanda
|
||||
Comment[ro]=Un demon de Internet ce pornește serviciile de rețea la cerere
|
||||
Comment[ru]=Служба установления подключения при запросе сетевых ресурсов
|
||||
Comment[se]=Interneahtta-duogášprográmma mii álggaha fierpmádatbálvalusaid go dárbbašuvvo
|
||||
Comment[si]=ඉල්ලුම පරිදි ජාල සේවා ආරම්භ කරන අන්තර්ජාල ඩීමනය
|
||||
Comment[sk]=Internetový démon, ktorý spúšťa sieťové služby na požiadanie
|
||||
Comment[sl]=Internetni strežnik, ki zažene omrežne storitve na zahtevo
|
||||
Comment[sr]=Интернет демон који покреће мрежне сервисе по захтеву
|
||||
Comment[sr@ijekavian]=Интернет демон који покреће мрежне сервисе по захтеву
|
||||
Comment[sr@ijekavianlatin]=Internet demon koji pokreće mrežne servise po zahtevu
|
||||
Comment[sr@ijekavian]=Интернет демон који покреће мрежне сервисе по захтјеву
|
||||
Comment[sr@ijekavianlatin]=Internet demon koji pokreće mrežne servise po zahtjevu
|
||||
Comment[sr@latin]=Internet demon koji pokreće mrežne servise po zahtevu
|
||||
Comment[sv]=Internetdemon som startar nätverkstjänster vid behov
|
||||
Comment[ta]=ஒரு இணைய டேமொன், டேமொன் பிணைய சேவையை ஆரம்பிக்கிறது
|
||||
Comment[tg]=Азозили шабакавие, ки хидматрасони шабакавиро бо дархост сар медиҳад
|
||||
Comment[th]=ดมอนอินเทอร์เน็ตซึ่งจะเริ่มทำงานบริการเครือข่ายเมื่อมีความต้องการใช้
|
||||
Comment[tr]=Başlangıçta ağ servisleri tarafından istenen internet hayalet programı
|
||||
Comment[tr]=Başlangıçta ağ servisleri tarafından istenen Internet hayalet programı
|
||||
Comment[uk]=Фонова служба Інтернет, що запускає служби мережі при запиті
|
||||
Comment[uz]=Talab qilinganda tarmoq xizmatlarini ishga tushuruvchi Internet demoni
|
||||
Comment[uz@cyrillic]=Талаб қилинганда тармоқ хизматларини ишга тушурувчи Интернет демони
|
||||
|
||||
276
kinetd/kinetd.h
276
kinetd/kinetd.h
@@ -31,168 +31,170 @@
|
||||
#include <q3ptrlist.h>
|
||||
#include "kserviceregistry.h"
|
||||
|
||||
class PortListener : public QObject {
|
||||
Q_OBJECT
|
||||
class PortListener : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
bool m_valid;
|
||||
QString m_serviceName;
|
||||
QString m_serviceURL, m_serviceAttributes;
|
||||
QStringList m_registeredServiceURLs;
|
||||
QString m_dnssdName, m_dnssdType;
|
||||
QMap<QString,QString> m_dnssdData;
|
||||
int m_serviceLifetime;
|
||||
int m_port;
|
||||
int m_portBase, m_autoPortRange;
|
||||
int m_defaultPortBase, m_defaultAutoPortRange;
|
||||
bool m_multiInstance;
|
||||
QString m_execPath;
|
||||
QString m_argument;
|
||||
bool m_enabled;
|
||||
bool m_serviceRegistered, m_registerService;
|
||||
bool m_dnssdRegister, m_dnssdRegistered;
|
||||
QDateTime m_expirationTime;
|
||||
QDateTime m_slpLifetimeEnd;
|
||||
QString m_uuid;
|
||||
bool m_valid;
|
||||
QString m_serviceName;
|
||||
QString m_serviceURL, m_serviceAttributes;
|
||||
QStringList m_registeredServiceURLs;
|
||||
QString m_dnssdName, m_dnssdType;
|
||||
QMap<QString, QString> m_dnssdData;
|
||||
int m_serviceLifetime;
|
||||
int m_port;
|
||||
int m_portBase, m_autoPortRange;
|
||||
int m_defaultPortBase, m_defaultAutoPortRange;
|
||||
bool m_multiInstance;
|
||||
QString m_execPath;
|
||||
QString m_argument;
|
||||
bool m_enabled;
|
||||
bool m_serviceRegistered, m_registerService;
|
||||
bool m_dnssdRegister, m_dnssdRegistered;
|
||||
QDateTime m_expirationTime;
|
||||
QDateTime m_slpLifetimeEnd;
|
||||
QString m_uuid;
|
||||
|
||||
KNetwork::KServerSocket *m_socket;
|
||||
K3Process m_process;
|
||||
KNetwork::KServerSocket *m_socket;
|
||||
K3Process m_process;
|
||||
|
||||
KConfig *m_config;
|
||||
KServiceRegistry *m_srvreg;
|
||||
DNSSD::PublicService *m_dnssdreg;
|
||||
KConfig *m_config;
|
||||
KServiceRegistry *m_srvreg;
|
||||
DNSSD::PublicService *m_dnssdreg;
|
||||
|
||||
void freePort();
|
||||
void loadConfig(KService::Ptr s);
|
||||
void setEnabledInternal(bool e, const QDateTime &ex);
|
||||
void dnssdRegister(bool enabled);
|
||||
void setServiceRegistrationEnabledInternal(bool enabled);
|
||||
void freePort();
|
||||
void loadConfig(KService::Ptr s);
|
||||
void setEnabledInternal(bool e, const QDateTime &ex);
|
||||
void dnssdRegister(bool enabled);
|
||||
void setServiceRegistrationEnabledInternal(bool enabled);
|
||||
|
||||
public:
|
||||
PortListener(KService::Ptr s, KConfig *c, KServiceRegistry *srvreg);
|
||||
~PortListener();
|
||||
PortListener(KService::Ptr s, KConfig *c, KServiceRegistry *srvreg);
|
||||
~PortListener();
|
||||
|
||||
bool acquirePort();
|
||||
bool isValid();
|
||||
QString name();
|
||||
void setEnabled(bool enabled);
|
||||
void setEnabled(const QDateTime &expiration);
|
||||
void setServiceRegistrationEnabled(bool enabled);
|
||||
bool isServiceRegistrationEnabled();
|
||||
QDateTime expiration();
|
||||
QDateTime serviceLifetimeEnd();
|
||||
bool isEnabled();
|
||||
int port();
|
||||
QStringList processServiceTemplate(const QString &a);
|
||||
bool setPort(int port = -1, int autoProbeRange = 1);
|
||||
void refreshRegistration();
|
||||
bool acquirePort();
|
||||
bool isValid();
|
||||
QString name();
|
||||
void setEnabled(bool enabled);
|
||||
void setEnabled(const QDateTime &expiration);
|
||||
void setServiceRegistrationEnabled(bool enabled);
|
||||
bool isServiceRegistrationEnabled();
|
||||
QDateTime expiration();
|
||||
QDateTime serviceLifetimeEnd();
|
||||
bool isEnabled();
|
||||
int port();
|
||||
QStringList processServiceTemplate(const QString &a);
|
||||
bool setPort(int port = -1, int autoProbeRange = 1);
|
||||
void refreshRegistration();
|
||||
|
||||
private slots:
|
||||
void accepted(KSocket*);
|
||||
void accepted(KSocket *);
|
||||
};
|
||||
|
||||
class KInetD : public KDEDModule {
|
||||
Q_OBJECT
|
||||
class KInetD : public KDEDModule
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Returns a list of all registered services in KInetd.
|
||||
* To add a service you need to add a .desktop file with
|
||||
* the servicetype "KInetDModule" into the services director
|
||||
* (see kinetdmodule.desktop in servicetypes dir).
|
||||
* @return a list with the names of all services
|
||||
*/
|
||||
QStringList services();
|
||||
/**
|
||||
* Returns a list of all registered services in KInetd.
|
||||
* To add a service you need to add a .desktop file with
|
||||
* the servicetype "KInetDModule" into the services director
|
||||
* (see kinetdmodule.desktop in servicetypes dir).
|
||||
* @return a list with the names of all services
|
||||
*/
|
||||
QStringList services();
|
||||
|
||||
/**
|
||||
* Returns true if the service exists and is available.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return true if a service with the given name exists and is enabled
|
||||
*/
|
||||
bool isEnabled(QString service);
|
||||
/**
|
||||
* Returns true if the service exists and is available.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return true if a service with the given name exists and is enabled
|
||||
*/
|
||||
bool isEnabled(QString service);
|
||||
|
||||
/**
|
||||
* Enables or disabled the given service. Ignored if the given service
|
||||
* does not exist.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param enable true to enable, false to disable.
|
||||
*/
|
||||
void setEnabled(QString service, bool enable);
|
||||
/**
|
||||
* Enables or disabled the given service. Ignored if the given service
|
||||
* does not exist.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param enable true to enable, false to disable.
|
||||
*/
|
||||
void setEnabled(QString service, bool enable);
|
||||
|
||||
/**
|
||||
* Enables the given service until the given time. Ignored if the given
|
||||
* service does not exist.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param expiration the time the service will be disabled at
|
||||
*/
|
||||
void setEnabled(QString service, QDateTime expiration);
|
||||
/**
|
||||
* Enables the given service until the given time. Ignored if the given
|
||||
* service does not exist.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param expiration the time the service will be disabled at
|
||||
*/
|
||||
void setEnabled(QString service, QDateTime expiration);
|
||||
|
||||
/**
|
||||
* Returns the port of the service, or -1 if not listening.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return the port or -1 if no port used or service does not exist
|
||||
*/
|
||||
int port(QString service);
|
||||
/**
|
||||
* Returns the port of the service, or -1 if not listening.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return the port or -1 if no port used or service does not exist
|
||||
*/
|
||||
int port(QString service);
|
||||
|
||||
/**
|
||||
* Sets the port of the service, and possibly a range of ports to try.
|
||||
* It will return true if a port could be found. If it did not find one
|
||||
* but is enabled it will start a timer that probes that port every 30s.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param port the first port number to try or -1 to restore defaults
|
||||
* @param autoPortRange the number of ports to try
|
||||
* @return true if a port could be found or service is disabled, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool setPort(QString service, int port = -1, int autoPortRange = 1);
|
||||
/**
|
||||
* Sets the port of the service, and possibly a range of ports to try.
|
||||
* It will return true if a port could be found. If it did not find one
|
||||
* but is enabled it will start a timer that probes that port every 30s.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param port the first port number to try or -1 to restore defaults
|
||||
* @param autoPortRange the number of ports to try
|
||||
* @return true if a port could be found or service is disabled, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool setPort(QString service, int port = -1, int autoPortRange = 1);
|
||||
|
||||
/**
|
||||
* Tests whether the given service is installed..
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return true if installed, false otherwise
|
||||
*/
|
||||
bool isInstalled(QString service);
|
||||
/**
|
||||
* Tests whether the given service is installed..
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return true if installed, false otherwise
|
||||
*/
|
||||
bool isInstalled(QString service);
|
||||
|
||||
/**
|
||||
* Enables or disables the SLP registration. Ignored if the service does
|
||||
* not have a service URL. If the service is disabled the service will
|
||||
* registered as soon as it is enabled.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param enable true to enable, false to disable.
|
||||
*/
|
||||
void setServiceRegistrationEnabled(QString service, bool enabled);
|
||||
/**
|
||||
* Enables or disables the SLP registration. Ignored if the service does
|
||||
* not have a service URL. If the service is disabled the service will
|
||||
* registered as soon as it is enabled.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @param enable true to enable, false to disable.
|
||||
*/
|
||||
void setServiceRegistrationEnabled(QString service, bool enabled);
|
||||
|
||||
/**
|
||||
* Returns true if service registration for the given service is enabled.
|
||||
* Note that this does not mean that the service is currently registered,
|
||||
* because the service may be disabled.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return true if service registration is enabled
|
||||
*/
|
||||
bool isServiceRegistrationEnabled(QString service);
|
||||
/**
|
||||
* Returns true if service registration for the given service is enabled.
|
||||
* Note that this does not mean that the service is currently registered,
|
||||
* because the service may be disabled.
|
||||
* @param service name of a service as specified in its .desktop file
|
||||
* @return true if service registration is enabled
|
||||
*/
|
||||
bool isServiceRegistrationEnabled(QString service);
|
||||
|
||||
private:
|
||||
QDateTime getNextExpirationTime();
|
||||
void setPortRetryTimer(bool retry);
|
||||
void setReregistrationTimer();
|
||||
private:
|
||||
QDateTime getNextExpirationTime();
|
||||
void setPortRetryTimer(bool retry);
|
||||
void setReregistrationTimer();
|
||||
|
||||
KConfig *m_config;
|
||||
KServiceRegistry *m_srvreg;
|
||||
Q3PtrList<PortListener> m_portListeners;
|
||||
QTimer m_expirationTimer;
|
||||
QTimer m_portRetryTimer;
|
||||
QTimer m_reregistrationTimer;
|
||||
KConfig *m_config;
|
||||
KServiceRegistry *m_srvreg;
|
||||
Q3PtrList<PortListener> m_portListeners;
|
||||
QTimer m_expirationTimer;
|
||||
QTimer m_portRetryTimer;
|
||||
QTimer m_reregistrationTimer;
|
||||
|
||||
private slots:
|
||||
void setExpirationTimer();
|
||||
void expirationTimer();
|
||||
void portRetryTimer();
|
||||
void reregistrationTimer();
|
||||
private slots:
|
||||
void setExpirationTimer();
|
||||
void expirationTimer();
|
||||
void portRetryTimer();
|
||||
void reregistrationTimer();
|
||||
|
||||
public:
|
||||
KInetD(QObject* parent, const QList<QVariant>&);
|
||||
virtual ~KInetD();
|
||||
void loadServiceList();
|
||||
PortListener *getListenerByName(QString name);
|
||||
public:
|
||||
KInetD(QObject *parent, const QList<QVariant>&);
|
||||
virtual ~KInetD();
|
||||
void loadServiceList();
|
||||
PortListener *getListenerByName(QString name);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ IconName=kinetd
|
||||
Comment=KInetD
|
||||
Comment[ar]=KInetD
|
||||
Comment[ast]=KInetD
|
||||
Comment[bg]=KInetD
|
||||
Comment[bn]=কে-আইনেট-ডি
|
||||
Comment[br]=KInetD
|
||||
Comment[bs]=KInetD
|
||||
Comment[ca]=KInetD
|
||||
Comment[ca@valencia]=KInetD
|
||||
Comment[cs]=KInetD
|
||||
@@ -26,6 +28,7 @@ Comment[hi]=के-इनिट-डी
|
||||
Comment[hne]=के-इनिट-डी
|
||||
Comment[hr]=KInetD
|
||||
Comment[hu]=KInetD
|
||||
Comment[ia]=KInetD
|
||||
Comment[is]=KInetD
|
||||
Comment[it]=KInetD
|
||||
Comment[ja]=KInetD
|
||||
@@ -47,8 +50,10 @@ Comment[pt]=KInetD
|
||||
Comment[pt_BR]=KInetD
|
||||
Comment[ro]=KInetD
|
||||
Comment[ru]=KInetD
|
||||
Comment[si]=KInetD
|
||||
Comment[sk]=KInetD
|
||||
Comment[sl]=KInetD
|
||||
Comment[sq]=KInetD
|
||||
Comment[sr]=КинетД
|
||||
Comment[sr@ijekavian]=КинетД
|
||||
Comment[sr@ijekavianlatin]=KInetD
|
||||
@@ -58,6 +63,7 @@ Comment[ta]=KInetD
|
||||
Comment[tg]=KInetD
|
||||
Comment[tr]=KInetD
|
||||
Comment[uk]=KInetD
|
||||
Comment[wa]=KInetD
|
||||
Comment[xh]=KInetD
|
||||
Comment[x-test]=xxKInetDxx
|
||||
Comment[zh_CN]=KInetD
|
||||
@@ -68,8 +74,10 @@ Comment[zh_TW]=KInetD
|
||||
Name=IncomingConnection
|
||||
Name[ar]=اتصال وارد
|
||||
Name[ast]=Conexón entrante
|
||||
Name[bg]=Входяща връзка
|
||||
Name[bn]=অন্তর্মুখী সংযোগ
|
||||
Name[br]=Kevreadenn resev
|
||||
Name[bs]=Dolazna veza
|
||||
Name[ca]=Connexió entrant
|
||||
Name[ca@valencia]=Connexió entrant
|
||||
Name[cs]=Příchozí spojení
|
||||
@@ -91,6 +99,7 @@ Name[hi]=आवक-कनेक्शन
|
||||
Name[hne]=आवक-कनेक्सन
|
||||
Name[hr]=DolaznaVeza
|
||||
Name[hu]=Bejövő kapcsolat
|
||||
Name[ia]=Connexion in arrivata
|
||||
Name[is]=IncomingConnection
|
||||
Name[it]=Connessioni in entrata
|
||||
Name[ja]=外部からの接続
|
||||
@@ -112,6 +121,7 @@ Name[pt]=IncomingConnection
|
||||
Name[pt_BR]=Conexões de entrada
|
||||
Name[ro]=ConexiuneDeIntrare
|
||||
Name[ru]=Входящее соединение
|
||||
Name[si]=පැමිණෙන සබැඳිය
|
||||
Name[sk]=Prichádzajúce pripojenie
|
||||
Name[sl]=Prejeta povezava
|
||||
Name[sr]=Долазна веза
|
||||
@@ -133,7 +143,9 @@ Comment=Received incoming connection
|
||||
Comment[af]=Ontvang inkomende verbinding
|
||||
Comment[ar]=تلقي اتصال وارد
|
||||
Comment[ast]=Recibida conexón entrante
|
||||
Comment[bg]=Получана е входяща връзка
|
||||
Comment[bn]=অন্তর্মুখী সংযোগ গ্রহণ করল
|
||||
Comment[bs]=Primljena dolazeća veza
|
||||
Comment[ca]=Rebuda connexió entrant
|
||||
Comment[ca@valencia]=Rebuda connexió entrant
|
||||
Comment[cs]=Obdrženo příchozí spojení
|
||||
@@ -155,6 +167,7 @@ Comment[hi]=आवक कनेक्शन प्राप्त
|
||||
Comment[hne]=आवक कनेक्सन प्राप्त
|
||||
Comment[hr]=Primio dolaznu vezu
|
||||
Comment[hu]=Csatlakozási kérés érkezett
|
||||
Comment[ia]=Connexion in arrivata recipite
|
||||
Comment[is]=Tók á móti uppkalli
|
||||
Comment[it]=Ricevuta connessione in entrata
|
||||
Comment[ja]=外部からの接続がありました
|
||||
@@ -176,6 +189,7 @@ Comment[pt]=Foi recebida uma ligação
|
||||
Comment[pt_BR]=Recebendo conexão de entrada
|
||||
Comment[ro]=Conexiune de intrare recepționată
|
||||
Comment[ru]=Входящее соединение завершилось успешно
|
||||
Comment[si]=ලැබුනු පැමිණෙන සබැඳිය
|
||||
Comment[sk]=Prijaté prichádzajúce pripojenie
|
||||
Comment[sl]=Prejeta je prihajajoča povezava
|
||||
Comment[sr]=Примљена је долазна веза
|
||||
@@ -199,6 +213,7 @@ Name=ProcessFailed
|
||||
Name[ar]=فشلت العملية
|
||||
Name[ast]=Procesu fallíu
|
||||
Name[bn]=প্রসেস ব্যর্থ
|
||||
Name[bs]=Neuspio proces
|
||||
Name[ca]=Procés erroni
|
||||
Name[ca@valencia]=Procés erroni
|
||||
Name[cs]=Proces selhal
|
||||
@@ -220,6 +235,7 @@ Name[hi]=प्रक्रिया-असफल
|
||||
Name[hne]=काम-फेल
|
||||
Name[hr]=ProcesNeuspješan
|
||||
Name[hu]=Hibás folyamat
|
||||
Name[ia]=Processo falleva
|
||||
Name[is]=ProcessFailed
|
||||
Name[it]=Processo non riuscito
|
||||
Name[ja]=プロセス失敗
|
||||
@@ -241,11 +257,12 @@ Name[pt]=ProcessFailed
|
||||
Name[pt_BR]=Falha de processo
|
||||
Name[ro]=ProcesEșuat
|
||||
Name[ru]=Ошибка процесса
|
||||
Name[si]=සැකසුම අසාර්ථකයි
|
||||
Name[sk]=Proces zlyhal
|
||||
Name[sl]=Proces ni uspel
|
||||
Name[sr]=Процес није успео
|
||||
Name[sr@ijekavian]=Процес није успео
|
||||
Name[sr@ijekavianlatin]=Proces nije uspeo
|
||||
Name[sr@ijekavian]=Процес није успио
|
||||
Name[sr@ijekavianlatin]=Proces nije uspio
|
||||
Name[sr@latin]=Proces nije uspeo
|
||||
Name[sv]=Process misslyckades
|
||||
Name[ta]=செயல் தோல்வியுற்றது
|
||||
@@ -263,6 +280,7 @@ Comment[af]=Kon nie roep proses na handvatsel verbinding
|
||||
Comment[ar]= لا يمكن نداء الإجراء إلى مؤشر الاتصال
|
||||
Comment[ast]=Nun puede llamase a un procesu pa remanar la conexón
|
||||
Comment[bn]=সংযোগ পরিচালনা করতে প্রসেস শুরু করতে পারল না
|
||||
Comment[bs]=Nisam mogao da pozovem proces da opsluži vezu
|
||||
Comment[ca]=No es pot cridar al procés per a manejar la connexió
|
||||
Comment[ca@valencia]=No es pot cridar al procés per a manejar la connexió
|
||||
Comment[cs]=Nelze spustit proces k obsluze spojení
|
||||
@@ -284,6 +302,7 @@ Comment[hi]=कनेक्शन हैंडल करने के लिए
|
||||
Comment[hne]=कनेक्सन हेंडल करे बर काम काल नइ कर सकिस
|
||||
Comment[hr]=Nisam mogao pozvati proces za kontrolu veze
|
||||
Comment[hu]=A kapcsolat kezelése nem sikerült
|
||||
Comment[ia]=Il non pote appellar processo pro manear connexion
|
||||
Comment[is]=Gat ekki kallað á forrit til að höndla tengingu
|
||||
Comment[it]=Impossibile richiamare il processo per gestire la connessione
|
||||
Comment[ja]=接続を扱うプロセスを呼び出せません
|
||||
@@ -304,6 +323,7 @@ Comment[pt]=Não foi possível invocar o processo para lidar com as ligações
|
||||
Comment[pt_BR]=Não foi possível chamar o processo de controle da conexão
|
||||
Comment[ro]=Procesul ce manipulează conexiunea nu a putut fi apelat
|
||||
Comment[ru]=Не удаётся запустить процесс обработки соединения
|
||||
Comment[si]=සබඳතාව හැසිරවීම සඳහා සැකසීම නොකැඳවන්න
|
||||
Comment[sk]=Nepodarilo sa spustiť proces na spracovanie pripojenia
|
||||
Comment[sl]=Ni možno poklicati procesa za upravljanje s povezavo
|
||||
Comment[sr]=Нисам могао да позовем процес да опслужи везу
|
||||
|
||||
@@ -9,6 +9,7 @@ Name[ast]=Triba de módulu KInetD
|
||||
Name[bg]=Модул на KInetD
|
||||
Name[bn]=কে-আইনেট-ডি মডিউল ধরন
|
||||
Name[br]=Seurt ar mollad KInetD
|
||||
Name[bs]=Vrsta modula KInetD-a
|
||||
Name[ca]=Tipus de mòdul del KInetD
|
||||
Name[ca@valencia]=Tipus de mòdul del KInetD
|
||||
Name[cs]=Typ modulu KInetD
|
||||
@@ -21,7 +22,7 @@ Name[eo]=KInetD modulotipo
|
||||
Name[es]=Tipo de módulo KInetD
|
||||
Name[et]=KInetD mooduli tüüp
|
||||
Name[eu]=KInetD modulu mota
|
||||
Name[fa]=نوع پیمانۀ KInetD
|
||||
Name[fa]=نوع پیمانه KInetD
|
||||
Name[fi]=KInetD-moduulityyppi
|
||||
Name[fr]=Type de module de KInetD
|
||||
Name[ga]=Cineál Modúil KInetD
|
||||
@@ -31,6 +32,7 @@ Name[hi]=के-इनिट-डी मॉड्यूल प्रकार
|
||||
Name[hne]=के-इनिट-डी माड्यूल किसम
|
||||
Name[hr]=Tip KInetD Modula
|
||||
Name[hu]=KInetD modultípus
|
||||
Name[ia]=Typo de modulo KInetD
|
||||
Name[is]=KInetD Module tegund
|
||||
Name[it]=Tipo di modulo KInetD
|
||||
Name[ja]=KInetD モジュールタイプ
|
||||
@@ -54,6 +56,7 @@ Name[pt_BR]=Módulo KInetD
|
||||
Name[ro]=Tip modul KInetD
|
||||
Name[ru]=Модуль KInetD
|
||||
Name[se]=KInetD-moduvlašládja
|
||||
Name[si]=KInetD මොඩියුල වර්ගය
|
||||
Name[sk]=Typ modulu KInetD
|
||||
Name[sl]=Vrsta modula KInetD
|
||||
Name[sr]=Врста модула КинетД‑а
|
||||
@@ -63,7 +66,7 @@ Name[sr@latin]=Vrsta modula KInetD‑a
|
||||
Name[sv]=Kinetd-modultyp
|
||||
Name[ta]=KInetD கூறு வகை
|
||||
Name[tg]=Навъи Модули KInetD
|
||||
Name[tr]=KDED Modül Türü
|
||||
Name[tr]=KInetD Modül Türü
|
||||
Name[uk]=Тип модулю KinetD
|
||||
Name[vi]=Kiểu môđun KInetD
|
||||
Name[xh]=Udidi Lomqongo womlinganiselo we KInetD
|
||||
|
||||
144
krfb/CMakeLists.txt
Normal file
144
krfb/CMakeLists.txt
Normal file
@@ -0,0 +1,144 @@
|
||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config-krfb.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config-krfb.h
|
||||
)
|
||||
|
||||
#####################################
|
||||
# First target: libkrfbprivate - a library
|
||||
# for linking plugins against.
|
||||
|
||||
set (krfbprivate_SRCS
|
||||
framebuffer.cpp
|
||||
framebufferplugin.cpp
|
||||
)
|
||||
|
||||
kde4_add_library (krfbprivate
|
||||
SHARED
|
||||
${krfbprivate_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfbprivate
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${X11_X11_LIB}
|
||||
)
|
||||
|
||||
set_target_properties (krfbprivate PROPERTIES
|
||||
VERSION ${GENERIC_LIB_VERSION}
|
||||
SOVERSION ${GENERIC_LIB_VERSION}
|
||||
)
|
||||
|
||||
install (TARGETS krfbprivate
|
||||
${INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
LIBRARY NAMELINK_SKIP
|
||||
)
|
||||
|
||||
install (FILES
|
||||
krfb-framebuffer.desktop
|
||||
DESTINATION ${SERVICETYPES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
#####################################
|
||||
# Second target: krfb - the app
|
||||
# itself.
|
||||
|
||||
if(BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
add_definitions(-DKRFB_WITH_TELEPATHY_TUBES)
|
||||
include_directories(${TELEPATHY_QT4_INCLUDE_DIR})
|
||||
endif(BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
|
||||
set (krfb_SRCS
|
||||
connectiondialog.cpp
|
||||
events.cpp
|
||||
framebuffermanager.cpp
|
||||
invitation.cpp
|
||||
invitedialog.cpp
|
||||
invitationmanager.cpp
|
||||
main.cpp
|
||||
manageinvitationsdialog.cpp
|
||||
personalinvitedialog.cpp
|
||||
sockethelpers.cpp
|
||||
trayicon.cpp
|
||||
rfbservermanager.cpp
|
||||
rfbserver.cpp
|
||||
rfbclient.cpp
|
||||
invitationsrfbserver.cpp
|
||||
invitationsrfbclient.cpp
|
||||
)
|
||||
|
||||
if (BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
set (krfb_SRCS
|
||||
${krfb_SRCS}
|
||||
tubesrfbserver.cpp
|
||||
tubesrfbclient.cpp
|
||||
tubesclienthandler.cpp
|
||||
)
|
||||
endif (BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
|
||||
kde4_add_kcfg_files (krfb_SRCS
|
||||
krfbconfig.kcfgc
|
||||
)
|
||||
|
||||
kde4_add_ui_files (krfb_SRCS
|
||||
ui/configtcp.ui
|
||||
ui/configsecurity.ui
|
||||
ui/connectionwidget.ui
|
||||
ui/invitewidget.ui
|
||||
ui/manageinvitations.ui
|
||||
ui/personalinvitewidget.ui
|
||||
)
|
||||
|
||||
if (BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
kde4_add_ui_files(krfb_SRCS ui/tubesconnectionwidget.ui)
|
||||
endif(BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
|
||||
kde4_add_executable (krfb
|
||||
${krfb_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb
|
||||
krfbprivate
|
||||
vncserver
|
||||
${JPEG_LIBRARIES}
|
||||
${X11_Xext_LIB}
|
||||
${X11_X11_LIB}
|
||||
${X11_Xdamage_LIB}
|
||||
${QT_QTNETWORK_LIBRARY}
|
||||
${KDE4_KDNSSD_LIBS}
|
||||
${KDE4_KDEUI_LIBS}
|
||||
)
|
||||
|
||||
if (BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
target_link_libraries(krfb
|
||||
${TELEPATHY_QT4_LIBRARIES}
|
||||
)
|
||||
endif (BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
|
||||
if (X11_XTest_FOUND)
|
||||
target_link_libraries (krfb
|
||||
${X11_XTest_LIB}
|
||||
)
|
||||
endif (X11_XTest_FOUND)
|
||||
|
||||
install (TARGETS krfb
|
||||
${INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
)
|
||||
|
||||
if (BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
configure_file(org.freedesktop.Telepathy.Client.krfb_rfb_handler.service.in
|
||||
org.freedesktop.Telepathy.Client.krfb_rfb_handler.service)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.krfb_rfb_handler.service
|
||||
DESTINATION ${DBUS_SERVICES_INSTALL_DIR})
|
||||
|
||||
install(FILES krfb_rfb_handler.client DESTINATION ${CMAKE_INSTALL_PREFIX}/share/telepathy/clients/)
|
||||
endif (BUILD_EXPERIMENTAL_TUBES_SUPPORT AND TELEPATHY_QT4_FOUND)
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install (PROGRAMS krfb.desktop
|
||||
DESTINATION ${XDG_APPS_INSTALL_DIR}
|
||||
)
|
||||
|
||||
install (FILES krfb.notifyrc
|
||||
DESTINATION ${DATA_INSTALL_DIR}/krfb
|
||||
)
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
#! /bin/sh
|
||||
$EXTRACTRC ui/*.ui *.kcfg >> rc.cpp
|
||||
$XGETTEXT *.cpp -o $podir/krfb.pot
|
||||
88
krfb/connectiondialog.cpp
Normal file
88
krfb/connectiondialog.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "connectiondialog.h"
|
||||
|
||||
#include <KIconLoader>
|
||||
#include <KLocale>
|
||||
#include <KStandardGuiItem>
|
||||
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <QtGui/QLabel>
|
||||
|
||||
template <typename UI>
|
||||
ConnectionDialog<UI>::ConnectionDialog(QWidget *parent)
|
||||
: KDialog(parent)
|
||||
{
|
||||
setCaption(i18n("New Connection"));
|
||||
setButtons(Ok | Cancel);
|
||||
setDefaultButton(Cancel);
|
||||
setModal(true);
|
||||
|
||||
setMinimumSize(500, 200);
|
||||
|
||||
m_connectWidget = new QWidget(this);
|
||||
m_ui.setupUi(m_connectWidget);
|
||||
|
||||
m_ui.pixmapLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
|
||||
KGuiItem accept = KStandardGuiItem::ok();
|
||||
accept.setText(i18n("Accept Connection"));
|
||||
setButtonGuiItem(Ok, accept);
|
||||
|
||||
KGuiItem refuse = KStandardGuiItem::cancel();
|
||||
refuse.setText(i18n("Refuse Connection"));
|
||||
setButtonGuiItem(Cancel, refuse);
|
||||
|
||||
setMainWidget(m_connectWidget);
|
||||
}
|
||||
|
||||
//**********
|
||||
|
||||
InvitationsConnectionDialog::InvitationsConnectionDialog(QWidget *parent)
|
||||
: ConnectionDialog<Ui::ConnectionWidget>(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void InvitationsConnectionDialog::setRemoteHost(const QString &host)
|
||||
{
|
||||
m_ui.remoteHost->setText(host);
|
||||
}
|
||||
|
||||
//**********
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
|
||||
TubesConnectionDialog::TubesConnectionDialog(QWidget *parent)
|
||||
: ConnectionDialog<Ui::TubesConnectionWidget>(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void TubesConnectionDialog::setContactName(const QString & name)
|
||||
{
|
||||
QString txt = i18n("You have requested to share your desktop with %1. If you proceed, "
|
||||
"you will allow the remote user to watch your desktop.", name);
|
||||
m_ui.mainTextLabel->setText(txt);
|
||||
}
|
||||
|
||||
#endif // KRFB_WITH_TELEPATHY_TUBES
|
||||
|
||||
#include "connectiondialog.moc"
|
||||
82
krfb/connectiondialog.h
Normal file
82
krfb/connectiondialog.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTIONDIALOG_H
|
||||
#define CONNECTIONDIALOG_H
|
||||
|
||||
#include "ui_connectionwidget.h"
|
||||
#include <KDialog>
|
||||
|
||||
template <typename UI>
|
||||
class ConnectionDialog : public KDialog
|
||||
{
|
||||
public:
|
||||
ConnectionDialog(QWidget *parent);
|
||||
~ConnectionDialog() {};
|
||||
|
||||
void setAllowRemoteControl(bool b);
|
||||
bool allowRemoteControl();
|
||||
|
||||
protected:
|
||||
QWidget *m_connectWidget;
|
||||
UI m_ui;
|
||||
};
|
||||
|
||||
template <typename UI>
|
||||
void ConnectionDialog<UI>::setAllowRemoteControl(bool b)
|
||||
{
|
||||
m_ui.cbAllowRemoteControl->setChecked(b);
|
||||
m_ui.cbAllowRemoteControl->setVisible(b);
|
||||
}
|
||||
|
||||
template <typename UI>
|
||||
bool ConnectionDialog<UI>::allowRemoteControl()
|
||||
{
|
||||
return m_ui.cbAllowRemoteControl->isChecked();
|
||||
}
|
||||
|
||||
//*********
|
||||
|
||||
class InvitationsConnectionDialog : public ConnectionDialog<Ui::ConnectionWidget>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
InvitationsConnectionDialog(QWidget *parent);
|
||||
void setRemoteHost(const QString & host);
|
||||
};
|
||||
|
||||
//*********
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
# include "ui_tubesconnectionwidget.h"
|
||||
|
||||
class TubesConnectionDialog : public ConnectionDialog<Ui::TubesConnectionWidget>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TubesConnectionDialog(QWidget *parent);
|
||||
void setContactName(const QString & name);
|
||||
};
|
||||
|
||||
#endif // KRFB_WITH_TELEPATHY_TUBES
|
||||
|
||||
#endif // CONNECTIONDIALOG_H
|
||||
|
||||
200
krfb/events.cpp
Normal file
200
krfb/events.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
Copyright (C) 2010 Collabora Ltd.
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QX11Info>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <KGlobal>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
enum {
|
||||
LEFTSHIFT = 1,
|
||||
RIGHTSHIFT = 2,
|
||||
ALTGR = 4
|
||||
};
|
||||
|
||||
class EventData
|
||||
{
|
||||
public:
|
||||
EventData();
|
||||
|
||||
//keyboard
|
||||
Display *dpy;
|
||||
signed char modifiers[0x100];
|
||||
KeyCode keycodes[0x100];
|
||||
KeyCode leftShiftCode;
|
||||
KeyCode rightShiftCode;
|
||||
KeyCode altGrCode;
|
||||
char modifierState;
|
||||
|
||||
//mouse
|
||||
int buttonMask;
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
K_GLOBAL_STATIC(EventData, data)
|
||||
|
||||
EventData::EventData()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void EventData::init()
|
||||
{
|
||||
dpy = QX11Info::display();
|
||||
buttonMask = 0;
|
||||
|
||||
//initialize keycodes
|
||||
KeySym key, *keymap;
|
||||
int i, j, minkey, maxkey, syms_per_keycode;
|
||||
|
||||
memset(modifiers, -1, sizeof(modifiers));
|
||||
|
||||
XDisplayKeycodes(dpy, &minkey, &maxkey);
|
||||
Q_ASSERT(minkey >= 8);
|
||||
Q_ASSERT(maxkey < 256);
|
||||
keymap = (KeySym *) XGetKeyboardMapping(dpy, minkey,
|
||||
(maxkey - minkey + 1),
|
||||
&syms_per_keycode);
|
||||
Q_ASSERT(keymap);
|
||||
|
||||
for (i = minkey; i <= maxkey; i++) {
|
||||
for (j = 0; j < syms_per_keycode; j++) {
|
||||
key = keymap[(i-minkey)*syms_per_keycode+j];
|
||||
|
||||
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
|
||||
keycodes[key] = i;
|
||||
modifiers[key] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
|
||||
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
|
||||
|
||||
XFree((char *)keymap);
|
||||
}
|
||||
|
||||
/* this function adjusts the modifiers according to mod (as from modifiers) and data->modifierState */
|
||||
static void tweakModifiers(signed char mod, bool down)
|
||||
{
|
||||
bool isShift = data->modifierState & (LEFTSHIFT | RIGHTSHIFT);
|
||||
|
||||
if (mod < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isShift && mod != 1) {
|
||||
if (data->modifierState & LEFTSHIFT) {
|
||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if (data->modifierState & RIGHTSHIFT) {
|
||||
XTestFakeKeyEvent(data->dpy, data->rightShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isShift && mod == 1) {
|
||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if ((data->modifierState & ALTGR) && mod != 2) {
|
||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
|
||||
if (!(data->modifierState & ALTGR) && mod == 2) {
|
||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
||||
{
|
||||
#define ADJUSTMOD(sym,state) \
|
||||
if(keySym==sym) { if(down) data->modifierState|=state; else data->modifierState&=~state; }
|
||||
|
||||
ADJUSTMOD(XK_Shift_L, LEFTSHIFT);
|
||||
ADJUSTMOD(XK_Shift_R, RIGHTSHIFT);
|
||||
ADJUSTMOD(XK_Mode_switch, ALTGR);
|
||||
|
||||
if (keySym >= ' ' && keySym < 0x100) {
|
||||
KeyCode k;
|
||||
|
||||
if (down) {
|
||||
tweakModifiers(data->modifiers[keySym], True);
|
||||
}
|
||||
|
||||
k = data->keycodes[keySym];
|
||||
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
|
||||
}
|
||||
|
||||
if (down) {
|
||||
tweakModifiers(data->modifiers[keySym], False);
|
||||
}
|
||||
} else {
|
||||
KeyCode k = XKeysymToKeycode(data->dpy, keySym);
|
||||
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::handlePointer(int buttonMask, int x, int y)
|
||||
{
|
||||
QDesktopWidget *desktopWidget = QApplication::desktop();
|
||||
|
||||
int screen = desktopWidget->screenNumber();
|
||||
|
||||
if (screen < 0) {
|
||||
screen = 0;
|
||||
}
|
||||
|
||||
XTestFakeMotionEvent(data->dpy, screen, x, y, CurrentTime);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if ((data->buttonMask&(1 << i)) != (buttonMask&(1 << i))) {
|
||||
XTestFakeButtonEvent(data->dpy,
|
||||
i + 1,
|
||||
(buttonMask&(1 << i)) ? True : False,
|
||||
CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
data->buttonMask = buttonMask;
|
||||
}
|
||||
37
krfb/events.h
Normal file
37
krfb/events.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
Copyright (C) 2010 Collabora Ltd.
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef EVENTS_H
|
||||
#define EVENTS_H
|
||||
|
||||
#include "rfb.h"
|
||||
|
||||
class EventHandler
|
||||
{
|
||||
public:
|
||||
static void handleKeyboard(bool down, rfbKeySym key);
|
||||
static void handlePointer(int buttonMask, int x, int y);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -8,15 +8,14 @@
|
||||
*/
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include "framebuffer.moc"
|
||||
|
||||
#include <config-krfb.h>
|
||||
#include "config-krfb.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
|
||||
FrameBuffer::FrameBuffer(WId id, QObject *parent)
|
||||
: QObject(parent), win(id)
|
||||
: QObject(parent), win(id)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -25,7 +24,7 @@ FrameBuffer::~FrameBuffer()
|
||||
delete fb;
|
||||
}
|
||||
|
||||
char * FrameBuffer::data()
|
||||
char *FrameBuffer::data()
|
||||
{
|
||||
return fb;
|
||||
}
|
||||
@@ -69,3 +68,6 @@ void FrameBuffer::stopMonitor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#include "framebuffer.moc"
|
||||
|
||||
@@ -10,28 +10,29 @@
|
||||
#ifndef FRAMEBUFFER_H
|
||||
#define FRAMEBUFFER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QRect>
|
||||
#include <QList>
|
||||
#include <QWidget>
|
||||
#include "rfb.h"
|
||||
|
||||
#include <kdemacros.h>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QRect>
|
||||
#include <QtCore/QList>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class KDE_EXPORT FrameBuffer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
virtual ~FrameBuffer();
|
||||
|
||||
char * data();
|
||||
char *data();
|
||||
|
||||
virtual QList<QRect> modifiedTiles();
|
||||
virtual int paddedWidth();
|
||||
@@ -64,25 +64,26 @@ void FrameBufferManager::loadPlugins()
|
||||
KService::List offers = KServiceTypeTrader::self()->query("krfb/framebuffer");
|
||||
|
||||
KService::List::const_iterator iter;
|
||||
for (iter = offers.constBegin(); iter < offers.constEnd(); ++iter) {
|
||||
QString error;
|
||||
KService::Ptr service = *iter;
|
||||
|
||||
KPluginFactory *factory = KPluginLoader(service->library()).factory();
|
||||
for (iter = offers.constBegin(); iter < offers.constEnd(); ++iter) {
|
||||
QString error;
|
||||
KService::Ptr service = *iter;
|
||||
|
||||
KPluginFactory *factory = KPluginLoader(service->library()).factory();
|
||||
|
||||
if (!factory) {
|
||||
kWarning() << "KPluginFactory could not load the plugin:" << service->library();
|
||||
continue;
|
||||
}
|
||||
|
||||
FrameBufferPlugin *plugin = factory->create<FrameBufferPlugin>(this);
|
||||
FrameBufferPlugin *plugin = factory->create<FrameBufferPlugin>(this);
|
||||
|
||||
if (plugin) {
|
||||
kDebug() << "Loaded plugin:" << service->name();
|
||||
m_plugins.insert(service->library(), plugin);
|
||||
} else {
|
||||
kDebug() << error;
|
||||
}
|
||||
if (plugin) {
|
||||
kDebug() << "Loaded plugin:" << service->name();
|
||||
m_plugins.insert(service->library(), plugin);
|
||||
} else {
|
||||
kDebug() << error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +105,8 @@ QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id)
|
||||
}
|
||||
|
||||
// We don't already have that frame buffer.
|
||||
QMap<QString, FrameBufferPlugin*>::const_iterator iter = m_plugins.constBegin();
|
||||
QMap<QString, FrameBufferPlugin *>::const_iterator iter = m_plugins.constBegin();
|
||||
|
||||
while (iter != m_plugins.constEnd()) {
|
||||
|
||||
if (iter.key() == KrfbConfig::preferredFrameBufferPlugin()) {
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QWeakPointer>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
class FrameBufferPlugin;
|
||||
@@ -53,7 +54,7 @@ private:
|
||||
|
||||
void loadPlugins();
|
||||
|
||||
QMap<QString, FrameBufferPlugin*> m_plugins;
|
||||
QMap<QString, FrameBufferPlugin *> m_plugins;
|
||||
QMap<WId, QWeakPointer<FrameBuffer> > m_frameBuffers;
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "framebuffer.h"
|
||||
|
||||
FrameBufferPlugin::FrameBufferPlugin(QObject *parent, const QVariantList &)
|
||||
: QObject(parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <kdemacros.h>
|
||||
|
||||
#include <QtCore/QVariantList>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
@@ -21,35 +21,45 @@
|
||||
|
||||
// a random string that doesn't contain i, I, o, O, 1, 0
|
||||
// based on KRandom::randomString()
|
||||
static QString readableRandomString(int length) {
|
||||
QString str;
|
||||
while (length)
|
||||
{
|
||||
int r = KRandom::random() % 62;
|
||||
r += 48;
|
||||
if (r > 57)
|
||||
r += 7;
|
||||
if (r > 90)
|
||||
r += 6;
|
||||
char c = char(r);
|
||||
if ((c == 'i') ||
|
||||
(c == 'I') ||
|
||||
(c == '1') ||
|
||||
(c == 'o') ||
|
||||
(c == 'O') ||
|
||||
(c == '0'))
|
||||
continue;
|
||||
str += c;
|
||||
length--;
|
||||
}
|
||||
return str;
|
||||
static QString readableRandomString(int length)
|
||||
{
|
||||
QString str;
|
||||
|
||||
while (length) {
|
||||
int r = KRandom::random() % 62;
|
||||
r += 48;
|
||||
|
||||
if (r > 57) {
|
||||
r += 7;
|
||||
}
|
||||
|
||||
if (r > 90) {
|
||||
r += 6;
|
||||
}
|
||||
|
||||
char c = char(r);
|
||||
|
||||
if ((c == 'i') ||
|
||||
(c == 'I') ||
|
||||
(c == '1') ||
|
||||
(c == 'o') ||
|
||||
(c == 'O') ||
|
||||
(c == '0')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
str += c;
|
||||
length--;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
Invitation::Invitation()
|
||||
{
|
||||
m_password = readableRandomString(4)+'-'+readableRandomString(3);
|
||||
m_creationTime = QDateTime::currentDateTime();
|
||||
m_expirationTime = QDateTime::currentDateTime().addSecs(INVITATION_DURATION);
|
||||
m_password = readableRandomString(4) + '-' + readableRandomString(3);
|
||||
m_creationTime = QDateTime::currentDateTime();
|
||||
m_expirationTime = QDateTime::currentDateTime().addSecs(INVITATION_DURATION);
|
||||
}
|
||||
|
||||
Invitation::Invitation(const Invitation &x)
|
||||
@@ -57,47 +67,54 @@ Invitation::Invitation(const Invitation &x)
|
||||
{
|
||||
}
|
||||
|
||||
Invitation::Invitation(const KConfigGroup &config) {
|
||||
m_password = KStringHandler::obscure(config.readEntry("password", QString()));
|
||||
Invitation::Invitation(const KConfigGroup &config)
|
||||
{
|
||||
m_password = KStringHandler::obscure(config.readEntry("password", QString()));
|
||||
kDebug() << "read: " << config.readEntry("password", QString()) << " = " << m_password;
|
||||
m_creationTime = config.readEntry("creation", QDateTime());
|
||||
m_expirationTime = config.readEntry("expiration", QDateTime());
|
||||
m_creationTime = config.readEntry("creation", QDateTime());
|
||||
m_expirationTime = config.readEntry("expiration", QDateTime());
|
||||
}
|
||||
|
||||
Invitation::~Invitation() {
|
||||
Invitation::~Invitation()
|
||||
{
|
||||
}
|
||||
|
||||
Invitation &Invitation::operator= (const Invitation&x) {
|
||||
m_password = x.m_password;
|
||||
m_creationTime = x.m_creationTime;
|
||||
m_expirationTime = x.m_expirationTime;
|
||||
return *this;
|
||||
Invitation &Invitation::operator= (const Invitation &x)
|
||||
{
|
||||
m_password = x.m_password;
|
||||
m_creationTime = x.m_creationTime;
|
||||
m_expirationTime = x.m_expirationTime;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Invitation::save(KConfigGroup &config) const
|
||||
void Invitation::save(KConfigGroup &config) const
|
||||
{
|
||||
config.writeEntry("password", KStringHandler::obscure(m_password));
|
||||
config.writeEntry("creation", m_creationTime);
|
||||
config.writeEntry("expiration", m_expirationTime);
|
||||
}
|
||||
|
||||
QString Invitation::password() const {
|
||||
return m_password;
|
||||
QString Invitation::password() const
|
||||
{
|
||||
return m_password;
|
||||
}
|
||||
|
||||
QDateTime Invitation::expirationTime() const {
|
||||
return m_expirationTime;
|
||||
QDateTime Invitation::expirationTime() const
|
||||
{
|
||||
return m_expirationTime;
|
||||
}
|
||||
|
||||
QDateTime Invitation::creationTime() const {
|
||||
return m_creationTime;
|
||||
QDateTime Invitation::creationTime() const
|
||||
{
|
||||
return m_creationTime;
|
||||
}
|
||||
|
||||
bool Invitation::isValid() const {
|
||||
return m_expirationTime > QDateTime::currentDateTime();
|
||||
bool Invitation::isValid() const
|
||||
{
|
||||
return m_expirationTime > QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
bool Invitation::operator ==(const Invitation & ot)
|
||||
bool Invitation::operator ==(const Invitation &ot)
|
||||
{
|
||||
return m_creationTime == ot.m_creationTime && m_password == ot.m_password;
|
||||
}
|
||||
@@ -20,33 +20,33 @@
|
||||
|
||||
#include <KApplication>
|
||||
#include <KConfig>
|
||||
#include <QObject>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
const int INVITATION_DURATION = 60 * 60;
|
||||
|
||||
const int INVITATION_DURATION = 60*60;
|
||||
|
||||
class Invitation {
|
||||
class Invitation
|
||||
{
|
||||
public:
|
||||
Invitation();
|
||||
~Invitation();
|
||||
Invitation(const KConfigGroup &config);
|
||||
Invitation(const Invitation &x);
|
||||
Invitation &operator= (const Invitation&x);
|
||||
Invitation();
|
||||
~Invitation();
|
||||
Invitation(const KConfigGroup &config);
|
||||
Invitation(const Invitation &x);
|
||||
Invitation &operator= (const Invitation &x);
|
||||
|
||||
bool operator == (const Invitation &ot);
|
||||
|
||||
QString password() const;
|
||||
QDateTime expirationTime() const;
|
||||
QDateTime creationTime() const;
|
||||
bool isValid() const;
|
||||
QString password() const;
|
||||
QDateTime expirationTime() const;
|
||||
QDateTime creationTime() const;
|
||||
bool isValid() const;
|
||||
|
||||
void save(KConfigGroup &config) const;
|
||||
void save(KConfigGroup &config) const;
|
||||
private:
|
||||
QString m_password;
|
||||
QDateTime m_creationTime;
|
||||
QDateTime m_expirationTime;
|
||||
QString m_password;
|
||||
QDateTime m_creationTime;
|
||||
QDateTime m_expirationTime;
|
||||
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <KConfig>
|
||||
#include <KGlobal>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
class InvitationManagerPrivate
|
||||
{
|
||||
@@ -23,7 +23,8 @@ public:
|
||||
|
||||
K_GLOBAL_STATIC(InvitationManagerPrivate, invitationManagerPrivate)
|
||||
|
||||
InvitationManager * InvitationManager::self() {
|
||||
InvitationManager *InvitationManager::self()
|
||||
{
|
||||
return &invitationManagerPrivate->instance;
|
||||
}
|
||||
|
||||
@@ -33,7 +34,7 @@ InvitationManager::InvitationManager()
|
||||
|
||||
QTimer *refreshTimer = new QTimer(this);
|
||||
connect(refreshTimer, SIGNAL(timeout()), SLOT(loadInvitations()));
|
||||
refreshTimer->start(1000*60);
|
||||
refreshTimer->start(1000 * 60);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,14 +43,16 @@ InvitationManager::~InvitationManager()
|
||||
|
||||
}
|
||||
|
||||
void InvitationManager::invalidateOldInvitations() {
|
||||
void InvitationManager::invalidateOldInvitations()
|
||||
{
|
||||
int invNum = invitationList.size();
|
||||
|
||||
while(invNum--) {
|
||||
while (invNum--) {
|
||||
if (!invitationList[invNum].isValid()) {
|
||||
invitationList.removeAt(invNum);
|
||||
}
|
||||
}
|
||||
|
||||
saveInvitations();
|
||||
}
|
||||
|
||||
@@ -60,15 +63,17 @@ void InvitationManager::loadInvitations()
|
||||
|
||||
KSharedConfigPtr conf = KGlobal::config();
|
||||
KConfigGroup invitationConfig(conf, "Invitations");
|
||||
int numInv = invitationConfig.readEntry("invitation_num",0);
|
||||
int numInv = invitationConfig.readEntry("invitation_num", 0);
|
||||
|
||||
invitationList.clear();
|
||||
|
||||
for (int i = 0; i < numInv; i++) {
|
||||
KConfigGroup ic(conf, QString("Invitation_%1").arg(i));
|
||||
invitationList.append(Invitation(ic));
|
||||
}
|
||||
|
||||
invalidateOldInvitations();
|
||||
|
||||
if (numInv != invNum) {
|
||||
emit invitationNumChanged(invitationList.size());
|
||||
}
|
||||
@@ -94,11 +99,13 @@ void InvitationManager::saveInvitations()
|
||||
KSharedConfigPtr conf = KGlobal::config();
|
||||
KConfigGroup invitationConfig(conf, "Invitations");
|
||||
int invNum = invitationList.size();
|
||||
invitationConfig.writeEntry("invitation_num",invNum);
|
||||
invitationConfig.writeEntry("invitation_num", invNum);
|
||||
|
||||
for (int i = 0; i < invNum; i++) {
|
||||
KConfigGroup ic(conf, QString("Invitation_%1").arg(i));
|
||||
invitationList[i].save(ic);
|
||||
}
|
||||
|
||||
conf->sync();
|
||||
}
|
||||
|
||||
@@ -108,7 +115,7 @@ int InvitationManager::activeInvitations()
|
||||
return invitationList.size();
|
||||
}
|
||||
|
||||
void InvitationManager::removeInvitation(const Invitation & inv)
|
||||
void InvitationManager::removeInvitation(const Invitation &inv)
|
||||
{
|
||||
invitationList.removeAll(inv);
|
||||
saveInvitations();
|
||||
@@ -9,19 +9,19 @@
|
||||
#ifndef INVITATIONMANAGER_H
|
||||
#define INVITATIONMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include "invitation.h"
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class InvitationManagerPrivate;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class InvitationManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class InvitationManagerPrivate;
|
||||
Q_OBJECT
|
||||
friend class InvitationManagerPrivate;
|
||||
public:
|
||||
static InvitationManager *self();
|
||||
|
||||
112
krfb/invitationsrfbclient.cpp
Normal file
112
krfb/invitationsrfbclient.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "invitationsrfbclient.h"
|
||||
#include "invitationmanager.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "sockethelpers.h"
|
||||
#include "connectiondialog.h"
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
|
||||
bool InvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
|
||||
{
|
||||
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
|
||||
QByteArray password = KrfbConfig::uninvitedConnectionPassword().toLocal8Bit();
|
||||
|
||||
bool authd = false;
|
||||
kDebug() << "about to start autentication";
|
||||
|
||||
if (allowUninvited) {
|
||||
authd = vncAuthCheckPassword(password, encryptedPassword);
|
||||
}
|
||||
|
||||
if (!authd) {
|
||||
QList<Invitation> invlist = InvitationManager::self()->invitations();
|
||||
|
||||
foreach(const Invitation & it, invlist) {
|
||||
kDebug() << "checking password";
|
||||
|
||||
if (vncAuthCheckPassword(it.password().toLocal8Bit(), encryptedPassword)
|
||||
&& it.isValid())
|
||||
{
|
||||
authd = true;
|
||||
InvitationManager::self()->removeInvitation(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!authd) {
|
||||
if (InvitationManager::self()->invitations().size() > 0) {
|
||||
KNotification::event("InvalidPasswordInvitations",
|
||||
i18n("Failed login attempt from %1: wrong password", name()));
|
||||
} else {
|
||||
KNotification::event("InvalidPassword",
|
||||
i18n("Failed login attempt from %1: wrong password", name()));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PendingInvitationsRfbClient::processNewClient()
|
||||
{
|
||||
QString host = peerAddress(m_rfbClient->sock) + ":" + QString::number(peerPort(m_rfbClient->sock));
|
||||
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
|
||||
|
||||
if (!allowUninvited && InvitationManager::self()->activeInvitations() == 0) {
|
||||
KNotification::event("UnexpectedConnection",
|
||||
i18n("Refused uninvited connection attempt from %1", host));
|
||||
reject();
|
||||
} else if (!KrfbConfig::askOnConnect()) {
|
||||
KNotification::event("NewConnectionAutoAccepted",
|
||||
i18n("Accepted connection from %1", host));
|
||||
accept(new InvitationsRfbClient(m_rfbClient, parent()));
|
||||
} else {
|
||||
KNotification::event("NewConnectionOnHold",
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
host));
|
||||
|
||||
InvitationsConnectionDialog *dialog = new InvitationsConnectionDialog(0);
|
||||
dialog->setRemoteHost(host);
|
||||
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
|
||||
connect(dialog, SIGNAL(cancelClicked()), SLOT(reject()));
|
||||
|
||||
dialog->show();
|
||||
}
|
||||
}
|
||||
|
||||
void PendingInvitationsRfbClient::dialogAccepted()
|
||||
{
|
||||
InvitationsConnectionDialog *dialog = qobject_cast<InvitationsConnectionDialog *>(sender());
|
||||
Q_ASSERT(dialog);
|
||||
|
||||
InvitationsRfbClient *client = new InvitationsRfbClient(m_rfbClient, parent());
|
||||
client->setControlEnabled(dialog->allowRemoteControl());
|
||||
accept(client);
|
||||
}
|
||||
|
||||
#include "invitationsrfbclient.moc"
|
||||
48
krfb/invitationsrfbclient.h
Normal file
48
krfb/invitationsrfbclient.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef INVITATIONSRFBCLIENT_H
|
||||
#define INVITATIONSRFBCLIENT_H
|
||||
|
||||
#include "rfbclient.h"
|
||||
|
||||
class InvitationsRfbClient : public RfbClient
|
||||
{
|
||||
public:
|
||||
InvitationsRfbClient(rfbClientPtr client, QObject* parent = 0)
|
||||
: RfbClient(client, parent) {}
|
||||
|
||||
protected:
|
||||
virtual bool checkPassword(const QByteArray & encryptedPassword);
|
||||
};
|
||||
|
||||
|
||||
class PendingInvitationsRfbClient : public PendingRfbClient
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent = 0)
|
||||
: PendingRfbClient(client, parent) {}
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void processNewClient();
|
||||
|
||||
private Q_SLOTS:
|
||||
void dialogAccepted();
|
||||
};
|
||||
|
||||
#endif // INVITATIONSRFBCLIENT_H
|
||||
71
krfb/invitationsrfbserver.cpp
Normal file
71
krfb/invitationsrfbserver.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "invitationsrfbserver.h"
|
||||
#include "invitationsrfbclient.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "rfbservermanager.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
#include <KMessageBox>
|
||||
#include <KUser>
|
||||
#include <DNSSD/PublicService>
|
||||
|
||||
void InvitationsRfbServer::init()
|
||||
{
|
||||
InvitationsRfbServer *server;
|
||||
server = new InvitationsRfbServer;
|
||||
server->setListeningPort(KrfbConfig::port());
|
||||
server->setListeningAddress("0.0.0.0"); // Listen on all available network addresses
|
||||
server->setPasswordRequired(true);
|
||||
QTimer::singleShot(0, server, SLOT(startAndCheck()));
|
||||
}
|
||||
|
||||
PendingRfbClient* InvitationsRfbServer::newClient(rfbClientPtr client)
|
||||
{
|
||||
return new PendingInvitationsRfbClient(client, this);
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::startAndCheck()
|
||||
{
|
||||
if (!start()) {
|
||||
KMessageBox::error(0, i18n("Failed to start the krfb server. Invitation-based sharing "
|
||||
"will not work. Try setting another port in the settings and "
|
||||
"restart krfb."));
|
||||
} else {
|
||||
//publish service
|
||||
if (KrfbConfig::publishService()) {
|
||||
DNSSD::PublicService *service = new DNSSD::PublicService(i18n("%1@%2 (shared desktop)",
|
||||
KUser().loginName(),
|
||||
QHostInfo::localHostName()),
|
||||
"_rfb._tcp",
|
||||
listeningPort());
|
||||
service->publishAsync();
|
||||
}
|
||||
|
||||
//disconnect when qApp quits
|
||||
connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(stop()));
|
||||
}
|
||||
}
|
||||
|
||||
#include "invitationsrfbserver.moc"
|
||||
43
krfb/invitationsrfbserver.h
Normal file
43
krfb/invitationsrfbserver.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef INVITATIONSRFBSERVER_H
|
||||
#define INVITATIONSRFBSERVER_H
|
||||
|
||||
#include "rfbserver.h"
|
||||
|
||||
class InvitationsRfbServer : public RfbServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void init();
|
||||
|
||||
protected:
|
||||
InvitationsRfbServer() : RfbServer(0) {}
|
||||
|
||||
virtual PendingRfbClient* newClient(rfbClientPtr client);
|
||||
|
||||
private Q_SLOTS:
|
||||
void startAndCheck();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(InvitationsRfbServer)
|
||||
};
|
||||
|
||||
#endif // INVITATIONSRFBSERVER_H
|
||||
87
krfb/invitedialog.cpp
Normal file
87
krfb/invitedialog.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "invitedialog.h"
|
||||
|
||||
#include <KIconLoader>
|
||||
#include <KLocale>
|
||||
#include <KStandardGuiItem>
|
||||
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QToolTip>
|
||||
|
||||
InviteDialog::InviteDialog(QWidget *parent)
|
||||
: KDialog(parent)
|
||||
{
|
||||
setCaption(i18n("Invitation"));
|
||||
setButtons(User1 | Close | Help);
|
||||
setHelp(QString(), "krfb");
|
||||
setDefaultButton(NoDefault);
|
||||
|
||||
setMinimumSize(500, 300);
|
||||
|
||||
m_inviteWidget = new QWidget(this);
|
||||
setupUi(m_inviteWidget);
|
||||
|
||||
pixmapLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
setMainWidget(m_inviteWidget);
|
||||
|
||||
setButtonGuiItem(User1, KStandardGuiItem::configure());
|
||||
|
||||
connect(btnCreateInvite, SIGNAL(clicked()),
|
||||
SIGNAL(createInviteClicked()));
|
||||
connect(btnEmailInvite, SIGNAL(clicked()),
|
||||
SIGNAL(emailInviteClicked()));
|
||||
connect(btnManageInvite, SIGNAL(clicked()),
|
||||
SIGNAL(manageInviteClicked()));
|
||||
connect(helpLabel, SIGNAL(linkActivated(QString)),
|
||||
SLOT(showWhatsthis()));
|
||||
}
|
||||
|
||||
void InviteDialog::slotUser1()
|
||||
{
|
||||
emit configureClicked();
|
||||
}
|
||||
|
||||
void InviteDialog::enableInviteButton(bool enable)
|
||||
{
|
||||
btnCreateInvite->setEnabled(enable);
|
||||
}
|
||||
|
||||
void InviteDialog::setInviteCount(int count)
|
||||
{
|
||||
btnManageInvite->setText(
|
||||
i18n("&Manage Invitations (%1)...", count));
|
||||
}
|
||||
|
||||
void InviteDialog::showWhatsthis()
|
||||
{
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
i18n("An invitation creates a one-time password that allows the receiver to connect to your desktop.\n"
|
||||
"It is valid for only one successful connection and will expire after an hour if it has not been used. \n"
|
||||
"When somebody connects to your computer a dialog will appear and ask you for permission.\n "
|
||||
"The connection will not be established before you accept it. In this dialog you can also\n restrict "
|
||||
"the other person to view your desktop only, without the ability to move your\n mouse pointer or press "
|
||||
"keys.\nIf you want to create a permanent password for Desktop Sharing, allow 'Uninvited Connections' \n"
|
||||
"in the configuration."));
|
||||
}
|
||||
|
||||
#include "invitedialog.moc"
|
||||
@@ -28,28 +28,28 @@ class QWidget;
|
||||
|
||||
class InviteDialog : public KDialog, public Ui::InviteWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InviteDialog( QWidget *parent );
|
||||
public:
|
||||
InviteDialog(QWidget *parent);
|
||||
~InviteDialog() {}
|
||||
|
||||
void enableInviteButton( bool enable );
|
||||
void enableInviteButton(bool enable);
|
||||
|
||||
public Q_SLOTS:
|
||||
void setInviteCount( int count );
|
||||
public Q_SLOTS:
|
||||
void setInviteCount(int count);
|
||||
void showWhatsthis();
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void createInviteClicked();
|
||||
void emailInviteClicked();
|
||||
void manageInviteClicked();
|
||||
void configureClicked();
|
||||
|
||||
protected Q_SLOTS:
|
||||
protected Q_SLOTS:
|
||||
void slotUser1();
|
||||
|
||||
protected:
|
||||
protected:
|
||||
QWidget *m_inviteWidget;
|
||||
};
|
||||
|
||||
@@ -4,31 +4,41 @@ X-KDE-ServiceType=krfb/framebuffer
|
||||
|
||||
Comment=Frame Buffer plugins for KRfb
|
||||
Comment[ast]=Complementu de buffer pa KRfb
|
||||
Comment[bs]=Priključci framebafera za KRfb
|
||||
Comment[ca]=Connectors de «framebuffer» per al KRfb.
|
||||
Comment[ca@valencia]=Connectors de «framebuffer» per al KRfb.
|
||||
Comment[cs]=Moduly Frame bufferu pro KRfb
|
||||
Comment[da]=Framebuffer-plugins til KRfb
|
||||
Comment[de]=Framebuffer-Module für KRfb
|
||||
Comment[el]=Πρόσθετα μνήμης εξόδου βίντεο καρέ για το KRfb
|
||||
Comment[en_GB]=Frame Buffer plugins for KRfb
|
||||
Comment[es]=Complemento de buffer para KRfb
|
||||
Comment[es]=Complementos de memoria intermedia de vídeo para KRfb
|
||||
Comment[et]=KRfb kaadripuhvri plugin
|
||||
Comment[eu]=Irteerako bideoaren pluginak KRfb-rentzako
|
||||
Comment[fi]=Kehyspuskuriliitännäinen kohteelle KRfb
|
||||
Comment[fr]=Modules de sortie vidéo pour KRfb
|
||||
Comment[ga]=Breiseáin Mhaoláin Fráma le haghaidh KRfb
|
||||
Comment[gl]=Engadido de frame buffer para KRfb
|
||||
Comment[hr]=Priključci za međuspremnike okvira za KRfb
|
||||
Comment[hu]=Framebuffer bővítmények a Krfb-hez
|
||||
Comment[ia]=Plug-ins de Frame Buffer per KRfb
|
||||
Comment[it]=Estensioni del framebuffer per KRfb
|
||||
Comment[ja]=KRfb の フレームバッファプラグイン
|
||||
Comment[kk]=KRfb кадр буфер плагині
|
||||
Comment[km]=កម្មវិធីជំនួយ Frame Buffer សម្រាប់ KRfb
|
||||
Comment[ko]=KRfb 프레임버퍼 플러그인
|
||||
Comment[lt]=Frame Buffer priedai skirti KRfb
|
||||
Comment[lv]=Kadru bufera sprudņi priekš KRfb
|
||||
Comment[nb]=Rammebuffer-programtillegg for KRfb
|
||||
Comment[nds]=Bildpuffer-Modulen för KRfb
|
||||
Comment[nl]=Framebuffer-plugins voor KRfb
|
||||
Comment[nn]=Framebuffer-tillegg KRfb
|
||||
Comment[pa]=KRfb ਲਈ ਫਰੇਮ ਬਫ਼ਰ ਪਲੱਗਇਨ
|
||||
Comment[pl]=Wtyczki buforów ramek dla KRfb
|
||||
Comment[pt]='Plugins' de 'framebuffers' para o KRfb
|
||||
Comment[pt_BR]=Plug-ins de framebuffers para o KRfb
|
||||
Comment[pt_BR]=Plugins de framebuffers para o KRfb
|
||||
Comment[ru]=Модуль буфера кадров для KRfb
|
||||
Comment[si]=KRfb සඳහා රාමු බෆර ප්ලගින
|
||||
Comment[sk]=Frame Buffer modul pre KRfb
|
||||
Comment[sl]=Vstavki slikovnih medpomnilnikov za KRFB
|
||||
Comment[sr]=Прикључци кадробафера за КРФБ
|
||||
13
krfb.desktop → krfb/krfb.desktop
Normal file → Executable file
13
krfb.desktop → krfb/krfb.desktop
Normal file → Executable file
@@ -11,6 +11,7 @@ Name[ast]=Krfb
|
||||
Name[bg]=Krfb
|
||||
Name[bn]=কে-আর-এফ-বি
|
||||
Name[br]=Krfb
|
||||
Name[bs]=Krfb
|
||||
Name[ca]=Krfb
|
||||
Name[ca@valencia]=Krfb
|
||||
Name[cs]=Krfb
|
||||
@@ -31,6 +32,7 @@ Name[hi]=केआरएफबी
|
||||
Name[hne]=केआरएफबी
|
||||
Name[hr]=Krfb
|
||||
Name[hu]=Krfb
|
||||
Name[ia]=Krfb
|
||||
Name[is]=Krfb
|
||||
Name[it]=Krfb
|
||||
Name[ja]=Krfb
|
||||
@@ -51,14 +53,17 @@ Name[pt]=Krfb
|
||||
Name[pt_BR]=Krfb
|
||||
Name[ro]=Krfb
|
||||
Name[ru]=Krfb
|
||||
Name[si]=Krfb
|
||||
Name[sk]=Krfb
|
||||
Name[sl]=Krfb
|
||||
Name[sq]=Krfb
|
||||
Name[sr]=КРФБ
|
||||
Name[sr@ijekavian]=КРФБ
|
||||
Name[sr@ijekavianlatin]=KRFB
|
||||
Name[sr@latin]=KRFB
|
||||
Name[sv]=Krfb
|
||||
Name[tr]=Krfb
|
||||
Name[ug]=Krfb
|
||||
Name[uk]=Krfb
|
||||
Name[uz]=Krfb
|
||||
Name[uz@cyrillic]=Krfb
|
||||
@@ -66,13 +71,14 @@ Name[vi]=Krfb
|
||||
Name[x-test]=xxKrfbxx
|
||||
Name[zh_CN]=Krfb
|
||||
Name[zh_HK]=Krfb
|
||||
Name[zh_TW]=Krfb 桌面分享
|
||||
Name[zh_TW]=桌面分享_Krfb
|
||||
GenericName=Desktop Sharing
|
||||
GenericName[ar]=مشاركة سطح المكتب
|
||||
GenericName[ast]=Escritoriu compartíu
|
||||
GenericName[bg]=Споделяне на работното място
|
||||
GenericName[bg]=Споделяне на работния плот
|
||||
GenericName[bn]=ডেস্কটপ ভাগাভাগি
|
||||
GenericName[br]=Rannañ ar vurev
|
||||
GenericName[bs]=Dijeljenje radne površine
|
||||
GenericName[ca]=Compartició de l'escriptori
|
||||
GenericName[ca@valencia]=Compartició de l'escriptori
|
||||
GenericName[cs]=Sdílení pracovní plochy
|
||||
@@ -95,6 +101,7 @@ GenericName[hi]=डेस्कटॉप साझेदारी
|
||||
GenericName[hne]=डेस्कटाप साझेदारी
|
||||
GenericName[hr]=Dijeljenje radne površine
|
||||
GenericName[hu]=Munkaasztal-megosztás
|
||||
GenericName[ia]=Compartir de scriptorio
|
||||
GenericName[is]=Skjáborðsmiðlun
|
||||
GenericName[it]=Condivisione del desktop
|
||||
GenericName[ja]=デスクトップ共有
|
||||
@@ -115,6 +122,7 @@ GenericName[pt]=Partilha do Ecrã
|
||||
GenericName[pt_BR]=Compartilhamento de ambiente de trabalho
|
||||
GenericName[ro]=Partajare birou
|
||||
GenericName[ru]=Общий рабочий стол
|
||||
GenericName[si]=වැඩතල හවුල්
|
||||
GenericName[sk]=Zdieľanie pracovnej plochy
|
||||
GenericName[sl]=Deljenje namizja
|
||||
GenericName[sr]=Дељење површи
|
||||
@@ -124,6 +132,7 @@ GenericName[sr@latin]=Deljenje površi
|
||||
GenericName[sv]=Dela ut skrivbordet
|
||||
GenericName[th]=ใช้งานพื้นที่ทำงานร่วมกัน
|
||||
GenericName[tr]=Masaüstü Paylaşımı
|
||||
GenericName[ug]=ئۈستەلئۈستىنى ھەمبەھىرلەش
|
||||
GenericName[uk]=Спільні стільниці
|
||||
GenericName[uz]=Ish stoli bilan boʻlishish
|
||||
GenericName[uz@cyrillic]=Иш столи билан бўлишиш
|
||||
@@ -4,8 +4,10 @@ Comment=Desktop Sharing
|
||||
Comment[af]=Werkskerm Deeling
|
||||
Comment[ar]=مشاركة سطح المكتب
|
||||
Comment[ast]=Escritoriu compartíu
|
||||
Comment[bg]=Споделяне на работния плот
|
||||
Comment[bn]=ডেস্কটপ ভাগাভাগি
|
||||
Comment[br]=Rannañ ar vurev
|
||||
Comment[bs]=Dijeljenje radne površine
|
||||
Comment[ca]=Compartició de l'escriptori
|
||||
Comment[ca@valencia]=Compartició de l'escriptori
|
||||
Comment[cs]=Sdílení pracovní plochy
|
||||
@@ -27,6 +29,7 @@ Comment[hi]=डेस्कटॉप साझेदारी
|
||||
Comment[hne]=डेस्कटाप साझेदारी
|
||||
Comment[hr]=Dijeljenje radne površine
|
||||
Comment[hu]=Munkaasztal-megosztás
|
||||
Comment[ia]=Compartir de scriptorio
|
||||
Comment[is]=Skjáborðamiðlun
|
||||
Comment[it]=Condivisione del desktop
|
||||
Comment[ja]=デスクトップ共有
|
||||
@@ -48,6 +51,7 @@ Comment[pt]=Partilha do Ecrã
|
||||
Comment[pt_BR]=Compartilhamento do ambiente de trabalho
|
||||
Comment[ro]=Partajare birou
|
||||
Comment[ru]=Параметры общего рабочего стола
|
||||
Comment[si]=වැඩතල හවුල්
|
||||
Comment[sk]=Zdieľanie pracovnej plochy
|
||||
Comment[sl]=Deljenje namizja
|
||||
Comment[sr]=Дељење површи
|
||||
@@ -59,6 +63,7 @@ Comment[ta]=பணிமேடை பகிர்வு
|
||||
Comment[tg]=Истифодаи Муштараки Мизи Корӣ
|
||||
Comment[th]=ใช้งานพื้นที่ทำงานร่วมกัน
|
||||
Comment[tr]=Masaüstü Paylaşımı
|
||||
Comment[ug]=ئۈستەلئۈستىنى ھەمبەھىرلەش
|
||||
Comment[uk]=Спільні стільниці
|
||||
Comment[xh]=Ulwahlulelano lwe Desktop
|
||||
Comment[x-test]=xxDesktop Sharingxx
|
||||
@@ -70,6 +75,8 @@ Comment[zh_TW]=桌面分享
|
||||
Name=User Accepts Connection
|
||||
Name[ar]=المستخدم يقبل الاتصال
|
||||
Name[ast]=L'usuariu aceuta la conexón
|
||||
Name[bg]=Потребителят приема връзката
|
||||
Name[bs]=Korisnik prihvata vezu
|
||||
Name[ca]=L'usuari accepta la connexió
|
||||
Name[ca@valencia]=L'usuari accepta la connexió
|
||||
Name[cs]=Uživatel přijímá spojení
|
||||
@@ -89,6 +96,7 @@ Name[hi]=उपयोक्ता ने कनेक्शन स्वीक
|
||||
Name[hne]=कमइया हर कनेक्सन स्वीकारा
|
||||
Name[hr]=Korisnik prihvaća vezu
|
||||
Name[hu]=A felhasználó engedélyezi a csatlakozást
|
||||
Name[ia]=Usator da acceptation a connexion
|
||||
Name[is]=Notandi samþykkir tengingar
|
||||
Name[it]=L'utente accetta la connessione
|
||||
Name[ja]=ユーザが接続を許可
|
||||
@@ -108,6 +116,7 @@ Name[pt]=O Utilizador Aceita a Ligação
|
||||
Name[pt_BR]=O usuário aceita a conexão
|
||||
Name[ro]=Utilizatorul acceptă conexiunea
|
||||
Name[ru]=Пользователь принимает соединения
|
||||
Name[si]=සබැඳිය පරිශීලකයා තහවුරු කරයි
|
||||
Name[sk]=Užívateľ akceptuje pripojenie
|
||||
Name[sl]=Uporabnik sprejel povezavo
|
||||
Name[sr]=Корисник прихвата везу
|
||||
@@ -125,7 +134,9 @@ Comment=User accepts connection
|
||||
Comment[af]=Gebruiker aanvaar verbinding
|
||||
Comment[ar]=المستخدم يقبل الاتصال
|
||||
Comment[ast]=L'usuariu aceuta la conexón
|
||||
Comment[bg]=Потребителят приема връзката
|
||||
Comment[bn]=ব্যবহারকারী সংযোগ গ্রহণ করে
|
||||
Comment[bs]=Korisnik prihvata vezu
|
||||
Comment[ca]=L'usuari accepta la connexió
|
||||
Comment[ca@valencia]=L'usuari accepta la connexió
|
||||
Comment[cs]=Uživatel přijímá spojení
|
||||
@@ -147,6 +158,7 @@ Comment[hi]=उपयोक्ता ने कनेक्शन स्वी
|
||||
Comment[hne]=कमइया हर कनेक्सन स्वीकारा
|
||||
Comment[hr]=Korisnik prihvaća vezu
|
||||
Comment[hu]=A felhasználó engedélyezi a csatlakozást
|
||||
Comment[ia]=Usator da acceptation a connexion
|
||||
Comment[is]=Notandi samþykkir tengingu
|
||||
Comment[it]=L'utente accetta la connessione
|
||||
Comment[ja]=ユーザが接続を許可
|
||||
@@ -168,6 +180,7 @@ Comment[pt]=O utilizador aceita a ligação
|
||||
Comment[pt_BR]=O usuário aceita a conexão
|
||||
Comment[ro]=Utilizatorul acceptă conexiunea
|
||||
Comment[ru]=Пользователь принимает соединения
|
||||
Comment[si]=සබැඳිය පරිශීලකයා තහවුරු කරයි
|
||||
Comment[sk]=Užívateľ akceptuje pripojenie
|
||||
Comment[sl]=Uporabnik sprejel povezavo
|
||||
Comment[sr]=Корисник прихвата везу
|
||||
@@ -191,6 +204,8 @@ Action=Popup
|
||||
Name=User Refuses Connection
|
||||
Name[ar]=المستخدم يرفض الاتصال
|
||||
Name[ast]=L'usuariu refuga la conexón
|
||||
Name[bg]=Потребителят отказва връзката
|
||||
Name[bs]=Korisnik odbija vezu
|
||||
Name[ca]=L'usuari refusa la connexió
|
||||
Name[ca@valencia]=L'usuari refusa la connexió
|
||||
Name[cs]=Uživatel odmítá spojení
|
||||
@@ -210,6 +225,7 @@ Name[hi]=उपयोक्ता ने कनेक्शन अस्वी
|
||||
Name[hne]=कमइया हर कनेक्सन अस्वीकारा
|
||||
Name[hr]=Korisnik odbija vezu
|
||||
Name[hu]=A felhasználó elutasítja a csatlakozást
|
||||
Name[ia]=Usator refuta connexion
|
||||
Name[is]=Notandi hafnar tengingum
|
||||
Name[it]=L'utente rifiuta la connessione
|
||||
Name[ja]=ユーザが接続を拒否
|
||||
@@ -229,6 +245,7 @@ Name[pt]=O Utilizador Recusa a Ligação
|
||||
Name[pt_BR]=O usuário rejeita a conexão
|
||||
Name[ro]=Utilizatorul refuză conexiunea
|
||||
Name[ru]=Пользователь отклоняет соединения
|
||||
Name[si]=සබැඳිය පරිශීලකයා තහවුරු නොකරයි
|
||||
Name[sk]=Užívateľ odmieta pripojenie
|
||||
Name[sl]=Uporabnik zavrnil povezavo
|
||||
Name[sr]=Корисник одбија везу
|
||||
@@ -246,7 +263,9 @@ Comment=User refuses connection
|
||||
Comment[af]=Gebruiker weier verbinding
|
||||
Comment[ar]=المستخدم يرفض الاتصال
|
||||
Comment[ast]=L'usuariu refuga la conexón
|
||||
Comment[bg]=Потребителят отказва връзката
|
||||
Comment[bn]=ব্যবহারকারী সংযোগ অস্বীকার করে
|
||||
Comment[bs]=Korisnik odbija vezu
|
||||
Comment[ca]=L'usuari refusa la connexió
|
||||
Comment[ca@valencia]=L'usuari refusa la connexió
|
||||
Comment[cs]=Uživatel odmítá spojení
|
||||
@@ -268,6 +287,7 @@ Comment[hi]=उपयोक्ता ने कनेक्शन अस्व
|
||||
Comment[hne]=कमइया हर कनेक्सन अस्वीकारा
|
||||
Comment[hr]=Korisnik odbija vezu
|
||||
Comment[hu]=A felhasználó elutasítja a csatlakozást
|
||||
Comment[ia]=Usator refuta connexion
|
||||
Comment[is]=Notandi hafnar tengingu
|
||||
Comment[it]=L'utente rifiuta la connessione
|
||||
Comment[ja]=ユーザが接続を拒否
|
||||
@@ -289,6 +309,7 @@ Comment[pt]=O utilizador recusa a ligação
|
||||
Comment[pt_BR]=O usuário rejeita a conexão
|
||||
Comment[ro]=Utilizatorul refuză conexiunea
|
||||
Comment[ru]=Пользователь отклоняет соединения
|
||||
Comment[si]=සබැඳිය පරිශීලකයා තහවුරු නොකරයි
|
||||
Comment[sk]=Užívateľ odmieta pripojenie
|
||||
Comment[sl]=Uporabnik zavrnil povezavo
|
||||
Comment[sr]=Корисник одбија везу
|
||||
@@ -312,6 +333,8 @@ Action=Popup
|
||||
Name=Connection Closed
|
||||
Name[ar]=الاتصال أغلق
|
||||
Name[ast]=Conexón zarrada
|
||||
Name[bg]=Връзката е прекъсната
|
||||
Name[bs]=Konekcija zatvorena
|
||||
Name[ca]=Connexió tancada
|
||||
Name[ca@valencia]=Connexió tancada
|
||||
Name[cs]=Spojení ukončeno
|
||||
@@ -331,6 +354,7 @@ Name[hi]=कनेक्शन बन्द
|
||||
Name[hne]=कनेक्सन बन्द
|
||||
Name[hr]=Veza prekinuta
|
||||
Name[hu]=A kapcsolat megszűnt
|
||||
Name[ia]=Connexion claudite
|
||||
Name[is]=Tengingu lokað
|
||||
Name[it]=Connessione chiusa
|
||||
Name[ja]=接続切断
|
||||
@@ -351,8 +375,10 @@ Name[pt]=Ligação Fechada
|
||||
Name[pt_BR]=Conexão encerrada
|
||||
Name[ro]=Conexiune închisă
|
||||
Name[ru]=Соединение закрыто
|
||||
Name[sk]=Pripojenie ukončené
|
||||
Name[si]=සබඳතාව වසා දැමිනි
|
||||
Name[sk]=Pripojenie bolo ukončené
|
||||
Name[sl]=Povezava zaprta
|
||||
Name[sq]=Lidhja u Mbyll
|
||||
Name[sr]=Веза затворена
|
||||
Name[sr@ijekavian]=Веза затворена
|
||||
Name[sr@ijekavianlatin]=Veza zatvorena
|
||||
@@ -368,8 +394,10 @@ Comment=Connection closed
|
||||
Comment[af]=Verbinding gesluit
|
||||
Comment[ar]=تمّ غلق الاتصال
|
||||
Comment[ast]=Conexón zarrada
|
||||
Comment[bg]=Връзката е прекъсната
|
||||
Comment[bn]=সংযোগ বন্ধ করা হল
|
||||
Comment[br]=Serret eo ar gevreadenn
|
||||
Comment[bs]=Veza je zatvorena
|
||||
Comment[ca]=Connexió tancada
|
||||
Comment[ca@valencia]=Connexió tancada
|
||||
Comment[cs]=Spojení ukončeno
|
||||
@@ -391,6 +419,7 @@ Comment[hi]=कनेक्शन बन्द
|
||||
Comment[hne]=कनेक्सन बन्द
|
||||
Comment[hr]=Veza prekinuta
|
||||
Comment[hu]=A kapcsolat megszűnt
|
||||
Comment[ia]=Connexion claudite
|
||||
Comment[is]=Tengingu lokað
|
||||
Comment[it]=Connessione chiusa
|
||||
Comment[ja]=接続が閉じられました
|
||||
@@ -412,8 +441,10 @@ Comment[pt]=A ligação foi encerrada
|
||||
Comment[pt_BR]=Conexão encerrada
|
||||
Comment[ro]=Conexiune închisă
|
||||
Comment[ru]=Соединение закрыто
|
||||
Comment[sk]=Pripojenie ukončené
|
||||
Comment[si]=සබඳතාව වසාදැමිනි
|
||||
Comment[sk]=Pripojenie bolo ukončené
|
||||
Comment[sl]=Povezava zaprta
|
||||
Comment[sq]=Lidhja u mbyll
|
||||
Comment[sr]=Веза је затворена
|
||||
Comment[sr@ijekavian]=Веза је затворена
|
||||
Comment[sr@ijekavianlatin]=Veza je zatvorena
|
||||
@@ -423,6 +454,7 @@ Comment[ta]=இணைப்புகள் மூடப்பட்டது
|
||||
Comment[tg]=Пайвастшавӣ пӯшида аст
|
||||
Comment[th]=การเชื่อมต่อยุติ
|
||||
Comment[tr]=Bağlantı kapatıldı
|
||||
Comment[ug]=باغلىنىش تاقالدى
|
||||
Comment[uk]=З'єднання закрито
|
||||
Comment[uz]=Aloqa uzildi
|
||||
Comment[uz@cyrillic]=Алоқа узилди
|
||||
@@ -437,6 +469,8 @@ Action=Popup
|
||||
Name=Invalid Password
|
||||
Name[ar]=كلمة المرور غير صحيحة
|
||||
Name[ast]=Contraseña incorreuta
|
||||
Name[bg]=Неправилна парола
|
||||
Name[bs]=Neispravna šifra
|
||||
Name[ca]=Contrasenya no vàlida
|
||||
Name[ca@valencia]=Contrasenya no vàlida
|
||||
Name[cs]=Neplatné heslo
|
||||
@@ -456,6 +490,7 @@ Name[hi]=अवैध पासवर्ड
|
||||
Name[hne]=अवैध पासवर्ड
|
||||
Name[hr]=Nevažeća zaporka
|
||||
Name[hu]=Érvénytelen jelszó
|
||||
Name[ia]=Contrasigno invalide
|
||||
Name[is]=Ógilt lykilorð
|
||||
Name[it]=Password non valida
|
||||
Name[ja]=無効なパスワード
|
||||
@@ -475,8 +510,10 @@ Name[pt]=Senha Inválida
|
||||
Name[pt_BR]=Senha inválida
|
||||
Name[ro]=Parolă nevalidă
|
||||
Name[ru]=Неверный пароль
|
||||
Name[si]=වැරදි මුරපදය
|
||||
Name[sk]=Neplatné heslo
|
||||
Name[sl]=Neveljavno geslo
|
||||
Name[sq]=Fjalëkalim i Pavlefshëm
|
||||
Name[sr]=Неисправна лозинка
|
||||
Name[sr@ijekavian]=Неисправна лозинка
|
||||
Name[sr@ijekavianlatin]=Neispravna lozinka
|
||||
@@ -484,7 +521,9 @@ Name[sr@latin]=Neispravna lozinka
|
||||
Name[sv]=Ogiltigt lösenord
|
||||
Name[th]=รหัสผ่านไม่ถูกต้อง
|
||||
Name[tr]=Geçersiz Parola
|
||||
Name[ug]=ئىناۋەتسىز ئىم
|
||||
Name[uk]=Неправильний пароль
|
||||
Name[wa]=Sicret nén valåbe
|
||||
Name[x-test]=xxInvalid Passwordxx
|
||||
Name[zh_CN]=无效密码
|
||||
Name[zh_TW]=不正確的密碼
|
||||
@@ -492,8 +531,10 @@ Comment=Invalid password
|
||||
Comment[af]=Ongeldige wagwoord
|
||||
Comment[ar]=كلمة المرور غير صحيحة
|
||||
Comment[ast]=Contraseña incorreuta
|
||||
Comment[bg]=Неправилна парола
|
||||
Comment[bn]=অবৈধ পাসওয়ার্ড
|
||||
Comment[br]=Tremenger siek
|
||||
Comment[bs]=Neispravna šifra
|
||||
Comment[ca]=Contrasenya no vàlida
|
||||
Comment[ca@valencia]=Contrasenya no vàlida
|
||||
Comment[cs]=Neplatné heslo
|
||||
@@ -515,6 +556,7 @@ Comment[hi]=अवैध पासवर्ड
|
||||
Comment[hne]=अवैध पासवर्ड
|
||||
Comment[hr]=Nevažeća šifra
|
||||
Comment[hu]=Érvénytelen jelszó
|
||||
Comment[ia]=Contrasigno invalide
|
||||
Comment[is]=Lykilorð ógilt
|
||||
Comment[it]=Password non valida
|
||||
Comment[ja]=無効なパスワード
|
||||
@@ -538,8 +580,10 @@ Comment[pt]=A senha é inválida
|
||||
Comment[pt_BR]=Senha inválida
|
||||
Comment[ro]=Parolă nevalidă
|
||||
Comment[ru]=Неверный пароль
|
||||
Comment[si]=වැරදි මුරපදය
|
||||
Comment[sk]=Neplatné heslo
|
||||
Comment[sl]=Neveljavno geslo
|
||||
Comment[sq]=Fjalëkalim i pavlefshëm
|
||||
Comment[sr]=Неисправна лозинка
|
||||
Comment[sr@ijekavian]=Неисправна лозинка
|
||||
Comment[sr@ijekavianlatin]=Neispravna lozinka
|
||||
@@ -549,6 +593,7 @@ Comment[ta]=செல்லாத கடவுச்சொல்
|
||||
Comment[tg]=Гузарвожаи нодуруст
|
||||
Comment[th]=รหัสผ่านไม่ถูกต้อง
|
||||
Comment[tr]=Geçersiz parola
|
||||
Comment[ug]=ئىناۋەتسىز ئىم
|
||||
Comment[uk]=Неправильний пароль
|
||||
Comment[uz]=Maxfiy soʻz haqiqiy emas
|
||||
Comment[uz@cyrillic]=Махфий сўз ҳақиқий эмас
|
||||
@@ -564,6 +609,8 @@ Action=Popup
|
||||
Name=Invalid Password Invitations
|
||||
Name[ar]=كلمة المرور الدعوات غير صحيحة
|
||||
Name[ast]=Contraseñas d'invitaciones incorreutes
|
||||
Name[bg]=Неправилна парола за покана
|
||||
Name[bs]=Neispravna šifra pozivnice
|
||||
Name[ca]=Contrasenya de les invitacions no vàlides
|
||||
Name[ca@valencia]=Contrasenya de les invitacions no vàlides
|
||||
Name[cs]=Neplatné hesla výzev
|
||||
@@ -574,7 +621,7 @@ Name[en_GB]=Invalid Password Invitations
|
||||
Name[eo]=Nevalidaj pasvortaj invitoj
|
||||
Name[es]=Contraseñas de invitaciones incorrectas
|
||||
Name[et]=Kutsutu vale parool
|
||||
Name[eu]=Baliogabeko pasahitz gonbidapena
|
||||
Name[eu]=Gonbitearen pasahitza baliogabea
|
||||
Name[fi]=Virheellinen salasana kutsuun
|
||||
Name[fr]=Invitations de mot de passe non valables
|
||||
Name[ga]=Cuirí Neamhbhailí Focal Faire
|
||||
@@ -583,12 +630,13 @@ Name[hi]=अवैध पासवर्ड निमंत्रण
|
||||
Name[hne]=अवैध पासवर्ड निमंत्रन
|
||||
Name[hr]=Pozivnice s nevažećim zaporkama
|
||||
Name[hu]=Érvénytelen jelszavas meghívó
|
||||
Name[ia]=Invitationes de contrasigno invalide
|
||||
Name[is]=Ógild lykilorðsboð
|
||||
Name[it]=Password di invito non valida
|
||||
Name[ja]=招待に対する無効なパスワード
|
||||
Name[kk]=Жарамсыз паролімен шақыру
|
||||
Name[km]=ការអញ្ជើញពាក្យសម្ងាត់មិនត្រឹមត្រូវ
|
||||
Name[ko]=잘못된 비밀번호 초대장
|
||||
Name[ko]=잘못된 암호 초대장
|
||||
Name[lt]=Neteisingas kvietimo slaptažodis
|
||||
Name[lv]=Nepareiza parole ar ielūgumu
|
||||
Name[ml]=അസാധുവായ അടയാളവാക്ക് ക്ഷണങ്ങള്
|
||||
@@ -602,6 +650,7 @@ Name[pt]=Convites de Senha Inválidos
|
||||
Name[pt_BR]=Avisos de senha inválida
|
||||
Name[ro]=Parolă nevalidă Invitații
|
||||
Name[ru]=Неверный пароль приглашения
|
||||
Name[si]=වැරදි මුරපද ආරාධනාවක්
|
||||
Name[sk]=Neplatné heslo pozvánky
|
||||
Name[sl]=Povabila z neveljavnimi gesli
|
||||
Name[sr]=Неисправна лозинка позивнице
|
||||
@@ -619,7 +668,9 @@ Comment=The invited party sent an invalid password. Connection refused.
|
||||
Comment[af]=Die uitgenooi party gestuur 'n ongeldige wagwoord. Verbinding geweier.
|
||||
Comment[ar]=المدعو أرسل كلمة مرور غير صحيحة. رفض الإتصال.
|
||||
Comment[ast]=L'invitáu unvió una contraseña incorreuta. Conexón refugada.
|
||||
Comment[bg]=Поканената страна изпрати неправилна парола. Връзката е отказана.
|
||||
Comment[bn]=আমন্ত্রিত দল একটি অবৈধ পাসওয়ার্ড পাঠাল। সংযোগ অস্বীকার করা হল।
|
||||
Comment[bs]=Pozvana strana je poslala pogrešnu šifru. Veza je odbijena.
|
||||
Comment[ca]=La part invitada ha enviat una contrasenya no vàlida. Connexió refusada.
|
||||
Comment[ca@valencia]=La part invitada ha enviat una contrasenya no vàlida. Connexió refusada.
|
||||
Comment[cs]=Pozvaná strana poslala neplatné heslo. Spojení odmítnuto.
|
||||
@@ -631,7 +682,7 @@ Comment[en_GB]=The invited party sent an invalid password. Connection refused.
|
||||
Comment[eo]=La invitita kliento sendis nevalidan pasvorton. Konekto rifuzita.
|
||||
Comment[es]=El invitado envió una contraseña incorrecta. Conexión rechazada.
|
||||
Comment[et]=Kutsutu saatis vigase parooli. Ühendusest keelduti.
|
||||
Comment[eu]=Gonbidatutako parekoak baliogabeko pasahitza bidali du. Konexioa ukatu da.
|
||||
Comment[eu]=Gonbidatutako parekoak baliogabeko pasahitza bidali du. Konexioa ukatuta.
|
||||
Comment[fi]=Kutsuttu taho lähetti virheellisen salasanan. Yhteys hylättiin.
|
||||
Comment[fr]=La partie invitée a envoyé un mot de passe non valable. Connexion refusée.
|
||||
Comment[ga]=Sheol an duine le cuireadh focal faire neamhbhailí. Diúltaíodh an ceangal.
|
||||
@@ -641,12 +692,13 @@ Comment[hi]=निमंत्रित पार्टी ने अवैध
|
||||
Comment[hne]=निमंत्रित पार्टी हर अवैध पासवर्ड भेजिस. कनेक्सन अस्वीकृत.
|
||||
Comment[hr]=Stranka koju ste pozvali je poslala nevažeću šifru. Veza odbijena.
|
||||
Comment[hu]=A meghívott fél érvénytelen jelszót küldött. A csatlakozási kérés elutasítva.
|
||||
Comment[ia]=Le partita invitate inviava un contrasigno invalide. Connexion refusate.
|
||||
Comment[is]=Boðinn aðili sendi ógilt lykilorð. Tengingu hafnað
|
||||
Comment[it]=La parte invitata ha inviato una password non valida. Connessione rifiutata.
|
||||
Comment[ja]=招待された人が無効なパスワードを送ってきました。接続を拒否しました。
|
||||
Comment[kk]=Шқырылған жақ дұрыс емес парольді жіберді. Қосылымдан бас тартылды..
|
||||
Comment[km]=ភាគីដែលបានអញ្ជើញ បានផ្ញើពាក្យសម្ងាត់មិនត្រឹមត្រូវ ។ ការតភ្ជាប់ត្រូវបានបដិសេធ ។
|
||||
Comment[ko]=초대한 사람이 잘못된 비밀번호를 보냈습니다. 연결이 잘못되었습니다.
|
||||
Comment[ko]=초대한 사람이 잘못된 암호를 보냈습니다. 연결이 잘못되었습니다.
|
||||
Comment[lt]=Pakviestoji pusė atsiuntė neteisingą slaptažodį. Ryšys nutrauktas.
|
||||
Comment[lv]=Ielūgtā persona nosūtīja nepareizu paroli. Savienojums noraidīts.
|
||||
Comment[mk]=Поканетата страна испрати невалидна лозинка. Поврзувањето е одбиено.
|
||||
@@ -660,8 +712,9 @@ Comment[pl]=Z drugiej strony podano błędne hasło. Połączenie odrzucone.
|
||||
Comment[pt]=O utilizador convidado enviou uma senha inválida. A ligação foi recusada.
|
||||
Comment[pt_BR]=A parte "convidada" enviou uma senha inválida. Conexão recusada.
|
||||
Comment[ro]=Partea care invită a trimis o parolă nevalidă. Conexiune refuzată.
|
||||
Comment[ru]=Приглашенный пользователь ввёл неверный пароль. Соединение отклонено.
|
||||
Comment[sk]=Pozvaná strana poslala neplatné heslo. Pripojenie odmietnuté.
|
||||
Comment[ru]=Приглашённый пользователь ввёл неправильный пароль. Соединение отклонено.
|
||||
Comment[si]=ආරාධිත පාර්ශවය වැරදි මුරපදයක් එවන ලද බැවින් සබඳතාව ප්රතික්ෂේප විය.
|
||||
Comment[sk]=Pozvaná strana poslala neplatné heslo. Pripojenie bolo odmietnuté.
|
||||
Comment[sl]=Povabljena stranka je poslala neveljavno geslo. Povezava zavrnjena.
|
||||
Comment[sr]=Позвана страна је послала погрешну лозинку. Веза је одбијена.
|
||||
Comment[sr@ijekavian]=Позвана страна је послала погрешну лозинку. Веза је одбијена.
|
||||
@@ -671,7 +724,7 @@ Comment[sv]=Den inbjudna personen skickade ett ogiltigt lösenord. Anslutning v
|
||||
Comment[ta]=அழைத்த நபர் தவறான கடவுச்சொல்லை அனுப்பியுள்ளார். இணைப்பு நிராகரிக்கப்பட்டது.
|
||||
Comment[tg]=Корванди дурдаст гузарвожаи нодурустро фиристод. Пайвастшавӣ манъ шудааст.
|
||||
Comment[th]=ผู้เข้าร่วมการเชิญชวนส่งรหัสผ่านมาไม่ถูกต้อง ทำการปฏิเสธการเชื่อมต่อ
|
||||
Comment[tr]=Davet edilenden gönderilmiş geçersiz parola. Bağlantı rededildi.
|
||||
Comment[tr]=Davet edilenden gönderilmiş geçersiz parola. Bağlantı reddedildi.
|
||||
Comment[uk]=Запрошений учасник надіслав некоректний пароль. У з’єднанні відмовлено.
|
||||
Comment[xh]=Umhlangano omenyiweyo uthumele igama lokugqitha elisebenzayo. Uxhulumano lwa liwe.
|
||||
Comment[x-test]=xxThe invited party sent an invalid password. Connection refused.xx
|
||||
@@ -684,6 +737,8 @@ Action=Popup
|
||||
Name=New Connection on Hold
|
||||
Name[ar]=اتصال جديد على التوقف
|
||||
Name[ast]=Conexón nueva a la espera
|
||||
Name[bg]=Изчакване на новата връзка
|
||||
Name[bs]=Nova veza je na čekanju
|
||||
Name[ca]=Nova connexió en espera
|
||||
Name[ca@valencia]=Nova connexió en espera
|
||||
Name[cs]=Nové spojení pozdrženo
|
||||
@@ -703,9 +758,10 @@ Name[hi]=नया कनेक्शन होल्ड पर रखा
|
||||
Name[hne]=नवा कनेक्सन होल्ड मं रखा
|
||||
Name[hr]=Nova veza na čekanju
|
||||
Name[hu]=Új kapcsolat tartva
|
||||
Name[ia]=Nove connexion in pausa
|
||||
Name[is]=Ný tenging á bið
|
||||
Name[it]=Nuova connessione in attesa
|
||||
Name[ja]=保留中の新規接続
|
||||
Name[ja]=保留中の新しい接続
|
||||
Name[kk]=Жаңа қосылым күтілуде
|
||||
Name[km]=ការតភ្ជាប់ថ្មី កំពុងស្ថិតនៅក្នុងការរង់ចាំ
|
||||
Name[ko]=새 연결 대기 중
|
||||
@@ -722,7 +778,8 @@ Name[pt]=Ligação Nova em Espera
|
||||
Name[pt_BR]=Nova conexão ativa
|
||||
Name[ro]=Conexiune nouă în așteptare
|
||||
Name[ru]=Новое соединение приостановлено
|
||||
Name[sk]=Nové pripojenie pozdržané
|
||||
Name[si]=නව සබඳතාවක් රඳවා ඇත
|
||||
Name[sk]=Nové pripojenie bolo pozdržané
|
||||
Name[sl]=Nova povezava na čakanju
|
||||
Name[sr]=Нова веза је на чекању
|
||||
Name[sr@ijekavian]=Нова веза је на чекању
|
||||
@@ -739,7 +796,9 @@ Comment=Connection requested, user must accept
|
||||
Comment[af]=Verbinding versoekte, gebruiker moet aanvaar
|
||||
Comment[ar]=الاتصال طلب، يجب موافقة المستخدم
|
||||
Comment[ast]=Conexón solicitada, l'usuario tien d'aceutala
|
||||
Comment[bg]=Поискана е връзка, следва потребителят да приеме
|
||||
Comment[bn]=সংযোগ অনুরোধ করা হল, ব্যবহারকারীকে অবশ্যই স্বীকার করতে হবে
|
||||
Comment[bs]=Veza je zahtijevana, korinik mora da je prihvati
|
||||
Comment[ca]=Connexió sol·licitada, l'usuari ha d'acceptar-la
|
||||
Comment[ca@valencia]=Connexió sol·licitada, l'usuari ha d'acceptar-la
|
||||
Comment[cs]=Vyžadováno spojení, uživatel musí přijmout
|
||||
@@ -751,7 +810,7 @@ Comment[en_GB]=Connection requested, user must accept
|
||||
Comment[eo]=Konekto pridemandita, la uzanto devas akcepti
|
||||
Comment[es]=Conexión solicitada, el usuario debe aceptarla
|
||||
Comment[et]=Nõutakse ühendust, kasutaja peab seda lubama
|
||||
Comment[eu]=Konexioa eskatu da, erabiltzaileak onartu behar du
|
||||
Comment[eu]=Konexioa eskatuta, erabiltzaileak onartu behar du
|
||||
Comment[fi]=Pyydettiin yhteyttä, käyttäjän tulee hyväksyä
|
||||
Comment[fr]=Connexion demandée, l'utilisateur doit accepter
|
||||
Comment[ga]=Ceangal iarrtha; ní mór don úsáideoir glacadh leis
|
||||
@@ -761,6 +820,7 @@ Comment[hi]=कनेक्शन निवेदित. उपयोक्त
|
||||
Comment[hne]=कनेक्सन निवेदित. कमइया ल स्वीकार होना चाही
|
||||
Comment[hr]=Veza je zatražena, korisnik mora prihvatiti
|
||||
Comment[hu]=Csatlakozási kérés, a felhasználónak el kell fogadnia
|
||||
Comment[ia]=Connexion requirite, usator debe dar acceptation
|
||||
Comment[is]=Beiðni um tengingu, notandi verður að samþykkja
|
||||
Comment[it]=Connessione richiesta, l'utente deve accettare
|
||||
Comment[ja]=接続が要求されています。ユーザが許可しなければなりません。
|
||||
@@ -782,7 +842,8 @@ Comment[pt]=Foi pedida uma ligação que o utilizador deverá aceitar
|
||||
Comment[pt_BR]=Conexão requisitada; o usuário deve aceitar
|
||||
Comment[ro]=Conexiune cerută, utilizatorul trebuie să accepte
|
||||
Comment[ru]=Запрос на соединение, требуется подтверждение пользователя
|
||||
Comment[sk]=Vyžiadané pripojenie, užívateľ musí akceptovať
|
||||
Comment[si]=සබඳතාව ඉල්ලා ඇත, පරිශීලක තහවුරු කල යුතුයි
|
||||
Comment[sk]=Vyžiadané pripojenie, užívateľ ho musí akceptovať
|
||||
Comment[sl]=Povezava zahtevana, uporabnik mora sprejeti
|
||||
Comment[sr]=Захтевана је веза, корисник мора да је прихвати
|
||||
Comment[sr@ijekavian]=Захтијевана је веза, корисник мора да је прихвати
|
||||
@@ -805,6 +866,8 @@ Action=Popup
|
||||
Name=New Connection Auto Accepted
|
||||
Name[ar]=اتصال جديد مقبول تلقائيا
|
||||
Name[ast]=Conexón nueva aceutada automáticamente
|
||||
Name[bg]=Автоматично приемане на новата връзка
|
||||
Name[bs]=Nova veza je automatski prihvaćena
|
||||
Name[ca]=Nova connexió acceptada automàticament
|
||||
Name[ca@valencia]=Nova connexió acceptada automàticament
|
||||
Name[cs]=Nové spojení automaticky přijato
|
||||
@@ -815,7 +878,7 @@ Name[en_GB]=New Connection Auto Accepted
|
||||
Name[eo]=Nova konekto aŭtomate akceptita
|
||||
Name[es]=Conexión nueva aceptada automáticamente
|
||||
Name[et]=Uue ühendusega automaatselt nõus
|
||||
Name[eu]=Konexio berria auto-onartu da
|
||||
Name[eu]=Konexio berria automatikoki onartuta
|
||||
Name[fi]=Uusi yhteys hyväksyttiin automaattisesti
|
||||
Name[fr]=Nouvelle connexion auto-acceptée
|
||||
Name[ga]=Ceangal nua bunaithe go huathoibríoch
|
||||
@@ -824,9 +887,10 @@ Name[hi]=नय कनेक्शन स्वचालित स्वीक
|
||||
Name[hne]=नय कनेक्सन अपने अपन स्वीकारा
|
||||
Name[hr]=Nova veza automatski prihvaćena
|
||||
Name[hu]=Új kapcsolat automatikusan engedélyezve
|
||||
Name[ia]=Nove connexion con acceptation automatic
|
||||
Name[is]=Ný tenging sjálfvirkt samþykkt
|
||||
Name[it]=Nuova connessione accettata automaticamente
|
||||
Name[ja]=新規接続の自動受け入れ
|
||||
Name[ja]=新しい接続の自動受け入れ
|
||||
Name[kk]=Жаңа қосылым автоқабылданды
|
||||
Name[km]=បានទទួលយកការតភ្ជាប់ថ្មីដោយស្វ័យប្រវត្តិ
|
||||
Name[ko]=새 연결 자동 수락
|
||||
@@ -843,7 +907,8 @@ Name[pt]=Nova Ligação Aceite Automaticamente
|
||||
Name[pt_BR]=Nova conexão com aceitação automática
|
||||
Name[ro]=Conexiune nouă acceptată automat
|
||||
Name[ru]=Новое соединение принимается автоматически
|
||||
Name[sk]=Nové pripojenie automaticky akceptované
|
||||
Name[si]=නව සබඳතාව ස්වයංක්රීයව පිළිගැණිනි
|
||||
Name[sk]=Nové pripojenie bolo automaticky akceptované
|
||||
Name[sl]=Nova povezava samodejno sprejeta
|
||||
Name[sr]=Нова веза је аутоматски прихваћена
|
||||
Name[sr@ijekavian]=Нова веза је аутоматски прихваћена
|
||||
@@ -860,7 +925,9 @@ Comment=New connection automatically established
|
||||
Comment[af]=Nuwe verbinding automaties vasgestel
|
||||
Comment[ar]=اتصال جديد مفعل تلقائيا
|
||||
Comment[ast]=Conexón nueva afitada automáticamente
|
||||
Comment[bg]=Новата връзка е автоматично приета
|
||||
Comment[bn]=নতুন সংযোগ স্বয়ংক্রীয়ভাবে স্থাপন করা হল
|
||||
Comment[bs]=Nova veza je automatski uspostavljena
|
||||
Comment[ca]=Nova connexió establerta automàticament
|
||||
Comment[ca@valencia]=Nova connexió establerta automàticament
|
||||
Comment[cs]=Automaticky navázáno nové spojení
|
||||
@@ -872,7 +939,7 @@ Comment[en_GB]=New connection automatically established
|
||||
Comment[eo]=Nova konekto aŭtomate establita
|
||||
Comment[es]=Conexión nueva establecida automáticamente
|
||||
Comment[et]=Uus ühendus automaatselt loodud
|
||||
Comment[eu]=Konexio berria automatikoki ezarri da
|
||||
Comment[eu]=Konexio berria automatikoki ezarrita
|
||||
Comment[fi]=Uusi yhteys muodostettiin automaattisesti
|
||||
Comment[fr]=Nouvelle connexion établie automatiquement
|
||||
Comment[ga]=Ceangal nua bunaithe go huathoibríoch
|
||||
@@ -882,9 +949,10 @@ Comment[hi]=नया कनेक्शन स्वचलित स्था
|
||||
Comment[hne]=नवा कनेक्सन अपने अपन स्थापित
|
||||
Comment[hr]=Nova veza automatski prihvaćena
|
||||
Comment[hu]=Automatikusan létrejött egy új kapcsolat
|
||||
Comment[ia]=Nove connexion establite automaticamente
|
||||
Comment[is]=Nýjar tengingar sjálfkrafa samþykktar
|
||||
Comment[it]=Nuova connessione stabilita automaticamente
|
||||
Comment[ja]=新規接続を自動的に確立しました
|
||||
Comment[ja]=新しい接続を自動的に確立しました
|
||||
Comment[kk]=Жаңа қосылым автоматты түрде орнатылды
|
||||
Comment[km]=បានបង្កើតការតភ្ជាប់ថ្មីដោយស្វ័យប្រវត្តិ
|
||||
Comment[ko]=새 연결이 자동으로 성립됨
|
||||
@@ -903,7 +971,8 @@ Comment[pt]=Foi estabelecida automaticamente uma nova ligação
|
||||
Comment[pt_BR]=Nova conexão estabelecida automaticamente
|
||||
Comment[ro]=Conexiune nouă stabilită automat
|
||||
Comment[ru]=Новое соединение устанавливается автоматически
|
||||
Comment[sk]=Nové pripojenie automaticky vytvorené
|
||||
Comment[si]=නව සබඳතාව ස්වයංක්රීයව සැකසිනි
|
||||
Comment[sk]=Nové pripojenie bolo automaticky nadviazané
|
||||
Comment[sl]=Nova povezava samodejno vzpostavljena
|
||||
Comment[sr]=Нова веза је аутоматски успостављена
|
||||
Comment[sr@ijekavian]=Нова веза је аутоматски успостављена
|
||||
@@ -926,6 +995,8 @@ Action=Popup
|
||||
Name=Too Many Connections
|
||||
Name[ar]=اتصالات عديدة
|
||||
Name[ast]=Abondes conexones
|
||||
Name[bg]=Твърде много връзки
|
||||
Name[bs]=Previše veza
|
||||
Name[ca]=Massa connexions
|
||||
Name[ca@valencia]=Massa connexions
|
||||
Name[cs]=Příliš mnoho spojení
|
||||
@@ -945,6 +1016,7 @@ Name[hi]=बहुत सारे कनेक्शन
|
||||
Name[hne]=बहुत अकन कनेक्सन
|
||||
Name[hr]=Previše veza
|
||||
Name[hu]=Túl sok kapcsolat
|
||||
Name[ia]=Nimie connexiones
|
||||
Name[is]=Of margar tengingar
|
||||
Name[it]=Troppe connessioni
|
||||
Name[ja]=多すぎる接続
|
||||
@@ -964,6 +1036,7 @@ Name[pt]=Demasiadas Ligações
|
||||
Name[pt_BR]=Conexões em excesso
|
||||
Name[ro]=Prea multe conexiuni
|
||||
Name[ru]=Слишком много соединений
|
||||
Name[si]=වඩා වැඩි සබඳතා ගණනක්
|
||||
Name[sk]=Príliš veľa pripojení
|
||||
Name[sl]=Preveč povezav
|
||||
Name[sr]=Исувише веза
|
||||
@@ -981,9 +1054,11 @@ Comment=Busy, connection refused
|
||||
Comment[af]=Besig, verbinding geweier
|
||||
Comment[ar]=مشغول، الإتصال رفض
|
||||
Comment[ast]=Ocupáu, conexón refugada
|
||||
Comment[bg]=Заето. Връзката е отказана.
|
||||
Comment[bn]=ব্যস্ত, সংযোগ অস্বীকার করল
|
||||
Comment[br]=Dalc'het, kevreadenn disteuleret
|
||||
Comment[ca]=Ocupat, connexió refusada
|
||||
Comment[bs]=Zauzeto, veza je odbijena
|
||||
Comment[ca]=Ocupat, connexió rebutjada
|
||||
Comment[ca@valencia]=Ocupat, connexió refusada
|
||||
Comment[cs]=Zaneprázdněn, spojení odmítnuto
|
||||
Comment[cy]=Prysur, gwrthodwyd y cysylltiad
|
||||
@@ -1004,6 +1079,7 @@ Comment[hi]=व्यस्त, कनेक्शन अस्वीकृत
|
||||
Comment[hne]=व्यस्त, कनेक्सन अस्वीकृत
|
||||
Comment[hr]=Zauzeto, veza odbijena
|
||||
Comment[hu]=A csatlakozási kérés elutasítva túlterhelés miatt
|
||||
Comment[ia]=Occupate, connexion refusate
|
||||
Comment[is]=Uptekinn, tengingu hafnað
|
||||
Comment[it]=Occupato, connessione rifiutata
|
||||
Comment[ja]=ビジーです、接続を拒否しました
|
||||
@@ -1025,7 +1101,8 @@ Comment[pt]=Ocupado, pelo a ligação foi recusada
|
||||
Comment[pt_BR]=Ocupado; conexão recusada
|
||||
Comment[ro]=Ocupat, conexiune refuzată
|
||||
Comment[ru]=Занят, соединение отклонено
|
||||
Comment[sk]=Zaneprázdnený, pripojenie odmietnuté
|
||||
Comment[si]=කාර්යබහුලයි, සබඳතාව නොපිළිගැණිනි
|
||||
Comment[sk]=Zaneprázdnený, pripojenie bolo odmietnuté
|
||||
Comment[sl]=Zaposlen, povezava zavrnjena
|
||||
Comment[sr]=Заузето, веза је одбијена
|
||||
Comment[sr@ijekavian]=Заузето, веза је одбијена
|
||||
@@ -1035,7 +1112,7 @@ Comment[sv]=Upptagen, anslutning vägras
|
||||
Comment[ta]=வேலையில் உள்ளது, இணைப்பு நிராகரிக்கப்பட்டது
|
||||
Comment[tg]=Банд, пайвастшавӣ рад гардидааст
|
||||
Comment[th]=ยังไม่ว่าง ทำการปฏิเสธการเชื่อมต่อ
|
||||
Comment[tr]=Meşgul, bağlantı rededildi
|
||||
Comment[tr]=Meşgul, bağlantı reddedildi
|
||||
Comment[uk]=Зайнято, у з’єднанні відмовлено
|
||||
Comment[uz]=Band, aloqa rad etildi
|
||||
Comment[uz@cyrillic]=Банд, алоқа рад этилди
|
||||
@@ -1050,6 +1127,8 @@ Action=Popup
|
||||
Name=Unexpected Connection
|
||||
Name[ar]=الاتصال غير متوقّع
|
||||
Name[ast]=Conexón inesperada
|
||||
Name[bg]=Неочаквана връзка
|
||||
Name[bs]=Neočekivana veza
|
||||
Name[ca]=Connexió inesperada
|
||||
Name[ca@valencia]=Connexió inesperada
|
||||
Name[cs]=Neočekávané spojení
|
||||
@@ -1069,6 +1148,7 @@ Name[hi]=अप्रत्याशित कनेक्शन
|
||||
Name[hne]=अप्रत्यासित कनेक्सन
|
||||
Name[hr]=Neočekivana veza
|
||||
Name[hu]=Nem várt kapcsolat
|
||||
Name[ia]=Connexion impreviste
|
||||
Name[is]=Óvænt Tenging
|
||||
Name[it]=Connessione inattesa
|
||||
Name[ja]=予期しない接続
|
||||
@@ -1088,8 +1168,10 @@ Name[pt]=Ligação Inesperada
|
||||
Name[pt_BR]=Conexão inesperada
|
||||
Name[ro]=Conexiune neașteptată
|
||||
Name[ru]=Неожиданное соединение
|
||||
Name[si]=බලාපොරොත්තු රහිත සබඳතාවක්
|
||||
Name[sk]=Neočakávané pripojenie
|
||||
Name[sl]=Nepričakovana povezava
|
||||
Name[sq]=Lidhje e Papritur
|
||||
Name[sr]=Неочекивана веза
|
||||
Name[sr@ijekavian]=Неочекивана веза
|
||||
Name[sr@ijekavianlatin]=Neočekivana veza
|
||||
@@ -1097,6 +1179,7 @@ Name[sr@latin]=Neočekivana veza
|
||||
Name[sv]=Oväntad anslutning
|
||||
Name[th]=เกิดการเชื่อมต่อที่ไม่คาดคิด
|
||||
Name[tr]=Beklenmeyen Bağlantı
|
||||
Name[ug]=كۈتۈلمىگەن باغلىنىش
|
||||
Name[uk]=Неочікуване з’єднання
|
||||
Name[x-test]=xxUnexpected Connectionxx
|
||||
Name[zh_CN]=未预料的连接
|
||||
@@ -1105,7 +1188,9 @@ Comment=Received unexpected connection, abort
|
||||
Comment[af]=Ontvang onverwagte verbinding, staak
|
||||
Comment[ar]=استقبال اتصال غير متوقع، إنهاء
|
||||
Comment[ast]=Recibióse conexón inesperada, albortando
|
||||
Comment[bg]=Получена е неочаквана връзка. Прекъсване.
|
||||
Comment[bn]=অপ্রত্যাশিত সংযোগ গ্রহণ করল, বাতিল করুন
|
||||
Comment[bs]=Primljena je neočekivana veza, prekini
|
||||
Comment[ca]=Rebuda una connexió inesperada, avortant
|
||||
Comment[ca@valencia]=Rebuda una connexió inesperada, avortant
|
||||
Comment[cs]=Obdrženo neočekávané spojení, přerušeno
|
||||
@@ -1117,7 +1202,7 @@ Comment[en_GB]=Received unexpected connection, abort
|
||||
Comment[eo]=Ricevis neatenditan konekton, ĉesi
|
||||
Comment[es]=Recibida conexión inesperada, interrumpir
|
||||
Comment[et]=Saadi ootamatu ühendus, loobuti
|
||||
Comment[eu]=Ustegabeko konexioa jaso da, abortatzen
|
||||
Comment[eu]=Ustekabeko konexioa jaso da, abortatzen
|
||||
Comment[fi]=Vastaanotettiin odottamaton yhteys, lopeta
|
||||
Comment[fr]=Reçu une connexion inattendue, interruption
|
||||
Comment[ga]=Fuarthas ceangal gan choinne, á thobscor
|
||||
@@ -1127,6 +1212,7 @@ Comment[hi]=अप्रत्याशित कनेक्शन प्रा
|
||||
Comment[hne]=अप्रत्यासित कनेक्सन प्राप्त. छोड़ा
|
||||
Comment[hr]=Primio sam neočekivanu vezu, prekid
|
||||
Comment[hu]=Nem várt csatlakozási kérés érkezett, megszakítás
|
||||
Comment[ia]=On recipeva connexion impreviste, aborta
|
||||
Comment[is]=Tók á móti óvæntri tengingu, hætti
|
||||
Comment[it]=Ricevuta connessione inattesa, terminata
|
||||
Comment[ja]=予期しない接続を受信しました。廃棄します。
|
||||
@@ -1147,6 +1233,7 @@ Comment[pt]=Foi recebida uma ligação inesperada, pelo que foi interrompida
|
||||
Comment[pt_BR]=Conexão recebida inesperadamente; abortar
|
||||
Comment[ro]=Conexiune neașteptată recepționată, abandonare
|
||||
Comment[ru]=Получено неожиданное соединение. Отключение
|
||||
Comment[si]=බලාපොරොත්තු රහිත සබඳතාවක් ලැබිනි, පිටවෙමින්
|
||||
Comment[sk]=Prijaté neočakávané pripojenie, prerušené
|
||||
Comment[sl]=Prejeta nepričakovana povezava, prekinjeno
|
||||
Comment[sr]=Примљена је неочекивана веза, прекидам
|
||||
@@ -1157,7 +1244,7 @@ Comment[sv]=Tog emot oväntad anslutning, avbryter
|
||||
Comment[ta]=எதிர்பாராத இணைப்பு, நிறுத்தப்பட்டது
|
||||
Comment[tg]=Пайвастшавии ғайричашмдош қабул гардид, кандашавӣ
|
||||
Comment[th]=ได้รับการเชื่อมต่อมาอย่างไม่คาดคิด ทำการยกเลิก
|
||||
Comment[tr]=Babul edilmiş beklenmedik bağlantı, durdur
|
||||
Comment[tr]=Beklenmeyen bir bağlantı alındı, vazgeçiliyor
|
||||
Comment[uk]=Отримано з’єднання, яке не очікувалось, припиняється
|
||||
Comment[xh]=Ufumene uxhulumaniso olungalindelekanga, lahla
|
||||
Comment[x-test]=xxReceived unexpected connection, abortxx
|
||||
7
krfb/krfb_rfb_handler.client
Normal file
7
krfb/krfb_rfb_handler.client
Normal file
@@ -0,0 +1,7 @@
|
||||
[org.freedesktop.Telepathy.Client]
|
||||
Interfaces=org.freedesktop.Telepathy.Client.Handler;
|
||||
|
||||
[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 0]
|
||||
org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.StreamTube
|
||||
org.freedesktop.Telepathy.Channel.Type.StreamTube.Service s=rfb
|
||||
org.freedesktop.Telepathy.Channel.Requested b=true
|
||||
130
krfb/main.cpp
Normal file
130
krfb/main.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/***************************************************************************
|
||||
main.cpp
|
||||
-------------------
|
||||
begin : Sat Dec 8 03:23:02 CET 2001
|
||||
copyright : (C) 2001-2003 by Tim Jansen
|
||||
email : tim@tjansen.de
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "manageinvitationsdialog.h"
|
||||
#include "trayicon.h"
|
||||
#include "invitationsrfbserver.h"
|
||||
|
||||
#include <KAboutApplicationDialog>
|
||||
#include <KAboutData>
|
||||
#include <KAction>
|
||||
#include <KApplication>
|
||||
#include <KCmdLineArgs>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <KMessageBox>
|
||||
#include <KNotification>
|
||||
|
||||
#include <QtGui/QPixmap>
|
||||
#include <QtGui/qwindowdefs.h>
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
# include "tubesclienthandler.h"
|
||||
# include <TelepathyQt4/ClientRegistrar>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
static const char description[] = I18N_NOOP("VNC-compatible server to share "
|
||||
"KDE desktops");
|
||||
|
||||
static bool checkX11Capabilities()
|
||||
{
|
||||
int bp1, bp2, majorv, minorv;
|
||||
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
|
||||
&majorv, &minorv);
|
||||
|
||||
if ((!r) || (((majorv * 1000) + minorv) < 2002)) {
|
||||
KMessageBox::error(0,
|
||||
i18n("Your X11 Server does not support the required XTest extension "
|
||||
"version 2.2. Sharing your desktop is not possible."),
|
||||
i18n("Desktop Sharing Error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
KAboutData aboutData("krfb", 0, ki18n("Desktop Sharing"), KDE_VERSION_STRING,
|
||||
ki18n(description), KAboutData::License_GPL,
|
||||
ki18n("(c) 2009-2010, Collabora Ltd.\n"
|
||||
"(c) 2007, Alessandro Praduroux\n"
|
||||
"(c) 2001-2003, Tim Jansen\n"
|
||||
"(c) 2001, Johannes E. Schindelin\n"
|
||||
"(c) 2000-2001, Const Kaplinsky\n"
|
||||
"(c) 2000, Tridia Corporation\n"
|
||||
"(c) 1999, AT&T Laboratories Boston\n"));
|
||||
aboutData.addAuthor(ki18n("George Goldberg"),
|
||||
ki18n("Telepathy tubes support"),
|
||||
"george.goldberg@collabora.co.uk");
|
||||
aboutData.addAuthor(ki18n("George Kiagiadakis"),
|
||||
KLocalizedString(),
|
||||
"george.kiagiadakis@collabora.co.uk");
|
||||
aboutData.addAuthor(ki18n("Alessandro Praduroux"), ki18n("KDE4 porting"), "pradu@pradu.it");
|
||||
aboutData.addAuthor(ki18n("Tim Jansen"), ki18n("Original author"), "tim@tjansen.de");
|
||||
aboutData.addCredit(ki18n("Johannes E. Schindelin"),
|
||||
ki18n("libvncserver"));
|
||||
aboutData.addCredit(ki18n("Const Kaplinsky"),
|
||||
ki18n("TightVNC encoder"));
|
||||
aboutData.addCredit(ki18n("Tridia Corporation"),
|
||||
ki18n("ZLib encoder"));
|
||||
aboutData.addCredit(ki18n("AT&T Laboratories Boston"),
|
||||
ki18n("original VNC encoders and "
|
||||
"protocol design"));
|
||||
KCmdLineArgs::init(argc, argv, &aboutData);
|
||||
|
||||
KCmdLineOptions options;
|
||||
options.add("nodialog", ki18n("Do not show the invitations management dialog at startup"));
|
||||
KCmdLineArgs::addCmdLineOptions(options);
|
||||
|
||||
KApplication app;
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
if (!checkX11Capabilities()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//init the core
|
||||
InvitationsRfbServer::init();
|
||||
|
||||
#ifdef KRFB_WITH_TELEPATHY_TUBES
|
||||
Tp::ClientRegistrarPtr clientRegistrar = Tp::ClientRegistrar::create();
|
||||
clientRegistrar->registerClient(Tp::AbstractClientPtr(new TubesClientHandler),
|
||||
"krfb_rfb_handler");
|
||||
#endif
|
||||
|
||||
//init the GUI
|
||||
ManageInvitationsDialog invitationsDialog;
|
||||
TrayIcon trayicon(&invitationsDialog);
|
||||
|
||||
if (app.isSessionRestored() && KMainWindow::canBeRestored(1)) {
|
||||
invitationsDialog.restore(1, false);
|
||||
} else if (KCmdLineArgs::parsedArgs()->isSet("dialog")) {
|
||||
invitationsDialog.show();
|
||||
}
|
||||
|
||||
sigset_t sigs;
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, SIGPIPE);
|
||||
sigprocmask(SIG_BLOCK, &sigs, 0);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
253
krfb/manageinvitationsdialog.cpp
Normal file
253
krfb/manageinvitationsdialog.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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.
|
||||
*/
|
||||
#include "manageinvitationsdialog.h"
|
||||
|
||||
#include "invitationmanager.h"
|
||||
#include "invitation.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "personalinvitedialog.h"
|
||||
#include "ui_configtcp.h"
|
||||
#include "ui_configsecurity.h"
|
||||
|
||||
#include <KConfigDialog>
|
||||
#include <KGlobal>
|
||||
#include <KIconLoader>
|
||||
#include <KLocale>
|
||||
#include <KMessageBox>
|
||||
#include <KStandardGuiItem>
|
||||
#include <KSystemTimeZone>
|
||||
#include <KToolInvocation>
|
||||
#include <KStandardAction>
|
||||
#include <KActionCollection>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QToolTip>
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
|
||||
class TCP: public QWidget, public Ui::TCP
|
||||
{
|
||||
public:
|
||||
TCP(QWidget *parent = 0) : QWidget(parent) {
|
||||
setupUi(this);
|
||||
}
|
||||
};
|
||||
|
||||
class Security: public QWidget, public Ui::Security
|
||||
{
|
||||
public:
|
||||
Security(QWidget *parent = 0) : QWidget(parent) {
|
||||
setupUi(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ManageInvitationsDialog::ManageInvitationsDialog(QWidget *parent)
|
||||
: KXmlGuiWindow(parent)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose, false);
|
||||
|
||||
QWidget *mainWidget = new QWidget;
|
||||
m_ui.setupUi(mainWidget);
|
||||
m_ui.pixmapLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
setCentralWidget(mainWidget);
|
||||
|
||||
connect(m_ui.helpLabel, SIGNAL(linkActivated(QString)), SLOT(showWhatsthis()));
|
||||
connect(m_ui.newPersonalInvitationButton, SIGNAL(clicked()), SLOT(inviteManually()));
|
||||
connect(m_ui.newEmailInvitationButton, SIGNAL(clicked()), SLOT(inviteByMail()));
|
||||
connect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)), SLOT(reloadInvitations()));
|
||||
connect(m_ui.deleteAllButton, SIGNAL(clicked()), SLOT(deleteAll()));
|
||||
connect(m_ui.deleteOneButton, SIGNAL(clicked()), SLOT(deleteCurrent()));
|
||||
connect(m_ui.invitationWidget, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged()));
|
||||
|
||||
KStandardAction::quit(QCoreApplication::instance(), SLOT(quit()), actionCollection());
|
||||
KStandardAction::preferences(this, SLOT(showConfiguration()), actionCollection());
|
||||
|
||||
setupGUI(QSize(550, 330));
|
||||
setAutoSaveSettings();
|
||||
|
||||
reloadInvitations();
|
||||
}
|
||||
|
||||
ManageInvitationsDialog::~ManageInvitationsDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::showWhatsthis()
|
||||
{
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
i18n("An invitation creates a one-time password that allows the receiver to connect to your desktop.\n"
|
||||
"It is valid for only one successful connection and will expire after an hour if it has not been used. \n"
|
||||
"When somebody connects to your computer a dialog will appear and ask you for permission.\n"
|
||||
"The connection will not be established before you accept it. In this dialog you can also\nrestrict "
|
||||
"the other person to view your desktop only, without the ability to move your\nmouse pointer or press "
|
||||
"keys.\nIf you want to create a permanent password for Desktop Sharing, allow 'Uninvited Connections' \n"
|
||||
"in the configuration."));
|
||||
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::inviteManually()
|
||||
{
|
||||
Invitation inv = InvitationManager::self()->addInvitation();
|
||||
PersonalInviteDialog *pid = new PersonalInviteDialog(this);
|
||||
pid->setPassword(inv.password());
|
||||
pid->setExpiration(inv.expirationTime());
|
||||
pid->show();
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::inviteByMail()
|
||||
{
|
||||
int r = KMessageBox::warningContinueCancel(this,
|
||||
i18n("When sending an invitation by email, note that everybody who reads this email "
|
||||
"will be able to connect to your computer for one hour, or until the first "
|
||||
"successful connection took place, whichever comes first. \n"
|
||||
"You should either encrypt the email or at least send it only in a "
|
||||
"secure network, but not over the Internet."),
|
||||
i18n("Send Invitation via Email"),
|
||||
KStandardGuiItem::cont(),
|
||||
KStandardGuiItem::cancel(),
|
||||
"showEmailInvitationWarning");
|
||||
|
||||
if (r == KMessageBox::Cancel) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QNetworkInterface> ifl = QNetworkInterface::allInterfaces();
|
||||
QString host;
|
||||
int port = KrfbConfig::port();
|
||||
foreach(const QNetworkInterface & nif, ifl) {
|
||||
if (nif.flags() & QNetworkInterface::IsLoopBack) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nif.flags() & QNetworkInterface::IsRunning) {
|
||||
if (!nif.addressEntries().isEmpty()) {
|
||||
host = nif.addressEntries()[0].ip().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Invitation inv = InvitationManager::self()->addInvitation();
|
||||
KUrl invUrl(QString("vnc://invitation:%1@%2:%3").arg(inv.password()).arg(host).arg(port));
|
||||
KToolInvocation::invokeMailer(QString(), QString(), QString(),
|
||||
i18n("Desktop Sharing (VNC) invitation"),
|
||||
ki18n("You have been invited to a VNC session. If you have the KDE Remote "
|
||||
"Desktop Connection installed, just click on the link below.\n\n"
|
||||
"%1\n\n"
|
||||
"Otherwise you can use any VNC client with the following parameters:\n\n"
|
||||
"Host: %2:%3\n"
|
||||
"Password: %4\n\n"
|
||||
"For security reasons this invitation will expire at %5 (%6).")
|
||||
.subs(invUrl.url())
|
||||
.subs(host)
|
||||
.subs(QString::number(port))
|
||||
.subs(inv.password())
|
||||
.subs(KGlobal::locale()->formatDateTime(inv.expirationTime()))
|
||||
.subs(KSystemTimeZones::local().name())
|
||||
.toString());
|
||||
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::reloadInvitations()
|
||||
{
|
||||
m_ui.invitationWidget->clear();
|
||||
KLocale *loc = KGlobal::locale();
|
||||
foreach(const Invitation & inv, InvitationManager::self()->invitations()) {
|
||||
QStringList strs;
|
||||
strs << loc->formatDateTime(inv.creationTime()) << loc->formatDateTime(inv.expirationTime());
|
||||
QTreeWidgetItem *it = new QTreeWidgetItem(strs);
|
||||
m_ui.invitationWidget->addTopLevelItem(it);
|
||||
it->setData(0, Qt::UserRole + 1, inv.creationTime());
|
||||
}
|
||||
m_ui.invitationWidget->resizeColumnToContents(0);
|
||||
m_ui.deleteAllButton->setEnabled(InvitationManager::self()->activeInvitations() > 0);
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::showConfiguration()
|
||||
{
|
||||
if (KConfigDialog::showDialog("settings")) {
|
||||
return;
|
||||
}
|
||||
|
||||
KConfigDialog *dialog = new KConfigDialog(this, "settings", KrfbConfig::self());
|
||||
dialog->addPage(new TCP, i18n("Network"), "network-workgroup");
|
||||
dialog->addPage(new Security, i18n("Security"), "security-high");
|
||||
dialog->setHelp(QString(), "krfb");
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::deleteAll()
|
||||
{
|
||||
if (KMessageBox::warningContinueCancel(this,
|
||||
i18n("<qt>Are you sure you want to delete all invitations?</qt>"),
|
||||
i18n("Confirm delete Invitations"),
|
||||
KStandardGuiItem::ok(),
|
||||
KStandardGuiItem::cancel(),
|
||||
QString("krfbdeleteallinv")) !=
|
||||
KMessageBox::Continue) {
|
||||
return;
|
||||
}
|
||||
|
||||
InvitationManager::self()->removeAllInvitations();
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::deleteCurrent()
|
||||
{
|
||||
if (KMessageBox::warningContinueCancel(this,
|
||||
i18n("<qt>Are you sure you want to delete this invitation?</qt>"),
|
||||
i18n("Confirm delete Invitations"),
|
||||
KStandardGuiItem::ok(),
|
||||
KStandardGuiItem::cancel(),
|
||||
QString("krfbdeleteoneinv")) !=
|
||||
KMessageBox::Continue) {
|
||||
return;
|
||||
}
|
||||
|
||||
// disable updates while deleting items, otherwise the list would invalidate itself
|
||||
disconnect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)),
|
||||
this, SLOT(reloadInvitations()));
|
||||
|
||||
QList<QTreeWidgetItem *> itl = m_ui.invitationWidget->selectedItems();
|
||||
foreach(QTreeWidgetItem * itm, itl) {
|
||||
foreach(const Invitation & inv, InvitationManager::self()->invitations()) {
|
||||
if (inv.creationTime() == itm->data(0, Qt::UserRole + 1)) {
|
||||
InvitationManager::self()->removeInvitation(inv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update it manually
|
||||
reloadInvitations();
|
||||
|
||||
connect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)),
|
||||
SLOT(reloadInvitations()));
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::selectionChanged()
|
||||
{
|
||||
m_ui.deleteOneButton->setEnabled(m_ui.invitationWidget->selectedItems().size() > 0);
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::readProperties(const KConfigGroup& group)
|
||||
{
|
||||
if (group.readEntry("Visible", true)) {
|
||||
show();
|
||||
}
|
||||
KMainWindow::readProperties(group);
|
||||
}
|
||||
|
||||
void ManageInvitationsDialog::saveProperties(KConfigGroup& group)
|
||||
{
|
||||
group.writeEntry("Visible", isVisible());
|
||||
KMainWindow::saveProperties(group);
|
||||
}
|
||||
|
||||
#include "manageinvitationsdialog.moc"
|
||||
|
||||
@@ -10,15 +10,16 @@
|
||||
#ifndef MANAGEINVITATIONSDIALOG_H
|
||||
#define MANAGEINVITATIONSDIALOG_H
|
||||
|
||||
#include <KDialog>
|
||||
#include "ui_manageinvitations.h"
|
||||
|
||||
#include <KXmlGuiWindow>
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class ManageInvitationsDialog : public KDialog, private Ui::ManageInvitationsDialog
|
||||
class ManageInvitationsDialog : public KXmlGuiWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
ManageInvitationsDialog(QWidget *parent = 0);
|
||||
|
||||
@@ -34,8 +35,12 @@ public Q_SLOTS:
|
||||
void deleteCurrent();
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
protected:
|
||||
virtual void readProperties(const KConfigGroup & group);
|
||||
virtual void saveProperties(KConfigGroup & group);
|
||||
|
||||
private:
|
||||
Ui::ManageInvitationsDialog m_ui;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
[D-BUS Service]
|
||||
Name=org.freedesktop.Telepathy.Client.krfb_rfb_handler
|
||||
Exec=@CMAKE_INSTALL_PREFIX@/bin/krfb --nodialog
|
||||
86
krfb/pendingrfbclient.cpp
Normal file
86
krfb/pendingrfbclient.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "pendingrfbclient.h"
|
||||
#include "connectiondialog.h"
|
||||
#include "krfbconfig.h"
|
||||
#include <KDebug>
|
||||
#include <KNotification>
|
||||
|
||||
PendingRfbClient::PendingRfbClient(rfbClientPtr client, QObject *parent)
|
||||
: QObject(parent), m_client(0), m_rfbClient(client)
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "processNewClient", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void PendingRfbClient::accept()
|
||||
{
|
||||
kDebug() << "accepted connection";
|
||||
|
||||
Q_ASSERT(m_client);
|
||||
m_client->setOnHold(false);
|
||||
Q_EMIT finished(m_client);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void PendingRfbClient::reject()
|
||||
{
|
||||
kDebug() << "refused connection";
|
||||
|
||||
rfbCloseClient(m_rfbClient);
|
||||
rfbClientConnectionGone(m_rfbClient);
|
||||
Q_EMIT finished(NULL);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void PendingRfbClient::showUserConfirmationDialog()
|
||||
{
|
||||
kDebug();
|
||||
Q_ASSERT(m_client);
|
||||
|
||||
if (!KrfbConfig::askOnConnect()) {
|
||||
KNotification::event("NewConnectionAutoAccepted",
|
||||
i18n("Accepted connection from %1", m_client->name()));
|
||||
accept();
|
||||
} else {
|
||||
KNotification::event("NewConnectionOnHold",
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
m_client->name()));
|
||||
|
||||
ConnectionDialog *dialog = new ConnectionDialog(0);
|
||||
dialog->setRemoteHost(m_client->name());
|
||||
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
|
||||
connect(dialog, SIGNAL(cancelClicked()), SLOT(dialogRejected()));
|
||||
|
||||
dialog->show();
|
||||
}
|
||||
}
|
||||
|
||||
void PendingRfbClient::dialogAccepted()
|
||||
{
|
||||
ConnectionDialog *dialog = qobject_cast<ConnectionDialog *>(sender());
|
||||
Q_ASSERT(dialog);
|
||||
m_client->setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
|
||||
accept();
|
||||
}
|
||||
|
||||
void PendingRfbClient::dialogRejected()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
46
krfb/pendingrfbclient.h
Normal file
46
krfb/pendingrfbclient.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PENDINGRFBCLIENT_H
|
||||
#define PENDINGRFBCLIENT_H
|
||||
|
||||
#include "rfbclient.h"
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class PendingRfbClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PendingRfbClient(rfbClientPtr client, QObject* parent = 0);
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished(RfbClient *client);
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void processNewClient() = 0;
|
||||
|
||||
void showUserConfirmationDialog();
|
||||
|
||||
void accept();
|
||||
void reject();
|
||||
|
||||
protected:
|
||||
RfbClient *m_client;
|
||||
rfbClientPtr m_rfbClient;
|
||||
};
|
||||
|
||||
#endif // PENDINGRFBCLIENT_H
|
||||
105
krfb/personalinvitedialog.cpp
Normal file
105
krfb/personalinvitedialog.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "personalinvitedialog.h"
|
||||
|
||||
#include "krfbconfig.h"
|
||||
|
||||
#include <KIconLoader>
|
||||
#include <KLocale>
|
||||
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QToolTip>
|
||||
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
|
||||
PersonalInviteDialog::PersonalInviteDialog(QWidget *parent)
|
||||
: KDialog(parent)
|
||||
{
|
||||
setCaption(i18n("Personal Invitation"));
|
||||
setButtons(Close);
|
||||
setDefaultButton(Close);
|
||||
setModal(true);
|
||||
|
||||
setMinimumSize(500, 250);
|
||||
|
||||
int port = KrfbConfig::port();
|
||||
|
||||
m_inviteWidget = new QWidget(this);
|
||||
setupUi(m_inviteWidget);
|
||||
pixmapLabel->setPixmap(KIcon("krfb").pixmap(128));
|
||||
|
||||
QList<QNetworkInterface> ifl = QNetworkInterface::allInterfaces();
|
||||
|
||||
foreach(const QNetworkInterface & nif, ifl) {
|
||||
if (nif.flags() & QNetworkInterface::IsLoopBack) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nif.flags() & QNetworkInterface::IsRunning && !nif.addressEntries().isEmpty()) {
|
||||
hostLabel->setText(QString("%1:%2").arg(nif.addressEntries().first().ip().toString()).arg(port));
|
||||
}
|
||||
}
|
||||
|
||||
connect(mainTextLabel, SIGNAL(linkActivated(QString)),
|
||||
SLOT(showWhatsthis(QString)));
|
||||
|
||||
connect(hostHelpLabel, SIGNAL(linkActivated(QString)),
|
||||
SLOT(showWhatsthis(QString)));
|
||||
|
||||
setMainWidget(m_inviteWidget);
|
||||
}
|
||||
|
||||
|
||||
void PersonalInviteDialog::setHost(const QString &host, uint port)
|
||||
{
|
||||
hostLabel->setText(QString("%1:%2")
|
||||
.arg(host).arg(port));
|
||||
}
|
||||
|
||||
void PersonalInviteDialog::setPassword(const QString &passwd)
|
||||
{
|
||||
passwordLabel->setText(passwd);
|
||||
}
|
||||
|
||||
void PersonalInviteDialog::setExpiration(const QDateTime &expire)
|
||||
{
|
||||
expirationLabel->setText(expire.toString(Qt::LocalDate));
|
||||
}
|
||||
|
||||
void PersonalInviteDialog::showWhatsthis(const QString &link)
|
||||
{
|
||||
if (link == "htc") {
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
i18n("Desktop Sharing uses the VNC protocol. You can use any VNC client to connect. \n"
|
||||
"In KDE the client is called 'Remote Desktop Connection'. Enter the host information\n"
|
||||
"into the client and it will connect.."));
|
||||
} else if (link == "help") {
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
i18n("This field contains the address of your computer and the display number, separated by a colon.\n"
|
||||
"The address is just a hint - you can use any address that can reach your computer. \n"
|
||||
"Desktop Sharing tries to guess your address from your network configuration, but does\n"
|
||||
"not always succeed in doing so. If your computer is behind a firewall it may have a\n"
|
||||
"different address or be unreachable for other computers."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "personalinvitedialog.moc"
|
||||
|
||||
@@ -20,21 +20,23 @@
|
||||
#ifndef PERSONALINVITEDIALOG_H
|
||||
#define PERSONALINVITEDIALOG_H
|
||||
|
||||
#include <qdatetime.h>
|
||||
#include <KDialog>
|
||||
#include "ui_personalinvitewidget.h"
|
||||
|
||||
#include <KDialog>
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
class QWidget;
|
||||
class PersonalInviteDialog : public KDialog, public Ui::PersonalInviteWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PersonalInviteDialog( QWidget *parent );
|
||||
PersonalInviteDialog(QWidget *parent);
|
||||
virtual ~PersonalInviteDialog() {}
|
||||
|
||||
void setHost( const QString &host, uint port );
|
||||
void setPassword( const QString &passwd );
|
||||
void setExpiration( const QDateTime &expire );
|
||||
void setHost(const QString &host, uint port);
|
||||
void setPassword(const QString &passwd);
|
||||
void setExpiration(const QDateTime &expire);
|
||||
|
||||
public Q_SLOTS:
|
||||
void showWhatsthis(const QString &);
|
||||
15
krfb/rfb.h
Normal file
15
krfb/rfb.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* This file should always be included instead of <rfb/rfb.h> because otherwise it's redefinition
|
||||
* of TRUE and FALSE plays havoc with other things.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_RFB_H
|
||||
#define KRFB_RFB_H
|
||||
|
||||
#include "../libvncserver/rfb/rfb.h"
|
||||
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
232
krfb/rfbclient.cpp
Normal file
232
krfb/rfbclient.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "rfbclient.h"
|
||||
#include "connectiondialog.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "sockethelpers.h"
|
||||
#include "events.h"
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <KDebug>
|
||||
#include <KNotification>
|
||||
#include <poll.h>
|
||||
#include <strings.h> //for bzero()
|
||||
|
||||
struct RfbClient::Private
|
||||
{
|
||||
Private(rfbClientPtr client) :
|
||||
controlEnabled(KrfbConfig::allowDesktopControl()),
|
||||
client(client)
|
||||
{}
|
||||
|
||||
bool controlEnabled;
|
||||
rfbClientPtr client;
|
||||
QSocketNotifier *notifier;
|
||||
QString remoteAddressString;
|
||||
};
|
||||
|
||||
RfbClient::RfbClient(rfbClientPtr client, QObject* parent)
|
||||
: QObject(parent), d(new Private(client))
|
||||
{
|
||||
d->remoteAddressString = peerAddress(d->client->sock) + ":" +
|
||||
QString::number(peerPort(d->client->sock));
|
||||
|
||||
d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this);
|
||||
d->notifier->setEnabled(false);
|
||||
connect(d->notifier, SIGNAL(activated(int)), this, SLOT(onSocketActivated()));
|
||||
}
|
||||
|
||||
RfbClient::~RfbClient()
|
||||
{
|
||||
kDebug();
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString RfbClient::name() const
|
||||
{
|
||||
return d->remoteAddressString;
|
||||
}
|
||||
|
||||
//static
|
||||
bool RfbClient::controlCanBeEnabled()
|
||||
{
|
||||
return KrfbConfig::allowDesktopControl();
|
||||
}
|
||||
|
||||
bool RfbClient::controlEnabled() const
|
||||
{
|
||||
return d->controlEnabled;
|
||||
}
|
||||
|
||||
void RfbClient::setControlEnabled(bool enabled)
|
||||
{
|
||||
if (controlCanBeEnabled() && d->controlEnabled != enabled) {
|
||||
d->controlEnabled = enabled;
|
||||
Q_EMIT controlEnabledChanged(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool RfbClient::isOnHold() const
|
||||
{
|
||||
return d->client->onHold ? true : false;
|
||||
}
|
||||
|
||||
void RfbClient::setOnHold(bool onHold)
|
||||
{
|
||||
if (isOnHold() != onHold) {
|
||||
d->client->onHold = onHold;
|
||||
d->notifier->setEnabled(!onHold);
|
||||
Q_EMIT holdStatusChanged(onHold);
|
||||
}
|
||||
}
|
||||
|
||||
void RfbClient::closeConnection()
|
||||
{
|
||||
d->notifier->setEnabled(false);
|
||||
rfbCloseClient(d->client);
|
||||
rfbClientConnectionGone(d->client);
|
||||
}
|
||||
|
||||
void RfbClient::handleKeyboardEvent(bool down, rfbKeySym keySym)
|
||||
{
|
||||
if (d->controlEnabled) {
|
||||
EventHandler::handleKeyboard(down, keySym);
|
||||
}
|
||||
}
|
||||
|
||||
void RfbClient::handleMouseEvent(int buttonMask, int x, int y)
|
||||
{
|
||||
if (d->controlEnabled) {
|
||||
EventHandler::handlePointer(buttonMask, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
bool RfbClient::checkPassword(const QByteArray & encryptedPassword)
|
||||
{
|
||||
Q_UNUSED(encryptedPassword);
|
||||
|
||||
return d->client->screen->authPasswdData == (void*)0;
|
||||
}
|
||||
|
||||
bool RfbClient::vncAuthCheckPassword(const QByteArray& password, const QByteArray& encryptedPassword) const
|
||||
{
|
||||
if (password.isEmpty() && encryptedPassword.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char passwd[MAXPWLEN];
|
||||
unsigned char challenge[CHALLENGESIZE];
|
||||
|
||||
memcpy(challenge, d->client->authChallenge, CHALLENGESIZE);
|
||||
bzero(passwd, MAXPWLEN);
|
||||
|
||||
if (!password.isEmpty()) {
|
||||
strncpy(passwd, password,
|
||||
(MAXPWLEN <= password.size()) ? MAXPWLEN : password.size());
|
||||
}
|
||||
|
||||
rfbEncryptBytes(challenge, passwd);
|
||||
return memcmp(challenge, encryptedPassword, encryptedPassword.size()) == 0;
|
||||
}
|
||||
|
||||
void RfbClient::onSocketActivated()
|
||||
{
|
||||
//Process not only one, but all pending messages.
|
||||
//poll() idea/code copied from vino:
|
||||
// Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
// License: GPL v2 or later
|
||||
struct pollfd pollfd = { d->client->sock, POLLIN|POLLPRI, 0 };
|
||||
|
||||
while(poll(&pollfd, 1, 0) == 1) {
|
||||
rfbProcessClientMessage(d->client);
|
||||
|
||||
//This is how we handle disconnection.
|
||||
//if rfbProcessClientMessage() finds out that it can't read the socket,
|
||||
//it closes it and sets it to -1. So, we just have to check this here
|
||||
//and call rfbClientConnectionGone() if necessary. This will call
|
||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
||||
//from the server manager and will call deleteLater() to delete it
|
||||
if (d->client->sock == -1) {
|
||||
kDebug() << "disconnected from socket signal";
|
||||
d->notifier->setEnabled(false);
|
||||
rfbClientConnectionGone(d->client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RfbClient::update()
|
||||
{
|
||||
rfbUpdateClient(d->client);
|
||||
|
||||
//This is how we handle disconnection.
|
||||
//if rfbUpdateClient() finds out that it can't write to the socket,
|
||||
//it closes it and sets it to -1. So, we just have to check this here
|
||||
//and call rfbClientConnectionGone() if necessary. This will call
|
||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
||||
//from the server manager and will call deleteLater() to delete it
|
||||
if (d->client->sock == -1) {
|
||||
kDebug() << "disconnected during update";
|
||||
d->notifier->setEnabled(false);
|
||||
rfbClientConnectionGone(d->client);
|
||||
}
|
||||
}
|
||||
|
||||
//*************
|
||||
|
||||
PendingRfbClient::PendingRfbClient(rfbClientPtr client, QObject *parent)
|
||||
: QObject(parent), m_rfbClient(client)
|
||||
{
|
||||
kDebug();
|
||||
QMetaObject::invokeMethod(this, "processNewClient", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
PendingRfbClient::~PendingRfbClient()
|
||||
{
|
||||
kDebug();
|
||||
}
|
||||
|
||||
void PendingRfbClient::accept(RfbClient *newClient)
|
||||
{
|
||||
kDebug() << "accepted connection";
|
||||
|
||||
m_rfbClient->clientData = newClient;
|
||||
newClient->setOnHold(false);
|
||||
|
||||
Q_EMIT finished(newClient);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
static void clientGoneHookNoop(rfbClientPtr cl) { Q_UNUSED(cl); }
|
||||
|
||||
void PendingRfbClient::reject()
|
||||
{
|
||||
kDebug() << "refused connection";
|
||||
|
||||
//override the clientGoneHook that was previously set by RfbServer
|
||||
m_rfbClient->clientGoneHook = clientGoneHookNoop;
|
||||
rfbCloseClient(m_rfbClient);
|
||||
rfbClientConnectionGone(m_rfbClient);
|
||||
|
||||
Q_EMIT finished(NULL);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
||||
#include "rfbclient.moc"
|
||||
105
krfb/rfbclient.h
Normal file
105
krfb/rfbclient.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RFBCLIENT_H
|
||||
#define RFBCLIENT_H
|
||||
|
||||
#include "rfb.h"
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class RfbClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool controlEnabled READ controlEnabled WRITE setControlEnabled NOTIFY controlEnabledChanged)
|
||||
Q_PROPERTY(bool onHold READ isOnHold WRITE setOnHold NOTIFY holdStatusChanged)
|
||||
public:
|
||||
RfbClient(rfbClientPtr client, QObject *parent = 0);
|
||||
virtual ~RfbClient();
|
||||
|
||||
/** Returns a name for the client, to be shown to the user */
|
||||
virtual QString name() const;
|
||||
|
||||
static bool controlCanBeEnabled();
|
||||
bool controlEnabled() const;
|
||||
bool isOnHold() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setControlEnabled(bool enabled);
|
||||
void setOnHold(bool onHold);
|
||||
void closeConnection();
|
||||
|
||||
Q_SIGNALS:
|
||||
void controlEnabledChanged(bool enabled);
|
||||
void holdStatusChanged(bool onHold);
|
||||
|
||||
protected:
|
||||
friend class RfbServer; //the following event handling methods are called by RfbServer
|
||||
|
||||
virtual void handleKeyboardEvent(bool down, rfbKeySym keySym);
|
||||
virtual void handleMouseEvent(int buttonMask, int x, int y);
|
||||
|
||||
/** This method is supposed to check if the provided \a encryptedPassword
|
||||
* matches the criteria for authenticating the client.
|
||||
* The default implementation returns false if a password is required.
|
||||
* Reimplement to do more useful stuff.
|
||||
*/
|
||||
virtual bool checkPassword(const QByteArray & encryptedPassword);
|
||||
|
||||
/** This method checks if the \a encryptedPassword that was sent from the remote
|
||||
* user matches the \a password that you have specified localy to be the password
|
||||
* for this connection. This assumes that the standard VNC authentication mechanism
|
||||
* is used. Returns true if the password matches or false otherwise.
|
||||
*/
|
||||
bool vncAuthCheckPassword(const QByteArray & password, const QByteArray & encryptedPassword) const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onSocketActivated();
|
||||
|
||||
private:
|
||||
///called by RfbServerManager to send framebuffer updates
|
||||
///and check for possible disconnection
|
||||
void update();
|
||||
friend class RfbServerManager;
|
||||
|
||||
struct Private;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
|
||||
class PendingRfbClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PendingRfbClient(rfbClientPtr client, QObject *parent = 0);
|
||||
virtual ~PendingRfbClient();
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished(RfbClient *client);
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void processNewClient() = 0;
|
||||
|
||||
void accept(RfbClient *newClient);
|
||||
void reject();
|
||||
|
||||
protected:
|
||||
rfbClientPtr m_rfbClient;
|
||||
};
|
||||
|
||||
#endif // RFBCLIENT_H
|
||||
268
krfb/rfbserver.cpp
Normal file
268
krfb/rfbserver.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "rfbserver.h"
|
||||
#include "rfbservermanager.h"
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <KDebug>
|
||||
|
||||
struct RfbServer::Private
|
||||
{
|
||||
QByteArray listeningAddress;
|
||||
int listeningPort;
|
||||
bool passwordRequired;
|
||||
rfbScreenInfoPtr screen;
|
||||
QSocketNotifier *notifier;
|
||||
};
|
||||
|
||||
RfbServer::RfbServer(QObject *parent)
|
||||
: QObject(parent), d(new Private)
|
||||
{
|
||||
d->listeningAddress = "0.0.0.0";
|
||||
d->listeningPort = 0;
|
||||
d->passwordRequired = true;
|
||||
d->screen = NULL;
|
||||
d->notifier = NULL;
|
||||
|
||||
RfbServerManager::instance()->registerServer(this);
|
||||
}
|
||||
|
||||
RfbServer::~RfbServer()
|
||||
{
|
||||
stop();
|
||||
if (d->screen) {
|
||||
rfbScreenCleanup(d->screen);
|
||||
}
|
||||
delete d;
|
||||
|
||||
RfbServerManager::instance()->unregisterServer(this);
|
||||
}
|
||||
|
||||
QByteArray RfbServer::listeningAddress() const
|
||||
{
|
||||
return d->listeningAddress;
|
||||
}
|
||||
|
||||
int RfbServer::listeningPort() const
|
||||
{
|
||||
return d->listeningPort;
|
||||
}
|
||||
|
||||
bool RfbServer::passwordRequired() const
|
||||
{
|
||||
return d->passwordRequired;
|
||||
}
|
||||
|
||||
void RfbServer::setListeningAddress(const QByteArray& address)
|
||||
{
|
||||
d->listeningAddress = address;
|
||||
}
|
||||
|
||||
void RfbServer::setListeningPort(int port)
|
||||
{
|
||||
d->listeningPort = port;
|
||||
}
|
||||
|
||||
void RfbServer::setPasswordRequired(bool passwordRequired)
|
||||
{
|
||||
d->passwordRequired = passwordRequired;
|
||||
}
|
||||
|
||||
bool RfbServer::start()
|
||||
{
|
||||
if (!d->screen) {
|
||||
d->screen = RfbServerManager::instance()->newScreen();
|
||||
if (!d->screen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// server hooks
|
||||
d->screen->screenData = this;
|
||||
d->screen->newClientHook = newClientHook;
|
||||
d->screen->kbdAddEvent = keyboardHook;
|
||||
d->screen->ptrAddEvent = pointerHook;
|
||||
d->screen->passwordCheck = passwordCheck;
|
||||
d->screen->setXCutText = clipboardHook;
|
||||
} else {
|
||||
//if we already have a screen, stop listening first
|
||||
rfbShutdownServer(d->screen, false);
|
||||
}
|
||||
|
||||
if (listeningAddress() != "0.0.0.0") {
|
||||
strncpy(d->screen->thisHost, listeningAddress().data(), 254);
|
||||
}
|
||||
|
||||
if (listeningPort() == 0) {
|
||||
d->screen->autoPort = 1;
|
||||
}
|
||||
|
||||
d->screen->port = listeningPort();
|
||||
|
||||
// Disable/Enable password checking
|
||||
if (passwordRequired()) {
|
||||
d->screen->authPasswdData = (void *)1;
|
||||
} else {
|
||||
d->screen->authPasswdData = (void *)0;
|
||||
}
|
||||
|
||||
kDebug() << "Starting server. Listen port:" << listeningPort()
|
||||
<< "Listen Address:" << listeningAddress()
|
||||
<< "Password enabled:" << passwordRequired();
|
||||
|
||||
rfbInitServer(d->screen);
|
||||
|
||||
if (!rfbIsActive(d->screen)) {
|
||||
kDebug() << "Failed to start server";
|
||||
rfbShutdownServer(d->screen, false);
|
||||
return false;
|
||||
};
|
||||
|
||||
d->notifier = new QSocketNotifier(d->screen->listenSock, QSocketNotifier::Read, this);
|
||||
d->notifier->setEnabled(true);
|
||||
connect(d->notifier, SIGNAL(activated(int)), this, SLOT(onListenSocketActivated()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RfbServer::stop(bool disconnectClients)
|
||||
{
|
||||
if (d->screen) {
|
||||
rfbShutdownServer(d->screen, disconnectClients);
|
||||
if (d->notifier) {
|
||||
d->notifier->setEnabled(false);
|
||||
d->notifier->deleteLater();
|
||||
d->notifier = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RfbServer::updateScreen(const QList<QRect> & modifiedTiles)
|
||||
{
|
||||
if (d->screen) {
|
||||
QList<QRect>::const_iterator it = modifiedTiles.constBegin();
|
||||
for(; it != modifiedTiles.constEnd(); ++it) {
|
||||
rfbMarkRectAsModified(d->screen, it->x(), it->y(), it->right(), it->bottom());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Code copied from vino's bundled libvncserver:
|
||||
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
* License: GPL v2 or later
|
||||
*/
|
||||
void krfb_rfbSetCursorPosition(rfbScreenInfoPtr screen, rfbClientPtr client, int x, int y)
|
||||
{
|
||||
rfbClientIteratorPtr iterator;
|
||||
rfbClientPtr cl;
|
||||
|
||||
if (x == screen->cursorX || y == screen->cursorY)
|
||||
return;
|
||||
|
||||
LOCK(screen->cursorMutex);
|
||||
screen->cursorX = x;
|
||||
screen->cursorY = y;
|
||||
UNLOCK(screen->cursorMutex);
|
||||
|
||||
/* Inform all clients about this cursor movement. */
|
||||
iterator = rfbGetClientIterator(screen);
|
||||
while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
|
||||
cl->cursorWasMoved = TRUE;
|
||||
}
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
/* The cursor was moved by this client, so don't send CursorPos. */
|
||||
if (client) {
|
||||
client->cursorWasMoved = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void RfbServer::updateCursorPosition(const QPoint & position)
|
||||
{
|
||||
if (d->screen) {
|
||||
krfb_rfbSetCursorPosition(d->screen, NULL, position.x(), position.y());
|
||||
}
|
||||
}
|
||||
|
||||
void RfbServer::onListenSocketActivated()
|
||||
{
|
||||
rfbProcessNewConnection(d->screen);
|
||||
}
|
||||
|
||||
void RfbServer::pendingClientFinished(RfbClient *client)
|
||||
{
|
||||
kDebug();
|
||||
if (client) {
|
||||
RfbServerManager::instance()->addClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
rfbNewClientAction RfbServer::newClientHook(rfbClientPtr cl)
|
||||
{
|
||||
kDebug() << "New client";
|
||||
RfbServer *server = static_cast<RfbServer*>(cl->screen->screenData);
|
||||
|
||||
PendingRfbClient *pendingClient = server->newClient(cl);
|
||||
connect(pendingClient, SIGNAL(finished(RfbClient*)),
|
||||
server, SLOT(pendingClientFinished(RfbClient*)));
|
||||
|
||||
cl->clientGoneHook = clientGoneHook;
|
||||
return RFB_CLIENT_ON_HOLD;
|
||||
}
|
||||
|
||||
//static
|
||||
void RfbServer::clientGoneHook(rfbClientPtr cl)
|
||||
{
|
||||
kDebug() << "client gone";
|
||||
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
|
||||
|
||||
RfbServerManager::instance()->removeClient(client);
|
||||
client->deleteLater();
|
||||
}
|
||||
|
||||
//static
|
||||
rfbBool RfbServer::passwordCheck(rfbClientPtr cl, const char *encryptedPassword, int len)
|
||||
{
|
||||
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
|
||||
return client->checkPassword(QByteArray::fromRawData(encryptedPassword, len));
|
||||
}
|
||||
|
||||
//static
|
||||
void RfbServer::keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
|
||||
{
|
||||
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
|
||||
client->handleKeyboardEvent(down ? true : false, keySym);
|
||||
}
|
||||
|
||||
//static
|
||||
void RfbServer::pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
||||
{
|
||||
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
|
||||
client->handleMouseEvent(bm, x, y);
|
||||
}
|
||||
|
||||
//static
|
||||
void RfbServer::clipboardHook(char *str, int len, rfbClientPtr cl)
|
||||
{
|
||||
//TODO implement me
|
||||
}
|
||||
|
||||
#include "rfbserver.moc"
|
||||
71
krfb/rfbserver.h
Normal file
71
krfb/rfbserver.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RFBSERVER_H
|
||||
#define RFBSERVER_H
|
||||
|
||||
#include "rfb.h"
|
||||
#include "rfbclient.h"
|
||||
#include <QtCore/QRect>
|
||||
|
||||
class RfbServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RfbServer(QObject *parent = 0);
|
||||
virtual ~RfbServer();
|
||||
|
||||
QByteArray listeningAddress() const;
|
||||
int listeningPort() const;
|
||||
bool passwordRequired() const;
|
||||
|
||||
void setListeningAddress(const QByteArray & address);
|
||||
void setListeningPort(int port);
|
||||
void setPasswordRequired(bool passwordRequired);
|
||||
|
||||
public Q_SLOTS:
|
||||
bool start();
|
||||
void stop(bool disconnectClients = true);
|
||||
|
||||
void updateScreen(const QList<QRect> & modifiedTiles);
|
||||
void updateCursorPosition(const QPoint & position);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onListenSocketActivated();
|
||||
void pendingClientFinished(RfbClient *client);
|
||||
|
||||
protected:
|
||||
virtual PendingRfbClient *newClient(rfbClientPtr client) = 0;
|
||||
|
||||
private:
|
||||
static rfbNewClientAction newClientHook(rfbClientPtr cl);
|
||||
static void clientGoneHook(rfbClientPtr cl);
|
||||
|
||||
static rfbBool passwordCheck(rfbClientPtr cl, const char *encryptedPassword, int len);
|
||||
static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl);
|
||||
static void pointerHook(int bm, int x, int y, rfbClientPtr cl);
|
||||
static void clipboardHook(char *str, int len, rfbClientPtr cl);
|
||||
|
||||
Q_DISABLE_COPY(RfbServer)
|
||||
|
||||
struct Private;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
#endif // RFBSERVER_H
|
||||
235
krfb/rfbservermanager.cpp
Normal file
235
krfb/rfbservermanager.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "rfbservermanager.h"
|
||||
#include "rfbserver.h"
|
||||
#include "framebuffer.h"
|
||||
#include "framebuffermanager.h"
|
||||
#include "sockethelpers.h"
|
||||
#include "krfbconfig.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
#include <KGlobal>
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <KUser>
|
||||
#include <KNotification>
|
||||
|
||||
static const char *cur =
|
||||
" "
|
||||
" x "
|
||||
" xx "
|
||||
" xxx "
|
||||
" xxxx "
|
||||
" xxxxx "
|
||||
" xxxxxx "
|
||||
" xxxxxxx "
|
||||
" xxxxxxxx "
|
||||
" xxxxxxxxx "
|
||||
" xxxxxxxxxx "
|
||||
" xxxxx "
|
||||
" xx xxx "
|
||||
" x xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" ";
|
||||
|
||||
static const char *mask =
|
||||
"xx "
|
||||
"xxx "
|
||||
"xxxx "
|
||||
"xxxxx "
|
||||
"xxxxxx "
|
||||
"xxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxxxxx "
|
||||
"xxxxxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xx xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxx ";
|
||||
|
||||
|
||||
struct RfbServerManagerStatic
|
||||
{
|
||||
RfbServerManager server;
|
||||
};
|
||||
|
||||
K_GLOBAL_STATIC(RfbServerManagerStatic, s_instance)
|
||||
|
||||
RfbServerManager* RfbServerManager::instance()
|
||||
{
|
||||
return &s_instance->server;
|
||||
}
|
||||
|
||||
|
||||
struct RfbServerManager::Private
|
||||
{
|
||||
QSharedPointer<FrameBuffer> fb;
|
||||
rfbCursorPtr myCursor;
|
||||
QByteArray desktopName;
|
||||
QTimer rfbUpdateTimer;
|
||||
QSet<RfbServer*> servers;
|
||||
QSet<RfbClient*> clients;
|
||||
};
|
||||
|
||||
|
||||
RfbServerManager::RfbServerManager()
|
||||
: QObject(), d(new Private)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
RfbServerManager::~RfbServerManager()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void RfbServerManager::init()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
d->fb = FrameBufferManager::instance()->frameBuffer(QApplication::desktop()->winId());
|
||||
d->myCursor = rfbMakeXCursor(19, 19, (char *) cur, (char *) mask);
|
||||
d->myCursor->cleanup = false;
|
||||
d->desktopName = QString("%1@%2 (shared desktop)") //FIXME check if we can use utf8
|
||||
.arg(KUser().loginName(),QHostInfo::localHostName()).toLatin1();
|
||||
|
||||
connect(&d->rfbUpdateTimer, SIGNAL(timeout()), SLOT(updateScreens()));
|
||||
connect(qApp, SIGNAL(aboutToQuit()), SLOT(cleanup()));
|
||||
}
|
||||
|
||||
void RfbServerManager::updateScreens()
|
||||
{
|
||||
QList<QRect> rects = d->fb->modifiedTiles();
|
||||
QPoint currentCursorPos = QCursor::pos();
|
||||
|
||||
Q_FOREACH(RfbServer *server, d->servers) {
|
||||
server->updateScreen(rects);
|
||||
server->updateCursorPosition(currentCursorPos);
|
||||
}
|
||||
|
||||
//update() might disconnect some of the clients, which will synchronously
|
||||
//call the removeClient() method and will change d->clients, so we need
|
||||
//to copy the set here to avoid problems.
|
||||
QSet<RfbClient*> clients = d->clients;
|
||||
Q_FOREACH(RfbClient *client, clients) {
|
||||
client->update();
|
||||
}
|
||||
}
|
||||
|
||||
void RfbServerManager::cleanup()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
//copy because d->servers is going to be modified while we delete the servers
|
||||
QSet<RfbServer*> servers = d->servers;
|
||||
Q_FOREACH(RfbServer *server, servers) {
|
||||
delete server;
|
||||
}
|
||||
|
||||
Q_ASSERT(d->servers.isEmpty());
|
||||
Q_ASSERT(d->clients.isEmpty());
|
||||
|
||||
d->myCursor->cleanup = true;
|
||||
rfbFreeCursor(d->myCursor);
|
||||
d->fb.clear();
|
||||
}
|
||||
|
||||
void RfbServerManager::registerServer(RfbServer* server)
|
||||
{
|
||||
d->servers.insert(server);
|
||||
}
|
||||
|
||||
void RfbServerManager::unregisterServer(RfbServer* server)
|
||||
{
|
||||
d->servers.remove(server);
|
||||
}
|
||||
|
||||
rfbScreenInfoPtr RfbServerManager::newScreen()
|
||||
{
|
||||
rfbScreenInfoPtr screen = NULL;
|
||||
|
||||
if (!d->fb.isNull()) {
|
||||
int w = d->fb->width();
|
||||
int h = d->fb->height();
|
||||
int depth = d->fb->depth();
|
||||
int bpp = depth >> 3;
|
||||
|
||||
if (bpp != 1 && bpp != 2 && bpp != 4) {
|
||||
bpp = 4;
|
||||
}
|
||||
|
||||
kDebug() << "bpp: " << bpp;
|
||||
|
||||
rfbLogEnable(0);
|
||||
|
||||
screen = rfbGetScreen(0, 0, w, h, 8, 3, bpp);
|
||||
screen->paddedWidthInBytes = d->fb->paddedWidth();
|
||||
d->fb->getServerFormat(screen->serverFormat);
|
||||
screen->frameBuffer = d->fb->data();
|
||||
|
||||
screen->desktopName = d->desktopName.constData();
|
||||
screen->cursor = d->myCursor;
|
||||
}
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
void RfbServerManager::addClient(RfbClient* cc)
|
||||
{
|
||||
if (d->clients.size() == 0) {
|
||||
kDebug() << "Starting framebuffer monitor";
|
||||
d->fb->startMonitor();
|
||||
d->rfbUpdateTimer.start(50);
|
||||
}
|
||||
d->clients.insert(cc);
|
||||
|
||||
KNotification::event("UserAcceptsConnection",
|
||||
i18n("The remote user %1 is now connected.", cc->name()));
|
||||
|
||||
Q_EMIT clientConnected(cc);
|
||||
}
|
||||
|
||||
void RfbServerManager::removeClient(RfbClient* cc)
|
||||
{
|
||||
d->clients.remove(cc);
|
||||
if (d->clients.size() == 0) {
|
||||
kDebug() << "Stopping framebuffer monitor";
|
||||
d->fb->stopMonitor();
|
||||
d->rfbUpdateTimer.stop();
|
||||
}
|
||||
|
||||
KNotification::event("ConnectionClosed", i18n("The remote user %1 disconnected.", cc->name()));
|
||||
|
||||
Q_EMIT clientDisconnected(cc);
|
||||
}
|
||||
|
||||
#include "rfbservermanager.moc"
|
||||
65
krfb/rfbservermanager.h
Normal file
65
krfb/rfbservermanager.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RFBSERVERMANAGER_H
|
||||
#define RFBSERVERMANAGER_H
|
||||
|
||||
#include "rfb.h"
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class RfbClient;
|
||||
class RfbServerManagerStatic;
|
||||
class RfbServer;
|
||||
|
||||
class RfbServerManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static RfbServerManager *instance();
|
||||
|
||||
Q_SIGNALS:
|
||||
void clientConnected(RfbClient *cc);
|
||||
void clientDisconnected(RfbClient *cc);
|
||||
|
||||
private Q_SLOTS:
|
||||
void init();
|
||||
void updateScreens();
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
void registerServer(RfbServer *server);
|
||||
void unregisterServer(RfbServer *server);
|
||||
|
||||
rfbScreenInfoPtr newScreen();
|
||||
|
||||
void addClient(RfbClient *cc);
|
||||
void removeClient(RfbClient *cc);
|
||||
|
||||
RfbServerManager();
|
||||
virtual ~RfbServerManager();
|
||||
Q_DISABLE_COPY(RfbServerManager)
|
||||
|
||||
friend class RfbServer;
|
||||
friend class RfbServerManagerStatic;
|
||||
|
||||
struct Private;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
#endif // RFBSERVERMANAGER_H
|
||||
106
krfb/sockethelpers.cpp
Normal file
106
krfb/sockethelpers.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "sockethelpers.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
QString peerAddress(int sock)
|
||||
{
|
||||
|
||||
const int ADDR_SIZE = 50;
|
||||
struct sockaddr sa;
|
||||
socklen_t salen = sizeof(struct sockaddr);
|
||||
|
||||
if (getpeername(sock, &sa, &salen) == 0) {
|
||||
if (sa.sa_family == AF_INET) {
|
||||
struct sockaddr_in *si = (struct sockaddr_in *)&sa;
|
||||
return QString(inet_ntoa(si->sin_addr));
|
||||
}
|
||||
|
||||
if (sa.sa_family == AF_INET6) {
|
||||
char inetbuf[ADDR_SIZE];
|
||||
inet_ntop(sa.sa_family, &sa, inetbuf, ADDR_SIZE);
|
||||
return QString(inetbuf);
|
||||
}
|
||||
|
||||
return QString("not a network address");
|
||||
}
|
||||
|
||||
return QString("unable to determine...");
|
||||
}
|
||||
|
||||
unsigned short peerPort(int sock)
|
||||
{
|
||||
|
||||
struct sockaddr sa;
|
||||
socklen_t salen = sizeof(struct sockaddr);
|
||||
|
||||
if (getpeername(sock, &sa, &salen) == 0) {
|
||||
struct sockaddr_in *si = (struct sockaddr_in *)&sa;
|
||||
return ntohs(si->sin_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString localAddress(int sock)
|
||||
{
|
||||
|
||||
const int ADDR_SIZE = 50;
|
||||
struct sockaddr sa;
|
||||
socklen_t salen = sizeof(struct sockaddr);
|
||||
|
||||
if (getsockname(sock, &sa, &salen) == 0) {
|
||||
if (sa.sa_family == AF_INET) {
|
||||
struct sockaddr_in *si = (struct sockaddr_in *)&sa;
|
||||
return QString(inet_ntoa(si->sin_addr));
|
||||
}
|
||||
|
||||
if (sa.sa_family == AF_INET6) {
|
||||
char inetbuf[ADDR_SIZE];
|
||||
inet_ntop(sa.sa_family, &sa, inetbuf, ADDR_SIZE);
|
||||
return QString(inetbuf);
|
||||
}
|
||||
|
||||
return QString("not a network address");
|
||||
}
|
||||
|
||||
return QString("unable to determine...");
|
||||
}
|
||||
|
||||
unsigned short localPort(int sock)
|
||||
{
|
||||
|
||||
struct sockaddr sa;
|
||||
socklen_t salen = sizeof(struct sockaddr);
|
||||
|
||||
if (getsockname(sock, &sa, &salen) == 0) {
|
||||
struct sockaddr_in *si = (struct sockaddr_in *)&sa;
|
||||
return ntohs(si->sin_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
@@ -17,29 +20,11 @@
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTIONDIALOG_H
|
||||
#define CONNECTIONDIALOG_H
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <KDialog>
|
||||
#include "ui_connectionwidget.h"
|
||||
QString peerAddress(int sock);
|
||||
unsigned short peerPort(int sock);
|
||||
|
||||
class QWidget;
|
||||
|
||||
class ConnectionDialog : public KDialog, public Ui::ConnectionWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConnectionDialog( QWidget *parent );
|
||||
~ConnectionDialog() {};
|
||||
|
||||
void setRemoteHost( const QString &host );
|
||||
void setAllowRemoteControl( bool b );
|
||||
bool allowRemoteControl();
|
||||
|
||||
protected:
|
||||
QWidget *m_connectWidget;
|
||||
};
|
||||
|
||||
#endif // CONNECTIONDIALOG_H
|
||||
QString localAddress(int sock);
|
||||
unsigned short localPort(int sock);
|
||||
|
||||
153
krfb/trayicon.cpp
Normal file
153
krfb/trayicon.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2001-2002 Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "trayicon.h"
|
||||
|
||||
#include "invitedialog.h"
|
||||
#include "manageinvitationsdialog.h"
|
||||
#include "rfbservermanager.h"
|
||||
#include "rfbclient.h"
|
||||
|
||||
#include <KAboutApplicationDialog>
|
||||
#include <KActionCollection>
|
||||
#include <KDialog>
|
||||
#include <KGlobal>
|
||||
#include <KLocale>
|
||||
#include <KMenu>
|
||||
#include <KStandardAction>
|
||||
#include <KDebug>
|
||||
|
||||
|
||||
class ClientActions
|
||||
{
|
||||
public:
|
||||
ClientActions(RfbClient *client, KMenu *menu, QAction *before);
|
||||
virtual ~ClientActions();
|
||||
|
||||
private:
|
||||
KMenu *m_menu;
|
||||
QAction *m_title;
|
||||
QAction *m_disconnectAction;
|
||||
QAction *m_enableControlAction;
|
||||
QAction *m_separator;
|
||||
};
|
||||
|
||||
ClientActions::ClientActions(RfbClient* client, KMenu* menu, QAction* before)
|
||||
: m_menu(menu)
|
||||
{
|
||||
m_title = m_menu->addTitle(client->name(), before);
|
||||
|
||||
m_disconnectAction = new KAction(i18n("Disconnect"), m_menu);
|
||||
m_menu->insertAction(before, m_disconnectAction);
|
||||
|
||||
QObject::connect(m_disconnectAction, SIGNAL(triggered()), client, SLOT(closeConnection()));
|
||||
|
||||
if (client->controlCanBeEnabled()) {
|
||||
m_enableControlAction = new KToggleAction(i18n("Enable Remote Control"), m_menu);
|
||||
m_enableControlAction->setChecked(client->controlEnabled());
|
||||
m_menu->insertAction(before, m_enableControlAction);
|
||||
|
||||
QObject::connect(m_enableControlAction, SIGNAL(triggered(bool)),
|
||||
client, SLOT(setControlEnabled(bool)));
|
||||
QObject::connect(client, SIGNAL(controlEnabledChanged(bool)),
|
||||
m_enableControlAction, SLOT(setChecked(bool)));
|
||||
} else {
|
||||
m_enableControlAction = NULL;
|
||||
}
|
||||
|
||||
m_separator = m_menu->insertSeparator(before);
|
||||
}
|
||||
|
||||
ClientActions::~ClientActions()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
m_menu->removeAction(m_title);
|
||||
delete m_title;
|
||||
|
||||
m_menu->removeAction(m_disconnectAction);
|
||||
delete m_disconnectAction;
|
||||
|
||||
if (m_enableControlAction) {
|
||||
m_menu->removeAction(m_enableControlAction);
|
||||
delete m_enableControlAction;
|
||||
}
|
||||
|
||||
m_menu->removeAction(m_separator);
|
||||
delete m_separator;
|
||||
}
|
||||
|
||||
//**********
|
||||
|
||||
TrayIcon::TrayIcon(QWidget *mainWindow)
|
||||
: KStatusNotifierItem(mainWindow)
|
||||
{
|
||||
setIconByPixmap(KIcon("krfb").pixmap(22, 22, KIcon::Disabled));
|
||||
|
||||
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
||||
setCategory(KStatusNotifierItem::ApplicationStatus);
|
||||
|
||||
connect(RfbServerManager::instance(), SIGNAL(clientConnected(RfbClient*)),
|
||||
this, SLOT(onClientConnected(RfbClient*)));
|
||||
connect(RfbServerManager::instance(), SIGNAL(clientDisconnected(RfbClient*)),
|
||||
this, SLOT(onClientDisconnected(RfbClient*)));
|
||||
|
||||
m_aboutAction = KStandardAction::aboutApp(this, SLOT(showAbout()), actionCollection());
|
||||
contextMenu()->addAction(m_aboutAction);
|
||||
}
|
||||
|
||||
void TrayIcon::onClientConnected(RfbClient* client)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
if (m_clientActions.isEmpty()) { //first client connected
|
||||
setIconByName("krfb");
|
||||
setToolTipTitle(i18n("Desktop Sharing - connected with %1", client->name()));
|
||||
setStatus(KStatusNotifierItem::Active);
|
||||
} else { //Nth client connected, N != 1
|
||||
setToolTipTitle(i18n("Desktop Sharing - connected"));
|
||||
}
|
||||
|
||||
m_clientActions[client] = new ClientActions(client, contextMenu(), m_aboutAction);
|
||||
}
|
||||
|
||||
void TrayIcon::onClientDisconnected(RfbClient* client)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
ClientActions *actions = m_clientActions.take(client);
|
||||
delete actions;
|
||||
|
||||
if (m_clientActions.isEmpty()) {
|
||||
setIconByPixmap(KIcon("krfb").pixmap(22, 22, KIcon::Disabled));
|
||||
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
||||
setStatus(KStatusNotifierItem::Passive);
|
||||
} else if (m_clientActions.size() == 1) { //clients number dropped back to 1
|
||||
RfbClient *client = m_clientActions.constBegin().key();
|
||||
setToolTipTitle(i18n("Desktop Sharing - connected with %1", client->name()));
|
||||
}
|
||||
}
|
||||
|
||||
void TrayIcon::showAbout()
|
||||
{
|
||||
KDialog *dlg = new KAboutApplicationDialog(KGlobal::mainComponent().aboutData());
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
dlg->show();
|
||||
}
|
||||
|
||||
#include "trayicon.moc"
|
||||
@@ -18,44 +18,32 @@
|
||||
#ifndef TRAYICON_H
|
||||
#define TRAYICON_H
|
||||
|
||||
#include <kpassivepopup.h>
|
||||
#include <KActionCollection>
|
||||
#include <KStatusNotifierItem>
|
||||
#include <KToggleAction>
|
||||
#include <kstatusnotifieritem.h>
|
||||
|
||||
class KDialog;
|
||||
class RfbClient;
|
||||
class ClientActions;
|
||||
|
||||
/**
|
||||
* Implements the trayicon.
|
||||
* @author Tim Jansen
|
||||
*/
|
||||
|
||||
class TrayIcon : public KStatusNotifierItem {
|
||||
Q_OBJECT
|
||||
class TrayIcon : public KStatusNotifierItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrayIcon(KDialog*);
|
||||
~TrayIcon();
|
||||
|
||||
signals:
|
||||
|
||||
void disconnectedMessageDisplayed();
|
||||
void enableDesktopControl(bool);
|
||||
void quitApp();
|
||||
TrayIcon(QWidget *mainWindow);
|
||||
|
||||
public Q_SLOTS:
|
||||
void prepareQuit();
|
||||
void showConnectedMessage(const QString &host);
|
||||
void showDisconnectedMessage();
|
||||
void setDesktopControlSetting(bool);
|
||||
void showManageInvitations();
|
||||
void onClientConnected(RfbClient *client);
|
||||
void onClientDisconnected(RfbClient *client);
|
||||
void showAbout();
|
||||
|
||||
private:
|
||||
KAction* manageInvitationsAction;
|
||||
KAction* aboutAction;
|
||||
KToggleAction* enableControlAction;
|
||||
bool quitting;
|
||||
|
||||
KAction *m_aboutAction;
|
||||
QHash<RfbClient*, ClientActions*> m_clientActions;
|
||||
};
|
||||
|
||||
#endif
|
||||
95
krfb/tubesclienthandler.cpp
Normal file
95
krfb/tubesclienthandler.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "tubesclienthandler.h"
|
||||
#include "tubesrfbserver.h"
|
||||
|
||||
#include <TelepathyQt4/ChannelClassSpecList>
|
||||
#include <TelepathyQt4/Constants>
|
||||
#include <TelepathyQt4/Debug>
|
||||
|
||||
#include <KDebug>
|
||||
|
||||
using namespace Tp;
|
||||
|
||||
static inline Tp::ChannelClassSpecList channelClassSpecList()
|
||||
{
|
||||
Tp::ChannelClassSpec spec = Tp::ChannelClassSpec();
|
||||
spec.setChannelType(TP_QT4_IFACE_CHANNEL_TYPE_STREAM_TUBE);
|
||||
spec.setTargetHandleType(Tp::HandleTypeContact);
|
||||
spec.setRequested(true);
|
||||
spec.setProperty(QString(TP_QT4_IFACE_CHANNEL_TYPE_STREAM_TUBE) + ".Service", QVariant("rfb"));
|
||||
return Tp::ChannelClassSpecList() << spec;
|
||||
}
|
||||
|
||||
TubesClientHandler::TubesClientHandler()
|
||||
: AbstractClientHandler(channelClassSpecList())
|
||||
{
|
||||
kDebug();
|
||||
|
||||
Tp::enableDebug(false);
|
||||
Tp::enableWarnings(true);
|
||||
|
||||
/* Registering telepathy types */
|
||||
registerTypes();
|
||||
}
|
||||
|
||||
TubesClientHandler::~TubesClientHandler()
|
||||
{
|
||||
kDebug();
|
||||
}
|
||||
|
||||
bool TubesClientHandler::bypassApproval() const
|
||||
{
|
||||
// Don't bypass approval of channels.
|
||||
return false;
|
||||
}
|
||||
|
||||
void TubesClientHandler::handleChannels(const Tp::MethodInvocationContextPtr<> &context,
|
||||
const Tp::AccountPtr &account,
|
||||
const Tp::ConnectionPtr &connection,
|
||||
const QList<Tp::ChannelPtr> &channels,
|
||||
const QList<Tp::ChannelRequestPtr> &requestsSatisfied,
|
||||
const QDateTime &userActionTime,
|
||||
const Tp::AbstractClientHandler::HandlerInfo &handlerInfo)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
Q_UNUSED(account);
|
||||
Q_UNUSED(connection);
|
||||
Q_UNUSED(requestsSatisfied);
|
||||
Q_UNUSED(userActionTime);
|
||||
Q_UNUSED(handlerInfo);
|
||||
|
||||
foreach(const Tp::ChannelPtr &channel, channels) {
|
||||
kDebug() << "Incoming channel: " << channel;
|
||||
|
||||
QVariantMap properties = channel->immutableProperties();
|
||||
|
||||
if (properties[TELEPATHY_INTERFACE_CHANNEL ".ChannelType"] ==
|
||||
TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAM_TUBE) {
|
||||
|
||||
kDebug() << "Channel is a stream tube. Handling: " << channel;
|
||||
new TubesRfbServer(channel);
|
||||
}
|
||||
}
|
||||
context->setFinished();
|
||||
}
|
||||
|
||||
45
krfb/tubesclienthandler.h
Normal file
45
krfb/tubesclienthandler.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program 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 program 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 program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_TUBESCLIENTHANDLER_H
|
||||
#define KRFB_TUBESCLIENTHANDLER_H
|
||||
|
||||
#include <TelepathyQt4/AbstractClientHandler>
|
||||
|
||||
class TubesClientHandler : public Tp::AbstractClientHandler
|
||||
{
|
||||
public:
|
||||
TubesClientHandler();
|
||||
virtual ~TubesClientHandler();
|
||||
|
||||
virtual bool bypassApproval() const;
|
||||
virtual void handleChannels(const Tp::MethodInvocationContextPtr<> &context,
|
||||
const Tp::AccountPtr &account,
|
||||
const Tp::ConnectionPtr &connection,
|
||||
const QList<Tp::ChannelPtr> &channels,
|
||||
const QList<Tp::ChannelRequestPtr> &requestsSatisfied,
|
||||
const QDateTime &userActionTime,
|
||||
const Tp::AbstractClientHandler::HandlerInfo &handlerInfo);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
85
krfb/tubesrfbclient.cpp
Normal file
85
krfb/tubesrfbclient.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "tubesrfbclient.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "connectiondialog.h"
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
|
||||
QString TubesRfbClient::name() const
|
||||
{
|
||||
return m_contact->alias();
|
||||
}
|
||||
|
||||
|
||||
void PendingTubesRfbClient::setContact(const Tp::ContactPtr & contact)
|
||||
{
|
||||
m_contact = contact;
|
||||
if (m_processNewClientCalled) {
|
||||
//processNewClient has already been called, so we need to act here
|
||||
showConfirmationDialog();
|
||||
}
|
||||
}
|
||||
|
||||
void PendingTubesRfbClient::processNewClient()
|
||||
{
|
||||
if (!m_contact) {
|
||||
//no associated contact yet, hold.
|
||||
m_processNewClientCalled = true; //act when a contact is set
|
||||
} else {
|
||||
//we have a contact, begin handling
|
||||
showConfirmationDialog();
|
||||
}
|
||||
}
|
||||
|
||||
void PendingTubesRfbClient::showConfirmationDialog()
|
||||
{
|
||||
QString name = m_contact->alias();
|
||||
|
||||
if (!KrfbConfig::askOnConnect()) {
|
||||
KNotification::event("NewConnectionAutoAccepted",
|
||||
i18n("Accepted connection from %1", name));
|
||||
accept(new TubesRfbClient(m_rfbClient, m_contact, parent()));
|
||||
} else {
|
||||
KNotification::event("NewConnectionOnHold",
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
name));
|
||||
|
||||
TubesConnectionDialog *dialog = new TubesConnectionDialog(0);
|
||||
dialog->setContactName(name);
|
||||
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
|
||||
connect(dialog, SIGNAL(cancelClicked()), SLOT(reject()));
|
||||
|
||||
dialog->show();
|
||||
}
|
||||
}
|
||||
|
||||
void PendingTubesRfbClient::dialogAccepted()
|
||||
{
|
||||
TubesConnectionDialog *dialog = qobject_cast<TubesConnectionDialog *>(sender());
|
||||
Q_ASSERT(dialog);
|
||||
|
||||
TubesRfbClient *client = new TubesRfbClient(m_rfbClient, m_contact, parent());
|
||||
client->setControlEnabled(dialog->allowRemoteControl());
|
||||
accept(client);
|
||||
}
|
||||
|
||||
#include "tubesrfbclient.moc"
|
||||
58
krfb/tubesrfbclient.h
Normal file
58
krfb/tubesrfbclient.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TUBESRFBCLIENT_H
|
||||
#define TUBESRFBCLIENT_H
|
||||
|
||||
#include "rfbclient.h"
|
||||
#include <TelepathyQt4/Contact>
|
||||
|
||||
class TubesRfbClient : public RfbClient
|
||||
{
|
||||
public:
|
||||
TubesRfbClient(rfbClientPtr client, const Tp::ContactPtr & contact, QObject* parent = 0)
|
||||
: RfbClient(client, parent), m_contact(contact) {}
|
||||
|
||||
virtual QString name() const;
|
||||
|
||||
private:
|
||||
Tp::ContactPtr m_contact;
|
||||
};
|
||||
|
||||
|
||||
class PendingTubesRfbClient : public PendingRfbClient
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PendingTubesRfbClient(rfbClientPtr client, QObject* parent = 0)
|
||||
: PendingRfbClient(client, parent), m_processNewClientCalled(false) {}
|
||||
|
||||
void setContact(const Tp::ContactPtr & contact);
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void processNewClient();
|
||||
|
||||
private Q_SLOTS:
|
||||
void showConfirmationDialog();
|
||||
void dialogAccepted();
|
||||
|
||||
private:
|
||||
Tp::ContactPtr m_contact;
|
||||
bool m_processNewClientCalled;
|
||||
};
|
||||
|
||||
#endif // TUBESRFBCLIENT_H
|
||||
294
krfb/tubesrfbserver.cpp
Normal file
294
krfb/tubesrfbserver.cpp
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "tubesrfbserver.h"
|
||||
#include "tubesrfbclient.h"
|
||||
#include "sockethelpers.h"
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <KDebug>
|
||||
#include <KMessageBox>
|
||||
#include <KLocale>
|
||||
|
||||
#include <TelepathyQt4/Connection>
|
||||
#include <TelepathyQt4/Contact>
|
||||
#include <TelepathyQt4/ContactManager>
|
||||
#include <TelepathyQt4/PendingContacts>
|
||||
#include <TelepathyQt4/PendingOperation>
|
||||
#include <TelepathyQt4/PendingReady>
|
||||
|
||||
/* workaround for QtDBus bug */
|
||||
struct StreamTubeAddress
|
||||
{
|
||||
QString address;
|
||||
uint port;
|
||||
};
|
||||
Q_DECLARE_METATYPE(StreamTubeAddress);
|
||||
|
||||
//Marshall the StreamTubeAddress data into a D-Bus argument
|
||||
QDBusArgument &operator<<(QDBusArgument &argument,
|
||||
const StreamTubeAddress &streamTubeAddress)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << streamTubeAddress.address << streamTubeAddress.port;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
// Retrieve the StreamTubeAddress data from the D-Bus argument
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument,
|
||||
StreamTubeAddress &streamTubeAddress)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> streamTubeAddress.address >> streamTubeAddress.port;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
//**************
|
||||
|
||||
struct TubesRfbServer::Private
|
||||
{
|
||||
Tp::ChannelPtr channel;
|
||||
QHash<int, Tp::ContactPtr> contactsPerPort;
|
||||
QHash<int, PendingTubesRfbClient*> clientsPerPort;
|
||||
};
|
||||
|
||||
TubesRfbServer::TubesRfbServer(const Tp::ChannelPtr & channel, QObject *parent)
|
||||
: RfbServer(parent), d(new Private)
|
||||
{
|
||||
kDebug() << "starting ";
|
||||
|
||||
/* Registering struct containing the tube address */
|
||||
qDBusRegisterMetaType<StreamTubeAddress>();
|
||||
|
||||
d->channel = channel;
|
||||
connect(d->channel->becomeReady(),
|
||||
SIGNAL(finished(Tp::PendingOperation*)),
|
||||
SLOT(onChannelReady(Tp::PendingOperation*)));
|
||||
|
||||
setListeningPort(6789);
|
||||
setListeningAddress("127.0.0.1"); // Listen only on the loopback network interface
|
||||
setPasswordRequired(false);
|
||||
}
|
||||
|
||||
TubesRfbServer::~TubesRfbServer()
|
||||
{
|
||||
kDebug();
|
||||
delete d;
|
||||
}
|
||||
|
||||
PendingRfbClient* TubesRfbServer::newClient(rfbClientPtr client)
|
||||
{
|
||||
kDebug() << "new tubes client";
|
||||
|
||||
PendingTubesRfbClient *c = new PendingTubesRfbClient(client, this);
|
||||
int port = peerPort(client->sock);
|
||||
|
||||
d->clientsPerPort[port] = c;
|
||||
if (d->contactsPerPort.contains(port)) {
|
||||
kDebug() << "already have a contact";
|
||||
c->setContact(d->contactsPerPort[port]);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/************************** TP TUBES CODE ************************************/
|
||||
|
||||
void TubesRfbServer::close()
|
||||
{
|
||||
kDebug();
|
||||
d->channel->requestClose();
|
||||
}
|
||||
|
||||
void TubesRfbServer::cleanup()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
d->clientsPerPort.clear();
|
||||
d->contactsPerPort.clear();
|
||||
|
||||
stop();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void TubesRfbServer::onChannelReady(Tp::PendingOperation *op)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
if (op->isError()) {
|
||||
kWarning() << "Getting channel ready faied:" << op->errorName() << op->errorMessage();
|
||||
KMessageBox::error(QApplication::activeWindow(),
|
||||
i18n("An error occurred sharing your desktop."),
|
||||
i18n("Error"));
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
Tp::Contacts contacts = d->channel->groupContacts();
|
||||
|
||||
Tp::ContactManagerPtr contactManager = d->channel->connection()->contactManager();
|
||||
|
||||
if (!contactManager) {
|
||||
kWarning() << "Invalid Contact Manager.";
|
||||
KMessageBox::error(QApplication::activeWindow(),
|
||||
i18n("An unknown error occurred sharing your desktop."),
|
||||
i18n("Error"));
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
Tp::Features features;
|
||||
features << Tp::Contact::FeatureAlias;
|
||||
|
||||
connect(contactManager->upgradeContacts(contacts.toList(), features),
|
||||
SIGNAL(finished(Tp::PendingOperation*)),
|
||||
SLOT(onContactsUpgraded(Tp::PendingOperation*)));
|
||||
}
|
||||
|
||||
void TubesRfbServer::onContactsUpgraded(Tp::PendingOperation *op)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
if (op->isError()) {
|
||||
kWarning() << "Upgrading contacts failed:" << op->errorName() << op->errorMessage();
|
||||
KMessageBox::error(QApplication::activeWindow(),
|
||||
i18n("An unknown error occurred sharing your desktop."),
|
||||
i18n("Error"));
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
offerTube();
|
||||
}
|
||||
|
||||
void TubesRfbServer::offerTube()
|
||||
{
|
||||
kDebug() << "Channel is ready!";
|
||||
|
||||
//start the rfb server
|
||||
if (!start()) {
|
||||
kWarning() << "Could not start rfb server";
|
||||
KMessageBox::error(QApplication::activeWindow(),
|
||||
i18n("Failed to activate the rfb server."),
|
||||
i18n("Error"));
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(d->channel.data(),
|
||||
SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
|
||||
SLOT(onChannelInvalidated(Tp::DBusProxy*, const QString&,
|
||||
const QString&)));
|
||||
|
||||
/* Interface used to control the tube state */
|
||||
Tp::Client::ChannelInterfaceTubeInterface *tubeInterface = d->channel->interface<Tp::Client::ChannelInterfaceTubeInterface>();
|
||||
|
||||
/* Interface used to control stream tube */
|
||||
Tp::Client::ChannelTypeStreamTubeInterface *streamTubeInterface = d->channel->interface<Tp::Client::ChannelTypeStreamTubeInterface>();
|
||||
|
||||
if (streamTubeInterface && tubeInterface) {
|
||||
kDebug() << "Offering tube";
|
||||
|
||||
connect(tubeInterface,
|
||||
SIGNAL(TubeChannelStateChanged(uint)),
|
||||
SLOT(onTubeStateChanged(uint)));
|
||||
|
||||
// Offer the stream tube
|
||||
StreamTubeAddress streamTubeAddress;
|
||||
streamTubeAddress.address = listeningAddress();
|
||||
streamTubeAddress.port = listeningPort();
|
||||
|
||||
kDebug() << "Offering:" << streamTubeAddress.port << streamTubeAddress.address;
|
||||
|
||||
QDBusVariant address;
|
||||
address.setVariant(qVariantFromValue(streamTubeAddress));
|
||||
|
||||
QDBusPendingReply<> ret = streamTubeInterface->Offer(
|
||||
uint(Tp::SocketAddressTypeIPv4),
|
||||
address,
|
||||
uint(Tp::SocketAccessControlPort),
|
||||
QVariantMap());
|
||||
|
||||
connect(new QDBusPendingCallWatcher(ret, this), SIGNAL(finished(QDBusPendingCallWatcher*)),
|
||||
SLOT(onOfferTubeFinished(QDBusPendingCallWatcher*)));
|
||||
connect(streamTubeInterface,
|
||||
SIGNAL(NewRemoteConnection(uint,QDBusVariant,uint)),
|
||||
SLOT(onNewRemoteConnection(uint,QDBusVariant,uint)));
|
||||
}
|
||||
}
|
||||
|
||||
void TubesRfbServer::onOfferTubeFinished(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
QDBusPendingReply<void> reply = *watcher;
|
||||
if (reply.isError()) {
|
||||
kWarning() << "Offer tube failed:" << reply.error();
|
||||
|
||||
if (reply.error().name() == TELEPATHY_ERROR_NOT_AVAILABLE) {
|
||||
KMessageBox::error(QApplication::activeWindow(),
|
||||
i18n("An error occurred sharing your desktop. The person you are "
|
||||
"trying to share your desktop with does not have the required "
|
||||
"software installed to access it."),
|
||||
i18n("Error"));
|
||||
} else {
|
||||
KMessageBox::error(QApplication::activeWindow(),
|
||||
i18n("An unknown error occurred sharing your desktop."),
|
||||
i18n("Error"));
|
||||
}
|
||||
} else {
|
||||
kDebug() << "Offer Tube succeeded.";
|
||||
}
|
||||
}
|
||||
|
||||
void TubesRfbServer::onTubeStateChanged(uint state)
|
||||
{
|
||||
kDebug() << "Tube state changed:" << state;
|
||||
}
|
||||
|
||||
void TubesRfbServer::onNewRemoteConnection(uint handle, QDBusVariant connectionParam, uint connectionId)
|
||||
{
|
||||
Q_UNUSED(connectionId);
|
||||
|
||||
QVariant v = connectionParam.variant();
|
||||
kDebug() << "variant:" << v;
|
||||
StreamTubeAddress ipv4address = qdbus_cast<StreamTubeAddress>(v);
|
||||
|
||||
kDebug() << "NewRemoteConnection: port:" << ipv4address.port << ipv4address.address;
|
||||
|
||||
Q_FOREACH(const Tp::ContactPtr & c, d->channel->groupContacts()) {
|
||||
if (c->handle().value(0) == handle) {
|
||||
d->contactsPerPort[ipv4address.port] = c;
|
||||
if (d->clientsPerPort.contains(ipv4address.port)) {
|
||||
kDebug() << "client already exists";
|
||||
d->clientsPerPort[ipv4address.port]->setContact(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TubesRfbServer::onChannelInvalidated(Tp::DBusProxy *proxy,
|
||||
const QString &errorName, const QString &errorMessage)
|
||||
{
|
||||
Q_UNUSED(proxy);
|
||||
kDebug() << "Tube channel invalidated:" << errorName << errorMessage;
|
||||
cleanup();
|
||||
}
|
||||
|
||||
#include "tubesrfbserver.moc"
|
||||
52
krfb/tubesrfbserver.h
Normal file
52
krfb/tubesrfbserver.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd. <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This program 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 program 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 Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TUBESRFBSERVER_H
|
||||
#define TUBESRFBSERVER_H
|
||||
|
||||
#include "rfbserver.h"
|
||||
#include <TelepathyQt4/Channel>
|
||||
|
||||
class TubesRfbServer : public RfbServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TubesRfbServer(const Tp::ChannelPtr & channel, QObject* parent = 0);
|
||||
virtual ~TubesRfbServer();
|
||||
|
||||
virtual PendingRfbClient* newClient(rfbClientPtr client);
|
||||
|
||||
private Q_SLOTS:
|
||||
void close();
|
||||
void cleanup();
|
||||
void onChannelReady(Tp::PendingOperation *op);
|
||||
void onContactsUpgraded(Tp::PendingOperation *op);
|
||||
void offerTube();
|
||||
void onOfferTubeFinished(QDBusPendingCallWatcher *watcher);
|
||||
void onTubeStateChanged(uint state);
|
||||
void onNewRemoteConnection(uint handle, QDBusVariant connectionParam, uint connectionId);
|
||||
void onChannelInvalidated(Tp::DBusProxy *proxy,
|
||||
const QString &errorName,
|
||||
const QString &errorMessage);
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
#endif // TUBESRFBSERVER_H
|
||||
@@ -12,9 +12,15 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="kcfg_allowUninvitedConnections">
|
||||
<widget class="QCheckBox" name="kcfg_askOnConnect">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow uninvited connections</string>
|
||||
<string>Ask before accepting connections</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -29,15 +35,9 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="kcfg_askOnConnect">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QCheckBox" name="kcfg_allowUninvitedConnections">
|
||||
<property name="text">
|
||||
<string>Ask before accepting connections</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
<string>Allow uninvited connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -88,22 +88,6 @@
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>kcfg_allowUninvitedConnections</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>kcfg_askOnConnect</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>22</x>
|
||||
<y>24</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>29</x>
|
||||
<y>80</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>kcfg_allowUninvitedConnections</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
114
krfb/ui/tubesconnectionwidget.ui
Normal file
114
krfb/ui/tubesconnectionwidget.ui
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TubesConnectionWidget</class>
|
||||
<widget class="QWidget" name="TubesConnectionWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="pixmapLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="TextLabel5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>13</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Confirmation</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mainTextLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="midLineWidth">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbAllowRemoteControl">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>If you turn this option on, the remote user can enter keystrokes and use your mouse pointer. This gives them full control over your computer, so be careful. When the option is disabled the remote user can only watch your screen.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow remote user to &control keyboard and mouse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
322
krfbserver.cpp
322
krfbserver.cpp
@@ -1,322 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "krfbserver.h"
|
||||
#include "krfbserver.moc"
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
#include <QHostInfo>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QPointer>
|
||||
|
||||
#include <KGlobal>
|
||||
#include <KUser>
|
||||
#include <KLocale>
|
||||
#include <KDebug>
|
||||
#include <KMessageBox>
|
||||
#include <dnssd/publicservice.h>
|
||||
|
||||
#include "connectioncontroller.h"
|
||||
#include "framebuffer.h"
|
||||
#include "framebuffermanager.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "invitationmanager.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
|
||||
static const char* cur=
|
||||
" "
|
||||
" x "
|
||||
" xx "
|
||||
" xxx "
|
||||
" xxxx "
|
||||
" xxxxx "
|
||||
" xxxxxx "
|
||||
" xxxxxxx "
|
||||
" xxxxxxxx "
|
||||
" xxxxxxxxx "
|
||||
" xxxxxxxxxx "
|
||||
" xxxxx "
|
||||
" xx xxx "
|
||||
" x xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" ";
|
||||
|
||||
static const char* mask=
|
||||
"xx "
|
||||
"xxx "
|
||||
"xxxx "
|
||||
"xxxxx "
|
||||
"xxxxxx "
|
||||
"xxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxxxxx "
|
||||
"xxxxxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xx xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxx ";
|
||||
|
||||
static rfbCursorPtr myCursor;
|
||||
|
||||
|
||||
static enum rfbNewClientAction newClientHook(struct _rfbClientRec *cl)
|
||||
{
|
||||
KrfbServer *server = KrfbServer::self();
|
||||
return server->handleNewClient(cl);
|
||||
}
|
||||
|
||||
static rfbBool passwordCheck(rfbClientPtr cl,
|
||||
const char* encryptedPassword,
|
||||
int len)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
return cc->handleCheckPassword(cl, encryptedPassword, len);
|
||||
}
|
||||
|
||||
static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->handleKeyEvent(down ? true : false, keySym);
|
||||
}
|
||||
|
||||
static void pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->handlePointerEvent(bm, x, y);
|
||||
}
|
||||
|
||||
static void clipboardHook(char* str,int len, rfbClientPtr cl)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->clipboardToServer(QString::fromUtf8(str, len));
|
||||
}
|
||||
|
||||
|
||||
class KrfbServer::KrfbServerP {
|
||||
|
||||
public:
|
||||
KrfbServerP() : screen(0), numClients(0) {};
|
||||
|
||||
QSharedPointer<FrameBuffer> fb;
|
||||
QList< QPointer<ConnectionController> > controllers;
|
||||
rfbScreenInfoPtr screen;
|
||||
int numClients;
|
||||
QByteArray desktopName;
|
||||
QTimer rfbProcessEventTimer;
|
||||
};
|
||||
|
||||
class KrfbServerPrivate
|
||||
{
|
||||
public:
|
||||
KrfbServer instance;
|
||||
};
|
||||
|
||||
K_GLOBAL_STATIC(KrfbServerPrivate, krfbServerPrivate)
|
||||
|
||||
KrfbServer * KrfbServer::self() {
|
||||
return &krfbServerPrivate->instance;
|
||||
}
|
||||
|
||||
|
||||
KrfbServer::KrfbServer()
|
||||
:d(new KrfbServerP)
|
||||
{
|
||||
kDebug() << "starting ";
|
||||
d->fb = FrameBufferManager::instance()->frameBuffer(QApplication::desktop()->winId());
|
||||
QTimer::singleShot(0, this, SLOT(startListening()));
|
||||
connect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)),SLOT(updatePassword()));
|
||||
}
|
||||
|
||||
KrfbServer::~KrfbServer()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
void KrfbServer::startListening()
|
||||
{
|
||||
rfbScreenInfoPtr screen;
|
||||
|
||||
int port = KrfbConfig::port();
|
||||
|
||||
int w = d->fb->width();
|
||||
int h = d->fb->height();
|
||||
int depth = d->fb->depth();
|
||||
|
||||
int bpp = depth >> 3;
|
||||
if (bpp != 1 && bpp != 2 && bpp != 4) bpp = 4;
|
||||
kDebug() << "bpp: " << bpp;
|
||||
|
||||
rfbLogEnable(0);
|
||||
screen = rfbGetScreen(0, 0, w, h, 8, 3, bpp);
|
||||
|
||||
screen->paddedWidthInBytes = d->fb->paddedWidth();
|
||||
|
||||
d->fb->getServerFormat(screen->serverFormat);
|
||||
|
||||
screen->frameBuffer = d->fb->data();
|
||||
d->screen = screen;
|
||||
screen->autoPort = 0;
|
||||
screen->port = port;
|
||||
|
||||
// server hooks
|
||||
screen->newClientHook = newClientHook;
|
||||
|
||||
screen->kbdAddEvent = keyboardHook;
|
||||
screen->ptrAddEvent = pointerHook;
|
||||
screen->newClientHook = newClientHook;
|
||||
screen->passwordCheck = passwordCheck;
|
||||
screen->setXCutText = clipboardHook;
|
||||
|
||||
d->desktopName = i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()).toLatin1();
|
||||
screen->desktopName = d->desktopName.constData();
|
||||
|
||||
if (!myCursor) {
|
||||
myCursor = rfbMakeXCursor(19, 19, (char*) cur, (char*) mask);
|
||||
}
|
||||
screen->cursor = myCursor;
|
||||
|
||||
// configure passwords and desktop control here
|
||||
updateSettings();
|
||||
|
||||
rfbInitServer(screen);
|
||||
if (!rfbIsActive(screen)) {
|
||||
KMessageBox::error(0,i18n("Address already in use"),"krfb");
|
||||
shutdown();
|
||||
qApp->quit();
|
||||
return;
|
||||
};
|
||||
|
||||
if (KrfbConfig::publishService()) {
|
||||
DNSSD::PublicService *service = new DNSSD::PublicService(i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()),"_rfb._tcp",port);
|
||||
service->publishAsync();
|
||||
}
|
||||
|
||||
/* Integrate the rfb event mechanism with qt's event loop.
|
||||
* Call processRfbEvents() every time the qt event loop is run,
|
||||
* so that it also processes and delivers rfb events and call
|
||||
* shutdown() when QApplication exits to shutdown the rfb server
|
||||
* before the X11 connection goes down.
|
||||
*/
|
||||
connect(&d->rfbProcessEventTimer, SIGNAL(timeout()), SLOT(processRfbEvents()));
|
||||
connect(qApp, SIGNAL(aboutToQuit()), SLOT(shutdown()));
|
||||
d->rfbProcessEventTimer.start(0);
|
||||
}
|
||||
|
||||
void KrfbServer::processRfbEvents()
|
||||
{
|
||||
foreach(const QRect &r, d->fb->modifiedTiles()) {
|
||||
rfbMarkRectAsModified(d->screen, r.x(), r.y(), r.right(), r.bottom());
|
||||
}
|
||||
rfbProcessEvents(d->screen, 100);
|
||||
}
|
||||
|
||||
void KrfbServer::shutdown()
|
||||
{
|
||||
rfbShutdownServer(d->screen, true);
|
||||
// framebuffer has to be deleted before X11 connection goes down
|
||||
d->fb.clear();
|
||||
}
|
||||
|
||||
|
||||
void KrfbServer::enableDesktopControl(bool enable)
|
||||
{
|
||||
foreach (QPointer<ConnectionController> ptr, d->controllers) {
|
||||
if (ptr) {
|
||||
if (ptr->controlCanBeEnabled()) {
|
||||
ptr->setControlEnabled(enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum rfbNewClientAction KrfbServer::handleNewClient(struct _rfbClientRec * cl)
|
||||
{
|
||||
ConnectionController *cc = new ConnectionController(cl, this);
|
||||
if (d->numClients++ == 0)
|
||||
d->fb->startMonitor();
|
||||
|
||||
d->controllers.append(cc);
|
||||
cc->setControlEnabled(KrfbConfig::allowDesktopControl());
|
||||
cc->setControlCanBeEnabled(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(cc, SIGNAL(sessionEstablished(QString)), SIGNAL(sessionEstablished(QString)));
|
||||
connect(cc, SIGNAL(clientDisconnected(ConnectionController *)),SLOT(clientDisconnected(ConnectionController *)));
|
||||
|
||||
return cc->handleNewClient();
|
||||
}
|
||||
|
||||
void KrfbServer::updateSettings()
|
||||
{
|
||||
enableDesktopControl(KrfbConfig::allowDesktopControl());
|
||||
updatePassword();
|
||||
}
|
||||
|
||||
void KrfbServer::updatePassword()
|
||||
{
|
||||
|
||||
if (!d->screen) return;
|
||||
QString pw = KrfbConfig::uninvitedConnectionPassword();
|
||||
kDebug() << "password: " << pw << " allow " <<
|
||||
KrfbConfig::allowUninvitedConnections() <<
|
||||
" invitations " << InvitationManager::self()->activeInvitations() << endl;
|
||||
|
||||
if (pw.isEmpty() && InvitationManager::self()->activeInvitations() == 0) {
|
||||
kDebug() << "no password from now on";
|
||||
d->screen->authPasswdData = (void *)0;
|
||||
} else {
|
||||
kDebug() << "Ask for password to accept connections";
|
||||
d->screen->authPasswdData = (void *)1;
|
||||
}
|
||||
}
|
||||
|
||||
bool KrfbServer::checkX11Capabilities() {
|
||||
int bp1, bp2, majorv, minorv;
|
||||
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
|
||||
&majorv, &minorv);
|
||||
if ((!r) || (((majorv*1000)+minorv) < 2002)) {
|
||||
KMessageBox::error(0,
|
||||
i18n("Your X11 Server does not support the required XTest extension version 2.2. Sharing your desktop is not possible."),
|
||||
i18n("Desktop Sharing Error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KrfbServer::clientDisconnected(ConnectionController *cc)
|
||||
{
|
||||
kDebug() << "clients--: " << d->numClients;
|
||||
if (!--d->numClients) {
|
||||
d->fb->stopMonitor();
|
||||
kDebug() << "stopMonitor: d->numClients = " << d->numClients;
|
||||
}
|
||||
disconnect(cc, SIGNAL(clientDisconnected(ConnectionController*)),this, SLOT(clientDisconnected(ConnectionController*)));
|
||||
|
||||
Q_EMIT sessionFinished();
|
||||
}
|
||||
|
||||
|
||||
59
krfbserver.h
59
krfbserver.h
@@ -1,59 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program 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.
|
||||
*/
|
||||
|
||||
#ifndef KRFBSERVER_H
|
||||
#define KRFBSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
class ConnectionController;
|
||||
/**
|
||||
This class implements the listening server for the RFB protocol.
|
||||
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class KrfbServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class KrfbServerPrivate;
|
||||
public:
|
||||
|
||||
static KrfbServer *self();
|
||||
|
||||
~KrfbServer();
|
||||
|
||||
enum rfbNewClientAction handleNewClient(struct _rfbClientRec *cl);
|
||||
bool checkX11Capabilities();
|
||||
|
||||
signals:
|
||||
void sessionEstablished(QString);
|
||||
void sessionFinished();
|
||||
void desktopControlSettingChanged(bool);
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
void startListening();
|
||||
void processRfbEvents();
|
||||
void shutdown();
|
||||
void enableDesktopControl(bool);
|
||||
void updateSettings();
|
||||
void updatePassword();
|
||||
void clientDisconnected(ConnectionController *);
|
||||
|
||||
private:
|
||||
KrfbServer();
|
||||
static KrfbServer *_self;
|
||||
|
||||
class KrfbServerP;
|
||||
KrfbServerP * const d;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
132
libvncserver/CMakeLists.txt
Normal file
132
libvncserver/CMakeLists.txt
Normal file
@@ -0,0 +1,132 @@
|
||||
# Striped down version of libvncserver's original CMakeLists.txt
|
||||
|
||||
project(LibVNCServer)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckTypeSize)
|
||||
include(TestBigEndian)
|
||||
include(MacroBoolTo01)
|
||||
|
||||
set(FULL_PACKAGE_NAME "Krfb LibVNCServer")
|
||||
set(PACKAGE_VERSION "0.9.8-10-g17ce0c5")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
macro_optional_find_package(ZLIB)
|
||||
macro_log_feature(ZLIB_FOUND "ZLib" "The Zlib compression library" "http://www.zlib.net" FALSE "" "Used by the vncserver library.")
|
||||
|
||||
macro_optional_find_package(JPEG)
|
||||
macro_log_feature(JPEG_FOUND "LibJPEG" "The JPEG library" "" FALSE "" "Used by the vncserver library")
|
||||
|
||||
macro_bool_to_01(ZLIB_FOUND LIBVNCSERVER_HAVE_LIBZ)
|
||||
macro_bool_to_01(JPEG_FOUND LIBVNCSERVER_HAVE_LIBJPEG)
|
||||
option(LIBVNCSERVER_ALLOW24BPP "Allow 24 bpp" ON)
|
||||
# if(GNUTLS_FOUND)
|
||||
# set(LIBVNCSERVER_WITH_CLIENT_TLS 1)
|
||||
# endif(GNUTLS_FOUND)
|
||||
# if(LIBGCRYPT_LIBRARIES)
|
||||
# message(STATUS "Found libgcrypt: ${LIBGCRYPT_LIBRARIES}")
|
||||
# set(LIBVNCSERVER_WITH_CLIENT_GCRYPT 1)
|
||||
# endif(LIBGCRYPT_LIBRARIES)
|
||||
|
||||
|
||||
check_include_file("fcntl.h" LIBVNCSERVER_HAVE_FCNTL_H)
|
||||
check_include_file("netinet/in.h" LIBVNCSERVER_HAVE_NETINET_IN_H)
|
||||
check_include_file("sys/socket.h" LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
check_include_file("sys/stat.h" LIBVNCSERVER_HAVE_SYS_STAT_H)
|
||||
check_include_file("sys/time.h" LIBVNCSERVER_HAVE_SYS_TIME_H)
|
||||
check_include_file("sys/types.h" LIBVNCSERVER_HAVE_SYS_TYPES_H)
|
||||
check_include_file("sys/wait.h" LIBVNCSERVER_HAVE_SYS_WAIT_H)
|
||||
check_include_file("unistd.h" LIBVNCSERVER_HAVE_UNISTD_H)
|
||||
|
||||
# headers needed for check_type_size()
|
||||
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
|
||||
check_include_file("stdint.h" HAVE_STDINT_H)
|
||||
check_include_file("stddef.h" HAVE_STDDEF_H)
|
||||
check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
|
||||
|
||||
check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY)
|
||||
|
||||
macro_bool_to_01(CMAKE_USE_PTHREADS_INIT LIBVNCSERVER_HAVE_LIBPTHREAD)
|
||||
if(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
# socklen_t
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
|
||||
endif(LIBVNCSERVER_HAVE_SYS_SOCKET_H)
|
||||
if(HAVE_ARPA_INET_H)
|
||||
# in_addr_t
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "arpa/inet.h")
|
||||
endif(HAVE_ARPA_INET_H)
|
||||
|
||||
check_type_size(pid_t LIBVNCSERVER_PID_T)
|
||||
check_type_size(size_t LIBVNCSERVER_SIZE_T)
|
||||
check_type_size(socklen_t LIBVNCSERVER_SOCKLEN_T)
|
||||
check_type_size(in_addr_t LIBVNCSERVER_IN_ADDR_T)
|
||||
if(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
|
||||
set(LIBVNCSERVER_NEED_INADDR_T 1)
|
||||
endif(NOT HAVE_LIBVNCSERVER_IN_ADDR_T)
|
||||
|
||||
test_big_endian(LIBVNCSERVER_WORDS_BIGENDIAN)
|
||||
|
||||
|
||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/libvncserver-config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libvncserver-config.h
|
||||
)
|
||||
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
main.c
|
||||
rfbserver.c
|
||||
rfbregion.c
|
||||
auth.c
|
||||
sockets.c
|
||||
stats.c
|
||||
corre.c
|
||||
hextile.c
|
||||
rre.c
|
||||
translate.c
|
||||
cutpaste.c
|
||||
httpd.c
|
||||
cursor.c
|
||||
font.c
|
||||
draw.c
|
||||
selbox.c
|
||||
d3des.c
|
||||
vncauth.c
|
||||
cargs.c
|
||||
minilzo.c
|
||||
ultra.c
|
||||
scale.c
|
||||
)
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
add_definitions(-DLIBVNCSERVER_HAVE_LIBZ)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
${LIBVNCSERVER_SOURCES}
|
||||
zlib.c
|
||||
zrle.c
|
||||
zrleoutstream.c
|
||||
zrlepalettehelper.c
|
||||
)
|
||||
endif(ZLIB_FOUND)
|
||||
|
||||
if(JPEG_FOUND)
|
||||
add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG)
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
set(LIBVNCSERVER_SOURCES
|
||||
${LIBVNCSERVER_SOURCES}
|
||||
tight.c
|
||||
)
|
||||
endif(JPEG_FOUND)
|
||||
|
||||
|
||||
add_library(vncserver STATIC ${LIBVNCSERVER_SOURCES})
|
||||
|
||||
if(WIN32)
|
||||
set(ADDITIONAL_LIBS ws2_32)
|
||||
endif(WIN32)
|
||||
|
||||
target_link_libraries(vncserver
|
||||
${ADDITIONAL_LIBS}
|
||||
${ZLIB_LIBRARIES}
|
||||
${JPEG_LIBRARIES}
|
||||
)
|
||||
375
libvncserver/auth.c
Normal file
375
libvncserver/auth.c
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* auth.c - deal with authentication.
|
||||
*
|
||||
* This file implements the VNC authentication protocol when setting up an RFB
|
||||
* connection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/* RFB 3.8 clients are well informed */
|
||||
void rfbClientSendString(rfbClientPtr cl, const char *reason);
|
||||
|
||||
|
||||
/*
|
||||
* Handle security types
|
||||
*/
|
||||
|
||||
static rfbSecurityHandler* securityHandlers = NULL;
|
||||
|
||||
/*
|
||||
* This method registers a list of new security types.
|
||||
* It avoids same security type getting registered multiple times.
|
||||
* The order is not preserved if multiple security types are
|
||||
* registered at one-go.
|
||||
*/
|
||||
void
|
||||
rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
|
||||
{
|
||||
rfbSecurityHandler *head = securityHandlers, *next = NULL;
|
||||
|
||||
if(handler == NULL)
|
||||
return;
|
||||
|
||||
next = handler->next;
|
||||
|
||||
while(head != NULL) {
|
||||
if(head == handler) {
|
||||
rfbRegisterSecurityHandler(next);
|
||||
return;
|
||||
}
|
||||
|
||||
head = head->next;
|
||||
}
|
||||
|
||||
handler->next = securityHandlers;
|
||||
securityHandlers = handler;
|
||||
|
||||
rfbRegisterSecurityHandler(next);
|
||||
}
|
||||
|
||||
/*
|
||||
* This method unregisters a list of security types.
|
||||
* These security types won't be available for any new
|
||||
* client connection.
|
||||
*/
|
||||
void
|
||||
rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
|
||||
{
|
||||
rfbSecurityHandler *cur = NULL, *pre = NULL;
|
||||
|
||||
if(handler == NULL)
|
||||
return;
|
||||
|
||||
if(securityHandlers == handler) {
|
||||
securityHandlers = securityHandlers->next;
|
||||
rfbUnregisterSecurityHandler(handler->next);
|
||||
return;
|
||||
}
|
||||
|
||||
cur = pre = securityHandlers;
|
||||
|
||||
while(cur) {
|
||||
if(cur == handler) {
|
||||
pre->next = cur->next;
|
||||
break;
|
||||
}
|
||||
pre = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
rfbUnregisterSecurityHandler(handler->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the authentication challenge.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbVncAuthSendChallenge(rfbClientPtr cl)
|
||||
{
|
||||
|
||||
/* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth
|
||||
(same as rfbVncAuth). Just send the challenge. */
|
||||
rfbRandomBytes(cl->authChallenge);
|
||||
if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
|
||||
rfbLogPerror("rfbAuthNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbVncAuthProcessResponse. */
|
||||
cl->state = RFB_AUTHENTICATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the NO AUTHENTICATION. SCARR
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbVncAuthNone(rfbClientPtr cl)
|
||||
{
|
||||
uint32_t authResult;
|
||||
|
||||
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) {
|
||||
rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n");
|
||||
authResult = Swap32IfLE(rfbVncAuthOK);
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cl->state = RFB_INITIALISATION;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Advertise the supported security types (protocol 3.7). Here before sending
|
||||
* the list of security types to the client one more security type is added
|
||||
* to the list if primaryType is not set to rfbSecTypeInvalid. This security
|
||||
* type is the standard vnc security type which does the vnc authentication
|
||||
* or it will be security type for no authentication.
|
||||
* Different security types will be added by applications using this library.
|
||||
*/
|
||||
|
||||
static rfbSecurityHandler VncSecurityHandlerVncAuth = {
|
||||
rfbSecTypeVncAuth,
|
||||
rfbVncAuthSendChallenge,
|
||||
NULL
|
||||
};
|
||||
|
||||
static rfbSecurityHandler VncSecurityHandlerNone = {
|
||||
rfbSecTypeNone,
|
||||
rfbVncAuthNone,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
|
||||
{
|
||||
/* The size of the message is the count of security types +1,
|
||||
* since the first byte is the number of types. */
|
||||
int size = 1;
|
||||
rfbSecurityHandler* handler;
|
||||
#define MAX_SECURITY_TYPES 255
|
||||
uint8_t buffer[MAX_SECURITY_TYPES+1];
|
||||
|
||||
|
||||
/* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
|
||||
switch (primaryType) {
|
||||
case rfbSecTypeNone:
|
||||
rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
|
||||
break;
|
||||
case rfbSecTypeVncAuth:
|
||||
rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
|
||||
break;
|
||||
}
|
||||
|
||||
for (handler = securityHandlers;
|
||||
handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
|
||||
buffer[size] = handler->type;
|
||||
size++;
|
||||
}
|
||||
buffer[0] = (unsigned char)size-1;
|
||||
|
||||
/* Send the list. */
|
||||
if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
|
||||
rfbLogPerror("rfbSendSecurityTypeList: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if count is 0, we need to send the reason and close the connection.
|
||||
*/
|
||||
if(size <= 1) {
|
||||
/* This means total count is Zero and so reason msg should be sent */
|
||||
/* The execution should never reach here */
|
||||
char* reason = "No authentication mode is registered!";
|
||||
|
||||
rfbClientSendString(cl, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbProcessClientSecurityType. */
|
||||
cl->state = RFB_SECURITY_TYPE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Tell the client what security type will be used (protocol 3.3).
|
||||
*/
|
||||
static void
|
||||
rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
|
||||
{
|
||||
uint32_t value32;
|
||||
|
||||
/* Send the value. */
|
||||
value32 = Swap32IfLE(securityType);
|
||||
if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
|
||||
rfbLogPerror("rfbSendSecurityType: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Decide what to do next. */
|
||||
switch (securityType) {
|
||||
case rfbSecTypeNone:
|
||||
/* Dispatch client input to rfbProcessClientInitMessage. */
|
||||
cl->state = RFB_INITIALISATION;
|
||||
break;
|
||||
case rfbSecTypeVncAuth:
|
||||
/* Begin the standard VNC authentication procedure. */
|
||||
rfbVncAuthSendChallenge(cl);
|
||||
break;
|
||||
default:
|
||||
/* Impossible case (hopefully). */
|
||||
rfbLogPerror("rfbSendSecurityType: assertion failed");
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbAuthNewClient is called right after negotiating the protocol
|
||||
* version. Depending on the protocol version, we send either a code
|
||||
* for authentication scheme to be used (protocol 3.3), or a list of
|
||||
* possible "security types" (protocol 3.7).
|
||||
*/
|
||||
|
||||
void
|
||||
rfbAuthNewClient(rfbClientPtr cl)
|
||||
{
|
||||
int32_t securityType = rfbSecTypeInvalid;
|
||||
|
||||
if (!cl->screen->authPasswdData || cl->reverseConnection) {
|
||||
/* chk if this condition is valid or not. */
|
||||
securityType = rfbSecTypeNone;
|
||||
} else if (cl->screen->authPasswdData) {
|
||||
securityType = rfbSecTypeVncAuth;
|
||||
}
|
||||
|
||||
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
|
||||
{
|
||||
/* Make sure we use only RFB 3.3 compatible security types. */
|
||||
if (securityType == rfbSecTypeInvalid) {
|
||||
rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
|
||||
rfbClientConnFailed(cl, "Your viewer cannot handle required "
|
||||
"authentication methods");
|
||||
return;
|
||||
}
|
||||
rfbSendSecurityType(cl, securityType);
|
||||
} else {
|
||||
/* Here it's ok when securityType is set to rfbSecTypeInvalid. */
|
||||
rfbSendSecurityTypeList(cl, securityType);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the security type chosen by the client (protocol 3.7).
|
||||
*/
|
||||
|
||||
void
|
||||
rfbProcessClientSecurityType(rfbClientPtr cl)
|
||||
{
|
||||
int n;
|
||||
uint8_t chosenType;
|
||||
rfbSecurityHandler* handler;
|
||||
|
||||
/* Read the security type. */
|
||||
n = rfbReadExact(cl, (char *)&chosenType, 1);
|
||||
if (n <= 0) {
|
||||
if (n == 0)
|
||||
rfbLog("rfbProcessClientSecurityType: client gone\n");
|
||||
else
|
||||
rfbLogPerror("rfbProcessClientSecurityType: read");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure it was present in the list sent by the server. */
|
||||
for (handler = securityHandlers; handler; handler = handler->next) {
|
||||
if (chosenType == handler->type) {
|
||||
rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
|
||||
handler->handler(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbAuthProcessClientMessage is called when the client sends its
|
||||
* authentication response.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbAuthProcessClientMessage(rfbClientPtr cl)
|
||||
{
|
||||
int n;
|
||||
uint8_t response[CHALLENGESIZE];
|
||||
uint32_t authResult;
|
||||
|
||||
if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
|
||||
if (n != 0)
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: read");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
|
||||
rfbErr("rfbAuthProcessClientMessage: password check failed\n");
|
||||
authResult = Swap32IfLE(rfbVncAuthFailed);
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
}
|
||||
/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
|
||||
if (cl->protocolMinorVersion > 7) {
|
||||
rfbClientSendString(cl, "password check failed!");
|
||||
}
|
||||
else
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
authResult = Swap32IfLE(rfbVncAuthOK);
|
||||
|
||||
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
|
||||
rfbLogPerror("rfbAuthProcessClientMessage: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
cl->state = RFB_INITIALISATION;
|
||||
}
|
||||
213
libvncserver/cargs.c
Normal file
213
libvncserver/cargs.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* This parses the command line arguments. It was seperated from main.c by
|
||||
* Justin Dearing <jdeari01@longisland.poly.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
|
||||
* Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* see GPL (latest version) for full details
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
extern int rfbStringToAddr(char *str, in_addr_t *iface);
|
||||
|
||||
void
|
||||
rfbUsage(void)
|
||||
{
|
||||
rfbProtocolExtension* extension;
|
||||
|
||||
fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
|
||||
fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n");
|
||||
fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n"
|
||||
" (use 'storepasswd' to create a password file)\n");
|
||||
fprintf(stderr, "-rfbversion 3.x Set the version of the RFB we choose to advertise\n");
|
||||
fprintf(stderr, "-permitfiletransfer permit file transfer support\n");
|
||||
fprintf(stderr, "-passwd plain-password use authentication \n"
|
||||
" (use plain-password as password, USE AT YOUR RISK)\n");
|
||||
fprintf(stderr, "-deferupdate time time in ms to defer updates "
|
||||
"(default 40)\n");
|
||||
fprintf(stderr, "-deferptrupdate time time in ms to defer pointer updates"
|
||||
" (default none)\n");
|
||||
fprintf(stderr, "-desktop name VNC desktop name (default \"LibVNCServer\")\n");
|
||||
fprintf(stderr, "-alwaysshared always treat new clients as shared\n");
|
||||
fprintf(stderr, "-nevershared never treat new clients as shared\n");
|
||||
fprintf(stderr, "-dontdisconnect don't disconnect existing clients when a "
|
||||
"new non-shared\n"
|
||||
" connection comes in (refuse new connection "
|
||||
"instead)\n");
|
||||
fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n");
|
||||
fprintf(stderr, "-httpport portnum use portnum for http connection\n");
|
||||
fprintf(stderr, "-enablehttpproxy enable http proxy support\n");
|
||||
fprintf(stderr, "-progressive height enable progressive updating for slow links\n");
|
||||
fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n");
|
||||
fprintf(stderr, " addr ipaddr. '-listen localhost' and hostname work too.\n");
|
||||
|
||||
for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
|
||||
if(extension->usage)
|
||||
extension->usage();
|
||||
rfbReleaseExtensionIterator();
|
||||
}
|
||||
|
||||
/* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
|
||||
POSITION points to the first non purged argument afterwards. */
|
||||
void rfbPurgeArguments(int* argc,int* position,int count,char *argv[])
|
||||
{
|
||||
int amount=(*argc)-(*position)-count;
|
||||
if(amount)
|
||||
memmove(argv+(*position),argv+(*position)+count,sizeof(char*)*amount);
|
||||
(*argc)-=count;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
|
||||
{
|
||||
int i,i1;
|
||||
|
||||
if(!argc) return TRUE;
|
||||
|
||||
for (i = i1 = 1; i < *argc;) {
|
||||
if (strcmp(argv[i], "-help") == 0) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
} else if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->port = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->maxClientWait = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->authPasswdData = argv[++i];
|
||||
|
||||
} else if (strcmp(argv[i], "-permitfiletransfer") == 0) { /* -permitfiletransfer */
|
||||
rfbScreen->permitFileTransfer = TRUE;
|
||||
} else if (strcmp(argv[i], "-rfbversion") == 0) { /* -rfbversion 3.6 */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
sscanf(argv[++i],"%d.%d", &rfbScreen->protocolMajorVersion, &rfbScreen->protocolMinorVersion);
|
||||
} else if (strcmp(argv[i], "-passwd") == 0) { /* -passwd password */
|
||||
char **passwds = malloc(sizeof(char**)*2);
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
passwds[0] = argv[++i];
|
||||
passwds[1] = NULL;
|
||||
rfbScreen->authPasswdData = (void*)passwds;
|
||||
rfbScreen->passwordCheck = rfbCheckPasswordByList;
|
||||
} else if (strcmp(argv[i], "-deferupdate") == 0) { /* -deferupdate milliseconds */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->deferUpdateTime = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-deferptrupdate") == 0) { /* -deferptrupdate milliseconds */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->deferPtrUpdateTime = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->desktopName = argv[++i];
|
||||
} else if (strcmp(argv[i], "-alwaysshared") == 0) {
|
||||
rfbScreen->alwaysShared = TRUE;
|
||||
} else if (strcmp(argv[i], "-nevershared") == 0) {
|
||||
rfbScreen->neverShared = TRUE;
|
||||
} else if (strcmp(argv[i], "-dontdisconnect") == 0) {
|
||||
rfbScreen->dontDisconnect = TRUE;
|
||||
} else if (strcmp(argv[i], "-httpdir") == 0) { /* -httpdir directory-path */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->httpDir = argv[++i];
|
||||
} else if (strcmp(argv[i], "-httpport") == 0) { /* -httpport portnum */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->httpPort = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-enablehttpproxy") == 0) {
|
||||
rfbScreen->httpEnableProxyConnect = TRUE;
|
||||
} else if (strcmp(argv[i], "-progressive") == 0) { /* -httpport portnum */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
rfbScreen->progressiveSliceHeight = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-listen") == 0) { /* -listen ipaddr */
|
||||
if (i + 1 >= *argc) {
|
||||
rfbUsage();
|
||||
return FALSE;
|
||||
}
|
||||
if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
rfbProtocolExtension* extension;
|
||||
int handled=0;
|
||||
|
||||
for(extension=rfbGetExtensionIterator();handled==0 && extension;
|
||||
extension=extension->next)
|
||||
if(extension->processArgument)
|
||||
handled = extension->processArgument(*argc - i, argv + i);
|
||||
rfbReleaseExtensionIterator();
|
||||
|
||||
if(handled==0) {
|
||||
i++;
|
||||
i1=i;
|
||||
continue;
|
||||
}
|
||||
i+=handled-1;
|
||||
}
|
||||
/* we just remove the processed arguments from the list */
|
||||
rfbPurgeArguments(argc,&i1,i-i1+1,argv);
|
||||
i=i1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[])
|
||||
{
|
||||
int i,i1;
|
||||
|
||||
if(!argc) return TRUE;
|
||||
for (i = i1 = 1; i < *argc-1;) {
|
||||
if (strcmp(argv[i], "-bpp") == 0) {
|
||||
*bpp = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-width") == 0) {
|
||||
*width = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-height") == 0) {
|
||||
*height = atoi(argv[++i]);
|
||||
} else {
|
||||
i++;
|
||||
i1=i;
|
||||
continue;
|
||||
}
|
||||
rfbPurgeArguments(argc,&i1,i-i1,argv);
|
||||
i=i1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
342
libvncserver/corre.c
Normal file
342
libvncserver/corre.c
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* corre.c
|
||||
*
|
||||
* Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This
|
||||
* code is based on krw's original javatel rfbserver.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 RealVNC Ltd.
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
/*
|
||||
* cl->beforeEncBuf contains pixel data in the client's format.
|
||||
* cl->afterEncBuf contains the RRE encoded version. If the RRE encoded version is
|
||||
* larger than the raw data or if it exceeds cl->afterEncBufSize then
|
||||
* raw encoding is used instead.
|
||||
*/
|
||||
|
||||
static int subrectEncode8(rfbClientPtr cl, uint8_t *data, int w, int h);
|
||||
static int subrectEncode16(rfbClientPtr cl, uint16_t *data, int w, int h);
|
||||
static int subrectEncode32(rfbClientPtr cl, uint32_t *data, int w, int h);
|
||||
static uint32_t getBgColour(char *data, int size, int bpp);
|
||||
static rfbBool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
|
||||
int w, int h);
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE
|
||||
* encoding.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendRectEncodingCoRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
if (h > cl->correMaxHeight) {
|
||||
return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) &&
|
||||
rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w,
|
||||
h - cl->correMaxHeight));
|
||||
}
|
||||
|
||||
if (w > cl->correMaxWidth) {
|
||||
return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) &&
|
||||
rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
|
||||
w - cl->correMaxWidth, h));
|
||||
}
|
||||
|
||||
rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256)
|
||||
* rectangle using CoRRE encoding.
|
||||
*/
|
||||
|
||||
static rfbBool
|
||||
rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbRREHeader hdr;
|
||||
int nSubrects;
|
||||
int i;
|
||||
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
|
||||
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
|
||||
|
||||
int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height
|
||||
* (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->beforeEncBufSize < maxRawSize) {
|
||||
cl->beforeEncBufSize = maxRawSize;
|
||||
if (cl->beforeEncBuf == NULL)
|
||||
cl->beforeEncBuf = (char *)malloc(cl->beforeEncBufSize);
|
||||
else
|
||||
cl->beforeEncBuf = (char *)realloc(cl->beforeEncBuf, cl->beforeEncBufSize);
|
||||
}
|
||||
|
||||
if (cl->afterEncBufSize < maxRawSize) {
|
||||
cl->afterEncBufSize = maxRawSize;
|
||||
if (cl->afterEncBuf == NULL)
|
||||
cl->afterEncBuf = (char *)malloc(cl->afterEncBufSize);
|
||||
else
|
||||
cl->afterEncBuf = (char *)realloc(cl->afterEncBuf, cl->afterEncBufSize);
|
||||
}
|
||||
|
||||
(*cl->translateFn)(cl->translateLookupTable,&(cl->screen->serverFormat),
|
||||
&cl->format, fbptr, cl->beforeEncBuf,
|
||||
cl->scaledScreen->paddedWidthInBytes, w, h);
|
||||
|
||||
switch (cl->format.bitsPerPixel) {
|
||||
case 8:
|
||||
nSubrects = subrectEncode8(cl, (uint8_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 16:
|
||||
nSubrects = subrectEncode16(cl, (uint16_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
case 32:
|
||||
nSubrects = subrectEncode32(cl, (uint32_t *)cl->beforeEncBuf, w, h);
|
||||
break;
|
||||
default:
|
||||
rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nSubrects < 0) {
|
||||
|
||||
/* RRE encoding was too large, use raw */
|
||||
|
||||
return rfbSendRectEncodingRaw(cl, x, y, w, h);
|
||||
}
|
||||
|
||||
rfbStatRecordEncodingSent(cl,rfbEncodingCoRRE,
|
||||
sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + cl->afterEncBufLen,
|
||||
sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8));
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
|
||||
> UPDATE_BUF_SIZE)
|
||||
{
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.r.x = Swap16IfLE(x);
|
||||
rect.r.y = Swap16IfLE(y);
|
||||
rect.r.w = Swap16IfLE(w);
|
||||
rect.r.h = Swap16IfLE(h);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
hdr.nSubrects = Swap32IfLE(nSubrects);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader);
|
||||
cl->ublen += sz_rfbRREHeader;
|
||||
|
||||
for (i = 0; i < cl->afterEncBufLen;) {
|
||||
|
||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
||||
|
||||
if (i + bytesToCopy > cl->afterEncBufLen) {
|
||||
bytesToCopy = cl->afterEncBufLen - i;
|
||||
}
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], &cl->afterEncBuf[i], bytesToCopy);
|
||||
|
||||
cl->ublen += bytesToCopy;
|
||||
i += bytesToCopy;
|
||||
|
||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* subrectEncode() encodes the given multicoloured rectangle as a background
|
||||
* colour overwritten by single-coloured rectangles. It returns the number
|
||||
* of subrectangles in the encoded buffer, or -1 if subrect encoding won't
|
||||
* fit in the buffer. It puts the encoded rectangles in cl->afterEncBuf. The
|
||||
* single-colour rectangle partition is not optimal, but does find the biggest
|
||||
* horizontal or vertical rectangle top-left anchored to each consecutive
|
||||
* coordinate position.
|
||||
*
|
||||
* The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
|
||||
* <subrect> is [<colour><x><y><w><h>].
|
||||
*/
|
||||
|
||||
#define DEFINE_SUBRECT_ENCODE(bpp) \
|
||||
static int \
|
||||
subrectEncode##bpp(rfbClientPtr client, uint##bpp##_t *data, int w, int h) { \
|
||||
uint##bpp##_t cl; \
|
||||
rfbCoRRERectangle subrect; \
|
||||
int x,y; \
|
||||
int i,j; \
|
||||
int hx=0,hy,vx=0,vy; \
|
||||
int hyflag; \
|
||||
uint##bpp##_t *seg; \
|
||||
uint##bpp##_t *line; \
|
||||
int hw,hh,vw,vh; \
|
||||
int thex,they,thew,theh; \
|
||||
int numsubs = 0; \
|
||||
int newLen; \
|
||||
uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \
|
||||
\
|
||||
*((uint##bpp##_t*)client->afterEncBuf) = bg; \
|
||||
\
|
||||
client->afterEncBufLen = (bpp/8); \
|
||||
\
|
||||
for (y=0; y<h; y++) { \
|
||||
line = data+(y*w); \
|
||||
for (x=0; x<w; x++) { \
|
||||
if (line[x] != bg) { \
|
||||
cl = line[x]; \
|
||||
hy = y-1; \
|
||||
hyflag = 1; \
|
||||
for (j=y; j<h; j++) { \
|
||||
seg = data+(j*w); \
|
||||
if (seg[x] != cl) {break;} \
|
||||
i = x; \
|
||||
while ((seg[i] == cl) && (i < w)) i += 1; \
|
||||
i -= 1; \
|
||||
if (j == y) vx = hx = i; \
|
||||
if (i < vx) vx = i; \
|
||||
if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
|
||||
} \
|
||||
vy = j-1; \
|
||||
\
|
||||
/* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
|
||||
* We'll choose the bigger of the two. \
|
||||
*/ \
|
||||
hw = hx-x+1; \
|
||||
hh = hy-y+1; \
|
||||
vw = vx-x+1; \
|
||||
vh = vy-y+1; \
|
||||
\
|
||||
thex = x; \
|
||||
they = y; \
|
||||
\
|
||||
if ((hw*hh) > (vw*vh)) { \
|
||||
thew = hw; \
|
||||
theh = hh; \
|
||||
} else { \
|
||||
thew = vw; \
|
||||
theh = vh; \
|
||||
} \
|
||||
\
|
||||
subrect.x = thex; \
|
||||
subrect.y = they; \
|
||||
subrect.w = thew; \
|
||||
subrect.h = theh; \
|
||||
\
|
||||
newLen = client->afterEncBufLen + (bpp/8) + sz_rfbCoRRERectangle; \
|
||||
if ((newLen > (w * h * (bpp/8))) || (newLen > client->afterEncBufSize)) \
|
||||
return -1; \
|
||||
\
|
||||
numsubs += 1; \
|
||||
*((uint##bpp##_t*)(client->afterEncBuf + client->afterEncBufLen)) = cl; \
|
||||
client->afterEncBufLen += (bpp/8); \
|
||||
memcpy(&client->afterEncBuf[client->afterEncBufLen],&subrect,sz_rfbCoRRERectangle); \
|
||||
client->afterEncBufLen += sz_rfbCoRRERectangle; \
|
||||
\
|
||||
/* \
|
||||
* Now mark the subrect as done. \
|
||||
*/ \
|
||||
for (j=they; j < (they+theh); j++) { \
|
||||
for (i=thex; i < (thex+thew); i++) { \
|
||||
data[j*w+i] = bg; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return numsubs; \
|
||||
}
|
||||
|
||||
DEFINE_SUBRECT_ENCODE(8)
|
||||
DEFINE_SUBRECT_ENCODE(16)
|
||||
DEFINE_SUBRECT_ENCODE(32)
|
||||
|
||||
|
||||
/*
|
||||
* getBgColour() gets the most prevalent colour in a byte array.
|
||||
*/
|
||||
static uint32_t
|
||||
getBgColour(char *data, int size, int bpp)
|
||||
{
|
||||
|
||||
#define NUMCLRS 256
|
||||
|
||||
static int counts[NUMCLRS];
|
||||
int i,j,k;
|
||||
|
||||
int maxcount = 0;
|
||||
uint8_t maxclr = 0;
|
||||
|
||||
if (bpp != 8) {
|
||||
if (bpp == 16) {
|
||||
return ((uint16_t *)data)[0];
|
||||
} else if (bpp == 32) {
|
||||
return ((uint32_t *)data)[0];
|
||||
} else {
|
||||
rfbLog("getBgColour: bpp %d?\n",bpp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<NUMCLRS; i++) {
|
||||
counts[i] = 0;
|
||||
}
|
||||
|
||||
for (j=0; j<size; j++) {
|
||||
k = (int)(((uint8_t *)data)[j]);
|
||||
if (k >= NUMCLRS) {
|
||||
rfbLog("getBgColour: unusual colour = %d\n", k);
|
||||
return 0;
|
||||
}
|
||||
counts[k] += 1;
|
||||
if (counts[k] > maxcount) {
|
||||
maxcount = counts[k];
|
||||
maxclr = ((uint8_t *)data)[j];
|
||||
}
|
||||
}
|
||||
|
||||
return maxclr;
|
||||
}
|
||||
756
libvncserver/cursor.c
Normal file
756
libvncserver/cursor.c
Normal file
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
* cursor.c - support for cursor shape updates.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
#include "rfb/rfbregion.h"
|
||||
#include "private.h"
|
||||
|
||||
void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2);
|
||||
|
||||
/*
|
||||
* Send cursor shape either in X-style format or in client pixel format.
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendCursorShape(rfbClientPtr cl)
|
||||
{
|
||||
rfbCursorPtr pCursor;
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
rfbXCursorColors colors;
|
||||
int saved_ublen;
|
||||
int bitmapRowBytes, maskBytes, dataBytes;
|
||||
int i, j;
|
||||
uint8_t *bitmapData;
|
||||
uint8_t bitmapByte;
|
||||
|
||||
/* TODO: scale the cursor data to the correct size */
|
||||
|
||||
pCursor = cl->screen->getCursorPtr(cl);
|
||||
/*if(!pCursor) return TRUE;*/
|
||||
|
||||
if (cl->useRichCursorEncoding) {
|
||||
if(pCursor && !pCursor->richSource)
|
||||
rfbMakeRichCursorFromXCursor(cl->screen,pCursor);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
|
||||
} else {
|
||||
if(pCursor && !pCursor->source)
|
||||
rfbMakeXCursorFromRichCursor(cl->screen,pCursor);
|
||||
rect.encoding = Swap32IfLE(rfbEncodingXCursor);
|
||||
}
|
||||
|
||||
/* If there is no cursor, send update with empty cursor data. */
|
||||
|
||||
if ( pCursor && pCursor->width == 1 &&
|
||||
pCursor->height == 1 &&
|
||||
pCursor->mask[0] == 0 ) {
|
||||
pCursor = NULL;
|
||||
}
|
||||
|
||||
if (pCursor == NULL) {
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
rect.r.x = rect.r.y = 0;
|
||||
rect.r.w = rect.r.h = 0;
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Calculate data sizes. */
|
||||
|
||||
bitmapRowBytes = (pCursor->width + 7) / 8;
|
||||
maskBytes = bitmapRowBytes * pCursor->height;
|
||||
dataBytes = (cl->useRichCursorEncoding) ?
|
||||
(pCursor->width * pCursor->height *
|
||||
(cl->format.bitsPerPixel / 8)) : maskBytes;
|
||||
|
||||
/* Send buffer contents if needed. */
|
||||
|
||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
|
||||
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
|
||||
return FALSE; /* FIXME. */
|
||||
}
|
||||
|
||||
saved_ublen = cl->ublen;
|
||||
|
||||
/* Prepare rectangle header. */
|
||||
|
||||
rect.r.x = Swap16IfLE(pCursor->xhot);
|
||||
rect.r.y = Swap16IfLE(pCursor->yhot);
|
||||
rect.r.w = Swap16IfLE(pCursor->width);
|
||||
rect.r.h = Swap16IfLE(pCursor->height);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
/* Prepare actual cursor data (depends on encoding used). */
|
||||
|
||||
if (!cl->useRichCursorEncoding) {
|
||||
/* XCursor encoding. */
|
||||
colors.foreRed = (char)(pCursor->foreRed >> 8);
|
||||
colors.foreGreen = (char)(pCursor->foreGreen >> 8);
|
||||
colors.foreBlue = (char)(pCursor->foreBlue >> 8);
|
||||
colors.backRed = (char)(pCursor->backRed >> 8);
|
||||
colors.backGreen = (char)(pCursor->backGreen >> 8);
|
||||
colors.backBlue = (char)(pCursor->backBlue >> 8);
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
|
||||
cl->ublen += sz_rfbXCursorColors;
|
||||
|
||||
bitmapData = (uint8_t *)pCursor->source;
|
||||
|
||||
for (i = 0; i < pCursor->height; i++) {
|
||||
for (j = 0; j < bitmapRowBytes; j++) {
|
||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* RichCursor encoding. */
|
||||
int bpp1=cl->screen->serverFormat.bitsPerPixel/8,
|
||||
bpp2=cl->format.bitsPerPixel/8;
|
||||
(*cl->translateFn)(cl->translateLookupTable,
|
||||
&(cl->screen->serverFormat),
|
||||
&cl->format, (char*)pCursor->richSource,
|
||||
&cl->updateBuf[cl->ublen],
|
||||
pCursor->width*bpp1, pCursor->width, pCursor->height);
|
||||
|
||||
cl->ublen += pCursor->width*bpp2*pCursor->height;
|
||||
}
|
||||
|
||||
/* Prepare transparency mask. */
|
||||
|
||||
bitmapData = (uint8_t *)pCursor->mask;
|
||||
|
||||
for (i = 0; i < pCursor->height; i++) {
|
||||
for (j = 0; j < bitmapRowBytes; j++) {
|
||||
bitmapByte = bitmapData[i * bitmapRowBytes + j];
|
||||
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send everything we have prepared in the cl->updateBuf[]. */
|
||||
rfbStatRecordEncodingSent(cl, (cl->useRichCursorEncoding ? rfbEncodingRichCursor : rfbEncodingXCursor),
|
||||
sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen), sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen));
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send cursor position (PointerPos pseudo-encoding).
|
||||
*/
|
||||
|
||||
rfbBool
|
||||
rfbSendCursorPos(rfbClientPtr cl)
|
||||
{
|
||||
rfbFramebufferUpdateRectHeader rect;
|
||||
|
||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
|
||||
rect.r.x = Swap16IfLE(cl->screen->cursorX);
|
||||
rect.r.y = Swap16IfLE(cl->screen->cursorY);
|
||||
rect.r.w = 0;
|
||||
rect.r.h = 0;
|
||||
|
||||
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
|
||||
sz_rfbFramebufferUpdateRectHeader);
|
||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
||||
|
||||
rfbStatRecordEncodingSent(cl, rfbEncodingPointerPos, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
|
||||
|
||||
if (!rfbSendUpdateBuf(cl))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* conversion routine for predefined cursors in LSB order */
|
||||
unsigned char rfbReverseByte[0x100] = {
|
||||
/* copied from Xvnc/lib/font/util/utilbitmap.c */
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
||||
};
|
||||
|
||||
void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
|
||||
{
|
||||
int i,t=(width+7)/8*height;
|
||||
for(i=0;i<t;i++)
|
||||
bitmap[i]=rfbReverseByte[(int)bitmap[i]];
|
||||
}
|
||||
|
||||
/* Cursor creation. You "paint" a cursor and let these routines do the work */
|
||||
|
||||
rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
|
||||
{
|
||||
int i,j,w=(width+7)/8;
|
||||
rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
|
||||
char* cp;
|
||||
unsigned char bit;
|
||||
|
||||
cursor->cleanup=TRUE;
|
||||
cursor->width=width;
|
||||
cursor->height=height;
|
||||
/*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
|
||||
cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
|
||||
|
||||
cursor->source = (unsigned char*)calloc(w,height);
|
||||
cursor->cleanupSource = TRUE;
|
||||
for(j=0,cp=cursorString;j<height;j++)
|
||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
||||
if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
|
||||
|
||||
if(maskString) {
|
||||
cursor->mask = (unsigned char*)calloc(w,height);
|
||||
for(j=0,cp=maskString;j<height;j++)
|
||||
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
|
||||
if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
|
||||
} else
|
||||
cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source);
|
||||
cursor->cleanupMask = TRUE;
|
||||
|
||||
return(cursor);
|
||||
}
|
||||
|
||||
char* rfbMakeMaskForXCursor(int width,int height,char* source)
|
||||
{
|
||||
int i,j,w=(width+7)/8;
|
||||
char* mask=(char*)calloc(w,height);
|
||||
unsigned char c;
|
||||
|
||||
for(j=0;j<height;j++)
|
||||
for(i=w-1;i>=0;i--) {
|
||||
c=source[j*w+i];
|
||||
if(j>0) c|=source[(j-1)*w+i];
|
||||
if(j<height-1) c|=source[(j+1)*w+i];
|
||||
|
||||
if(i>0 && (c&0x80))
|
||||
mask[j*w+i-1]|=0x01;
|
||||
if(i<w-1 && (c&0x01))
|
||||
mask[j*w+i+1]|=0x80;
|
||||
|
||||
mask[j*w+i]|=(c<<1)|c|(c>>1);
|
||||
}
|
||||
|
||||
return(mask);
|
||||
}
|
||||
|
||||
/* this function dithers the alpha using Floyd-Steinberg */
|
||||
|
||||
char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource)
|
||||
{
|
||||
int* error=(int*)calloc(sizeof(int),width);
|
||||
int i,j,currentError=0,maskStride=(width+7)/8;
|
||||
unsigned char* result=(unsigned char*)calloc(maskStride,height);
|
||||
|
||||
for(j=0;j<height;j++)
|
||||
for(i=0;i<width;i++) {
|
||||
int right,middle,left;
|
||||
currentError+=alphaSource[i+width*j]+error[i];
|
||||
|
||||
if(currentError<0x80) {
|
||||
/* set to transparent */
|
||||
/* alpha was treated as 0 */
|
||||
} else {
|
||||
/* set to solid */
|
||||
result[i/8+j*maskStride]|=(0x100>>(i&7));
|
||||
/* alpha was treated as 0xff */
|
||||
currentError-=0xff;
|
||||
}
|
||||
/* propagate to next row */
|
||||
right=currentError/16;
|
||||
middle=currentError*5/16;
|
||||
left=currentError*3/16;
|
||||
currentError-=right+middle+left;
|
||||
error[i]=right;
|
||||
if(i>0) {
|
||||
error[i-1]=middle;
|
||||
if(i>1)
|
||||
error[i-2]=left;
|
||||
}
|
||||
}
|
||||
free(error);
|
||||
return (char *) result;
|
||||
}
|
||||
|
||||
void rfbFreeCursor(rfbCursorPtr cursor)
|
||||
{
|
||||
if(cursor) {
|
||||
if(cursor->cleanupRichSource && cursor->richSource)
|
||||
free(cursor->richSource);
|
||||
if(cursor->cleanupRichSource && cursor->alphaSource)
|
||||
free(cursor->alphaSource);
|
||||
if(cursor->cleanupSource && cursor->source)
|
||||
free(cursor->source);
|
||||
if(cursor->cleanupMask && cursor->mask)
|
||||
free(cursor->mask);
|
||||
if(cursor->cleanup)
|
||||
free(cursor);
|
||||
else {
|
||||
cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask
|
||||
=cursor->cleanupRichSource=FALSE;
|
||||
cursor->source=cursor->mask=cursor->richSource=NULL;
|
||||
cursor->alphaSource=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* background and foregroud colour have to be set beforehand */
|
||||
void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
||||
{
|
||||
rfbPixelFormat* format=&rfbScreen->serverFormat;
|
||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
|
||||
width=cursor->width*bpp;
|
||||
uint32_t background;
|
||||
char *back=(char*)&background;
|
||||
unsigned char bit;
|
||||
int interp = 0, db = 0;
|
||||
|
||||
if(cursor->source && cursor->cleanupSource)
|
||||
free(cursor->source);
|
||||
cursor->source=(unsigned char*)calloc(w,cursor->height);
|
||||
cursor->cleanupSource=TRUE;
|
||||
|
||||
if(format->bigEndian) {
|
||||
back+=4-bpp;
|
||||
}
|
||||
|
||||
/* all zeros means we should interpolate to black+white ourselves */
|
||||
if (!cursor->backRed && !cursor->backGreen && !cursor->backBlue &&
|
||||
!cursor->foreRed && !cursor->foreGreen && !cursor->foreBlue) {
|
||||
if (format->trueColour && (bpp == 1 || bpp == 2 || bpp == 4)) {
|
||||
interp = 1;
|
||||
cursor->foreRed = cursor->foreGreen = cursor->foreBlue = 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
background = ((format->redMax * cursor->backRed) / 0xffff) << format->redShift |
|
||||
((format->greenMax * cursor->backGreen) / 0xffff) << format->greenShift |
|
||||
((format->blueMax * cursor->backBlue) / 0xffff) << format->blueShift;
|
||||
|
||||
#define SETRGB(u) \
|
||||
r = (255 * (((format->redMax << format->redShift) & (*u)) >> format->redShift)) / format->redMax; \
|
||||
g = (255 * (((format->greenMax << format->greenShift) & (*u)) >> format->greenShift)) / format->greenMax; \
|
||||
b = (255 * (((format->blueMax << format->blueShift) & (*u)) >> format->blueShift)) / format->blueMax;
|
||||
|
||||
if (db) fprintf(stderr, "interp: %d\n", interp);
|
||||
|
||||
for(j=0;j<cursor->height;j++) {
|
||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1) {
|
||||
if (interp) {
|
||||
int r = 0, g = 0, b = 0, grey;
|
||||
unsigned char *p = cursor->richSource+j*width+i*bpp;
|
||||
if (bpp == 1) {
|
||||
unsigned char* uc = (unsigned char*) p;
|
||||
SETRGB(uc);
|
||||
} else if (bpp == 2) {
|
||||
unsigned short* us = (unsigned short*) p;
|
||||
SETRGB(us);
|
||||
} else if (bpp == 4) {
|
||||
unsigned int* ui = (unsigned int*) p;
|
||||
SETRGB(ui);
|
||||
}
|
||||
grey = (r + g + b) / 3;
|
||||
if (grey >= 128) {
|
||||
cursor->source[j*w+i/8]|=bit;
|
||||
if (db) fprintf(stderr, "1");
|
||||
} else {
|
||||
if (db) fprintf(stderr, "0");
|
||||
}
|
||||
|
||||
} else if(memcmp(cursor->richSource+j*width+i*bpp, back, bpp)) {
|
||||
cursor->source[j*w+i/8]|=bit;
|
||||
}
|
||||
}
|
||||
if (db) fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
|
||||
{
|
||||
rfbPixelFormat* format=&rfbScreen->serverFormat;
|
||||
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
|
||||
uint32_t background,foreground;
|
||||
char *back=(char*)&background,*fore=(char*)&foreground;
|
||||
unsigned char *cp;
|
||||
unsigned char bit;
|
||||
|
||||
if(cursor->richSource && cursor->cleanupRichSource)
|
||||
free(cursor->richSource);
|
||||
cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
|
||||
cursor->cleanupRichSource=TRUE;
|
||||
|
||||
if(format->bigEndian) {
|
||||
back+=4-bpp;
|
||||
fore+=4-bpp;
|
||||
}
|
||||
|
||||
background=cursor->backRed<<format->redShift|
|
||||
cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
|
||||
foreground=cursor->foreRed<<format->redShift|
|
||||
cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
|
||||
|
||||
for(j=0;j<cursor->height;j++)
|
||||
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
|
||||
if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
|
||||
else memcpy(cp,back,bpp);
|
||||
}
|
||||
|
||||
/* functions to draw/hide cursor directly in the frame buffer */
|
||||
|
||||
void rfbHideCursor(rfbClientPtr cl)
|
||||
{
|
||||
rfbScreenInfoPtr s=cl->screen;
|
||||
rfbCursorPtr c=s->cursor;
|
||||
int j,x1,x2,y1,y2,bpp=s->serverFormat.bitsPerPixel/8,
|
||||
rowstride=s->paddedWidthInBytes;
|
||||
LOCK(s->cursorMutex);
|
||||
if(!c) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* restore what is under the cursor */
|
||||
x1=cl->cursorX-c->xhot;
|
||||
x2=x1+c->width;
|
||||
if(x1<0) x1=0;
|
||||
if(x2>=s->width) x2=s->width-1;
|
||||
x2-=x1; if(x2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
y1=cl->cursorY-c->yhot;
|
||||
y2=y1+c->height;
|
||||
if(y1<0) y1=0;
|
||||
if(y2>=s->height) y2=s->height-1;
|
||||
y2-=y1; if(y2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get saved data */
|
||||
for(j=0;j<y2;j++)
|
||||
memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
|
||||
s->underCursorBuffer+j*x2*bpp,
|
||||
x2*bpp);
|
||||
|
||||
/* Copy to all scaled versions */
|
||||
rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
|
||||
|
||||
UNLOCK(s->cursorMutex);
|
||||
}
|
||||
|
||||
void rfbShowCursor(rfbClientPtr cl)
|
||||
{
|
||||
rfbScreenInfoPtr s=cl->screen;
|
||||
rfbCursorPtr c=s->cursor;
|
||||
int i,j,x1,x2,y1,y2,i1,j1,bpp=s->serverFormat.bitsPerPixel/8,
|
||||
rowstride=s->paddedWidthInBytes,
|
||||
bufSize,w;
|
||||
rfbBool wasChanged=FALSE;
|
||||
|
||||
if(!c) return;
|
||||
LOCK(s->cursorMutex);
|
||||
|
||||
bufSize=c->width*c->height*bpp;
|
||||
w=(c->width+7)/8;
|
||||
if(s->underCursorBufferLen<bufSize) {
|
||||
if(s->underCursorBuffer!=NULL)
|
||||
free(s->underCursorBuffer);
|
||||
s->underCursorBuffer=malloc(bufSize);
|
||||
s->underCursorBufferLen=bufSize;
|
||||
}
|
||||
|
||||
/* save what is under the cursor */
|
||||
i1=j1=0; /* offset in cursor */
|
||||
x1=cl->cursorX-c->xhot;
|
||||
x2=x1+c->width;
|
||||
if(x1<0) { i1=-x1; x1=0; }
|
||||
if(x2>=s->width) x2=s->width-1;
|
||||
x2-=x1; if(x2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
y1=cl->cursorY-c->yhot;
|
||||
y2=y1+c->height;
|
||||
if(y1<0) { j1=-y1; y1=0; }
|
||||
if(y2>=s->height) y2=s->height-1;
|
||||
y2-=y1; if(y2<=0) {
|
||||
UNLOCK(s->cursorMutex);
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
/* save data */
|
||||
for(j=0;j<y2;j++) {
|
||||
char* dest=s->underCursorBuffer+j*x2*bpp;
|
||||
const char* src=s->frameBuffer+(y1+j)*rowstride+x1*bpp;
|
||||
unsigned int count=x2*bpp;
|
||||
if(wasChanged || memcmp(dest,src,count)) {
|
||||
wasChanged=TRUE;
|
||||
memcpy(dest,src,count);
|
||||
}
|
||||
}
|
||||
|
||||
if(!c->richSource)
|
||||
rfbMakeRichCursorFromXCursor(s,c);
|
||||
|
||||
if (c->alphaSource) {
|
||||
int rmax, rshift;
|
||||
int gmax, gshift;
|
||||
int bmax, bshift;
|
||||
int amax = 255; /* alphaSource is always 8bits of info per pixel */
|
||||
unsigned int rmask, gmask, bmask;
|
||||
|
||||
rmax = s->serverFormat.redMax;
|
||||
gmax = s->serverFormat.greenMax;
|
||||
bmax = s->serverFormat.blueMax;
|
||||
rshift = s->serverFormat.redShift;
|
||||
gshift = s->serverFormat.greenShift;
|
||||
bshift = s->serverFormat.blueShift;
|
||||
|
||||
rmask = (rmax << rshift);
|
||||
gmask = (gmax << gshift);
|
||||
bmask = (bmax << bshift);
|
||||
|
||||
for(j=0;j<y2;j++) {
|
||||
for(i=0;i<x2;i++) {
|
||||
/*
|
||||
* we loop over the whole cursor ignoring c->mask[],
|
||||
* using the extracted alpha value instead.
|
||||
*/
|
||||
char *dest;
|
||||
unsigned char *src, *aptr;
|
||||
unsigned int val, dval, sval;
|
||||
int rdst, gdst, bdst; /* fb RGB */
|
||||
int asrc, rsrc, gsrc, bsrc; /* rich source ARGB */
|
||||
|
||||
dest = s->frameBuffer + (j+y1)*rowstride + (i+x1)*bpp;
|
||||
src = c->richSource + (j+j1)*c->width*bpp + (i+i1)*bpp;
|
||||
aptr = c->alphaSource + (j+j1)*c->width + (i+i1);
|
||||
|
||||
asrc = *aptr;
|
||||
if (!asrc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bpp == 1) {
|
||||
dval = *((unsigned char*) dest);
|
||||
sval = *((unsigned char*) src);
|
||||
} else if (bpp == 2) {
|
||||
dval = *((unsigned short*) dest);
|
||||
sval = *((unsigned short*) src);
|
||||
} else if (bpp == 3) {
|
||||
unsigned char *dst = (unsigned char *) dest;
|
||||
dval = 0;
|
||||
dval |= ((*(dst+0)) << 0);
|
||||
dval |= ((*(dst+1)) << 8);
|
||||
dval |= ((*(dst+2)) << 16);
|
||||
sval = 0;
|
||||
sval |= ((*(src+0)) << 0);
|
||||
sval |= ((*(src+1)) << 8);
|
||||
sval |= ((*(src+2)) << 16);
|
||||
} else if (bpp == 4) {
|
||||
dval = *((unsigned int*) dest);
|
||||
sval = *((unsigned int*) src);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* extract dest and src RGB */
|
||||
rdst = (dval & rmask) >> rshift; /* fb */
|
||||
gdst = (dval & gmask) >> gshift;
|
||||
bdst = (dval & bmask) >> bshift;
|
||||
|
||||
rsrc = (sval & rmask) >> rshift; /* richcursor */
|
||||
gsrc = (sval & gmask) >> gshift;
|
||||
bsrc = (sval & bmask) >> bshift;
|
||||
|
||||
/* blend in fb data. */
|
||||
if (! c->alphaPreMultiplied) {
|
||||
rsrc = (asrc * rsrc)/amax;
|
||||
gsrc = (asrc * gsrc)/amax;
|
||||
bsrc = (asrc * bsrc)/amax;
|
||||
}
|
||||
rdst = rsrc + ((amax - asrc) * rdst)/amax;
|
||||
gdst = gsrc + ((amax - asrc) * gdst)/amax;
|
||||
bdst = bsrc + ((amax - asrc) * bdst)/amax;
|
||||
|
||||
val = 0;
|
||||
val |= (rdst << rshift);
|
||||
val |= (gdst << gshift);
|
||||
val |= (bdst << bshift);
|
||||
|
||||
/* insert the cooked pixel into the fb */
|
||||
memcpy(dest, &val, bpp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* now the cursor has to be drawn */
|
||||
for(j=0;j<y2;j++)
|
||||
for(i=0;i<x2;i++)
|
||||
if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
|
||||
memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
|
||||
c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
|
||||
}
|
||||
|
||||
/* Copy to all scaled versions */
|
||||
rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
|
||||
|
||||
UNLOCK(s->cursorMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* If enableCursorShapeUpdates is FALSE, and the cursor is hidden, make sure
|
||||
* that if the frameBuffer was transmitted with a cursor drawn, then that
|
||||
* region gets redrawn.
|
||||
*/
|
||||
|
||||
void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion)
|
||||
{
|
||||
rfbScreenInfoPtr s = cl->screen;
|
||||
rfbCursorPtr c = s->cursor;
|
||||
|
||||
if(c) {
|
||||
int x,y,x2,y2;
|
||||
|
||||
x = cl->cursorX-c->xhot;
|
||||
y = cl->cursorY-c->yhot;
|
||||
x2 = x+c->width;
|
||||
y2 = y+c->height;
|
||||
|
||||
if(sraClipRect2(&x,&y,&x2,&y2,0,0,s->width,s->height)) {
|
||||
sraRegionPtr rect;
|
||||
rect = sraRgnCreateRect(x,y,x2,y2);
|
||||
if(updateRegion) {
|
||||
sraRgnOr(updateRegion,rect);
|
||||
} else {
|
||||
LOCK(cl->updateMutex);
|
||||
sraRgnOr(cl->modifiedRegion,rect);
|
||||
UNLOCK(cl->updateMutex);
|
||||
}
|
||||
sraRgnDestroy(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static void rfbPrintXCursor(rfbCursorPtr cursor)
|
||||
{
|
||||
int i,i1,j,w=(cursor->width+7)/8;
|
||||
unsigned char bit;
|
||||
for(j=0;j<cursor->height;j++) {
|
||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
||||
if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
|
||||
putchar(':');
|
||||
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
|
||||
if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
|
||||
{
|
||||
rfbClientIteratorPtr iterator;
|
||||
rfbClientPtr cl;
|
||||
|
||||
LOCK(rfbScreen->cursorMutex);
|
||||
|
||||
if(rfbScreen->cursor) {
|
||||
iterator=rfbGetClientIterator(rfbScreen);
|
||||
while((cl=rfbClientIteratorNext(iterator)))
|
||||
if(!cl->enableCursorShapeUpdates)
|
||||
rfbRedrawAfterHideCursor(cl,NULL);
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
if(rfbScreen->cursor->cleanup)
|
||||
rfbFreeCursor(rfbScreen->cursor);
|
||||
}
|
||||
|
||||
rfbScreen->cursor = c;
|
||||
|
||||
iterator=rfbGetClientIterator(rfbScreen);
|
||||
while((cl=rfbClientIteratorNext(iterator))) {
|
||||
cl->cursorWasChanged = TRUE;
|
||||
if(!cl->enableCursorShapeUpdates)
|
||||
rfbRedrawAfterHideCursor(cl,NULL);
|
||||
}
|
||||
rfbReleaseClientIterator(iterator);
|
||||
|
||||
UNLOCK(rfbScreen->cursorMutex);
|
||||
}
|
||||
|
||||
38
libvncserver/cutpaste.c
Normal file
38
libvncserver/cutpaste.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* cutpaste.c - routines to deal with cut & paste buffers / selection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
|
||||
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
|
||||
/*
|
||||
* rfbSetXCutText sets the cut buffer to be the given string. We also clear
|
||||
* the primary selection. Ideally we'd like to set it to the same thing, but I
|
||||
* can't work out how to do that without some kind of helper X client.
|
||||
*/
|
||||
|
||||
void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len)
|
||||
{
|
||||
rfbSendServerCutText(rfbScreen, str, len);
|
||||
}
|
||||
436
libvncserver/d3des.c
Normal file
436
libvncserver/d3des.c
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
||||
* triple-length support removed for use in VNC. Also the bytebit[] array
|
||||
* has been reversed so that the most significant bit in each byte of the
|
||||
* key is ignored, not the least significant.
|
||||
*
|
||||
* These changes are:
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* D3DES (V5.09) -
|
||||
*
|
||||
* A portable, public domain, version of the Data Encryption Standard.
|
||||
*
|
||||
* Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
|
||||
* Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
|
||||
* code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
|
||||
* Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
|
||||
* for humouring me on.
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
|
||||
* (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
|
||||
*/
|
||||
|
||||
#include "d3des.h"
|
||||
|
||||
static void scrunch(unsigned char *, unsigned long *);
|
||||
static void unscrun(unsigned long *, unsigned char *);
|
||||
static void desfunc(unsigned long *, unsigned long *);
|
||||
static void cookey(unsigned long *);
|
||||
|
||||
static unsigned long KnL[32] = { 0L };
|
||||
/*
|
||||
static unsigned long KnR[32] = { 0L };
|
||||
static unsigned long Kn3[32] = { 0L };
|
||||
static unsigned char Df_Key[24] = {
|
||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
|
||||
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
|
||||
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
|
||||
*/
|
||||
|
||||
static unsigned short bytebit[8] = {
|
||||
01, 02, 04, 010, 020, 040, 0100, 0200 };
|
||||
|
||||
static unsigned long bigbyte[24] = {
|
||||
0x800000L, 0x400000L, 0x200000L, 0x100000L,
|
||||
0x80000L, 0x40000L, 0x20000L, 0x10000L,
|
||||
0x8000L, 0x4000L, 0x2000L, 0x1000L,
|
||||
0x800L, 0x400L, 0x200L, 0x100L,
|
||||
0x80L, 0x40L, 0x20L, 0x10L,
|
||||
0x8L, 0x4L, 0x2L, 0x1L };
|
||||
|
||||
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
|
||||
|
||||
static unsigned char pc1[56] = {
|
||||
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
|
||||
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
|
||||
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
|
||||
|
||||
static unsigned char totrot[16] = {
|
||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
|
||||
|
||||
static unsigned char pc2[48] = {
|
||||
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
|
||||
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
|
||||
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
|
||||
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
|
||||
|
||||
void rfbDesKey(unsigned char *key,
|
||||
int edf)
|
||||
{
|
||||
register int i, j, l, m, n;
|
||||
unsigned char pc1m[56], pcr[56];
|
||||
unsigned long kn[32];
|
||||
|
||||
for ( j = 0; j < 56; j++ ) {
|
||||
l = pc1[j];
|
||||
m = l & 07;
|
||||
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
|
||||
}
|
||||
for( i = 0; i < 16; i++ ) {
|
||||
if( edf == DE1 ) m = (15 - i) << 1;
|
||||
else m = i << 1;
|
||||
n = m + 1;
|
||||
kn[m] = kn[n] = 0L;
|
||||
for( j = 0; j < 28; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 28 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 28; j < 56; j++ ) {
|
||||
l = j + totrot[i];
|
||||
if( l < 56 ) pcr[j] = pc1m[l];
|
||||
else pcr[j] = pc1m[l - 28];
|
||||
}
|
||||
for( j = 0; j < 24; j++ ) {
|
||||
if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
|
||||
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
|
||||
}
|
||||
}
|
||||
cookey(kn);
|
||||
return;
|
||||
}
|
||||
|
||||
static void cookey(register unsigned long *raw1)
|
||||
{
|
||||
register unsigned long *cook, *raw0;
|
||||
unsigned long dough[32];
|
||||
register int i;
|
||||
|
||||
cook = dough;
|
||||
for( i = 0; i < 16; i++, raw1++ ) {
|
||||
raw0 = raw1++;
|
||||
*cook = (*raw0 & 0x00fc0000L) << 6;
|
||||
*cook |= (*raw0 & 0x00000fc0L) << 10;
|
||||
*cook |= (*raw1 & 0x00fc0000L) >> 10;
|
||||
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
|
||||
*cook = (*raw0 & 0x0003f000L) << 12;
|
||||
*cook |= (*raw0 & 0x0000003fL) << 16;
|
||||
*cook |= (*raw1 & 0x0003f000L) >> 4;
|
||||
*cook++ |= (*raw1 & 0x0000003fL);
|
||||
}
|
||||
rfbUseKey(dough);
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbCPKey(register unsigned long *into)
|
||||
{
|
||||
register unsigned long *from, *endp;
|
||||
|
||||
from = KnL, endp = &KnL[32];
|
||||
while( from < endp ) *into++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbUseKey(register unsigned long *from)
|
||||
{
|
||||
register unsigned long *to, *endp;
|
||||
|
||||
to = KnL, endp = &KnL[32];
|
||||
while( to < endp ) *to++ = *from++;
|
||||
return;
|
||||
}
|
||||
|
||||
void rfbDes(unsigned char *inblock,
|
||||
unsigned char *outblock)
|
||||
{
|
||||
unsigned long work[2];
|
||||
|
||||
scrunch(inblock, work);
|
||||
desfunc(work, KnL);
|
||||
unscrun(work, outblock);
|
||||
return;
|
||||
}
|
||||
|
||||
static void scrunch(register unsigned char *outof,
|
||||
register unsigned long *into)
|
||||
{
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into++ |= (*outof++ & 0xffL);
|
||||
*into = (*outof++ & 0xffL) << 24;
|
||||
*into |= (*outof++ & 0xffL) << 16;
|
||||
*into |= (*outof++ & 0xffL) << 8;
|
||||
*into |= (*outof & 0xffL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void unscrun(register unsigned long *outof,
|
||||
register unsigned char *into)
|
||||
{
|
||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
||||
*into++ = (unsigned char)( *outof++ & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
|
||||
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
|
||||
*into = (unsigned char)( *outof & 0xffL);
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned long SP1[64] = {
|
||||
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
|
||||
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
|
||||
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
|
||||
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
|
||||
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
|
||||
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
|
||||
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
|
||||
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
|
||||
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
|
||||
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
|
||||
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
|
||||
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
|
||||
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
|
||||
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
|
||||
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
|
||||
|
||||
static unsigned long SP2[64] = {
|
||||
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
|
||||
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
|
||||
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
|
||||
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
|
||||
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
|
||||
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
|
||||
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
|
||||
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
|
||||
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
|
||||
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
|
||||
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
|
||||
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
|
||||
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
|
||||
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
|
||||
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
|
||||
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
|
||||
|
||||
static unsigned long SP3[64] = {
|
||||
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
|
||||
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
|
||||
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
|
||||
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
|
||||
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
|
||||
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
|
||||
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
|
||||
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
|
||||
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
|
||||
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
|
||||
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
|
||||
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
|
||||
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
|
||||
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
|
||||
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
|
||||
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
|
||||
|
||||
static unsigned long SP4[64] = {
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
|
||||
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
|
||||
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
|
||||
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
|
||||
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
|
||||
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
|
||||
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
|
||||
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
|
||||
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
|
||||
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
|
||||
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
|
||||
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
|
||||
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
|
||||
|
||||
static unsigned long SP5[64] = {
|
||||
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
|
||||
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
|
||||
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
|
||||
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
|
||||
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
|
||||
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
|
||||
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
|
||||
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
|
||||
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
|
||||
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
|
||||
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
|
||||
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
|
||||
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
|
||||
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
|
||||
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
|
||||
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
|
||||
|
||||
static unsigned long SP6[64] = {
|
||||
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
|
||||
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
|
||||
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
|
||||
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
|
||||
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
|
||||
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
|
||||
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
|
||||
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
|
||||
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
|
||||
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
|
||||
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
|
||||
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
|
||||
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
|
||||
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
|
||||
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
|
||||
|
||||
static unsigned long SP7[64] = {
|
||||
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
|
||||
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
|
||||
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
|
||||
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
|
||||
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
|
||||
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
|
||||
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
|
||||
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
|
||||
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
|
||||
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
|
||||
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
|
||||
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
|
||||
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
|
||||
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
|
||||
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
|
||||
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
|
||||
|
||||
static unsigned long SP8[64] = {
|
||||
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
|
||||
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
|
||||
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
|
||||
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
|
||||
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
|
||||
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
|
||||
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
|
||||
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
|
||||
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
|
||||
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
|
||||
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
|
||||
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
|
||||
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
|
||||
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
|
||||
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
|
||||
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
|
||||
|
||||
static void desfunc(register unsigned long *block,
|
||||
register unsigned long *keys)
|
||||
{
|
||||
register unsigned long fval, work, right, leftt;
|
||||
register int round;
|
||||
|
||||
leftt = block[0];
|
||||
right = block[1];
|
||||
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 4);
|
||||
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 16);
|
||||
work = ((right >> 2) ^ leftt) & 0x33333333L;
|
||||
leftt ^= work;
|
||||
right ^= (work << 2);
|
||||
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 8);
|
||||
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
|
||||
|
||||
for( round = 0; round < 8; round++ ) {
|
||||
work = (right << 28) | (right >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = right ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
leftt ^= fval;
|
||||
work = (leftt << 28) | (leftt >> 4);
|
||||
work ^= *keys++;
|
||||
fval = SP7[ work & 0x3fL];
|
||||
fval |= SP5[(work >> 8) & 0x3fL];
|
||||
fval |= SP3[(work >> 16) & 0x3fL];
|
||||
fval |= SP1[(work >> 24) & 0x3fL];
|
||||
work = leftt ^ *keys++;
|
||||
fval |= SP8[ work & 0x3fL];
|
||||
fval |= SP6[(work >> 8) & 0x3fL];
|
||||
fval |= SP4[(work >> 16) & 0x3fL];
|
||||
fval |= SP2[(work >> 24) & 0x3fL];
|
||||
right ^= fval;
|
||||
}
|
||||
|
||||
right = (right << 31) | (right >> 1);
|
||||
work = (leftt ^ right) & 0xaaaaaaaaL;
|
||||
leftt ^= work;
|
||||
right ^= work;
|
||||
leftt = (leftt << 31) | (leftt >> 1);
|
||||
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
|
||||
right ^= work;
|
||||
leftt ^= (work << 8);
|
||||
work = ((leftt >> 2) ^ right) & 0x33333333L;
|
||||
right ^= work;
|
||||
leftt ^= (work << 2);
|
||||
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 16);
|
||||
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
|
||||
leftt ^= work;
|
||||
right ^= (work << 4);
|
||||
*block++ = right;
|
||||
*block = leftt;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validation sets:
|
||||
*
|
||||
* Single-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : c957 4425 6a5e d31d
|
||||
*
|
||||
* Double-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : 7f1d 0a77 826b 8aff
|
||||
*
|
||||
* Double-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
|
||||
*
|
||||
* Triple-length key, single-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cde7
|
||||
* Cipher : de0b 7c06 ae5e 0ed5
|
||||
*
|
||||
* Triple-length key, double-length plaintext -
|
||||
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
|
||||
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
|
||||
* Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
|
||||
*
|
||||
* d3des V5.0a rwo 9208.07 18:44 Graven Imagery
|
||||
**********************************************************************/
|
||||
56
libvncserver/d3des.h
Normal file
56
libvncserver/d3des.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef D3DES_H
|
||||
#define D3DES_H
|
||||
|
||||
/*
|
||||
* This is D3DES (V5.09) by Richard Outerbridge with the double and
|
||||
* triple-length support removed for use in VNC.
|
||||
*
|
||||
* These changes are:
|
||||
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* d3des.h -
|
||||
*
|
||||
* Headers and defines for d3des.c
|
||||
* Graven Imagery, 1992.
|
||||
*
|
||||
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
|
||||
* (GEnie : OUTER; CIS : [71755,204])
|
||||
*/
|
||||
|
||||
#define EN0 0 /* MODE == encrypt */
|
||||
#define DE1 1 /* MODE == decrypt */
|
||||
|
||||
extern void rfbDesKey(unsigned char *, int);
|
||||
/* hexkey[8] MODE
|
||||
* Sets the internal key register according to the hexadecimal
|
||||
* key contained in the 8 bytes of hexkey, according to the DES,
|
||||
* for encryption or decryption according to MODE.
|
||||
*/
|
||||
|
||||
extern void rfbUseKey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Loads the internal key register with the data in cookedkey.
|
||||
*/
|
||||
|
||||
extern void rfbCPKey(unsigned long *);
|
||||
/* cookedkey[32]
|
||||
* Copies the contents of the internal key register into the storage
|
||||
* located at &cookedkey[0].
|
||||
*/
|
||||
|
||||
extern void rfbDes(unsigned char *, unsigned char *);
|
||||
/* from[8] to[8]
|
||||
* Encrypts/Decrypts (according to the key currently loaded in the
|
||||
* internal key register) one block of eight bytes at address 'from'
|
||||
* into the block at address 'to'. They can be the same.
|
||||
*/
|
||||
|
||||
/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
|
||||
********************************************************************/
|
||||
|
||||
#endif
|
||||
61
libvncserver/draw.c
Normal file
61
libvncserver/draw.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "rfb/rfb.h"
|
||||
|
||||
void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
int i,j;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
for(j=y1;j<y2;j++)
|
||||
for(i=x1;i<x2;i++)
|
||||
memcpy(s->frameBuffer+j*rowstride+i*bpp,colour,bpp);
|
||||
rfbMarkRectAsModified(s,x1,y1,x2,y2);
|
||||
}
|
||||
|
||||
#define SETPIXEL(x,y) \
|
||||
memcpy(s->frameBuffer+(y)*rowstride+(x)*bpp,colour,bpp)
|
||||
|
||||
void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
SETPIXEL(x,y);
|
||||
rfbMarkRectAsModified(s,x,y,x+1,y+1);
|
||||
}
|
||||
|
||||
void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col)
|
||||
{
|
||||
int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3;
|
||||
int i;
|
||||
char* colour=(char*)&col;
|
||||
|
||||
if(!rfbEndianTest)
|
||||
colour += 4-bpp;
|
||||
|
||||
#define SWAPPOINTS { i=x1; x1=x2; x2=i; i=y1; y1=y2; y2=i; }
|
||||
if(abs(x1-x2)<abs(y1-y2)) {
|
||||
if(y1>y2)
|
||||
SWAPPOINTS
|
||||
for(i=y1;i<=y2;i++)
|
||||
SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i);
|
||||
/* TODO: Maybe make this more intelligently? */
|
||||
if(x2<x1) { i=x1; x1=x2; x2=i; }
|
||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
||||
} else {
|
||||
if(x1>x2)
|
||||
SWAPPOINTS
|
||||
else if(x1==x2) {
|
||||
rfbDrawPixel(s,x1,y1,col);
|
||||
return;
|
||||
}
|
||||
for(i=x1;i<=x2;i++)
|
||||
SETPIXEL(i,y1+(i-x1)*(y2-y1)/(x2-x1));
|
||||
if(y2<y1) { i=y1; y1=y2; y2=i; }
|
||||
rfbMarkRectAsModified(s,x1,y1,x2+1,y2+1);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user