devdraw, acme, snarfer: remove 64KB snarf buffer limit
The snarf code silently dropped text larger than SnarfSize (64KB), causing paste to produce nothing. Replace the static clip buffer with a dynamically allocated one, remove all the size checks, and read the actual X11 property size instead of capping at SnarfSize.
This commit is contained in:
committed by
Dan Cross
parent
ae4fdf4268
commit
0d87d4b75e
@@ -547,10 +547,6 @@ extern void drawsetdebug(int);
|
|||||||
/*
|
/*
|
||||||
* Snarf buffer
|
* Snarf buffer
|
||||||
*/
|
*/
|
||||||
enum
|
|
||||||
{
|
|
||||||
SnarfSize = 64*1024
|
|
||||||
};
|
|
||||||
char *getsnarf(void);
|
char *getsnarf(void);
|
||||||
void putsnarf(char*);
|
void putsnarf(char*);
|
||||||
|
|
||||||
|
|||||||
@@ -1090,11 +1090,6 @@ iconinit(void)
|
|||||||
* fd here rather than use snarffd
|
* fd here rather than use snarffd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* rio truncates larges snarf buffers, so this avoids using the
|
|
||||||
* service if the string is huge */
|
|
||||||
|
|
||||||
#define MAXSNARF 100*1024
|
|
||||||
|
|
||||||
void
|
void
|
||||||
acmeputsnarf(void)
|
acmeputsnarf(void)
|
||||||
{
|
{
|
||||||
@@ -1104,8 +1099,6 @@ acmeputsnarf(void)
|
|||||||
|
|
||||||
if(snarfbuf.nc==0)
|
if(snarfbuf.nc==0)
|
||||||
return;
|
return;
|
||||||
if(snarfbuf.nc > MAXSNARF)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fmtstrinit(&f);
|
fmtstrinit(&f);
|
||||||
for(i=0; i<snarfbuf.nc; i+=n){
|
for(i=0; i<snarfbuf.nc; i+=n){
|
||||||
|
|||||||
@@ -1109,7 +1109,7 @@ rpc_getsnarf(void)
|
|||||||
void
|
void
|
||||||
rpc_putsnarf(char *s)
|
rpc_putsnarf(char *s)
|
||||||
{
|
{
|
||||||
if(s == nil || strlen(s) >= SnarfSize)
|
if(s == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dispatch_sync(dispatch_get_main_queue(), ^(void) {
|
dispatch_sync(dispatch_get_main_queue(), ^(void) {
|
||||||
|
|||||||
@@ -1454,9 +1454,8 @@ rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
QLock lk;
|
QLock lk;
|
||||||
char buf[SnarfSize];
|
char *buf;
|
||||||
#ifdef APPLESNARF
|
#ifdef APPLESNARF
|
||||||
Rune rbuf[SnarfSize];
|
|
||||||
PasteboardRef apple;
|
PasteboardRef apple;
|
||||||
#endif
|
#endif
|
||||||
} clip;
|
} clip;
|
||||||
@@ -1498,7 +1497,7 @@ _xgetsnarffrom(Xwin *w, XWindow xw, Atom clipboard, Atom target, int timeout0, i
|
|||||||
|
|
||||||
/* get the property */
|
/* get the property */
|
||||||
xdata = nil;
|
xdata = nil;
|
||||||
XGetWindowProperty(_x.display, w->drawable, prop, 0, SnarfSize/sizeof(ulong), 0,
|
XGetWindowProperty(_x.display, w->drawable, prop, 0, (len+3)/4, 0,
|
||||||
AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
|
AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
|
||||||
if((type != target && type != XA_STRING && type != _x.utf8string) || len == 0){
|
if((type != target && type != XA_STRING && type != _x.utf8string) || len == 0){
|
||||||
if(xdata)
|
if(xdata)
|
||||||
@@ -1538,6 +1537,8 @@ rpc_getsnarf(void)
|
|||||||
// TODO check more
|
// TODO check more
|
||||||
if(xw == w->drawable){
|
if(xw == w->drawable){
|
||||||
mine:
|
mine:
|
||||||
|
data = nil;
|
||||||
|
if(clip.buf != nil)
|
||||||
data = (uchar*)strdup(clip.buf);
|
data = (uchar*)strdup(clip.buf);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1577,12 +1578,11 @@ __xputsnarf(char *data)
|
|||||||
XButtonEvent e;
|
XButtonEvent e;
|
||||||
Xwin *w;
|
Xwin *w;
|
||||||
|
|
||||||
if(strlen(data) >= SnarfSize)
|
|
||||||
return;
|
|
||||||
qlock(&clip.lk);
|
qlock(&clip.lk);
|
||||||
xlock();
|
xlock();
|
||||||
w = _x.windows;
|
w = _x.windows;
|
||||||
strcpy(clip.buf, data);
|
free(clip.buf);
|
||||||
|
clip.buf = strdup(data);
|
||||||
/* leave note for mouse proc to assert selection ownership */
|
/* leave note for mouse proc to assert selection ownership */
|
||||||
_x.putsnarf++;
|
_x.putsnarf++;
|
||||||
|
|
||||||
@@ -1627,8 +1627,12 @@ if(0) fprint(2, "xselect target=%d requestor=%d property=%d selection=%d (sizeof
|
|||||||
/* text/plain;charset=utf-8 is used by xfce4-terminal 1.0.4 */
|
/* text/plain;charset=utf-8 is used by xfce4-terminal 1.0.4 */
|
||||||
/* if the target is STRING we're supposed to reply with Latin1 XXX */
|
/* if the target is STRING we're supposed to reply with Latin1 XXX */
|
||||||
qlock(&clip.lk);
|
qlock(&clip.lk);
|
||||||
|
if(clip.buf)
|
||||||
XChangeProperty(_x.display, xe->requestor, xe->property, xe->target,
|
XChangeProperty(_x.display, xe->requestor, xe->property, xe->target,
|
||||||
8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
|
8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
|
||||||
|
else
|
||||||
|
XChangeProperty(_x.display, xe->requestor, xe->property, xe->target,
|
||||||
|
8, PropModeReplace, (uchar*)"", 0);
|
||||||
qunlock(&clip.lk);
|
qunlock(&clip.lk);
|
||||||
}else{
|
}else{
|
||||||
if(strcmp(name, "TIMESTAMP") != 0)
|
if(strcmp(name, "TIMESTAMP") != 0)
|
||||||
@@ -1674,6 +1678,8 @@ _applegetsnarf(void)
|
|||||||
}
|
}
|
||||||
flags = PasteboardSynchronize(clip.apple);
|
flags = PasteboardSynchronize(clip.apple);
|
||||||
if(flags&kPasteboardClientIsOwner){
|
if(flags&kPasteboardClientIsOwner){
|
||||||
|
s = nil;
|
||||||
|
if(clip.buf != nil)
|
||||||
s = strdup(clip.buf);
|
s = strdup(clip.buf);
|
||||||
qunlock(&clip.lk);
|
qunlock(&clip.lk);
|
||||||
return s;
|
return s;
|
||||||
@@ -1716,14 +1722,21 @@ _appleputsnarf(char *s)
|
|||||||
{
|
{
|
||||||
CFDataRef cfdata;
|
CFDataRef cfdata;
|
||||||
PasteboardSyncFlags flags;
|
PasteboardSyncFlags flags;
|
||||||
|
Rune *r;
|
||||||
|
int n;
|
||||||
|
|
||||||
/* fprint(2, "appleputsnarf\n"); */
|
/* fprint(2, "appleputsnarf\n"); */
|
||||||
|
|
||||||
if(strlen(s) >= SnarfSize)
|
|
||||||
return;
|
|
||||||
qlock(&clip.lk);
|
qlock(&clip.lk);
|
||||||
strcpy(clip.buf, s);
|
free(clip.buf);
|
||||||
runesnprint(clip.rbuf, nelem(clip.rbuf), "%s", s);
|
clip.buf = strdup(s);
|
||||||
|
n = utflen(s) + 1;
|
||||||
|
r = malloc(n * sizeof(Rune));
|
||||||
|
if(r == nil){
|
||||||
|
qunlock(&clip.lk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runesnprint(r, n, "%s", s);
|
||||||
if(clip.apple == nil){
|
if(clip.apple == nil){
|
||||||
if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
|
if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){
|
||||||
fprint(2, "apple pasteboard create failed\n");
|
fprint(2, "apple pasteboard create failed\n");
|
||||||
@@ -1733,17 +1746,20 @@ _appleputsnarf(char *s)
|
|||||||
}
|
}
|
||||||
if(PasteboardClear(clip.apple) != noErr){
|
if(PasteboardClear(clip.apple) != noErr){
|
||||||
fprint(2, "apple pasteboard clear failed\n");
|
fprint(2, "apple pasteboard clear failed\n");
|
||||||
|
free(r);
|
||||||
qunlock(&clip.lk);
|
qunlock(&clip.lk);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
flags = PasteboardSynchronize(clip.apple);
|
flags = PasteboardSynchronize(clip.apple);
|
||||||
if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
|
if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
|
||||||
fprint(2, "apple pasteboard cannot assert ownership\n");
|
fprint(2, "apple pasteboard cannot assert ownership\n");
|
||||||
|
free(r);
|
||||||
qunlock(&clip.lk);
|
qunlock(&clip.lk);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cfdata = CFDataCreate(kCFAllocatorDefault,
|
cfdata = CFDataCreate(kCFAllocatorDefault,
|
||||||
(uchar*)clip.rbuf, runestrlen(clip.rbuf)*2);
|
(uchar*)r, runestrlen(r)*2);
|
||||||
|
free(r);
|
||||||
if(cfdata == nil){
|
if(cfdata == nil){
|
||||||
fprint(2, "apple pasteboard cfdatacreate failed\n");
|
fprint(2, "apple pasteboard cfdatacreate failed\n");
|
||||||
qunlock(&clip.lk);
|
qunlock(&clip.lk);
|
||||||
|
|||||||
@@ -54,11 +54,8 @@ AUTOFRAMEWORK(Carbon)
|
|||||||
#undef time
|
#undef time
|
||||||
AUTOLIB(draw) /* to cause link of X11 */
|
AUTOLIB(draw) /* to cause link of X11 */
|
||||||
|
|
||||||
enum {
|
char *snarf;
|
||||||
SnarfSize = 65536
|
Rune *rsnarf;
|
||||||
};
|
|
||||||
char snarf[3*SnarfSize+1];
|
|
||||||
Rune rsnarf[SnarfSize+1];
|
|
||||||
XDisplay *xdisplay;
|
XDisplay *xdisplay;
|
||||||
XWindow drawable;
|
XWindow drawable;
|
||||||
Atom xclipboard;
|
Atom xclipboard;
|
||||||
@@ -98,6 +95,7 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}ARGEND
|
}ARGEND
|
||||||
|
|
||||||
|
snarf = strdup("");
|
||||||
if((xdisplay = XOpenDisplay(nil)) == nil)
|
if((xdisplay = XOpenDisplay(nil)) == nil)
|
||||||
sysfatal("XOpenDisplay: %r");
|
sysfatal("XOpenDisplay: %r");
|
||||||
drawable = XCreateWindow(xdisplay, DefaultRootWindow(xdisplay),
|
drawable = XCreateWindow(xdisplay, DefaultRootWindow(xdisplay),
|
||||||
@@ -256,18 +254,16 @@ xgetsnarf(void)
|
|||||||
return nil;
|
return nil;
|
||||||
/* get the property */
|
/* get the property */
|
||||||
data = nil;
|
data = nil;
|
||||||
XGetWindowProperty(xd, drawable, prop, 0, SnarfSize/sizeof(ulong), 0,
|
XGetWindowProperty(xd, drawable, prop, 0, (len+3)/4, 0,
|
||||||
AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
|
AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
|
||||||
if(xdata == nil || (type != XA_STRING && type != xutf8string) || len == 0){
|
if(xdata == nil || (type != XA_STRING && type != xutf8string) || len == 0){
|
||||||
if(xdata)
|
if(xdata)
|
||||||
XFree(xdata);
|
XFree(xdata);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
if(strlen((char*)xdata) >= SnarfSize){
|
free(snarf);
|
||||||
|
snarf = strdup((char*)xdata);
|
||||||
XFree(xdata);
|
XFree(xdata);
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
strcpy(snarf, (char*)xdata);
|
|
||||||
return snarf;
|
return snarf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,8 +282,16 @@ appleputsnarf(void)
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
CFDataRef cfdata;
|
CFDataRef cfdata;
|
||||||
PasteboardSyncFlags flags;
|
PasteboardSyncFlags flags;
|
||||||
|
int n;
|
||||||
|
|
||||||
runesnprint(rsnarf, nelem(rsnarf), "%s", snarf);
|
if(snarf == nil)
|
||||||
|
return;
|
||||||
|
n = utflen(snarf) + 1;
|
||||||
|
free(rsnarf);
|
||||||
|
rsnarf = malloc(n * sizeof(Rune));
|
||||||
|
if(rsnarf == nil)
|
||||||
|
return;
|
||||||
|
runesnprint(rsnarf, n, "%s", snarf);
|
||||||
if(PasteboardClear(appleclip) != noErr){
|
if(PasteboardClear(appleclip) != noErr){
|
||||||
fprint(2, "apple pasteboard clear failed\n");
|
fprint(2, "apple pasteboard clear failed\n");
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user