aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Args.c19
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Clipboard.c228
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Options.c1
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Options.h7
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/man/nxagent.113
5 files changed, 261 insertions, 7 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.c b/nx-X11/programs/Xserver/hw/nxagent/Args.c
index be13efacd..ea17e4813 100644
--- a/nx-X11/programs/Xserver/hw/nxagent/Args.c
+++ b/nx-X11/programs/Xserver/hw/nxagent/Args.c
@@ -972,6 +972,12 @@ int ddxProcessArgument(int argc, char *argv[], int i)
return 2;
}
+ if (!strcmp(argv[i], "-textclipboard"))
+ {
+ nxagentChangeOption(TextClipboard, True);
+ return 1;
+ }
+
if (!strcmp(argv[i], "-bs"))
{
nxagentChangeOption(BackingStore, BackingStoreNever);
@@ -1487,6 +1493,18 @@ static void nxagentParseSingleOption(char *name, char *value)
}
return;
}
+ else if (!strcmp(name, "textclipboard"))
+ {
+ if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(TextClipboard, False);
+ }
+ else
+ {
+ nxagentChangeOption(TextClipboard, True);
+ }
+ return;
+ }
else
{
#ifdef DEBUG
@@ -2129,6 +2147,7 @@ void ddxUseMsg(void)
ErrorF("-nokbreset don't reset keyboard device if the session is resumed\n");
ErrorF("-noxkblock always allow applications to change layout through XKEYBOARD\n");
ErrorF("-autograb enable autograb\n");
+ ErrorF("-textclipboard limit clipboard data to text only\n");
ErrorF("-irlimit maximum image data rate to the encoder input in kB/s.\n");
ErrorF("-tile WxH maximum size of image tiles (minimum allowed: 32x32)\n");
ErrorF("-keystrokefile file file with keyboard shortcut definitions\n");
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c
index 28d56b758..fb2595e68 100644
--- a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c
+++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c
@@ -264,6 +264,7 @@ XFixesAgentInfoRec nxagentXFixesInfo = { -1, -1, -1, False };
extern Display *nxagentDisplay;
+static Bool isTextTarget(XlibAtom target);
static void setClientSelectionStage(int stage, int index);
static void endTransfer(Bool success, int index);
#define SELECTION_SUCCESS True
@@ -562,6 +563,48 @@ static void sendSelectionNotifyEventToClient(ClientPtr client,
sendEventToClient(client, &x);
}
+/*
+ * Check if target is a valid text content type target sent by the real X
+ * server, like .e.g XA_STRING or UTF8_STRING.
+ */
+static Bool isTextTarget(XlibAtom target)
+{
+ if (target == XA_STRING)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: valid target [XA_STRING].\n", __func__);
+ #endif
+ return True;
+ }
+ else if (target == serverTEXT)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: valid target [TEXT].\n", __func__);
+ #endif
+ return True;
+ }
+ else if (target == serverUTF8_STRING)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: valid target [UTF8_STRING].\n", __func__);
+ #endif
+ return True;
+ }
+ else if (target == serverCOMPOUND_TEXT)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: valid target [COMPOUND_TEXT].\n", __func__);
+ #endif
+ return True;
+ }
+ /* FIXME: add text/plain */
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: not a text target [%lu].\n", __func__, target);
+ #endif
+ return False;
+}
+
static void initSelectionOwnerData(int index)
{
lastSelectionOwner[index].client = NullClient;
@@ -806,7 +849,61 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X)
return;
}
- if (X->xselectionrequest.target == serverTIMESTAMP)
+ if (X->xselectionrequest.target == serverTARGETS)
+ {
+ /*
+ * In TextClipboard mode answer with a predefined list of
+ * targets. This is just the previous implementation of handling
+ * the clipboard.
+ */
+ if (nxagentOption(TextClipboard))
+ {
+ /*
+ * the selection request target is TARGETS. The requestor is
+ * asking for a list of supported data formats.
+ *
+ * The selection does not matter here, we will return this for
+ * PRIMARY and CLIPBOARD.
+ *
+ * The list is aligned with the one in nxagentConvertSelection()
+ * and in isTextTarget().
+ */
+
+ XlibAtom targets[] = {XA_STRING, serverUTF8_STRING, serverTEXT, serverCOMPOUND_TEXT,
+ serverTARGETS, serverTIMESTAMP};
+ int numTargets = sizeof(targets) / sizeof(targets[0]);
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets);
+ for (int i = 0; i < numTargets; i++)
+ {
+ fprintf(stderr, "%s: %ld %s\n", __func__, targets[i], NameForRemAtom(targets[i]));
+ }
+ fprintf(stderr, "\n");
+ #endif
+
+ /*
+ * pass on the requested list by setting the property provided
+ * by the requestor accordingly.
+ */
+ XChangeProperty(nxagentDisplay,
+ X->xselectionrequest.requestor,
+ X->xselectionrequest.property,
+ XInternAtom(nxagentDisplay, "ATOM", 0),
+ 32,
+ PropModeReplace,
+ (unsigned char*)targets,
+ numTargets);
+
+ replyRequestSelectionToXServer(X, True);
+ return;
+ }
+ else
+ {
+ /* do nothing, let TARGETS be passed on to the owner later */
+ }
+ }
+ else if (X->xselectionrequest.target == serverTIMESTAMP)
{
/*
* Section 2.6.2 of the ICCCM states:
@@ -882,12 +979,28 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X)
replyRequestSelectionToXServer(X, False);
return;
}
- else
+
+ if (nxagentOption(TextClipboard))
{
- fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target,
- NameForRemAtom(X->xselectionrequest.target));
+ if (!isTextTarget(X->xselectionrequest.target))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: denying request for non-text target [%ld][%s].\n", __func__,
+ X->xselectionrequest.target, NameForRemAtom(X->xselectionrequest.target));
+ #endif
+
+ replyRequestSelectionToXServer(X, False);
+
+ return;
+ }
+ /* go on, target is acceptable */
}
+ #ifdef DEBUG
+ fprintf(stderr, "%s: target [%ld][%s].\n", __func__, X->xselectionrequest.target,
+ NameForRemAtom(X->xselectionrequest.target));
+ #endif
+
/*
* reaching this means the request is a normal, valid request. We
* can process it now.
@@ -967,12 +1080,34 @@ void nxagentHandleSelectionRequestFromXServer(XEvent *X)
/*
* Don't send the same window, some programs are clever and
* verify cut and paste operations inside the same window and
- * don't Notify at all.
+ * don't notify at all.
*
* x.u.selectionRequest.requestor = lastSelectionOwner[index].window;
*/
- x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target);
+ /*
+ * if textclipboard is requested simply use the previous clipboard
+ * handling code
+ */
+ if (nxagentOption(TextClipboard))
+ {
+ /* by dimbor */
+ if (X->xselectionrequest.target != XA_STRING)
+ {
+ lastServers[index].target = serverUTF8_STRING;
+ /* by dimbor (idea from zahvatov) */
+ x.u.selectionRequest.target = clientUTF8_STRING;
+ }
+ else
+ {
+ x.u.selectionRequest.target = XA_STRING;
+ }
+ }
+ else
+ {
+ x.u.selectionRequest.target = nxagentRemoteToLocalAtom(X->xselectionrequest.target);
+ }
+
sendEventToClient(lastSelectionOwner[index].client, &x);
#ifdef DEBUG
@@ -2009,6 +2144,64 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection,
}
/*
+ * The selection request target is TARGETS. The requestor is asking
+ * for a list of supported data formats.
+ */
+
+ if (target == clientTARGETS)
+ {
+ /*
+ * In TextClipboard mode answer with a predefined list that was used
+ * in in previous versions.
+ */
+ if (nxagentOption(TextClipboard))
+ {
+ /*
+ * The list is aligned with the one in
+ * nxagentHandleSelectionRequestFromXServer.
+ */
+ Atom targets[] = {XA_STRING,
+ clientUTF8_STRING,
+#if 0
+ clientTEXT,
+ clientCOMPOUND_TEXT,
+#endif
+ clientTARGETS,
+ clientTIMESTAMP};
+ int numTargets = sizeof(targets) / sizeof(targets[0]);
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: Sending %d available targets:\n", __func__, numTargets);
+ for (int i = 0; i < numTargets; i++)
+ {
+ fprintf(stderr, "%s: %d %s\n", __func__, targets[i], NameForIntAtom(targets[i]));
+ }
+ #endif
+
+ ChangeWindowProperty(pWin,
+ property,
+ MakeAtom("ATOM", 4, 1),
+ sizeof(Atom)*8,
+ PropModeReplace,
+ numTargets,
+ targets,
+ 1);
+
+ sendSelectionNotifyEventToClient(client, time, requestor, selection,
+ target, property);
+
+ return 1;
+ }
+ else
+ {
+ /*
+ * do nothing - TARGETS will be handled like any other target
+ * and passed on to the owner on the remote side.
+ */
+ }
+ }
+
+ /*
* Section 2.6.2 of the ICCCM states:
* "TIMESTAMP - To avoid some race conditions, it is important
* that requestors be able to discover the timestamp the owner
@@ -2018,7 +2211,7 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection,
* support conversion to TIMESTAMP, returning the timestamp they
* used to obtain the selection."
*/
- if (target == clientTIMESTAMP)
+ else if (target == clientTIMESTAMP)
{
/*
* "If the specified property is not None, the owner should place
@@ -2087,6 +2280,27 @@ int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection,
return 1;
}
+ /* in TextClipboard mode reject all non-text targets */
+ if (nxagentOption(TextClipboard))
+ {
+ if (!isTextTarget(translateLocalToRemoteTarget(target)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: denying request for non-text target [%d][%s].\n", __func__,
+ target, NameForIntAtom(target));
+ #endif
+
+ sendSelectionNotifyEventToClient(client, time, requestor, selection, target, None);
+ return 1;
+ }
+ /* go on, target is acceptable */
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: target [%d][%s].\n", __func__, target,
+ NameForIntAtom(target));
+ #endif
+
if (lastClients[index].clientPtr == client)
{
if (GetTimeInMillis() - lastClients[index].reqTime < ACCUM_TIME)
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.c b/nx-X11/programs/Xserver/hw/nxagent/Options.c
index be6e5d5e1..8e6249e4c 100644
--- a/nx-X11/programs/Xserver/hw/nxagent/Options.c
+++ b/nx-X11/programs/Xserver/hw/nxagent/Options.c
@@ -88,6 +88,7 @@ void nxagentInitOptions(void)
nxagentOptions.BackingStore = BackingStoreUndefined;
nxagentOptions.Clipboard = ClipboardBoth;
+ nxagentOptions.TextClipboard = False;
nxagentOptions.SharedMemory = True;
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.h b/nx-X11/programs/Xserver/hw/nxagent/Options.h
index a99f4aee2..d3c8c7150 100644
--- a/nx-X11/programs/Xserver/hw/nxagent/Options.h
+++ b/nx-X11/programs/Xserver/hw/nxagent/Options.h
@@ -195,6 +195,13 @@ typedef struct _AgentOptions
ClipboardMode Clipboard;
/*
+ * transfer TARGETS to remote side or answer with a limited
+ * hardcoded text target list
+ * Should be Bool but we'd have to include Xlib.h for that
+ */
+ int TextClipboard;
+
+ /*
* Enable agent to use the MITSHM extension in path from remote
* proxy to the real X server.
*/
diff --git a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1
index 74349cda7..f373cb239 100644
--- a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1
+++ b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1
@@ -465,6 +465,10 @@ The session id.
.B \-autograb
enable autograb mode on \fBnxagent\fR startup. The autograb feature can be toggled via nxagent keystrokes
.TP 8
+.B \-textclipboard
+force text-only clipboard \fBnxagent\fR startup. See option file
+option \fBtextclipboard=<bool>\fR for an explanation.
+.TP 8
.B \-nxrealwindowprop
set property NX_REAL_WINDOW for each X11 client inside \fBnxagent\fR,
providing the window XID of the corresponding window object on the X
@@ -721,6 +725,15 @@ Limit clipboard data exchange to work only in one direction: from nxagent to rea
Disable any clipboard data exchange. Clipboard will still work inside the nxagent and on the real X server, but no data exchange will be possible.
.RE
.TP 8
+.B textclipboard=<bool>
+enable (set to \fI1\fR) or disable (set to \fI0\fR) text-only
+clipboard. Text-only clipboard is the old (<= 3.5.99.26) clipboard
+behaviour where you could only copy and paste text strings (no
+graphics, no rich text, ...). Using this mode been seen as a security feature
+as it effectively prevents transferring dangerous binary data,
+e.g. manipulated graphics by accident. On the other hand it's also
+less comfortable. (default: disabled)
+.TP 8
.B streaming=<bool>
enable (set to \fI1\fR) or disable (set to \fI0\fR) streaming support for images, not fully implemented yet and thus non-functional. (default: disabled)
.TP 8