diff --git a/droidvncgrab/Android.mk b/droidvncgrab/Android.mk new file mode 100755 index 0000000..83ff374 --- /dev/null +++ b/droidvncgrab/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES = \ + droidVncGrab.cpp + +#LOCAL_CFLAGS += -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) + +LOCAL_C_INCLUDES += $(LOCAL_PATH) + +LOCAL_PRELINK_MODULE:=false #override prelink map +LOCAL_MODULE:= droidvncgrab_sdk$(PLATFORM_SDK_VERSION) +LOCAL_MODULE_TAGS:= optional + +ifeq ($(PLATFORM_SDK_VERSION),9) +LOCAL_SHARED_LIBRARIES := libsurfaceflinger_client libui libbinder libutils libcutils #libcrypto libssl libhardware +else ifeq ($(PLATFORM_SDK_VERSION),15) +LOCAL_SHARED_LIBRARIES := libgui libui libbinder libcutils +else +#add here more sdk versions +LOCAL_SHARED_LIBRARIES := libsurfaceflinger_client libui libbinder libutils libcutils #libcrypto libssl libhardware +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/droidvncgrab/README b/droidvncgrab/README new file mode 100644 index 0000000..28eb82f --- /dev/null +++ b/droidvncgrab/README @@ -0,0 +1 @@ +This diff --git a/droidvncgrab/droidVncGrab.cpp b/droidvncgrab/droidVncGrab.cpp new file mode 100755 index 0000000..95d7a2e --- /dev/null +++ b/droidvncgrab/droidVncGrab.cpp @@ -0,0 +1,83 @@ +/* + droid vnc server - Android VNC server + Copyright (C) 2009 Jose Pereira + + 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 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "droidVncGrab.h" +#include "screenFormat.h" + +#include +#include +#include + +#include +#include +#include + +using namespace android; + +ScreenshotClient *screenshotClient=NULL; + +extern "C" screenFormat getScreenFormat() +{ + //get format on PixelFormat struct + PixelFormat f=screenshotClient->getFormat(); + + PixelFormatInfo pf; + getPixelFormatInfo(f,&pf); + + screenFormat format; + + format.bitsPerPixel = pf.bitsPerPixel; + format.width = screenshotClient->getWidth(); + format.height = screenshotClient->getHeight(); + format.size = pf.bitsPerPixel*format.width*format.height/CHAR_BIT; + format.redShift = pf.l_red; + format.redMax = pf.h_red; + format.greenShift = pf.l_green; + format.greenMax = pf.h_green-pf.h_red; + format.blueShift = pf.l_blue; + format.blueMax = pf.h_blue-pf.h_green; + format.alphaShift = pf.l_alpha; + format.alphaMax = pf.h_alpha-pf.h_blue; + + return format; +} + + +extern "C" int initScreenGrab() +{ + int errno; + + L("--Initializing gingerbread access method--\n"); + + screenshotClient=new ScreenshotClient(); + errno=screenshotClient->update(); + if (errno != NO_ERROR) { + L("screen capture failed: %s\n", strerror(-errno)); + return -1; + } + + return 0; +} + +extern "C" unsigned int * getScreenBuffer() +{ + screenshotClient->update(); + return (unsigned int*)screenshotClient->getPixels(); +} + diff --git a/droidvncgrab/droidVncGrab.h b/droidvncgrab/droidVncGrab.h new file mode 100755 index 0000000..76366b3 --- /dev/null +++ b/droidvncgrab/droidVncGrab.h @@ -0,0 +1,36 @@ +/* + droid vnc server - Android VNC server + Copyright (C) 2009 Jose Pereira + + 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 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DISPLAY_BINDER +#define DISPLAY_BINDER + +#ifdef __cplusplus +#define L(...) __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); + + +extern "C" { +#endif + unsigned int * updateScreen(); + int initScreenGrab(); +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/droidvncgrab/screenFormat.h b/droidvncgrab/screenFormat.h new file mode 100644 index 0000000..a8d35ff --- /dev/null +++ b/droidvncgrab/screenFormat.h @@ -0,0 +1,26 @@ +#include + + +typedef struct _screenFormat +{ + + uint16_t width; + uint16_t height; + + uint8_t bitsPerPixel; + + uint16_t redMax; + uint16_t greenMax; + uint16_t blueMax; + uint16_t alphaMax; + + uint8_t redShift; + uint8_t greenShift; + uint8_t blueShift; + uint8_t alphaShift; + + uint32_t size; + + uint32_t pad; + +} screenFormat; diff --git a/droidvncgrab/vnc/.droidvncserver.c.swp b/droidvncgrab/vnc/.droidvncserver.c.swp new file mode 100644 index 0000000..3264dfc Binary files /dev/null and b/droidvncgrab/vnc/.droidvncserver.c.swp differ diff --git a/droidvncgrab/vnc/Android.mk b/droidvncgrab/vnc/Android.mk new file mode 100755 index 0000000..a83c1e9 --- /dev/null +++ b/droidvncgrab/vnc/Android.mk @@ -0,0 +1,94 @@ + + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +local_c_flags += -Wall -O3 -DLIBVNCSERVER_WITH_WEBSOCKETS -DLIBVNCSERVER_HAVE_LIBPNG + +local_src_files:= \ + input.c \ + gui.c \ + adb_method.c \ + framebuffer_method.c \ + suinput.c \ + droidvncserver.c \ + gralloc_method.c \ + libvncserver-kanaka/libvncserver/scale.c \ + libvncserver-kanaka/libvncserver/main.c \ + libvncserver-kanaka/libvncserver/rfbserver.c \ + libvncserver-kanaka/libvncserver/rfbregion.c \ + libvncserver-kanaka/libvncserver/auth.c \ + libvncserver-kanaka/libvncserver/sockets.c \ + libvncserver-kanaka/libvncserver/stats.c \ + libvncserver-kanaka/libvncserver/corre.c \ + libvncserver-kanaka/libvncserver/hextile.c \ + libvncserver-kanaka/libvncserver/rre.c \ + libvncserver-kanaka/libvncserver/translate.c \ + libvncserver-kanaka/libvncserver/cutpaste.c \ + libvncserver-kanaka/libvncserver/httpd.c \ + libvncserver-kanaka/libvncserver/cursor.c \ + libvncserver-kanaka/libvncserver/font.c \ + libvncserver-kanaka/libvncserver/draw.c \ + libvncserver-kanaka/libvncserver/selbox.c \ + libvncserver-kanaka/libvncserver/minilzo.c \ + libvncserver-kanaka/libvncserver/vncauth.c \ + libvncserver-kanaka/libvncserver/d3des.c \ + libvncserver-kanaka/libvncserver/md5.c \ + libvncserver-kanaka/libvncserver/cargs.c \ + libvncserver-kanaka/libvncserver/ultra.c \ + libvncserver-kanaka/libvncserver/zlib.c \ + libvncserver-kanaka/libvncserver/zrle.c \ + libvncserver-kanaka/libvncserver/zrleoutstream.c \ + libvncserver-kanaka/libvncserver/zrlepalettehelper.c \ + libvncserver-kanaka/libvncserver/tight.c \ + libvncserver-kanaka/libvncserver/zywrletemplate.c \ + libvncserver-kanaka/libvncserver/websockets.c + +ginger_up := displaybinder.cpp + + +local_c_includes := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/libvncserver-kanaka/libvncserver \ + $(LOCAL_PATH)/libvncserver-kanaka \ + $(LOCAL_PATH)/libvncserver-kanaka/common \ + $(LOCAL_PATH)/../../zlib \ + $(LOCAL_PATH)/../../jpeg \ + $(LOCAL_PATH)/../../openssl/include \ + $(LOCAL_PATH)/../../libpng \ + +####################################### + +# target +include $(CLEAR_VARS) +LOCAL_SRC_FILES += $(local_src_files) +LOCAL_CFLAGS += $(local_c_flags) -DANDROID_FROYO +LOCAL_C_INCLUDES += $(local_c_includes) + + +LOCAL_MODULE:= androidvncserver_froyo +LOCAL_MODULE_TAGS:= optional + +LOCAL_STATIC_LIBRARIES := libcutils libz libpng jpeg +LOCAL_SHARED_LIBRARIES := libcrypto libssl libhardware + +include $(BUILD_EXECUTABLE) + +####################################### + +# target +include $(CLEAR_VARS) +LOCAL_SRC_FILES += $(local_src_files) $(ginger_up) +LOCAL_CFLAGS += $(local_c_flags) +LOCAL_C_INCLUDES += $(local_c_includes) + + +LOCAL_MODULE:= androidvncserver_gingerup +LOCAL_MODULE_TAGS:= optional + +LOCAL_STATIC_LIBRARIES := libcutils libz libpng jpeg +LOCAL_SHARED_LIBRARIES := libcrypto libssl libhardware libsurfaceflinger_client libui + +include $(BUILD_EXECUTABLE) diff --git a/droidvncgrab/vnc/adb_method.c b/droidvncgrab/vnc/adb_method.c new file mode 100755 index 0000000..7da3e1a --- /dev/null +++ b/droidvncgrab/vnc/adb_method.c @@ -0,0 +1,284 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "adb_method.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#include "common.h" + + + +#define A_CNXN 0x4e584e43 +#define A_OKAY 0x59414b4f +#define A_CLSE 0x45534c43 +#define A_WRTE 0x45545257 + + +#define DDMS_RAWIMAGE_VERSION 1 + +char connect_string[] = { +0x43, 0x4e, 0x58, 0x4e, 0x00, 0x00, 0x00, 0x01, +0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, +0x32, 0x02, 0x00, 0x00, 0xbc, 0xb1, 0xa7, 0xb1, +0x68, 0x6f, 0x73, 0x74, 0x3a, 0x3a, 0x00 }; + +char framebuffer_string[] = { +0x4f, 0x50, 0x45, 0x4e, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, +0xbf, 0x04, 0x00, 0x00, 0xb0, 0xaf, 0xba, 0xb1, +0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66, +0x66, 0x65, 0x72, 0x3a, 0x00 }; + +char okay_string[24]; + +struct fbinfo *fb_info; +struct _message *message,*okay_message; +int sockfd; + +ssize_t write_socket(int fd, const void *buf, size_t count) +{ +// L("--Writing %d \n",count); + + int n = write(fd,buf,count); + + if (n < 0) + perror("ERROR writing to socket"); + + return n; +} + + +void read_socket(int fd, void *buf, size_t count) +{ + int n=0; + + while (count>0) + { + n=read(fd,buf,count); + + if (n < 0) + L("ERROR reading from socket\n"); + + + count-=n; + } + return; +} + +void send_connect_string() +{ + write_socket(sockfd,connect_string,sizeof(connect_string)); + + read_socket(sockfd,message,sizeof(struct _message)); + + if (message->command!=A_CNXN) + L("bad A_CNXN response\n"); + + //lets read, i don't want this + read_socket(sockfd,message,message->data_length); +} + +void send_framebuffer_string(); + +int initADB() +{ + L("--Initializing adb access method--\n"); + int portno; + struct sockaddr_in serv_addr; + struct hostent *server; + adbbuf=NULL; + + property_set("service.adb.tcp.port", "5555"); + system("setprop service.adb.tcp.port 5555"); + system("adbd"); + + message=malloc(sizeof(struct _message)); + okay_message=malloc(sizeof(struct _message)); + + +// L("1\n"); + + portno = 5555; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + L("adb ERROR opening socket\n"); + return -1; + } +#ifdef ANDROID + server = gethostbyname("127.0.0.1"); +#else + server = gethostbyname("192.168.10.6"); +#endif + if (server == NULL) { + L("adb ERROR, no such host\n"); + return -1; + } + +// L("2\n"); + + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port = htons(portno); + if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) + { + L("adb ERROR connecting\n"); + return -1; + } + +// L("3\n"); + send_connect_string(); +// L("4\n"); +return 0; + } + + + +void send_framebuffer_string()//returns the fb struct size from adb +{ + int n; + char *buffer=NULL; + write_socket(sockfd,framebuffer_string,sizeof(framebuffer_string)); + read_socket(sockfd,okay_message,sizeof(struct _message)); + + if (okay_message->command!=A_OKAY) + { + L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + L("bad OKAY response on send_framebuffer_string\n"); + + } + + n=okay_message->arg0; + okay_message->arg0=okay_message->arg1; + okay_message->arg1=n; + + +// L("arg0=%08X\narg1=%08X\n",okay_message->arg0,okay_message->arg1); + //we now have our okay message + + //lets receive fb info... + read_socket(sockfd,message,sizeof(struct _message)); + + + if (message->command!=A_WRTE) + L("bad WRTE response\n"); + +// L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + +// if (message->data_length!=sizeof(struct _message)) +// error("Size should match..."); + + buffer=(char*)malloc(sizeof(char)*message->data_length); + + read_socket(sockfd,&displayInfo,sizeof(struct fbinfo)); + +// L("sizeof(struct fbinfo)=%d\n",sizeof(struct fbinfo)); + +// L("ADB framebuffer method:\nversion=%d\nbpp=%d\nsize=%d bytes\nwidth=%dpx\nheight=%dpx\nsize=%d\n", +// displayInfo.version,displayInfo.bpp,displayInfo.size,displayInfo.width,displayInfo.height,displayInfo.size); + +// L("sizeof(struct _message)=%d\n",sizeof(struct _message)); + write_socket(sockfd,okay_message,sizeof(struct _message)); + if (adbbuf==NULL) + adbbuf=(unsigned int*)malloc(displayInfo.size); + +} + +void updateADBFrame() + { + int n=0; + int count=0; + + send_framebuffer_string(); + +// L("1\n"); + + while (message->command!=A_CLSE) + { + read_socket(sockfd,message,sizeof(struct _message)); + +// L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + + if (message->command==A_CLSE) + break; + else if (message->command!=A_WRTE) + { + L("Weird command received... %08X\n",message->command); + L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + } + + + char * s=(char*)adbbuf+count; + read_socket(sockfd,s,message->data_length); + count+=message->data_length; + +// L("ahah %d %d\n",message->data_length,n); + + n=write_socket(sockfd,okay_message,sizeof(struct _message)); + if (n<0) + break; + } + +// L("Exit updating...\n"); +// L("Received %d bytes\n",count); + +// if (resp!=A_OKAY) +// error("bad OKAY response"); + + } + +#ifndef ANDROID + void main() +{ + connect_to_adb(); + L("up\n"); + update_frame(); + L("up\n"); + update_frame(); +} + +#endif +// int main(int argc, char *argv[]) +// { +// message=(struct _message*)malloc(sizeof(struct _message)); +// okay_message=(struct _message*)malloc(sizeof(struct _message)); +// +// connect_to_adb(); +// +// // adbbuf=calloc(fb_info->size,1); +// +// update_frame(); +// +// +// close(sockfd); +// return 0; +// } diff --git a/droidvncgrab/vnc/adb_method.h b/droidvncgrab/vnc/adb_method.h new file mode 100755 index 0000000..68631b0 --- /dev/null +++ b/droidvncgrab/vnc/adb_method.h @@ -0,0 +1,66 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ADB_CONNECT_METHOD +#define ADB_CONNECT_METHOD + +#include +#include +#include +#include +#include +#include +#include +#include +// #include + +#include "common.h" + + + +#define A_CNXN 0x4e584e43 +#define A_OKAY 0x59414b4f +#define A_CLSE 0x45534c43 +#define A_WRTE 0x45545257 + + +#define DDMS_RAWIMAGE_VERSION 1 + +struct _message { + unsigned int command; /* command identifier constant */ + unsigned int arg0; /* first argument */ + unsigned int arg1; /* second argument */ + unsigned int data_length; /* length of payload (0 is allowed) */ + unsigned int data_crc32; /* crc32 of data payload */ + unsigned int magic; /* command ^ 0xffffffff */ +} __attribute__((packed)); + + + +// void error(const char *msg); +// ssize_t write_socket(int fd, const void *buf, size_t count); +// ssize_t read_socket(int fd, void *buf, size_t count); +// void send_connect_string(); + +int initADB(); +void updateADBFrame(); + +unsigned int *adbbuf; + +#endif diff --git a/droidvncgrab/vnc/common.h b/droidvncgrab/vnc/common.h new file mode 100755 index 0000000..f4fd1b3 --- /dev/null +++ b/droidvncgrab/vnc/common.h @@ -0,0 +1,97 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef COMMON_H +#define COMMON_H + +//android log +#include + + +#ifndef __cplusplus +/* libvncserver */ +#include "rfb/rfb.h" +#include "libvncserver/scale.h" +#include "rfb/keysym.h" +#include "suinput.h" + + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include /* For makedev() */ + +#include +#include +#include + +#include +#include + +#define SOCK_PATH "org.onaips.vnc.gui" + + +#include + + +// #define L(...) do { __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__); } while (0) + +// #define L(...) __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); + #define L(...) do{ __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); } while (0); +#endif + +struct fbinfo { + unsigned int version; + unsigned int bpp; + unsigned int size; + unsigned int width; + unsigned int height; + unsigned int red_offset; + unsigned int red_length; + unsigned int blue_offset; + unsigned int blue_length; + unsigned int green_offset; + unsigned int green_length; + unsigned int alpha_offset; + unsigned int alpha_length; +} __attribute__((packed)); + + + +void rotate(int); +int getCurrentRotation(); +int isIdle(); +void setIdle(int i); +void close_app(); +struct fbinfo displayInfo; + + + +#endif diff --git a/droidvncgrab/vnc/displaybinder.cpp b/droidvncgrab/vnc/displaybinder.cpp new file mode 100755 index 0000000..703c8f6 --- /dev/null +++ b/droidvncgrab/vnc/displaybinder.cpp @@ -0,0 +1,75 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "displaybinder.h" +#include "common.h" + +#include +#include +#include + +#include +#include +#include + +using namespace android; + +ScreenshotClient *screenshotclient; + +extern "C" int initGingerbreadMethod() +{ + + L("--Initializing gingerbread access method--\n"); + + screenshotclient=new ScreenshotClient(); + int err=screenshotclient->update(); + if (err != NO_ERROR) { + L("screen capture failed: %s\n", strerror(-err)); + //mandar msg incompatible + return -1; + } + + PixelFormat f=screenshotclient->getFormat(); + + PixelFormatInfo pf; + getPixelFormatInfo(f,&pf); + + + displayInfo.bpp = pf.bitsPerPixel; + displayInfo.width = screenshotclient->getWidth(); + displayInfo.height = screenshotclient->getHeight();; + displayInfo.size = pf.bitsPerPixel*displayInfo.width*displayInfo.height/CHAR_BIT; + displayInfo.red_offset = pf.l_red; + displayInfo.red_length = pf.h_red; + displayInfo.green_offset = pf.l_green; + displayInfo.green_length = pf.h_green-pf.h_red; + displayInfo.blue_offset = pf.l_blue; + displayInfo.blue_length = pf.h_blue-pf.h_green; + displayInfo.alpha_offset = pf.l_alpha; + displayInfo.alpha_length = pf.h_alpha-pf.h_blue; + + return 0; + } + +extern "C" void updateScreen() +{ + screenshotclient->update(); + gingerbuf=(unsigned int*)screenshotclient->getPixels(); +} + diff --git a/droidvncgrab/vnc/displaybinder.h b/droidvncgrab/vnc/displaybinder.h new file mode 100755 index 0000000..99ee228 --- /dev/null +++ b/droidvncgrab/vnc/displaybinder.h @@ -0,0 +1,42 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef DISPLAY_BINDER +#define DISPLAY_BINDER + + +unsigned int *gingerbuf; + +#ifdef __cplusplus +#define L(...) __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); + + +extern "C" { +#endif +void updateScreen(); +int initGingerbreadMethod(); + +#ifdef __cplusplus +} + +#endif + + + +#endif \ No newline at end of file diff --git a/droidvncgrab/vnc/droidvncserver.c b/droidvncgrab/vnc/droidvncserver.c new file mode 100755 index 0000000..7778ce9 --- /dev/null +++ b/droidvncgrab/vnc/droidvncserver.c @@ -0,0 +1,513 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "common.h" +#include "framebuffer_method.h" +#include "gralloc_method.h" +#include "adb_method.h" + +#include "gui.h" +#include "input.h" +#include "displaybinder.h" + + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + + +char VNC_PASSWORD[256] = ""; +int VNC_PORT=5901; +/* Android already has 5900 bound natively in some devices. */ + + +unsigned int *cmpbuf; +unsigned int *vncbuf; + +static rfbScreenInfoPtr vncscr; + +int idle=0,standby=0, rotation=0,scaling=100; +char *rhost=NULL; +int rport=5500; +void (*update_screen)(void)=NULL; + +enum method_type {AUTO,FRAMEBUFFER,ADB,GRALLOC +#ifndef ANDROID_FROYO +,GINGERBREAD}; +#else +}; +#endif + +enum method_type method=AUTO; + +#define PIXEL_TO_VIRTUALPIXEL_FB(i,j) ((j+scrinfo.yoffset)*scrinfo.xres_virtual+i+scrinfo.xoffset) +#define PIXEL_TO_VIRTUALPIXEL(i,j) ((j*displayInfo.width)+i) + +#define OUT 8 +#include "update_screen.c" +#undef OUT + +#define OUT 16 +#include "update_screen.c" +#undef OUT + +// #define OUT 24 +// #include "update_screen.c" +// #undef OUT + +#define OUT 32 +#include "update_screen.c" +#undef OUT + +inline int getCurrentRotation() +{ + return rotation; +} + +inline int isIdle() +{ + return idle; +} + +void setIdle(int i) +{ + idle=i; +} + +ClientGoneHookPtr clientGone(rfbClientPtr cl) +{ + sendMsgToGui("~DISCONNECTED|\n"); + return 0; +} + +rfbNewClientHookPtr clientHook(rfbClientPtr cl) +{ + if (scaling!=100) + { + rfbScalingSetup(cl, vncscr->width*scaling/100.0, vncscr->height*scaling/100.0); + L("Scaling to w=%d h=%d\n",(int)(vncscr->width*scaling/100.0), (int)(vncscr->height*scaling/100.0)); +// rfbSendNewScaleSize(cl); + } + + cl->clientGoneHook=(ClientGoneHookPtr)clientGone; + + char *header="~CONNECTED|"; + char *msg=malloc(sizeof(char)*((strlen(cl->host)) + strlen(header)+1)); + msg[0]='\0'; + strcat(msg,header); + strcat(msg,cl->host); + strcat(msg,"\n"); + sendMsgToGui(msg); + free (msg); + + return RFB_CLIENT_ACCEPT; +} + + +void CutText(char* str,int len, struct _rfbClientRec* cl) +{ + str[len]='\0'; + char *header="~CLIP|\n"; + char *msg=malloc(sizeof(char)*(strlen(str) + strlen(header)+1)); + msg[0]='\0'; + strcat(msg,header); + strcat(msg,str); + strcat(msg,"\n"); + sendMsgToGui(msg); + free(msg); +} + +void sendServerStarted(){ + sendMsgToGui("~SERVERSTARTED|\n"); +} + +void sendServerStopped() +{ + sendMsgToGui("~SERVERSTOPPED|\n"); +} + +void initVncServer(int argc, char **argv) +{ + + vncbuf = calloc(displayInfo.width * displayInfo.height, displayInfo.bpp/CHAR_BIT); + cmpbuf = calloc(displayInfo.width * displayInfo.height, displayInfo.bpp/CHAR_BIT); + + + assert(vncbuf != NULL); + assert(cmpbuf != NULL); + + + if (rotation==0 || rotation==180) + vncscr = rfbGetScreen(&argc, argv, displayInfo.width , displayInfo.height, 0 /* not used */ , 3, displayInfo.bpp/CHAR_BIT); + else + vncscr = rfbGetScreen(&argc, argv, displayInfo.height, displayInfo.width, 0 /* not used */ , 3, displayInfo.bpp/CHAR_BIT); + + assert(vncscr != NULL); + + vncscr->desktopName = "Android"; + + + vncscr->frameBuffer =(char *)vncbuf; + + + vncscr->port = VNC_PORT; + + vncscr->kbdAddEvent = keyEvent; + vncscr->ptrAddEvent = ptrEvent; + vncscr->newClientHook = (rfbNewClientHookPtr)clientHook; + + vncscr->setXCutText = CutText; + + if (strcmp(VNC_PASSWORD,"")!=0) + { + char **passwords = (char **)malloc(2 * sizeof(char **)); + passwords[0] = VNC_PASSWORD; + passwords[1] = NULL; + vncscr->authPasswdData = passwords; + vncscr->passwordCheck = rfbCheckPasswordByList; + } + + + vncscr->httpDir="/data/data/org.onaips.vnc/files/"; + vncscr->sslcertfile="self.pem"; + + vncscr->serverFormat.redShift=displayInfo.red_offset; + vncscr->serverFormat.greenShift=displayInfo.green_offset; + vncscr->serverFormat.blueShift=displayInfo.blue_offset; + + vncscr->serverFormat.redMax=((1<serverFormat.greenMax=((1<serverFormat.blueMax=((1<serverFormat.bitsPerPixel=displayInfo.bpp; + + vncscr->alwaysShared = TRUE; + vncscr->handleEventsEagerly = TRUE; + vncscr->deferUpdateTime = 5; + + rfbInitServer(vncscr); + + //assign update_screen depending on bpp + + if (vncscr->serverFormat.bitsPerPixel == 32) + update_screen=&CONCAT2E(update_screen_,32); +// else if (vncscr->serverFormat.bitsPerPixel == 24) +// update_screen=&CONCAT2E(update_screen_,24); + else if (vncscr->serverFormat.bitsPerPixel == 16) + update_screen=&CONCAT2E(update_screen_,16); + else if (vncscr->serverFormat.bitsPerPixel == 8) + update_screen=&CONCAT2E(update_screen_,8); + else { + L("Unsupported pixel depth: %d\n", + vncscr->serverFormat.bitsPerPixel); + + sendMsgToGui("~SHOW|Unsupported pixel depth, please send bug report.\n"); + return; + } + + + /* Mark as dirty since we haven't sent any updates at all yet. */ + + rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height); +} + + + +void rotate(int value) +{ + + L("rotate()"); + + + if (value==-1 || + ((value==90 || value==270) && (rotation==0 || rotation==180)) || + ((value==0 || value==180) && (rotation==90 || rotation==270))) + { + int h=vncscr->height; + int w=vncscr->width; + + vncscr->width = h; + vncscr->paddedWidthInBytes = h * displayInfo.bpp / CHAR_BIT; + vncscr->height = w; + + { + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + iterator = rfbGetClientIterator(vncscr); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) + cl->newFBSizePending = 1; + } + } + + if (value==-1) + { + rotation+=90; + rotation=rotation%360; + } + else + { + rotation=value; + } + + rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height); + +} + + +void close_app() +{ + L("Cleaning up...\n"); + cleanupFramebuffer(); + cleanupInput(); + sendServerStopped(); + unbindIPCserver(); + exit(0); /* normal exit status */ +} + + +void extractReverseHostPort(char *str) +{ + int len=strlen(str); + char *p; + /* copy in to host */ + rhost = (char *) malloc(len+1); + if (! rhost) { + L("reverse_connect: could not malloc string %d\n", len); + exit(-1); + } + strncpy(rhost, str, len); + rhost[len] = '\0'; + + /* extract port, if any */ + if ((p = strrchr(rhost, ':')) != NULL) { + rport = atoi(p+1); + if (rport < 0) { + rport = -rport; + } else if (rport < 20) { + rport = 5500 + rport; + } + *p = '\0'; + } +} + +void printUsage(char **argv) +{ + L("\nandroidvncserver [parameters]\n" + "-f \t- Framebuffer device (only with -m fb, default is /dev/graphics/fb0)\n" + "-h\t\t- Print this help\n" + "-m \t- Display grabber method\n\tfb: framebuffer\n\tgb: gingerbread+ devices\n\tadb: slower, but should be compatible with all devices\n" + "-p \t- Password to access server\n" + "-r \t- Screen rotation (degrees) (0,90,180,270)\n" + "-R \t- Host for reverse connection\n" + "-s \t- Scale percentage (20,30,50,100,150)\n\n" ); +} + + +int main(int argc, char **argv) +{ + signal(SIGINT, close_app);//pipe signals + signal(SIGKILL, close_app); + signal(SIGILL, close_app); + + if(argc > 1) + { + int i=1; + int r; + while(i < argc) + { + if(*argv[i] == '-') + { + switch(*(argv[i] + 1)) + { + case 'h': + printUsage(argv); + exit(0); + break; + case 'p': + i++; + strcpy(VNC_PASSWORD,argv[i]); + break; + case 'f': + i++; + setFramebufferDevice(argv[i]); + break; + case 'P': + i++; + VNC_PORT=atoi(argv[i]); + break; + case 'r': + i++; + r=atoi(argv[i]); + if (r==0 || r==90 || r==180 || r==270) + rotation=r; + L("rotating to %d degrees\n",rotation); + break; + case 's': + i++; + r=atoi(argv[i]); + if (r>=1 && r <= 150) + scaling=r; + else + scaling=100; + L("scaling to %d percent\n",scaling); + break; + case 'm': + i++; + if (strcmp(argv[i],"adb")==0) + { + method=ADB; + L("ADB display grabber selected\n"); + } + else if (strcmp(argv[i],"fb")==0) + { + method=FRAMEBUFFER; + L("Framebuffer display grabber selected\n"); + } + else if (strcmp(argv[i],"gralloc")==0) + { + method=GRALLOC; + L("Gralloc display grabber selected\n"); + } + #ifndef ANDROID_FROYO + else if (strcmp(argv[i],"gingerbread")==0) + { + method=GINGERBREAD; + L("Gingerbread display grabber selected\n"); + } + #endif + else + { + L("Grab method \"%s\" not found, reverting to default.\n",argv[i]); + } + break; + case 'R': + i++; + extractReverseHostPort(argv[i]); + break; + } + } + i++; + } + } + + L("Initializing grabber method...\n"); + + if (method==AUTO) + { + L("No grabber method selected, auto-detecting..."); + do + { + #ifndef ANDROID_FROYO + if (initGingerbreadMethod()!=-1) + method=GINGERBREAD; + else + #endif + if (init_gralloc()!=-1) + method=GRALLOC; + + else if (initFramebuffer()!=-1) + method=FRAMEBUFFER; + else if (initADB()!=-1) + { + method=ADB; + updateADBFrame(); + } + break; + } + while (0); + } + else if (method==FRAMEBUFFER) + initFramebuffer(); + else if (method==ADB) + { + initADB(); + updateADBFrame(); + } + else if (method==GRALLOC) + init_gralloc(); + #ifndef ANDROID_FROYO + else if (method==GINGERBREAD) + initGingerbreadMethod(); + #endif + + L("Initializing virtual keyboard and touch device...\n"); + initInput(); + + L("Initializing VNC server:\n"); + L(" width: %d\n", (int)displayInfo.width); + L(" height: %d\n", (int)displayInfo.height); + L(" bpp: %d\n", (int)displayInfo.bpp); + L(" port: %d\n", (int)VNC_PORT); + + + L("Colourmap_rgba=%d:%d:%d:%d lenght=%d:%d:%d:%d\n",displayInfo.red_offset,displayInfo.green_offset,displayInfo.blue_offset,displayInfo.alpha_offset, + displayInfo.red_length,displayInfo.green_length,displayInfo.blue_length,displayInfo.alpha_length); + + initVncServer(argc, argv); + + bindIPCserver(); + sendServerStarted(); + + + + if (rhost) + { + rfbClientPtr cl; + cl = rfbReverseConnection(vncscr, rhost, rport); + if (cl == NULL) + { + char *str=malloc(255*sizeof(char)); + sprintf(str,"~SHOW|Couldn't connect to remote host:\n%s\n",rhost); + + L("Couldn't connect to remote host: %s\n",rhost); + sendMsgToGui(str); + free(str); + } + else + { + cl->onHold = FALSE; + rfbStartOnHoldClient(cl); + } + } + + rfbRunEventLoop(vncscr,-1,TRUE); + + while (1) + { + usleep(300000*(standby/2.0)); + + + if (idle) + standby++; + else + standby=2; + + if (vncscr->clientHead == NULL) + continue; + + + update_screen(); + } + + close_app(); +} + + + \ No newline at end of file diff --git a/droidvncgrab/vnc/framebuffer_method.c b/droidvncgrab/vnc/framebuffer_method.c new file mode 100755 index 0000000..63acd8e --- /dev/null +++ b/droidvncgrab/vnc/framebuffer_method.c @@ -0,0 +1,136 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +Other contributors: +Oleksandr Andrushchenko + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "framebuffer_method.h" +#include "common.h" +#include "gui.h" + +int fbfd = -1; + + +char framebuffer_device[256] = "/dev/graphics/fb0"; + + +void setFramebufferDevice(char *s) +{ + strcpy(framebuffer_device,s); +} + + +int initFramebuffer(void) +{ + L("--Initializing framebuffer access method--\n"); + + fbmmap = MAP_FAILED; + + if ((fbfd = open(framebuffer_device, O_RDWR)) == -1) + { + L("Cannot open fb device %s\n", framebuffer_device); + sendMsgToGui("~SHOW|Cannot open fb device, please try out other display grab method\n"); + return -1; + } + + update_fb_info(); + + + if (ioctl(fbfd, FBIOGET_FSCREENINFO, &fscrinfo) != 0) + { + L("ioctl error\n"); + return -1; + } + + L("line_lenght=%d xres=%d, yres=%d, xresv=%d, yresv=%d, xoffs=%d, yoffs=%d, bpp=%d\n", + (int)fscrinfo.line_length,(int)scrinfo.xres, (int)scrinfo.yres, + (int)scrinfo.xres_virtual, (int)scrinfo.yres_virtual, + (int)scrinfo.xoffset, (int)scrinfo.yoffset, + (int)scrinfo.bits_per_pixel); + + + + + size_t size=scrinfo.yres_virtual; + if (size + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ADB_FRAMEBUFFER_METHOD +#define ADB_FRAMEBUFFER_METHOD + +#include "common.h" + +unsigned int *fbmmap; + +struct fb_var_screeninfo scrinfo; +struct fb_fix_screeninfo fscrinfo; + +int initFramebuffer(void); +void cleanupFramebuffer(void); +void update_fb_info(); +int roundUpToPageSize(int x); +void setFramebufferDevice(char *); + +#endif \ No newline at end of file diff --git a/droidvncgrab/vnc/gralloc_method.c b/droidvncgrab/vnc/gralloc_method.c new file mode 100644 index 0000000..59f3506 --- /dev/null +++ b/droidvncgrab/vnc/gralloc_method.c @@ -0,0 +1,245 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2011 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "gralloc_method.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define r(fd, ptr, size) (read((fd), (ptr), (size)) != (int)(size)) +#define w(fd, ptr, size) (write((fd), (ptr), (size)) != (int)(size)) + + +static int fill_format(struct fbinfo* info, int format) +{ + // bpp, red, green, blue, alpha + + static const int format_map[][9] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0}, // INVALID + {32, 0, 8, 8, 8, 16, 8, 24, 8}, // HAL_PIXEL_FORMAT_RGBA_8888 + {32, 0, 8, 8, 8, 16, 8, 0, 0}, // HAL_PIXEL_FORMAT_RGBX_8888 + {24, 16, 8, 8, 8, 0, 8, 0, 0}, // HAL_PIXEL_FORMAT_RGB_888 + {16, 11, 5, 5, 6, 0, 5, 0, 0}, // HAL_PIXEL_FORMAT_RGB_565 + {32, 16, 8, 8, 8, 0, 8, 24, 8}, // HAL_PIXEL_FORMAT_BGRA_8888 + {16, 11, 5, 6, 5, 1, 5, 0, 1}, // HAL_PIXEL_FORMAT_RGBA_5551 + {16, 12, 4, 8, 4, 4, 4, 0, 4} // HAL_PIXEL_FORMAT_RGBA_4444 + }; + const int *p; + + if (format == 0 || format > HAL_PIXEL_FORMAT_RGBA_4444) + return -ENOTSUP; + + p = format_map[format]; + + info->bpp = *(p++); + info->red_offset = *(p++); + info->red_length = *(p++); + info->green_offset = *(p++); + info->green_length = *(p++); + info->blue_offset = *(p++); + info->blue_length = *(p++); + info->alpha_offset = *(p++); + info->alpha_length = *(p++); + + return 0; +} +#if 0 +static int readfb_devfb (int fd) +{ + struct fb_var_screeninfo vinfo; + int fb, offset; + char x[256]; + int rv = -ENOTSUP; + + struct fbinfo fbinfo; + unsigned i, bytespp; + + fb = open("/dev/graphics/fb0", O_RDONLY); + if (fb < 0) goto done; + + if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; + fcntl(fb, F_SETFD, FD_CLOEXEC); + + bytespp = vinfo.bits_per_pixel / 8; + + fbinfo.bpp = vinfo.bits_per_pixel; + fbinfo.size = vinfo.xres * vinfo.yres * bytespp; + fbinfo.width = vinfo.xres; + fbinfo.height = vinfo.yres; + fbinfo.red_offset = vinfo.red.offset; + fbinfo.red_length = vinfo.red.length; + fbinfo.green_offset = vinfo.green.offset; + fbinfo.green_length = vinfo.green.length; + fbinfo.blue_offset = vinfo.blue.offset; + fbinfo.blue_length = vinfo.blue.length; + fbinfo.alpha_offset = vinfo.transp.offset; + fbinfo.alpha_length = vinfo.transp.length; + + /* HACK: for several of our 3d cores a specific alignment + * is required so the start of the fb may not be an integer number of lines + * from the base. As a result we are storing the additional offset in + * xoffset. This is not the correct usage for xoffset, it should be added + * to each line, not just once at the beginning */ + offset = vinfo.xoffset * bytespp; + + offset += vinfo.xres * vinfo.yoffset * bytespp; + + rv = 0; + + if (w(fd, &fbinfo, sizeof(fbinfo))) goto done; + + lseek(fb, offset, SEEK_SET); + for (i = 0; i < fbinfo.size; i += 256) { + if (r(fb, &x, 256)) goto done; + if (w(fd, &x, 256)) goto done; + } + + if (r(fb, &x, fbinfo.size % 256)) goto done; + if (w(fd, &x, fbinfo.size % 256)) goto done; + +done: + if (fb >= 0) close(fb); + return rv; +} + +#endif + + +struct gralloc_module_t *gralloc; +struct framebuffer_device_t *fbdev = 0; +struct alloc_device_t *allocdev = 0; +buffer_handle_t buf = 0; +unsigned char* data = 0; +int stride; + +#define CHECK_RV if (rv != 0){close_gralloc();return -1;} + +int init_gralloc() +{ + L("--Initializing gralloc access method--\n"); + grallocfb=0; + + int linebytes; + int rv; + + rv = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t**)&gralloc); + + CHECK_RV; + + rv = framebuffer_open(&gralloc->common, &fbdev); + + CHECK_RV; + + if (!fbdev->read) { + rv = -ENOTSUP; + close_gralloc(); + return rv; + } + + rv = gralloc_open(&gralloc->common, &allocdev); + + CHECK_RV; + + rv = allocdev->alloc(allocdev, fbdev->width, fbdev->height, + fbdev->format, GRALLOC_USAGE_SW_READ_OFTEN, + &buf, &stride); + + + rv = fbdev->read(fbdev, buf); + + CHECK_RV; + + rv = gralloc->lock(gralloc, buf, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, + fbdev->width, fbdev->height, (void**)&data); + CHECK_RV; + + rv = fill_format(&displayInfo, fbdev->format); + + CHECK_RV; + + stride *= (displayInfo.bpp >> 3); + linebytes = fbdev->width * (displayInfo.bpp >> 3); + displayInfo.size = linebytes * fbdev->height; + displayInfo.width = fbdev->width; + displayInfo.height = fbdev->height; + + // point of no return: don't attempt alternative means of reading + // after this + rv = 0; + + grallocfb=malloc(displayInfo.size); + + L("Stride=%d Linebytes=%d %p\n",stride,linebytes,fbdev->setUpdateRect); + + memcpy(grallocfb,data,displayInfo.size); + + if (data) + gralloc->unlock(gralloc, buf); + + L("Copy %d bytes\n",displayInfo.size); + + L("Returning rv=%d\n",rv); + return rv; +} + + +void close_gralloc() +{ + if (buf) + allocdev->free(allocdev, buf); + if (allocdev) + gralloc_close(allocdev); + if (fbdev) + framebuffer_close(fbdev); +} + + + + +int readfb_gralloc () +{ + int rv; + + + rv = fbdev->read(fbdev, buf); + + CHECK_RV; + + rv = gralloc->lock(gralloc, buf, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, + fbdev->width, fbdev->height, (void**)&data); + CHECK_RV; + + memcpy(grallocfb,data,displayInfo.size); + + if (data) + gralloc->unlock(gralloc, buf); + + return rv; +} + + diff --git a/droidvncgrab/vnc/gralloc_method.h b/droidvncgrab/vnc/gralloc_method.h new file mode 100644 index 0000000..c55eee8 --- /dev/null +++ b/droidvncgrab/vnc/gralloc_method.h @@ -0,0 +1,31 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRALLOC_H +#define GRALLOC_H + + +unsigned int *grallocfb; + +int init_gralloc(); +int readfb_gralloc(); +void close_gralloc(); + + +#endif \ No newline at end of file diff --git a/droidvncgrab/vnc/gui.c b/droidvncgrab/vnc/gui.c new file mode 100755 index 0000000..526e3c3 --- /dev/null +++ b/droidvncgrab/vnc/gui.c @@ -0,0 +1,131 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "gui.h" + +#define SOCKET_ERROR -1 +#define BUFFER_SIZE 1024 +#define QUEUE_SIZE 1 + +int hServerSocket; /* handle to socket */ +struct sockaddr_in Address; /* Internet socket address stuct */ +int nAddressSize=sizeof(struct sockaddr_in); +char pBuffer[BUFFER_SIZE]; +static int nHostPort; + +int sendMsgToGui(char *buffer) +{ + int sock, n; + unsigned int length; + struct sockaddr_in server; + + sock= socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) perror("socket"); + + bzero(&server,sizeof(server)); + server.sin_family = AF_INET; + server.sin_addr.s_addr=inet_addr("127.0.0.1"); + server.sin_port = htons(13131); + length=sizeof(struct sockaddr_in); + + n=sendto(sock,buffer, + strlen(buffer),0,(struct sockaddr *)&server,length); + if (n < 0) perror("Sendto"); + +// L("Sent %s\n",buffer); +// n = recvfrom(sock,buffer,256,0,(struct sockaddr *)&from, &length); +// if (n < 0) error("recvfrom"); +// write(1,"Got an ack: ",12); +// write(1,buffer,n); + + close(sock); + return 0; +} + +int bindIPCserver() +{ + nHostPort=13132; + + L("Starting IPC connection..."); + + /* make a socket */ + hServerSocket=socket(AF_INET,SOCK_DGRAM,0); + + if(hServerSocket == SOCKET_ERROR) + { + L("\nCould not make a socket\n"); + return 0; + } + + /* fill address struct */ + Address.sin_addr.s_addr=INADDR_ANY; + Address.sin_port=htons(nHostPort); + Address.sin_family=AF_INET; + + + /* bind to a port */ + if(bind(hServerSocket,(struct sockaddr*)&Address,sizeof(Address)) == SOCKET_ERROR) + { + L("\nCould not connect to IPC gui, another daemon already running?\n"); + sendMsgToGui("~SHOW|Could not connect to IPC gui, another daemon already running?\n"); + + exit(-1); + } + + + L("binded to port %d\n",nHostPort); + + pthread_t thread; + pthread_create( &thread,NULL,handle_connections,NULL); + + return 1; +} + + + +void *handle_connections() +{ + L("\nWaiting for a connection\n"); + struct sockaddr_in from; + int fromlen = sizeof(struct sockaddr_in); + int n; + + while (1) { + n = recvfrom(hServerSocket,pBuffer,BUFFER_SIZE,0,(struct sockaddr *)&from,&fromlen); + if (n < 0) perror("recvfrom"); + + L("Recebido: %s\n",pBuffer); + + if (strstr(pBuffer,"~PING|")!=NULL) + { + char *resp="~PONG|"; + n = sendto(hServerSocket,resp,strlen(resp), + 0,(struct sockaddr *)&from,fromlen); + if (n < 0) perror("sendto"); + } + else if (strstr(pBuffer,"~KILL|")!=NULL) + close_app(); + } +} + + +void unbindIPCserver() +{ + close(hServerSocket); +} \ No newline at end of file diff --git a/droidvncgrab/vnc/gui.h b/droidvncgrab/vnc/gui.h new file mode 100755 index 0000000..bc9452f --- /dev/null +++ b/droidvncgrab/vnc/gui.h @@ -0,0 +1,33 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GUI_COMM_H +#define GUI_COMM_H + +#include "common.h" + + + +int sendMsgToGui(char *msg); + + +int bindIPCserver(); +void unbindIPCserver(); +void *handle_connections(); +#endif diff --git a/droidvncgrab/vnc/input.c b/droidvncgrab/vnc/input.c new file mode 100755 index 0000000..9467054 --- /dev/null +++ b/droidvncgrab/vnc/input.c @@ -0,0 +1,325 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "input.h" + +int inputfd = -1; +// keyboard code modified from remote input by http://www.math.bme.hu/~morap/RemoteInput/ + +// q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m +int qwerty[] = {30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,19,31,20,22,47,17,45,21,44}; +// ,!,",#,$,%,&,',(,),*,+,,,-,.,/ +int spec1[] = {57,2,40,4,5,6,8,40,10,11,9,13,51,12,52,52}; +int spec1sh[] = {0,1,1,1,1,1,1,0,1,1,1,1,0,0,0,1}; +// :,;,<,=,>,?,@ +int spec2[] = {39,39,227,13,228,53,215}; +int spec2sh[] = {1,0,1,1,1,1,0}; +// [,\,],^,_,` +int spec3[] = {26,43,27,7,12,399}; +int spec3sh[] = {0,0,0,1,1,0}; +// {,|,},~ +int spec4[] = {26,43,27,215,14}; +int spec4sh[] = {1,1,1,1,0}; + + +void initInput() +{ + L("---Initializing uinput...---\n"); + struct input_id id = { + BUS_VIRTUAL, /* Bus type. */ + 1, /* Vendor id. */ + 1, /* Product id. */ + 1 /* Version id. */ + }; + + if((inputfd = suinput_open("qwerty", &id)) == -1) + { + L("cannot create virtual kbd device.\n"); + sendMsgToGui("~SHOW|Cannot create virtual input device!\n"); + // exit(EXIT_FAILURE); do not exit, so we still can see the framebuffer + } +} + + +int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt) +{ + int real=1; + if ('a' <= c && c <= 'z') + return qwerty[c-'a']; + if ('A' <= c && c <= 'Z') + { + (*sh)=1; + return qwerty[c-'A']; + } + if ('1' <= c && c <= '9') + return c-'1'+2; + if (c == '0') + return 11; + if (32 <= c && c <= 47) + { + (*sh) = spec1sh[c-32]; + return spec1[c-32]; + } + if (58 <= c && c <= 64) + { + (*sh) = spec2sh[c-58]; + return spec2[c-58]; + } + if (91 <= c && c <= 96) + { + (*sh) = spec3sh[c-91]; + return spec3[c-91]; + } + if (123 <= c && c <= 127) + { + (*sh) = spec4sh[c-123]; + return spec4[c-123]; + } + switch(c) + { + case 0xff08: return 14;// backspace + case 0xff09: return 15;// tab + case 1: (*alt)=1; return 34;// ctrl+a + case 3: (*alt)=1; return 46;// ctrl+c + case 4: (*alt)=1; return 32;// ctrl+d + case 18: (*alt)=1; return 31;// ctrl+r + case 0xff0D: return 28;// enter + case 0xff1B: return 158;// esc -> back + case 0xFF51: return 105;// left -> DPAD_LEFT + case 0xFF53: return 106;// right -> DPAD_RIGHT + case 0xFF54: return 108;// down -> DPAD_DOWN + case 0xFF52: return 103;// up -> DPAD_UP + // case 360: return 232;// end -> DPAD_CENTER (ball click) + case 0xff50: return KEY_HOME;// home + case 0xFFC8: rfbShutdownServer(cl->screen,TRUE); return 0; //F11 disconnect + case 0xFFC9: + L("F12 closing..."); + exit(0); //F10 closes daemon + break; + case 0xffc1: down?rotate(-1):0; return 0; // F4 rotate + case 0xffff: return 158;// del -> back + case 0xff55: return 229;// PgUp -> menu + case 0xffcf: return 127;// F2 -> search + case 0xffe3: return 127;// left ctrl -> search + case 0xff56: return 61;// PgUp -> call + case 0xff57: return 107;// End -> endcall + case 0xffc2: return 211;// F5 -> focus + case 0xffc3: return 212;// F6 -> camera + case 0xffc4: return 150;// F7 -> explorer + case 0xffc5: return 155;// F8 -> envelope + + case 50081: + case 225: (*alt)=1; + if (real) return 48; //a with acute + return 30; //a with acute -> a with ring above + case 50049: + case 193:(*sh)=1; (*alt)=1; + if (real) return 48; //A with acute + return 30; //A with acute -> a with ring above + case 50089: + case 233: (*alt)=1; return 18; //e with acute + case 50057: + case 201:(*sh)=1; (*alt)=1; return 18; //E with acute + case 50093: + case 0xffbf: (*alt)=1; + if (real) return 36; //i with acute + return 23; //i with acute -> i with grave + case 50061: + case 205: (*sh)=1; (*alt)=1; + if (real) return 36; //I with acute + return 23; //I with acute -> i with grave + case 50099: + case 243:(*alt)=1; + if (real) return 16; //o with acute + return 24; //o with acute -> o with grave + case 50067: + case 211:(*sh)=1; (*alt)=1; + if (real) return 16; //O with acute + return 24; //O with acute -> o with grave + case 50102: + case 246: (*alt)=1; return 25; //o with diaeresis + case 50070: + case 214: (*sh)=1; (*alt)=1; return 25; //O with diaeresis + case 50577: + case 245:(*alt)=1; + if (real) return 19; //Hungarian o + return 25; //Hungarian o -> o with diaeresis + case 50576: + case 213: (*sh)=1; (*alt)=1; + if (real) return 19; //Hungarian O + return 25; //Hungarian O -> O with diaeresis + case 50106: + // case 0xffbe: (*alt)=1; + // if (real) return 17; //u with acute + // return 22; //u with acute -> u with grave + case 50074: + case 218: (*sh)=1; (*alt)=1; + if (real) return 17; //U with acute + return 22; //U with acute -> u with grave + case 50108: + case 252: (*alt)=1; return 47; //u with diaeresis + case 50076: + case 220:(*sh)=1; (*alt)=1; return 47; //U with diaeresis + case 50609: + case 251: (*alt)=1; + if (real) return 45; //Hungarian u + return 47; //Hungarian u -> u with diaeresis + case 50608: + case 219: (*sh)=1; (*alt)=1; + if (real) return 45; //Hungarian U + return 47; //Hungarian U -> U with diaeresis + + } + return 0; +} + + +void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) +{ + int code; +// L("Got keysym: %04x (down=%d)\n", (unsigned int)key, (int)down); + + setIdle(0); + int sh = 0; + int alt = 0; + + if ((code = keysym2scancode(down, key, cl,&sh,&alt))) + { + + int ret=0; + + if (key && down) + { + if (sh) suinput_press(inputfd, 42); //left shift + if (alt) suinput_press(inputfd, 56); //left alt + + ret=suinput_press(inputfd,code); + ret=suinput_release(inputfd,code); + + if (alt) suinput_release(inputfd, 56); //left alt + if (sh) suinput_release(inputfd, 42); //left shift + } + else + ;//ret=suinput_release(inputfd,code); + +// L("injectKey (%d, %d) ret=%d\n", code , down,ret); + } +} + + + +void ptrEvent(int buttonMask, int x, int y, rfbClientPtr cl) +{ + + static int leftClicked=0,rightClicked=0,middleClicked=0; + setIdle(0); + transformTouchCoordinates(&x,&y,cl->screen->width,cl->screen->height); + + if((buttonMask & 1)&& leftClicked) {//left btn clicked and moving + static int i=0; + i=i+1; + + if (i%10==1)//some tweak to not report every move event + { + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + } + } + else if (buttonMask & 1)//left btn clicked + { + leftClicked=1; + + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd,EV_KEY,BTN_TOUCH,1); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + + + } + else if (leftClicked)//left btn released + { + leftClicked=0; + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd,EV_KEY,BTN_TOUCH,0); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + } + + if (buttonMask & 4)//right btn clicked + { + rightClicked=1; + suinput_press(inputfd,158); //back key + } + else if (rightClicked)//right button released + { + rightClicked=0; + suinput_release(inputfd,158); + } + + if (buttonMask & 2)//mid btn clicked + { + middleClicked=1; + suinput_press( inputfd,KEY_END); + } + else if (middleClicked)// mid btn released + { + middleClicked=0; + suinput_release( inputfd,KEY_END); + } +} + + +inline void transformTouchCoordinates(int *x, int *y,int width,int height) +{ + int scale=4096.0; + int old_x=*x,old_y=*y; + int rotation=getCurrentRotation(); + + if (rotation==0) + { + *x = old_x*scale/width-scale/2.0; + *y = old_y*scale/height-scale/2.0; + } + else if (rotation==90) + { + *x =old_y*scale/height-scale/2.0; + *y = (width - old_x)*scale/width-scale/2.0; + } + else if (rotation==180) + { + *x =(width - old_x)*scale/width-scale/2.0; + *y =(height - old_y)*scale/height-scale/2.0; + } + else if (rotation==270) + { + *y =old_x*scale/width-scale/2.0; + *x =(height - old_y)*scale/height-scale/2.0; + } + +} + + +void cleanupInput() +{ + if(inputfd != -1) + { + suinput_close(inputfd); + } +} \ No newline at end of file diff --git a/droidvncgrab/vnc/input.h b/droidvncgrab/vnc/input.h new file mode 100755 index 0000000..e7ce5b9 --- /dev/null +++ b/droidvncgrab/vnc/input.h @@ -0,0 +1,36 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +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 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYMANIP_H +#define KEYMANIP_H + +#include "common.h" +#include "gui.h" +#define BUS_VIRTUAL 0x06 + + + +void initInput(); +int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt); +void transformTouchCoordinates(int *x, int *y,int,int); +void ptrEvent(int buttonMask, int x, int y, rfbClientPtr cl); +void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl); +void cleanupInput(); + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/.cvsignore new file mode 100755 index 0000000..13d1958 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/.cvsignore @@ -0,0 +1,30 @@ +Makefile +Makefile.in +compile +configure +configure.lineno +config.status +config.log +LibVNCServer.spec.in +LibVNCServer.spec +x11vnc.spec.in +.deps +aclocal.m4 +autom4te.cache +libvncserver-config +_configs.sed +config.h +LibVNCServer*.tar.gz +upload_beta.sh +stamp-* +x11vnc*.tar.gz +config.h.in +rfbconfig.h +rfbconfig.h.in +install-sh +missing +mkinstalldirs +depcomp +description-pak +libvncserver*.deb + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/.gitignore b/droidvncgrab/vnc/libvncserver-kanaka/.gitignore new file mode 100755 index 0000000..4ac96c7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/.gitignore @@ -0,0 +1,73 @@ +*.swp +*~ +Makefile +Makefile.in +compile +configure +configure.lineno +config.status +config.log +LibVNCServer.spec.in +LibVNCServer.spec +x11vnc.spec.in +.deps +.libs +aclocal.m4 +autom4te.cache +libvncserver-config +_configs.sed +config.h +LibVNCServer*.tar.gz +upload_beta.sh +stamp-* +x11vnc*.tar.gz +config.h.in +rfbconfig.h +rfbconfig.h.in +install-sh +missing +mkinstalldirs +depcomp +description-pak +libvncserver*.deb +*.o +*.lo +CVS +client_examples/SDLvncviewer +client_examples/backchannel +client_examples/ppmtest +config.guess +config.sub +contrib/zippy +examples/backchannel +examples/blooptest +examples/camera +examples/colourmaptest +examples/example +examples/filetransfer +examples/fontsel +examples/pnmshow +examples/pnmshow24 +examples/regiontest +examples/rotate +examples/simple +examples/simple15 +examples/storepasswd +examples/vncev +libtool +libvncclient/libvncclient.la +libvncserver/libvncserver.la +rfb/rfbint.h +test/blooptest +test/cargstest +test/copyrecttest +test/cursortest +test/encodingstest +vncterm/LinuxVNC +vncterm/VNCommand +vncterm/example +x11vnc.spec +x11vnc/x11vnc +CMakeCache.txt +cmake_install.cmake +/CMakeFiles diff --git a/droidvncgrab/vnc/libvncserver-kanaka/AUTHORS b/droidvncgrab/vnc/libvncserver-kanaka/AUTHORS new file mode 100755 index 0000000..416dd01 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/AUTHORS @@ -0,0 +1,50 @@ +* LibVNCServer (C) 2001 Johannes E. Schindelin +is based on +* Original OSXvnc (C) 2001 Dan McGuirk , +which in turn is based on +* Original Xvnc (C) 1999 AT&T Laboratories Cambridge. + +Lots of improvements of this library are thanks to +* TightVNC (C) 2000-2003 Const Kaplinsky + +The ZRLE compression scheme is from +* RealVNC (James "Wez" Weatherall, who helped also with regions) + +The good folks from +* KRFB (I think it was Tim Jansen) +helped also a lot (some *big* bugs!). + +Karl Runge provides an x11vnc, which is a much, much improved version of my +original proof-of-concept. It really deserves to replace the old version, +as it is a state-of-the-art, fast and usable program by now! However, he +maintains it and improves it still in amazing ways! + +The file transfer protocol from TightVNC was implemented by Rohit Kumar. +This includes an implementation of RFB protocol version 3.7t. + +Occasional important patches were sent by (in order I found the names in my +archives and please don't beat me, if I forgot you, but just send me an +email!): Akira Hatakeyama, Karl J. Runge, Justin "Zippy" Dearing, +Oliver Mihatsch, Greg Sternberg, Werner Hofer, Giampiero Giancipoli, +Glenn Mabutt, Paul Kreiner, Erik Kunze, Mike Frysinger, Martin Waitz, +Mark McLoughlin, Paul Fox, Juan Jose Costello, Andre Leiadella, +Alberto Lusiani, Malvina Mazin, Dave Stuart, Rohit Kumar, Donald Dugger, +Steven Carr, Uwe Völker, Charles Coffing, Guillaume Rousse, +Alessandro Praduroux, Brad Hards, Timo Ketola, Christian Ehrlicher, +Noriaki Yamazaki, Ben Klopfenstein, Vic Lee, Christian Beier, +Alexander Dorokhine, Corentin Chary and Wouter Van Meir. + +Probably I forgot quite a few people sending a patch here and there, which +really made a difference. Without those, some obscure bugs still would +be unfound. + +A hearty unthanks goes to Michael and Erick, who provided me with nothing +but hollow words. Finally I got that configure and install working, but +it would have been so much better for them not just to complain, but also +help. As you showed me real egoism, you are the main reasons I am not +working one dot to make this library less than GPL, so that nobody ever +can make profit of my and others work without giving something back to me +and others. + +Speaking of hollow words, another hearty unthanks goes to Sam, who thought +he could let me work for him, not paying me in any way. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/CMakeLists.txt b/droidvncgrab/vnc/libvncserver-kanaka/CMakeLists.txt new file mode 100755 index 0000000..4e0337b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/CMakeLists.txt @@ -0,0 +1,253 @@ +cmake_minimum_required(VERSION 2.6) + +project(LibVNCServer) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckTypeSize) +include(TestBigEndian) + +set(PACKAGE_NAME "LibVNCServer") +set(FULL_PACKAGE_NAME "LibVNCServer") +set(PACKAGE_VERSION "0.9.7") +set(PROJECT_BUGREPORT_PATH "http://sourceforge.net/projects/libvncserver") + +include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/libvncserver) + +find_package(ZLIB) +find_package(JPEG) +find_package(SDL) +find_package(GnuTLS) +find_package(Threads) + +if(SDL_FOUND) # == pthread.h available + option(TIGHTVNC_FILETRANSFER "Enable filetransfer" ON) +endif(SDL_FOUND) +if(ZLIB_FOUND) + set(LIBVNCSERVER_HAVE_LIBZ 1) +endif(ZLIB_FOUND) +if(JPEG_FOUND) + set(LIBVNCSERVER_HAVE_LIBJPEG 1) +endif(JPEG_FOUND) +option(LIBVNCSERVER_ALLOW24BPP "Allow 24 bpp" ON) +if(GNUTLS_FOUND) + set(LIBVNCSERVER_WITH_CLIENT_TLS 1) +endif(GNUTLS_FOUND) + +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) + +if(CMAKE_USE_PTHREADS_INIT) + set(LIBVNCSERVER_HAVE_LIBPTHREAD 1) +endif(CMAKE_USE_PTHREADS_INIT) +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) + +# TODO: +# LIBVNCSERVER_ENOENT_WORKAROUND +# inline + +configure_file(${CMAKE_SOURCE_DIR}/rfb/rfbconfig.h.cmake ${CMAKE_BINARY_DIR}/rfb/rfbconfig.h) +configure_file(${CMAKE_SOURCE_DIR}/rfb/rfbint.h.cmake ${CMAKE_BINARY_DIR}/rfb/rfbint.h) + +set(LIBVNCSERVER_DIR ${CMAKE_SOURCE_DIR}/libvncserver) +set(LIBVNCCLIENT_DIR ${CMAKE_SOURCE_DIR}/libvncclient) +set(LIBVNCSRVTEST_DIR ${CMAKE_SOURCE_DIR}/examples) +set(LIBVNCCLITEST_DIR ${CMAKE_SOURCE_DIR}/client_examples) + +set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_DIR}/main.c + ${LIBVNCSERVER_DIR}/rfbserver.c + ${LIBVNCSERVER_DIR}/rfbregion.c + ${LIBVNCSERVER_DIR}/auth.c + ${LIBVNCSERVER_DIR}/sockets.c + ${LIBVNCSERVER_DIR}/stats.c + ${LIBVNCSERVER_DIR}/corre.c + ${LIBVNCSERVER_DIR}/hextile.c + ${LIBVNCSERVER_DIR}/rre.c + ${LIBVNCSERVER_DIR}/translate.c + ${LIBVNCSERVER_DIR}/cutpaste.c + ${LIBVNCSERVER_DIR}/httpd.c + ${LIBVNCSERVER_DIR}/cursor.c + ${LIBVNCSERVER_DIR}/font.c + ${LIBVNCSERVER_DIR}/draw.c + ${LIBVNCSERVER_DIR}/selbox.c + ${LIBVNCSERVER_DIR}/d3des.c + ${LIBVNCSERVER_DIR}/vncauth.c + ${LIBVNCSERVER_DIR}/cargs.c + ${LIBVNCSERVER_DIR}/minilzo.c + ${LIBVNCSERVER_DIR}/ultra.c + ${LIBVNCSERVER_DIR}/scale.c +) + +set(LIBVNCCLIENT_SOURCES + ${LIBVNCCLIENT_DIR}/cursor.c + ${LIBVNCCLIENT_DIR}/listen.c + ${LIBVNCCLIENT_DIR}/rfbproto.c + ${LIBVNCCLIENT_DIR}/sockets.c + ${LIBVNCCLIENT_DIR}/vncviewer.c + ${LIBVNCCLIENT_DIR}/minilzo.c + ${LIBVNCCLIENT_DIR}/tls.c +) + +if(ZLIB_FOUND) + add_definitions(-DLIBVNCSERVER_HAVE_LIBZ) + include_directories(${ZLIB_INCLUDE_DIR}) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/zlib.c + ${LIBVNCSERVER_DIR}/zrle.c + ${LIBVNCSERVER_DIR}/zrleoutstream.c + ${LIBVNCSERVER_DIR}/zrlepalettehelper.c + ) +endif(ZLIB_FOUND) + +if(JPEG_FOUND) + add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG) + include_directories(${JPEG_INCLUDE_DIR}) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/tight.c + ) +endif(JPEG_FOUND) + +if(TIGHTVNC_FILETRANSFER) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/rfbtightserver.c + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/handlefiletransferrequest.c + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/filetransfermsg.c + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/filelistinfo.c + ) +endif(TIGHTVNC_FILETRANSFER) + +add_library(vncclient SHARED ${LIBVNCCLIENT_SOURCES}) +add_library(vncserver SHARED ${LIBVNCSERVER_SOURCES}) +if(WIN32) + set(ADDITIONAL_LIBS ws2_32) +endif(WIN32) + +target_link_libraries(vncclient + ${ADDITIONAL_LIBS} + ${ZLIB_LIBRARIES} + ${JPEG_LIBRARIES} + ${SDL_LIBRARY} +) +target_link_libraries(vncserver + ${ADDITIONAL_LIBS} + ${ZLIB_LIBRARIES} + ${JPEG_LIBRARIES} + ${SDL_LIBRARY} +) + +# tests +set(LIBVNCSERVER_TESTS + backchannel + camera + colourmaptest + example + fontsel + pnmshow + pnmshow24 + regiontest + rotate + simple + simple15 + storepasswd + vncev + ) + +if(SDL_FOUND) + set(LIBVNCSERVER_TESTS + ${LIBVNCSERVER_TESTS} + blooptest + ) +endif(SDL_FOUND) + +if(TIGHTVNC_FILETRANSFER) + set(LIBVNCSERVER_TESTS + ${LIBVNCSERVER_TESTS} + filetransfer + ) +endif(TIGHTVNC_FILETRANSFER) + +if(MACOS) + set(LIBVNCSERVER_TESTS + ${LIBVNCSERVER_TESTS} + mac + ) +endif(MACOS) + +set(LIBVNCCLIENT_TESTS + backchannel + ppmtest +) + +if(SDL_FOUND) + include_directories(${SDL_INCLUDE_DIR}) + set(LIBVNCCLIENT_TESTS + ${LIBVNCCLIENT_TESTS} + SDLvncviewer + ) +endif(SDL_FOUND) + +if(HAVE_FFMPEG) + set(LIBVNCCLIENT_TESTS + ${LIBVNCCLIENT_TESTS} + vnc2mpg + ) +endif(HAVE_FFMPEG) + + +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/examples) +foreach(test ${LIBVNCSERVER_TESTS}) + add_executable(examples/${test} ${LIBVNCSRVTEST_DIR}/${test}.c) + target_link_libraries(examples/${test} vncserver ${CMAKE_THREAD_LIBS_INIT}) +endforeach(test ${LIBVNCSERVER_TESTS}) + +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/client_examples) +foreach(test ${LIBVNCCLIENT_TESTS}) + add_executable(client_examples/${test} ${LIBVNCCLITEST_DIR}/${test}.c) + target_link_libraries(client_examples/${test} vncclient ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${SDL_LIBRARY} ${FFMPEG_LIBRARIES}) +endforeach(test ${LIBVNCCLIENT_TESTS}) + +install_targets(/lib vncserver) +install_targets(/lib vncclient) +install_files(/include/rfb FILES + rfb/keysym.h + rfb/rfb.h + rfb/rfbclient.h + rfb/rfbconfig.h + rfb/rfbint.h + rfb/rfbproto.h + rfb/rfbregion.h +) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/COPYING b/droidvncgrab/vnc/libvncserver-kanaka/COPYING new file mode 100755 index 0000000..a3f6b12 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/ChangeLog new file mode 100755 index 0000000..efbaf3c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/ChangeLog @@ -0,0 +1,767 @@ +2010-05-08 Karl Runge + * libvncclient/rfbproto.c: rfbResizeFrameBuffer should also set + updateRect. + +2010-01-02 Karl Runge + * tightvnc-filetransfer/rfbtightserver.c: enabled fix + for tight security type for RFB 3.8 (debian bug 517422.) + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=517422 + http://sourceforge.net/tracker/?func=detail&aid=2647349&group_id=32584&atid=405858 + +2009-05-21 Karl Runge + * configure.ac: check for __thread. + * libvncserver/main.c, libvncserver/rfbserver.c: various + thread safe corrections including sendMutex guard. + * libvncserver/zrle.c, libvncserver/zrleencodetemplate.c: + thread safety via per-client buffers. + * libvncserver/tight.c, libvncserver/zlib.c: thread safety + corrections via thread local storage using __thread. + * rfb/rfb.h: new members for threaded usage. + * tightvnc-filetransfer/rfbtightserver.c: fix (currently disabled) + for tight security type for RFB 3.8 (debian bug 517422.) + NEEDS AUDIT. + +2009-03-12 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: support mouse wheel operations + +2009-03-08 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: support clipboard operations + +2009-03-07 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: force releasing Alt keys whenr + losing focus. This helps when you switch windows by pressing + Alt+Tab (SDLvncviewer would get the "Alt down" event, but not + the "Alt up" one). + +2009-03-07 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: make the viewer resizable + +2009-03-06 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: enable key repeat + +2009-02-03 Mike Frysinger + * autogen.sh, configure.ac, **/Makefile.am: major automake cleanups + +2009-01-04 Karl Runge + * configure.ac, CMakeLists.txt: set LibVNCServer version to 0.9.7 + +2009-01-04 Karl Runge + * prepare_x11vnc_dist.sh: fix SUBDIRS and DIST_SUBDIRS when using + --with-system-libvncserver + +2008-06-03 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: fix update after resize + +2008-02-18 Christian Ehrlicher + * libvncserver/rfbregion.c: please MS Visual C++ + +2008-02-04 Noriaki Yamazaki + * libvncclient/rfbproto.c, libvncclient/zrle.c: Add ZYWRLE + support to LibVNCClient + +2008-02-04 Noriaki Yamazaki + * libvncserver/zywrletemplate.c: Fix mis encode/decode when + width != scanline + +2008-02-02 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: fix buttons (2 & 3 were switched), + fix Tab key, and fix Ctrl+ + +2008-01-29 Christian Ehrlicher + * libvncserver/rfbserver.c: add missing #include + +2008-01-28 Noriaki Yamazaki + * rfb/rfbproto.h, libvncserver/rfbserver.c, libvncserver/scale.c, + libvncserver/zrle.c, libvncserver/zrleencodetemplate.c, + libvncserver/zywrletemplate.c: add (server-side) ZYWRLE support, + and fix a few endian/scale errors + +2008-01-27 Christian Ehrlicher + * CMakeLists, rfb/rfbconfig.h.cmake, rfb/rfbint.h.cmake: + support CMake + +2007-09-04 Karl Runge + * classes/ssl: improve timeouts, port fallback, and connection + time of the SSL Java viewers. + +2007-08-10 Timo Ketola + * libvncclient/rfbproto.c: add missing else (so that GotRect + handling overrides the default operation). + +2007-06-14 Karl Runge + * configure.ac: add a note on what you must do if you want to + re-run autoconf from the LibVNCServer-X.Y.Z.tar.gz tarball. + +2007-05-26 Karl Runge + * configure.ac, Makefile.am, x11vnc/Makefile.am: change + configure to make more of a split between libvncserver and + x11vnc packages. LibVNCServer pkg does not include x11vnc. + +2007-04-06 Brad Hards + * rfb/rfbclient.h: use 'extern "C"' to make it convenient to + include from C++. + +2007-04-05 Alessandro Praduroux + * rfb/rfb.h: do not misplace guards, which makes it possible to + double include rfb.h from C++. + +2007-03-31 Guillaume Rousse + * configure.ac, **/Makefile.am: build shared libraries + +2007-03-20 Karl Runge + * libvncserver/httpd.c: Add "Connection: close" to HTTP replies. + +2007-03-17 Charles Coffing + * libvncserver: fix a locking issue + +2007-02-01 Johannes E. Schindelin + * libvncclient: add updateRect member to rfbClient, to allow + requesting smaller updates than whole-screen. + +2007-01-31 Karl Runge + * libvncclient: add GotCursorShape() and GotCopyRect() hooks. + fix copyrect code in rfbproto.c, add copyrect to default list. + * Makefile.am and prepare_x11vnc_dist.sh: add x11vnc dependence + on libvncclient. + +2006-12-13 Karl Runge + * remove stray "-permitfiletransfer permit file transfer support" + print out. + +2006-11-21 Karl Runge + * configure.ac: add DPMS detection. + +2006-11-13 Karl Runge + * configure.ac: x11vnc warnings for no XTEST or SSL. + * prepare_x11vnc_dist.sh: to 0.8.4 + +2006-11-07 Karl Runge + * configure.ac: clean up -R linker case, add --without-macosx-native + * prepare_x11vnc_dist.sh: have "make rpm" work properly for + x11vnc package. + +2006-07-17 Karl Runge + * configure.ac: move non-X11 tests out of HAVE_X: set + SSL_LIBS and CRYPT_LIBS and some header checks. + +2006-07-12 Karl Runge + * libvncserver: release for CVE-2006-2450 fix. + +2006-07-08 Karl Runge + * configure.ac: add for linux console. + +2006-07-04 Karl Runge + * configure.ac: add getspnam. + +2006-06-08 Karl Runge + * prepare_x11vnc_dist.sh: to 0.8.2 + +2006-05-29 Steven Carr + * Identified and removed some memory leaks associated + with the Encodings RRE, CoRRE, ZLIB, and Ultra. + * KeyboardLedState now has portable masks defined. + * rfb >= 3.7 Security Type Handler list would grow 1 + entry for each new client connection. + +2006-05-16 Steven Carr + * Statistics output now fits in 80-column output + * Corrected Cursor Statistics reporting as messages + +2006-05-15 Steven Carr + * Default to RFB 3.8 + * Add command line options: + -rfbversion X.Y Sets the version thatthe server reports + -permitfiletransfer Permits File Transfer (Default is Deny) + +2006-05-15 Steven Carr + * The great UltraVNC Compatibility Commit! + libvncserver now supports the following messages: + SetSingleWindow - Select a single window to be the source of the + framebuffer. + ServerInput - Disable and blank the servers display + TextChat - TextChat between the remote/local user + (Bandwidth friendly VS the Notepad approach) + FileTransfer - Emulates a Windows Filesystem to the viewer + (Currently does not support Delta Transfers) + (Currently does not support Sending Directories) + UltraZip - Improved UltraZip support + * Improved Statistics SubSystem, now supports all encodings + * RFB 3.8 support! Error Messages are a 'Good Thing' (tm) + * Default to identify as RFB 3.6 to emulate UltraVNC server + (Server now has the ability to set the RFB version reported) + (permits the viewer to identify the server has FileTransfer ability) + * Client Encoding AutoSelection Supported (UltraViewer is speed aware) + * libvncclient has improved server detection/capabilities logic! + +2006-05-13 Karl Runge + * minilzo.c,minilzo.h,lzoconf.h: switch to non-CRLF versions. + * libvncclient/Makefile.am: add minilzo.c, minilzo.h, lzoconf.h + and ultra.c to materials lists. + * libvncserver/scale.c: remove libm dependency with CEIL and + FLOOR macros. + * libvncserver/rfbserver.c: remove C99 declarations. + * vncterm/Makefile.am: fix VPATH build. + +2006-05-06 Karl Runge + * configure.ac: add linux/videodev.h and linux/fb.h detection. + +2006-05-04 Steven Carr + * rfbEncodingSupportedEncodings - What encodings are supported? + * rfbEncodingSupportedMessages - What message types are supported? + This way a client can identify if a particular server supports a + specific message types. + * rfbEncodingServerIdentity - What is the servers version string? + ie: "x11vnc: 0.8.1 lastmod: 2006-04-25 (LibVNCServer 0.9pre)" + +2006-05-03 Steven Carr + * Server Side Scaling is now supported in libvncserver + Both PalmVNC and UltraVNC SetScale messages are supported + +2006-05-02 Steven Carr + * Ultra Encoding added. Tested against UltraVNC V1.01 + * libvncclient/rfbproto.c CopyRectangle() BPP!=8 bug fixed. + * Incompatible pointer usage warnings eliminated (gcc 4.0.1) + +2006-04-27 Johannes E. Schindelin + * examples/{rotate.c, rotatetemplate.c}: add modified pnmshow + which demonstrates fast rotating and flipping. + +2006-04-26 Karl Runge + * all Makefile.am: use -I $(top_srcdir) instead of -I .. so VPATH + builds will work. + * configure.ac: create rfb subdir for rfbint.h under VPATH. + +2006-04-17 Steven Carr + * Added an example camera application to demonstrate another + way to write a server application. + +2006-04-05 Karl Runge + * classes/ssl: SSL Java viewer workarounds for firewall + proxies (signed applet as last resort, proxy.vnc). + include ssl_vncviewer stunnel wrapper script. + +2006-03-28 Steven Carr + * SDLvncviewer.c, rfbproto.c, vncviewer.c, main.c, rfbserver.c, + rfb.h, rfbclient.h, rfbproto.h: add new encoding: KeyboardLedState + +2006-03-28 Karl Runge + * classes/ssl: patch to tightvnc Java viewer for SSL support + plus other fixes (richcursor colors, Tab keysym, etc). + * libvncserver/httpd.c: add missing \r in 200 OK. + +2006-03-27 Steven Carr + * rfbserver.c: Zlib encoding cannot have a limit via + maxRectsPerUpdate + +2006-02-28 Donald Dugger + * rfb.h, sockets.c, main.c: add a flag to handle all pending + input events instead of one at a time. + +2006-02-24 Karl Runge + * x11vnc: -unixpw and -stunnel options. Add clipboard input + to per-client input controls. + +2006-02-24 Rohit Kumar + * main.c, rfbtightserver.c, rfb.h: added method to get + extension specific client data. + +2006-02-22 Rohit Kumar + * auth.c, main.c, rfbtightserver.c, rfb.h: add methods to + unregister extensions and security types. + +2006-02-20 Karl Runge + * main.c, cursor.c, tightvnc-filetransfer: fix some non-gcc + compiler warnings. + +2006-01-14 Karl Runge + * x11vnc: add -8to24 option for some multi-depth displays. + +2006-01-12 Karl Runge + * configure.ac: add switches for most X extensions. + +2006-01-10 Johannes E. Schindelin + * libvncserver/{main.c,rfbserver.c}: fix timely closing of clients; + the client iterator in rfbProcessEvents() has to iterate also + over clients whose sock < 0. Noticed by Karl. + +2006-01-08 Karl Runge + * x11vnc: the big split. (and -afteraccept and -passwdfile read:..) + * examples/pnmshow24.c: fix typo. + +2006-01-08 Karl Runge + * libvncclient/vncviewer.c: fix non-jpeg/libz builds. + * examples/pnmshow24.c: fix non-ALLOW24BPP builds. + * libvncserver/main.c: fix 'static int' defn. + +2006-01-05 Karl Runge + * libvncserver/main.c: rfbRegisterProtocolExtension extMutex was + never initialized. + +2005-12-24 Karl Runge + * x11vnc: enhance -passwdfile features, filetransfer on by default. + +2005-12-19 Dave Stuart + * libvncserver/{main.c,rfbserver.c,cargs.c}, rfb/rfb.h: introduce + deferPtrUpdateTime, which defers the handling of pointer events + for a couple of milliseconds. + +2005-12-19 Johannes E. Schindelin + * client_examples/SDLvncviewer.c, libvncclient/{sockets.c,vncviewer.c}, + libvncserver/{main.c,rfbserver.c,sockets.c}: fix MinGW32 compilation + +2005-12-08 "Mazin, Malvina" + * configure.ac, libvncserver/sockets.c: on Solaris 2.7, write may + return ENOENT when it really means EAGAIN. + +2005-12-07 Giampiero Giancipoli + * libvncclient/vncviewer.c: plug memory leaks + +2005-12-07 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: use unicode to determine the keysym + (much more reliable than the old method) + +2005-11-25 Karl Runge + * configure.ac: disable tightvnc-filetransfer if no libpthread. + add --without-pthread option. + * libvncserver/Makefile.am: enable WITH_TIGHTVNC_FILETRANSFER + conditional. + * libvncserver/rfbserver.c: fix deadlock from + rfbReleaseExtensionIterator(), fix no libz/libjpeg builds. + * libvncserver/{main.c,private.h}, rfb/rfbclient.h, libvncclient/{rfbproto.c, + tight.c,vncviewer.c}: fix no libz/libjpeg builds. + * libvncserver/tightvnc-filetransfer/rfbtightserver.c: fix no + libz/libjpeg builds. rm // comments. + * libvncserver/tightvnc-filetransfer/filetransfermsg{.c,.h}, + libvncserver/auth.c: rm // comments. + * libvncserver/tightvnc-filetransfer/filelistinfo.h: set NAME_MAX if not + defined. + * x11vnc: throttle load if fb update requests not taking place. + +2005-10-22 Karl Runge + * x11vnc: -filexfer file transfer, -slow_fb, -blackout noptr... + +2005-10-06 Johannes E. Schindelin + * many a files: kill BackChannel and CustomClientMessage + support. The new extension mechanism is much more versatile. + To prove this, a new example shows how to implement the back + channel as an extension. Of course, this had to be tested, so + LibVNCClient now has beginnings of an extension mechanism, too. + And an example implementing the client side of the back channel. + +2005-10-03 Johannes E. Schindelin + * libvncserver/rfbserver.c, rfb/rfb.h: add a method to the + extension struct which is called to enable pseudo encodings. + This is a versatile mechanism to enable/disable custom + extensions with custom clients and servers. + +2005-09-28 Rohit Kumar + * examples/filetransfer.c, rfb/rfb.h, configure.ac, + libvncserver/{auth,cargs,main,rfbserver,sockets}.c, + libvncserver/tightvnc-extension/*: + Implement TightVNC's file transfer protocol. + +2005-09-27 Rohit Kumar + * libvncserver/{cargs,sockets,main,rfbserver}.c, + rfb/rfb.h: Provide a generic means to extend the RFB + protocol: rfbRegisterProtocolExtension(extension). This + deprecates the current (very limited) option to override + rfbScreenInfoPtr->processCustomClientMessage(client). + +2005-09-26 Rohit Kumar + * libvncserver/{auth,main,rfbserver}.c, rfb/{rfb,rfbproto}.h: + support VNC protocol version 3.7. This allows to add security + types. + +2005-08-21 Alberto Lusiani + * libvncserver.spec.in: split rpm into libvncserver, -devel and x11vnc + +2005-07-12 Karl Runge + * x11vnc: tweaks for release, fix queue buildup under -viewonly + +2005-07-10 Karl Runge + * x11vnc: -grab_buster for breaking XGrabServer deadlock, fix + scrolls and copyrect for -clip and -id cases. + +2005-07-06 Karl Runge + * x11vnc: -gui tray now embeds in systray; more improvements to gui. + +2005-07-01 Karl Runge + * libvncserver/httpd.c: make sure httpListenSock >=0 in rfbHttpCheckFds + * x11vnc: add simple "-gui tray" mode for small icon like x0rfbserver + had (someday/somehow to auto embed in a tray/dock) + +2005-06-28 Johannes E. Schindelin + * libvncclient/zrle.c: fix handling of raw and fill subtypes + (off-by-one and off-by-many bug) + +2005-06-27 Karl Runge + * libvncserver/main.c: move deferUpdateTime and maxRectsPerUpdate + defaults to before rfbProcessArguments(). + +2005-06-18 Karl Runge + * configure.ac: don't use -R on HP-UX and OSF1. + * x11vnc: don't free the current cursor, close stderr + for -inetd -q and no -o logfile, set DISPLAY for -solid + external calls. + +2005-06-14 Karl Runge + * configure.ac: XReadScreen and XReadDisplay checks. + * libvncserver/cursor.c: fix unsigned long crash for 64bits. + * x11vnc: first round of beta-testing fixes, RFE's. + +2005-06-10 Johannes E. Schindelin + * configure.ac: fix that annoying SUN /usr/ccs location of "ar" + +2005-06-03 Karl Runge + * libvncserver/main.c: remove sraRgnSubtract from copyRegion + * x11vnc: scrollcopyrect under -scale, add -fixscreen. + +2005-05-30 Karl Runge + * libvncserver/main.c: fix copyRect for non-cursor-shape-aware clients. + +2005-05-24 Karl Runge + * x11vnc: scrollcopyrect: GrabServer detection, autorepeat throttling.. + * prepare_x11vnc_dist.sh: grep out new libvncserver-config line. + +2005-05-23 Karl Runge + * configure.ac: malloc(0) is never used, so we don't need the check + +2005-05-15 Johannes E. Schindelin + * acinclude.m4: fix compilation for systems without socklen_t + +2005-05-17 Karl Runge + * x11vnc: more scrolling, -scr_term, -wait_ui, -nowait_bog + +2005-05-15 Johannes E. Schindelin + * almost every file: ANSIfy, fix warnings from Linus' sparse + +2005-05-14 Karl Runge + * x11vnc: more work on -scrollcopyrect and -xkb modes. + +2005-05-13 Johannes E. Schindelin + * libvncserver/{main,rfbserver,sockets}.c: fix memory leaks (valgrind) + +2005-05-07 Johannes E. Schindelin + * libvncserver/rfbserver.c: fix memory leak pointed out by Tim Jansen + * libvncserver/{httpd,main,rfbserver,sockets}.c, rfb/rfb.h: + replace "rfbBool socketInitDone" by "enum rfbSocketState + socketState" + +2005-05-03 Karl Runge + * libvncserver/main.c: fix leak in rfbDoCopyRect/rfbScheduleCopyRect + * configure.ac: guard against empty HAVE_X + +2005-05-02 Karl Runge + * configure.ac: fatal error for x11vnc package if no X present + * configure.ac: give warnings and info about missing libjpeg/libz + * x11vnc: X RECORD heuristics to detect scrolls: -scrollcopyrect, + build customizations, bandwidth/latency estimates. + +2005-04-27 Johannes E. Schindelin + * clear requested region (long standing TODO, pointed out by Karl) + +2005-04-19 Karl Runge + * x11vnc: -wireframe, -wirecopyrect. Back to the 90's with + wireframes to avoid window move/resize lurching. + * safer remote control defaults. -privremote, -safer, -nocmds. + * debug_xevents, debug_xdamage. -noviewonly for rawfb mode. + +2005-04-10 Karl Runge + * configure.ac: add mmap + * x11vnc: -rawfb, -pipeinput, -xtrap, -flag, ... + +2005-04-03 Karl Runge + * configure.ac: add conditional libXTrap checking + * x11vnc: use DEC-XTRAP on old X11R5 for grab control. + -shiftcmap n, -http, fix DAMAGE event leak. + +2005-03-29 Karl Runge + * x11vnc: fix event leaks, build-time customizations, -nolookup + +2005-03-19 Karl Runge + * x11vnc: scale cursors by default, -scale_cursor to tune, + -arrow n, -norepeat n, speed up integer magnification. + +2005-03-12 Karl Runge + * x11vnc: X DAMAGE support, -clip WxH+X+Y, identd. + +2005-03-05 Karl Runge + * autoconf: rpm -> rpmbuild and echo -n -> printf + +2005-03-04 Karl Runge + * libvncserver/{cargs.c,sockets.c}: add -listen option and + rfbScreen member listenInterface. + * rfb/rfb.h: rfbListenOnTCPPort() and rfbListenOnUDPPort() + function prototypes changed to include network interface. + +2005-02-14 Karl Runge + * x11vnc: -users lurk=, -solid for cde, -gui ez,.. beginner mode. + +2005-02-10 Karl Runge + * x11vnc: -input option to fine tune allowed client input, + additions to remote control and gui for this. + +2005-02-09 Karl Runge + * x11vnc: -users, fix -solid on gnome and kde. + * configure.ac: add pwd.h, wait.h, and utmpx.h checks. + +2005-02-06 Karl Runge + * configure.ac: add /usr/sfw on Solaris when XFIXES, add + --with-jpeg=DIR --with-zlib=DIR, workaround bug when + --without-jpeg was supplied. + * prepare_x11vnc_dist.sh: few tweaks for next release + +2005-02-05 Karl Runge + * x11vnc: -solid color, -opts/-? + * tightvnc-1.3dev5-vncviewer-alpha-cursor.patch: create, name + says it all. + +2005-01-23 Karl Runge + * x11vnc: -timeout, -noalphablend. make -R norepeat work. + * sync with new draw cursor mechanism. + +2005-01-20 Karl Runge + * libvncserver/{cursor.c,rfbserver.c}: fixed the "disappearing cursor" + problem + +2005-01-18 Johannes E. Schindelin + * rfb/rfb.h libvncserver/rfbserver.c: pointerClient was still static + * libvncserver/rfbserver.c: do not make requestedRegion empty without + reason. + * almost everything: the cursor handling for clients which don't handle + CursorShape updates was completely broken. It originally was very + complicated for performance reasons, however, in most cases it made + performance even worse, because at idle times there was way too much + checking going on, and furthermore, sometimes unnecessary updates + were inevitable. + The code now is much more elegant: the ClientRec structure knows + exactly where it last painted the cursor, and the ScreenInfo + structure knows where the cursor shall be. + As a consequence there is no more rfbDrawCursor()/rfbUndrawCursor(), + no more dontSendFramebufferUpdate, and no more isCursorDrawn. + It is now possible to have clients which understand CursorShape + updates and clients which don't at the same time. + * libvncserver/cursor.c: rfbSetCursor no longer has the option + freeOld; this is obsolete, as the cursor structure knows what + to free and what not. + +2005-01-15 Karl Runge + * rfb/rfb.h: add alphaSource and alphaPreMultiplied to rfbCursor. + * libvncserver/cursor.c: do cursor alpha blending in rfbDrawCursor() + for non-cursorshapeupdates clients. + * x11vnc: -alphablend, cursors fixes, -snapfb, more tweaks and bug + fixes. + +2004-12-27 Karl Runge + * x11vnc: improve alpha channel handling for XFIXES cursors. + * add more parameters to remote control. + +2004-12-20 Johannes E. Schindelin + * released version 0.7 + +2004-12-19 Karl Runge + * x11vnc: string cleanup, synchronous remote-control option -sync + * libvncserver/cursor.c: zero underCursorBufferLen when cursor freed. + +2004-12-16 Karl Runge + * test/encodingstest.c: fix decl bug in main() + * x11vnc: use XFIXES extension to show the exact cursor shape. + * remote control nearly everything on the fly, -remote/-query + * tcl/tk gui based on the remote control, -gui + * support screen size changes with XRANDR ext., -xrandr, -padgeom + * Misc: -overlay visual support on IRIX, -id pick, -pointer_mode n, + -sb n, RFB_MODE set in env. under -accept/-gone. + +2004-12-02 Johannes E. Schindelin + * make LibVNCServer compile & work on MinGW32 + +2004-11-30 "Leiradella, Andre V Matos Da Cunha" + * libvncclient/sockets.c: return TRUE in every case of success + +2004-08-29 Karl Runge + * x11vnc: yet another pointer input handling algorithm in + check_user_input(), revert to previous with -old_pointer2. + * modifiy prepare_x11vnc_dist.sh to install tightvnc Java viewer + in $prefix/share/x11vnc/classes + +2004-08-29 Johannes E. Schindelin + * */*.[ch]: API changes: global functions/structures should have + * either "rfb", "sra" or "zrle" as prefix, while structure members + * should not... + +2004-08-29 Karl Runge + * x11vnc: changes in cursor shape handling: use rfbSetCursor() + * cursor shape options: -cursor, -cursor (X|some|most) + * -vncconnect the default. + * configure.ac: add more macros for X extensions. + +2004-08-15 Karl Runge + * x11vnc: -overlay to fix colors with Sun 8+24 overlay visuals. + * -sid option. + +2004-08-03 Karl Runge + * x11vnc: manpage and README + * fix XKBlib.h detection on *BSD + +2004-07-31 Karl Runge + * x11vnc: -cursorpos now the default + +2004-07-28 Karl Runge + * x11vnc: -add_keysyms dynamically add missing keysyms to X server + +2004-07-26 Karl Runge + * x11vnc: first pass at doing modtweak via XKEYBOARD extension (-xkb) + * -skip_keycodes; reset modtweaks on event MappingNotify. + * fix bugs wrt PRIMARY handling. + * continuation lines "\" in x11vncrc. + +2004-07-15 Karl Runge + * x11vnc: modtweak is now the default + * check X11/XKBlib.h in configure.ac to work around Solaris 7 bug. + +2004-07-10 Karl Runge + * x11vnc: norepeat to turn off X server autorepeat when clients exist, + let the client side do the autorepeating. + +2004-06-26 Karl Runge + * x11vnc: add "-scale fraction" for global server-side scaling. + +2004-06-17 Karl Runge + * x11vnc: simple ~/.x11vncrc config file support, -rc, -norc + +2004-06-12 Karl Runge + * x11vnc: -clear_mods, -clear_keys, and -storepasswd, + * add RFB_SERVER_IP RFB_SERVER_PORT to -accept env. + +2004-06-07 Johannes E. Schindelin + * libvncserver/cursor.c, rfb/rfb.h: fix cursor trails + * */Makefile.am: stop automake nagging + * libvncclient/*, client_examples/*: streamline API, SDLvncviewer added + * examples/, libvncclient/, test/: moved tests to test/ + +2004-06-05 Karl Runge + * x11vnc: rearrange file for easier maintenance + * add RFB_CLIENT_COUNT to -accept and -gone commands + +2004-05-27 Karl Runge + * x11vnc: -viewpasswd, viewonly passwds. + * some typos in prepare_x11vnc_dist.sh + * libvncserver: fix view-only plain passwd and view-only CutText + +2004-05-25 Johannes E. Schindelin + * moved the library into libvncserver/ + * moved x11vnc into x11vnc/ + +2004-05-21 Karl Runge + * x11vnc: -gone, -passwdfile, -o logfile; add view-only to -accept + +2004-05-08 Karl Runge + * x11vnc: add -accept some-command/xmessage/popup + +2004-05-05 Karl Runge + * x11vnc: mouse button -> keystrokes and keystroke -> mouse button + mappings in -buttonmap and -remap + * shm OS blacklist revert to -onetile + +2004-04-28 Karl Runge + * x11vnc: -auth, more -cursorpos and -nofb work + +2004-04-19 Karl Runge + * x11vnc: -cursorpos, -sigpipe + +2004-04-13 Karl Runge + * x11vnc: do not send selection unless all clients + are in RFB_NORMAL state. + * increase rfbMaxClientWait when threaded to avoid + ReadExact() timeouts for some viewers. + +2004-04-08 Karl Runge + * x11vnc options -blackout, -xinerama, -xwarppointer + * modify configure.ac to pick up -lXinerama + * extend -remap to take mapping list. + * check cargs result for unused args. + +2004-03-22 Johannes E. Schindelin + * fix cargs.c (hopefully for the last time): + arguments were not correctly purged + +2004-03-15 Johannes E. Schindelin + * fix libvncserver-config to again return a linker when + called with --link + +2004-03-10 Karl Runge + * x11vnc options -vncconnect, -connect, -remap, + -debug_pointer, and -debug_keyboard + * support reverse connections, vncconnect(1), etc. + * expt. with user supplied keysym remapping. + * debug output option for pointer and keyboard. + +2004-02-29 Johannes E. Schindelin + * fixed warning of valgrind for regiontest + +2004-02-19 Karl Runge + * x11vnc options -nosel -noprimary -visual. + * add clipboard/selection handling. + * add visual option (mostly for testing and workarounds). + * improve shm cleanup on failures. + +2004-02-04 Johannes E. Schindelin + * Make examples (at least a few) compileable with g++, + as pointed out by Juan Jose Costello + +2004-01-30 Johannes E. Schindelin + * Thanks to Paul Fox from Bright Star Engineering, + a few more memory leaks were fixed. + +2004-01-29 Johannes E. Schindelin + * Honour the check for libz and libjpeg again. + +2004-01-21 Johannes E. Schindelin + * do not send unneccessary updates when drawing a cursor + * ignore SIGPIPE; it is handled by EPIPE + * add an example how to use rfbDoCopyRect + * add experimental progressive updating (off by default) + +2004-01-19 Karl Runge + * handle mouse button number mismatch + * improved pointer input handling during drags, etc. + * somewhat faster copy_tiles() -> copy_tiles() + * x11vnc options -buttonmap -old_pointer -old_copytile + +2004-01-16 Johannes E. Schindelin + * compile fix for cygwin + +2004-01-09 Karl Runge + * x11vnc options -allow, -localhost, -nodragging, -input_skip + * minimize memory usage under -nofb + +2003-12-08 Karl Runge + * add check for XKEYBOARD extension in configure.ac + * support XBell events (disable: "-nobell"), "-nofb" in x11vnc + +2003-11-07 Karl Runge + * support "-inetd", "-noshm", "-flipbyteorder" in x11vnc + +2003-10-26 Johannes E. Schindelin + * released Version 0.6 + +2003-09-11 Mark McLoughlin + + * Makefile.in, */Makefile.in, aclocal.m4, + bootstrap.sh, config.h.in, configure, + depcomp, install-sh, missing, mkinstalldirs, + Removed auto-generated files from CVS. + +2003-09-11 Mark McLoughlin + + * rdr/Exception.h, rdr/FdInStream.cxx, rdr/FdInStream.h, + rdr/FdOutStream.cxx, rdr/FdOutStream.h, rdr/FixedMemOutStream.h, + rdr/InStream.cxx, rdr/InStream.h, rdr/MemInStream.h, + rdr/MemOutStream.h, rdr/NullOutStream.cxx, rdr/NullOutStream.h, + rdr/OutStream.h, rdr/ZlibInStream.cxx, rdr/ZlibInStream.h, + rdr/ZlibOutStream.cxx, rdr/ZlibOutStream.h, rdr/types.h, + zrle.cxx, zrleDecode.h, zrleEncode.h: remove original + C++ ZRLE implementation. Its been ported to C. + + * NEWS: copy the existing ChangeLog to here and make + this a more detailed ChangeLog. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/INSTALL b/droidvncgrab/vnc/libvncserver-kanaka/INSTALL new file mode 100755 index 0000000..b42a17a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/Makefile.am new file mode 100755 index 0000000..7f3f229 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/Makefile.am @@ -0,0 +1,27 @@ +if WITH_X11VNC +X11VNC=x11vnc +endif + +SUBDIRS=libvncserver examples contrib libvncclient vncterm classes client_examples test $(X11VNC) +DIST_SUBDIRS=libvncserver examples contrib libvncclient vncterm classes client_examples test + +bin_SCRIPTS = libvncserver-config + +includedir=$(prefix)/include/rfb +#include_HEADERS=rfb.h rfbconfig.h rfbint.h rfbproto.h keysym.h rfbregion.h + +include_HEADERS=rfb/rfb.h rfb/rfbconfig.h rfb/rfbint.h rfb/rfbproto.h \ + rfb/keysym.h rfb/rfbregion.h rfb/rfbclient.h + +$(PACKAGE)-$(VERSION).tar.gz: dist + +if HAVE_RPM +# Rule to build RPM distribution package +rpm: $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE).spec + cp $(PACKAGE)-$(VERSION).tar.gz @RPMSOURCEDIR@ + rpmbuild -ba $(PACKAGE).spec +endif + +t: + $(MAKE) -C test test + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/NEWS b/droidvncgrab/vnc/libvncserver-kanaka/NEWS new file mode 100755 index 0000000..58f9285 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/NEWS @@ -0,0 +1,147 @@ + Mark sent me patches to no longer need C++ for ZRLE encoding! + added --disable-cxx Option for configure + x11vnc changes from Karl Runge: + - Changed all those whimpy printf(...)'s into manly fprintf(stdxxx,...)'s. + + - Added -q switch (quiet) to suppress printing all the debug-looking output. + + - Added -bg switch to fork into background after everything is set up. + (checks for LIBVNCSERVER_HAVE_FORK and LIBVNCSERVER_HAVE_SETSID) + + - Print this string out to stdout: 'PORT=XXXX' (usually XXXX = 5900). + Combining with -bg, easy to write a ssh/rsh wrapper with something like: + port=`ssh $host "x11vnc -bg .."` then run vncviewer based on $port output. + (tunneling the vnc traffic thru ssh a bit more messy, but doable) + + - Quite a bit of code to be more careful when doing 8bpp indexed color, e.g. + not assuming NCOLORS is 256, handling 8bit TrueColor and Direct Color, etc + (I did all this probably in April, not quite clear in my mind now, but + I did test it out a fair amount on my old Sparcstation 20 wrt a user's + questions). + introduce rfbErr for Errors (Erik) + make rfbLog overridable (suggested by Erik) + don't reutrn on EINTR in WriteExact()/ReadExact() (suggested by Erik) + use AX_PREFIX_CONFIG_H to prefix constants in config.h to avoid + name clashes (also suggested by Erik) + transformed Bool, KeySym, Pixel to rfbBool, rfbKeySym, rfbPixel + (as suggested by Erik) + purged exit() calls (suggested by Erik) + fixed bug with maxRectsPerUpdate and Tight Encoding (these are incompatible) + checked sync with TightVNC 1.2.8: + viewonly/full passwords; if given a list, only the first is a full one + vncRandomBytes is a little more secure now + new weights for tight encoding + checked sync with RealVNC 3.3.7 + introduced maxRectsPerUpdate + added first alpha version of LibVNCClient + added simple and simple15 example (really simple examples) + finally got around to fix configure in CVS + long standing http bug (.jar was sent twice) fixed by a friend of Karl named Mike + http options in cargs + when closing a client and no longer listening for new ones, don't crash + fixed a bug with ClientConnectionGone + endianness is checked at configure time + fixed a bug that prevented the first client from being closed + fixed that annoying "libvncserver-config --link" bug + make rfbReverseByte public (for rdp2vnc) + fixed compilation on OS X, IRIX, Solaris + install target for headers is now ${prefix}/include/rfb ("#include ") + renamed "sraRegion.h" to "rfbregion.h" + CARD{8,16,32} are more standard uint{8,16,32}_t now + fixed LinuxVNC colour handling + fixed a bug with pthreads where the connection was not closed + moved vncterm to main package (LinuxVNC included) + portability fixes (IRIX, OSX, Solaris) + more portable way to determine endianness and types of a given size + through autoconf based methods +0.5 + rpm packaging through autoconf + autoconf'ed the whole package (including optional support for zlib, + pthreads and libjpeg as well as zrle/c++) + moved appropriate files to contrib/ and examples/ respectively + fixed long standing cargs bug (Justin "Zippy" Dearing) + Even better x11vnc from Karl J. Runge! (supports different kbd layouts of + client/server) + Better x11vnc from Karl J. Runge! + fixed severe bug (Const Kaplinsky) + got patch from Const Kaplisnky with CursorPosUpdate encoding and some Docs + sync'ed with newest RealVNC (ZRLE encoding) + a HTTP request for tunnelling was added (to fool strict web proxies) + sync'ed with TightVNC 1.2.5 +0.4 + support for NewFB from Const Kaplinsky + memory leaks squashed (localtime pseudo leak is still there :-) + small improvements for OSXvnc (still not working correctly) + synced with TightVNC 1.2.3 + solaris compile cleanups + many x11vnc improvements + added backchannel, an encoding which needs special clients to pass + arbitrary data to the client + changes from Tim Jansen regarding multi threading and client blocking + as well as C++ compliancy + x11vnc can be controlled by starting again with special options if compiling + with LOCAL_CONTROL defined +0.3 + added x11vnc, a x0rfbserver clone + regard deferUpdateTime in processEvents, if usec<0 + initialize deferUpdateTime (memory "leak"!) + changed command line handling (arguments are parsed and then removed) + added very simple example: zippy + added rfbDrawLine, rfbDrawPixel +0.2 + inserted a deferUpdate mechanism (X11 independent). + removed deletion of requestedRegion + added rfbLoadConsoleFont + fixed font colour handling. + added rfbSelectBox + added rfbDrawCharWithClip to allow for clipping and a background colour. + fixed font colours + added rfbFillRect + added IO function to check password. + rfbNewClient now sets the socket in the fd_set (for the select() call) + when compiling the library with HAVE_PTHREADS and an application + which includes "rfb.h" without, the structures got mixed up. + So, the pthreads section is now always at the end, and also + you get a linker error for rfbInitServer when using two different + pthread setups. + fixed two deadlocks: when setting a cursor and when using CopyRect + fixed CopyRect when copying modified regions (they lost the modified + property) + WIN32 target compiles and works for example :-) + fixed CopyRect (was using the wrong order of rectangles...) + should also work with pthreads, because copyrects are + always sent immediately (so that two consecutive copy rects + cannot conflict). + changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because + this makes more sense! + flag backgroundLoop in rfbScreenInfo (if having pthreads) + CopyRect & CopyRegion were implemented. + if you use a rfbDoCopyR* function, it copies the data in the + framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR* + instead; this doesn't modify the frameBuffer. + added flag to optionally not send XCursor updates, but only RichCursor, + or if that is not possible, fall back to server side cursor. + This is useful if your cursor has many nice colours. + fixed java viewer on server side: + SendCursorUpdate would send data even before the client pixel format + was set, but the java applet doesn't like the server's format. + fixed two pthread issues: + rfbSendFramebuffer was sent by a ProcessClientMessage function + (unprotected by updateMutex). + cursor coordinates were set without protection by cursorMutex + source is now equivalent to TridiaVNC 1.2.1 + pthreads now work (use iterators!) + cursors are supported (rfbSetCursor automatically undraws cursor) + support for 3 bytes/pixel (slow!) + server side colourmap support + fixed rfbCloseClient not to close the connection (pthreads!) + this is done lazily (and with proper signalling). + cleaned up mac.c (from original OSXvnc); now compiles (untested!) + compiles cleanly on Linux, IRIX, BSD, Apple (Darwin) + fixed prototypes +0.1 + rewrote API to use pseudo-methods instead of required functions. + lots of clean up. + Example can show symbols now. + All encodings + HTTP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/README b/droidvncgrab/vnc/libvncserver-kanaka/README new file mode 100755 index 0000000..49c8a4e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/README @@ -0,0 +1,439 @@ +LibVNCServer: a library for easy implementation of a RDP/VNC server. +Copyright (C) 2001-2003 Johannes E. Schindelin + +If you already used LibVNCServer, you probably want to read NEWS. + +What is it? +----------- + +VNC is a set of programs using the RFB (Remote Frame Buffer) protocol. They +are designed to "export" a frame buffer via net (if you don't know VNC, I +suggest you read "Basics" below). It is already in wide use for +administration, but it is not that easy to program a server yourself. + +This has been changed by LibVNCServer. + +There are two examples included: + - example, a shared scribble sheet + - pnmshow, a program to show PNMs (pictures) over the net. + +The examples are not too well documented, but easy straight forward and a +good starting point. + +Try example: it outputs on which port it listens (default: 5900), so it is +display 0. To view, call + vncviewer :0 +You should see a sheet with a gradient and "Hello World!" written on it. Try +to paint something. Note that everytime you click, there is some bigger blot, +whereas when you drag the mouse while clicked you draw a line. The size of the +blot depends on the mouse button you click. Open a second vncviewer with +the same parameters and watch it as you paint in the other window. This also +works over internet. You just have to know either the name or the IP of your +machine. Then it is + vncviewer machine.where.example.runs.com:0 +or similar for the remote client. Now you are ready to type something. Be sure +that your mouse sits still, because everytime the mouse moves, the cursor is +reset to the position of the pointer! If you are done with that demo, press +the down or up arrows. If your viewer supports it, then the dimensions of the +sheet change. Just press Escape in the viewer. Note that the server still +runs, even if you closed both windows. When you reconnect now, everything you +painted and wrote is still there. You can press "Page Up" for a blank page. + +The demo pnmshow is much simpler: you either provide a filename as argument +or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file, +i.e. a truecolour graphics. Only the Escape key is implemented. This may be +the best starting point if you want to learn how to use LibVNCServer. You +are confronted with the fact that the bytes per pixel can only be 8, 16 or 32. + +Projects using it +---------------------------------------- + +VNC for KDE +http://www.tjansen.de/krfb + +GemsVNC +http://www.elilabs.com/~rj/gemsvnc/ + +VNC for Netware +http://forge.novell.com/modules/xfmod/project/?vncnw + +RDesktop +http://rdesktop.sourceforge.net + +Mail me, if your application is missing! + +How to use +---------- + +To make a server, you just have to initialise a server structure using the +function rfbDefaultScreenInit, like + rfbScreenInfoPtr rfbScreen = + rfbGetScreen(argc,argv,width,height,8,3,bpp); +where byte per pixel should be 1, 2 or 4. If performance doesn't matter, +you may try bpp=3 (internally one cannot use native data types in this +case; if you want to use this, look at pnmshow24). + + +You then can set hooks and io functions (see below) or other +options (see below). + +And you allocate the frame buffer like this: + rfbScreen->frameBuffer = (char*)malloc(width*height*bpp); + +After that, you initialize the server, like + rfbInitServer(rfbScreen); + +You can use a blocking event loop, a background (pthread based) event loop, +or implement your own using the rfbProcessEvents function. + +Making it interactive +--------------------- + +Input is handled by IO functions (see below). + +Whenever you change something in the frame buffer, call rfbMarkRectAsModified. +You should make sure that the cursor is not drawn before drawing yourself +by calling rfbUndrawCursor. You can also draw the cursor using rfbDrawCursor, +but it hardly seems necessary. For cursor details, see below. + +Utility functions +----------------- + +Whenever you draw something, you have to call + rfbMarkRectAsModified(screen,x1,y1,x2,y2). +This tells LibVNCServer to send updates to all connected clients. + +Before you draw something, be sure to call + rfbUndrawCursor(screen). +This tells LibVNCServer to hide the cursor. +Remark: There are vncviewers out there, which know a cursor encoding, so +that network traffic is low, and also the cursor doesn't need to be +drawn the cursor everytime an update is sent. LibVNCServer handles +all the details. Just set the cursor and don't bother any more. + +To set the mouse coordinates (or emulate mouse clicks), call + defaultPtrAddEvent(buttonMask,x,y,cl); +IMPORTANT: do this at the end of your function, because this actually draws +the cursor if no cursor encoding is active. + +What is the difference between rfbScreenInfoPtr and rfbClientPtr? +----------------------------------------------------------------- + +The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which +holds information about the server, like pixel format, io functions, +frame buffer etc. + +The rfbClientPtr is a pointer to an rfbClientRec structure, which holds +information about a client, like pixel format, socket of the +connection, etc. + +A server can have several clients, but needn't have any. So, if you +have a server and three clients are connected, you have one instance +of a rfbScreenInfo and three instances of rfbClientRec's. + +The rfbClientRec structure holds a member + rfbScreenInfoPtr screen +which points to the server and a member + rfbClientPtr next +to the next client. + +The rfbScreenInfo structure holds a member + rfbClientPtr rfbClientHead +which points to the first client. + +So, to access the server from the client structure, you use client->screen. +To access all clients from a server, get screen->rfbClientHead and +iterate using client->next. + +If you change client settings, be sure to use the provided iterator + rfbGetClientIterator(rfbScreen) +with + rfbClientIteratorNext(iterator) +and + rfbReleaseClientIterator +to prevent thread clashes. + +Other options +------------- + +These options have to be set between rfbGetScreen and rfbInitServer. + +If you already have a socket to talk to, just set rfbScreen->inetdSock +(originally this is for inetd handling, but why not use it for your purpose?). + +To also start an HTTP server (running on port 5800+display_number), you have +to set rfbScreen->httpdDir to a directory containing vncviewer.jar and +index.vnc (like the included "classes" directory). + +Hooks and IO functions +---------------------- + +There exist the following IO functions as members of rfbScreen: +kbdAddEvent, kbdReleaseAllKeys, ptrAddEvent and setXCutText + +kbdAddEvent(rfbBool down,rfbKeySym key,rfbClientPtr cl) + is called when a key is pressed. +kbdReleaseAllKeys(rfbClientPtr cl) + is not called at all (maybe in the future). +ptrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl) + is called when the mouse moves or a button is pressed. + WARNING: if you want to have proper cursor handling, call + defaultPtrAddEvent(buttonMask,x,y,cl) + in your own function. This sets the coordinates of the cursor. +setXCutText(char* str,int len,rfbClientPtr cl) + is called when the selection changes. + +There are only two hooks: +newClientHook(rfbClientPtr cl) + is called when a new client has connected. +displayHook + is called just before a frame buffer update is sent. + +You can also override the following methods: +getCursorPtr(rfbClientPtr cl) + This could be used to make an animated cursor (if you really want ...) +setTranslateFunction(rfbClientPtr cl) + If you insist on colour maps or something more obscure, you have to + implement this. Default is a trueColour mapping. + +Cursor handling +--------------- + +The screen holds a pointer + rfbCursorPtr cursor +to the current cursor. Whenever you set it, remember that any dynamically +created cursor (like return value from rfbMakeXCursor) is not free'd! + +The rfbCursor structure consists mainly of a mask and a source. The mask +describes, which pixels are drawn for the cursor (a cursor needn't be +rectangular). The source describes, which colour those pixels should have. + +The standard is an XCursor: a cursor with a foreground and a background +colour (stored in backRed,backGreen,backBlue and the same for foreground +in a range from 0-0xffff). Therefore, the arrays "mask" and "source" +contain pixels as single bits stored in bytes in MSB order. The rows are +padded, such that each row begins with a new byte (i.e. a 10x4 +cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits). + +It is however very easy to make a cursor like this: + +char* cur=" " + " xx " + " x " + " "; +char* mask="xxxx" + "xxxx" + "xxxx" + "xxx "; +rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask); + +You can even set "mask" to NULL in this call and LibVNCServer will calculate +a mask for you (dynamically, so you have to free it yourself). + +There is also an array named "richSource" for colourful cursors. They have +the same format as the frameBuffer (i.e. if the server is 32 bit, +a 10x4 cursor has 4x10x4 bytes). + +History +------- + +LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on +the original code from ORL/AT&T. + +When I began hacking with computers, my first interest was speed. So, when I +got around assembler, I programmed the floppy to do much of the work, because +it's clock rate was higher than that of my C64. This was my first experience +with client/server techniques. + +When I came around Xwindows (much later), I was at once intrigued by the +elegance of such connectedness between the different computers. I used it +a lot - not the least priority lay on games. However, when I tried it over +modem from home, it was no longer that much fun. + +When I started working with ASP (Application Service Provider) programs, I +tumbled across Tarantella and Citrix. Being a security fanatic, the idea of +running a server on windows didn't appeal to me, so Citrix went down the +basket. However, Tarantella has it's own problems (security as well as the +high price). But at the same time somebody told me about this "great little +administrator's tool" named VNC. Being used to windows programs' sizes, the +surprise was reciprocal inverse to the size of VNC! + +At the same time, the program "rdesktop" (a native Linux client for the +Terminal Services of Windows servers) came to my attention. There where even +works under way to make a protocol converter "rdp2vnc" out of this. However, +my primary goal was a slow connection and rdp2vnc could only speak RRE +encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original +author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is +better. I first tried that, but had no success at all (crunchy pictures). + +Also, I liked the idea of an HTTP server included and possibly other +encodings like the Tight Encodings from Const Kaplinsky. So I started looking +for libraries implementing a VNC server where I could steal what I can't make. +I found some programs based on the demo server from AT&T, which was also the +basis for rdp2vnc (can only speak Raw and RRE encoding). There were some +rumors that GGI has a VNC backend, but I didn't find any code, so probably +there wasn't a working version anyway. + +All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was +released. I looked at the code and it was not much of a problem to work out +a simple server - using every functionality there is in Xvnc. It became clear +to me that I *had* to build a library out of it, so everybody can use it. +Every change, every new feature can propagate to every user of it. + +It also makes everything easier: + You don't care about the cursor, once set (or use the standard cursor). +You don't care about those sockets. You don't care about encodings. +You just change your frame buffer and inform the library about it. Every once +in a while you call rfbProcessEvents and that's it. + +Basics +------ + +VNC (Virtual network computing) works like this: You set up a server and can +connect to it via vncviewers. The communication uses a protocol named RFB +(Remote Frame Buffer). If the server supports HTTP, you can also connect +using a java enabled browser. In this case, the server sends back a +vncviewer applet with the correct settings. + +There exist several encodings for VNC, which are used to compress the regions +which have changed before they are sent to the client. A client need not be +able to understand every encoding, but at least Raw encoding. Which encoding +it understands is negotiated by the RFB protocol. + +The following encodings are known to me: +Raw, RRE, CoRRE, Hextile, CopyRect from the original AT&T code and +Tight, ZLib, LastRect, XCursor, RichCursor from Const Kaplinsky et al. + +If you are using a modem, you want to try the "new" encodings. Especially +with my 56k modem I like ZLib or Tight with Quality 0. In my tests, it even +beats Tarantella. + +There is the possibility to set a password, which is also negotiated by the +RFB protocol, but IT IS NOT SECURE. Anybody sniffing your net can get the +password. You really should tunnel through SSH. + +Windows or: why do you do that to me? +-------------------------------------------- + +If you love products from Redmod, you better skip this paragraph. +I am always amazed how people react whenever Microsoft(tm) puts in some +features into their products which were around for a long time. Especially +reporters seem to not know dick about what they are reporting about! But +what is everytime annoying again, is that they don't do it right. Every +concept has it's new name (remember what enumerators used to be until +Mickeysoft(tm) claimed that enumerators are what we thought were iterators. +Yeah right, enumerators are also containers. They are not separated. Muddy.) + +There are three packages you want to get hold of: zlib, jpeg and pthreads. +The latter is not strictly necessary, but when you put something like this +into your source: + +#define MUTEX(s) + struct { + int something; + MUTEX(latex); + } + +Microsoft's C++ compiler doesn't do it. It complains that this is an error. +This, however, is how I implemented mutexes in case you don't need pthreads, +and so don't need the mutex. + +You can find the packages at +http://www.gimp.org/win32/extralibs-dev-20001007.zip + +Thanks go to all the GIMP team! + +What are those other targets in the Makefile? +--------------------------------------------- + +OSXvnc-server is the original OSXvnc adapted to use the library, which was in +turn adapted from OSXvnc. As you easily can see, the OSX dependend part is +minimal. + +storepasswd is the original program to save a vnc style password in a file. +Unfortunately, authentication as every vncviewer speaks it means the server +has to know the plain password. You really should tunnel via ssh or use +your own PasswordCheck to build a PIN/TAN system. + +sratest is a test unit. Run it to assert correct behaviour of sraRegion. I +wrote this to test my iterator implementation. + +blooptest is a test of pthreads. It is just the example, but with a background +loop to hunt down thread lockups. + +pnmshow24 is like pnmshow, but it uses 3 bytes/pixel internally, which is not +as efficient as 4 bytes/pixel for translation, because there is no native data +type of that size, so you have to memcpy pixels and be real cautious with +endianness. Anyway, it works. + +fontsel is a test for rfbSelectBox and rfbLoadConsoleFont. If you have Linux +console fonts, you can browse them via VNC. Directory browsing not implemented +yet :-( + +Why I don't feel bad about GPL +------------------------------ + +At the beginning of this projects I would have liked to make it a BSD +license. However, it is based on plenty of GPL'ed code, so it has to be +a GPL. I hear BeeGee complaining: "but that's invasive, every derivative +work, even just linking, makes my software GPL!" + +Yeah. That's right. It is because there are nasty jarheads out there who +would take anybody's work and claim it their own, selling it for much too +much money, stealing freedom and innovation from others, saying they were +the maintainers of innovation, lying, making money with that. + +The people at AT&T worked really well to produce something as clean and lean +as VNC. The managers decided that for their fame, they would release the +program for free. But not only that! They realized that by releasing also +the code for free, VNC would become an evolving little child, conquering +new worlds, making it's parents very proud. As well they can be! To protect +this innovation, they decided to make it GPL, not BSD. The principal +difference is: You can make closed source programs deriving from BSD, not +from GPL. You have to give proper credit with both. + +Now, why not BSD? Well, imagine your child being some famous actor. Along +comes a manager who exploits your child exclusively, that is: nobody else +can profit from the child, it itself included. Got it? + +What reason do you have now to use this library commercially? + +Several: You don't have to give away your product. Then you have effectively +circumvented the GPL, because you have the benefits of other's work and you +don't give back anything and you will be in hell for that. In fact, this +library, as my other projects, is a payback for all the free software I can +use (and sometimes, make better). For example, just now, I am using XEmacs +on top of XFree86, all running under Linux. + +Better: Use a concept like MySQL. This is free software, however, they make +money with it. If you want something implemented, you have the choice: +Ask them to do it (and pay a fair price), or do it yourself, normally giving +back your enhancements to the free world of computing. + +Learn from it: If you like the style this is written, learn how to imitate +it. If you don't like the style, learn how to avoid those things you don't +like. I learnt so much, just from looking at code like Linux, XEmacs, +LilyPond, STL, etc. + +License +------- + +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; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.dfdf + +Contact +------- + +To contact me, mail me: Johannes dot Schindelin at gmx dot de + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/README.cvs b/droidvncgrab/vnc/libvncserver-kanaka/README.cvs new file mode 100755 index 0000000..c76b479 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/README.cvs @@ -0,0 +1,22 @@ +If you check out CVS of LibVNCServer, everything should build as usual: + +./configure && make + +If your machine complains not having the right version of automake (which should +not be necessary, because every needed file is checked in), try + +find -name Makefile.in -exec touch {} \; + +and rerun ./configure && make + +If you want to make changes which require automake or autoconf (i.e. you +check for other headers or add files), you have to have a current +(>2.50) version of autoconf. Also, you need automake. + +Then, just do + sh autogen.sh && make +in LibVNCServer's directory, and you should see plenty of output and +finally have a complete build of LibVNCServer. + +Happy VNC'ing! + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/README.md b/droidvncgrab/vnc/libvncserver-kanaka/README.md new file mode 100755 index 0000000..a454608 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/README.md @@ -0,0 +1,42 @@ +## LibVNCServer with the Tight PNG encoding + +### LibVNCServer + +Copyright (C) 2001-2003 Johannes E. Schindelin + +[LibVNCServer](http://sourceforge.net/projects/libvncserver/) is +a library for easy implementation of a RDP/VNC server. + + +### Tight PNG + +Copyright (C) 2010 Joel Martin + +The [Tight PNG encoding](http://wiki.qemu.org/VNC_Tight_PNG) is +similar to the Tight encoding, but the basic compression (zlib) is +replaced with PNG data. + +This encoding allows for simple, fast clients and bandwidth efficient +clients: + +* The PNG data can be rendered directly by the client so there is + negligible decode work needed in the VNC client itself. +* PNG images are zlib compressed internally (along with other + optimizations) so tightPng is comparable in bandwith to tight. +* PNG images are natively supported in the browsers. This is optimal + for web based VNC clients such as + [noVNC](http://github.com/kanaka/noVNC) + + +### Usage + +See INSTALL for build instructions. To build with the tightPng +encoding, you must also have libpng development libraries install. For +example: + + sudo apt-get install libpng-dev + + +### TODO + +- Handle palette mode (non-truecolor). diff --git a/droidvncgrab/vnc/libvncserver-kanaka/TODO b/droidvncgrab/vnc/libvncserver-kanaka/TODO new file mode 100755 index 0000000..2afffc8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/TODO @@ -0,0 +1,26 @@ +immediate: +---------- + +make SDLvncviewer more versatile + - test for missing keys (especially "[]{}" with ./examples/mac), + - map Apple/Linux/Windows keys onto each other, + - handle selection + - handle scroll wheel +style fixes: use Linux' coding guidelines & ANSIfy tightvnc-filetransfer: + discuss on list +LibVNCClient cleanup: prefix with "rfbClient", and make sure it does + not deliberately die() or exit() anywhere! +java vncviewer doesn't do colour cursors? +MinGW32 doesn't do fcntl on sockets; use setsockopt instead... +make corre work again (libvncclient or libvncserver?) +teach SDLvncviewer about CopyRect... +implement "-record" in libvncclient + +later: +------ + +selectbox: scroll bars +authentification schemes (secure vnc) + IO function ptr exists; now explain how to tunnel and implement a + client address restriction scheme. +VisualNaCro testing diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.cvsignore new file mode 100755 index 0000000..3eeae3f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.cvsignore @@ -0,0 +1,22 @@ +aclocal.m4 +autom4te.cache +config.guess +config.log +config.status +config.sub +configure +COPYING +.cvsignore +INSTALL +install-sh +Makefile +Makefile.in +missing +mkinstalldirs +nacro.pm +nacro.so +nacro_wrap.c +visualnacro-* +.deps +.in +depcomp diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.gitignore b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.gitignore new file mode 100755 index 0000000..a7007d3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.gitignore @@ -0,0 +1,5 @@ +/COPYING +/INSTALL +/nacro.pm +/nacro.so +/nacro_wrap.c diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/AUTHORS b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/AUTHORS new file mode 100755 index 0000000..1081101 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/AUTHORS @@ -0,0 +1,2 @@ +Johannes Schindelin + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/ChangeLog new file mode 100755 index 0000000..78b9858 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/ChangeLog @@ -0,0 +1,15 @@ +2006-10-10: Johannes Schindelin + * implement --compact and --compact-dragging to shut up the + script about mouse movements or drags. + * add 'i', 'c' and 'r' menu keys. + +2006-09-12: Johannes Schindelin + * the reference rectangle is selected with a rubber band, + and can be shown with 'd'. + +2006-06-15: Johannes Schindelin + * added timing: you can record the events with their timestamps now + +2005-01-13: Johannes Schindelin + * started the project + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/Makefile.am new file mode 100755 index 0000000..7b1fe67 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/Makefile.am @@ -0,0 +1,51 @@ +INTERFACE=nacro.h +SRCS=nacro.c +OBJS=nacro.o +ISRCS=nacro_wrap.c +IOBJS=nacro_wrap.o +TARGET=nacro +LIBS= @LIBVNCSERVERLIBS@ + +nacro_CFLAGS= @LIBVNCSERVERCFLAGS@ + +SWIGOPT= + +EXTRA_DIST=autogen.sh $(INTERFACE) $(SRCS) $(ISRCS) nacro.pm recorder.pl + +all: $(LIBPREFIX)$(TARGET)$(SO) + +# the following is borrowed from SWIG + +SWIG= @SWIG@ + +################################################################## +##### PERL 5 ###### +################################################################## + +# You need to set this variable to the Perl5 directory containing the +# files "perl.h", "EXTERN.h" and "XSUB.h". With Perl5.003, it's +# usually something like /usr/local/lib/perl5/arch-osname/5.003/CORE. + +PERL5_INCLUDE= @PERL5EXT@ + +# Extra Perl specific dynamic linking options +PERL5_DLNK = @PERL5DYNAMICLINKING@ +PERL5_CCFLAGS = @PERL5CCFLAGS@ + +# ---------------------------------------------------------------- +# Build a Perl5 dynamically loadable module (C) +# ---------------------------------------------------------------- + +$(ISRCS): $(INTERFACE) + @test -n "$(SWIG)" || (echo "Need SWIG" && exit 1) + $(SWIG) -perl5 $(SWIGOPT) $(INTERFACE) + +$(OBJS): $(SRCS) $(INTERFACE) + $(CC) -c -Dbool=char $(CCSHARED) $(CFLAGS) -o $@ $< $(LIBVNCSERVERCFLAGS) $(INCLUDES) -I$(PERL5_INCLUDE) + +$(IOBJS): $(ISRCS) $(INTERFACE) + $(CC) -c -Dbool=char $(CCSHARED) $(CFLAGS) -o $@ $< $(INCLUDES) $(PERL5_CCFLAGS) -I$(PERL5_INCLUDE) + +$(LIBPREFIX)$(TARGET)$(SO): $(OBJS) $(IOBJS) + $(LDSHARED) $(OBJS) $(IOBJS) $(PERL5_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/NEWS b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/NEWS new file mode 100755 index 0000000..6707d33 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/NEWS @@ -0,0 +1,10 @@ +With --timing, you can actually record action scripts which are meaningful... +Earlier, the events just got garbled, because the GUI could not react as +fast as the events were churned out. + +Clipboard is supported (thanks to Uwe). + +Keys are recorded by their symbols with the --symbolic switch, provided you +have the X11::Keysyms module. + +After pressing Control twice, you can show the last reference image with 'd'. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/README b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/README new file mode 100755 index 0000000..8c92b32 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/README @@ -0,0 +1,88 @@ +This is VisualNaCro. + +DISCLAIMER: recorder.pl is not yet functional. + +What does it? + + It is a Perl module meant to remote control a VNC server. + + It includes a recorder (written in Perl) to make it easy to + record a macro, which is just a Perl script, and which you can + modify to your heart's content. + + The most important feature, however, is that you can mark a + rectangle which the Perl script will try to find again when you + run it. Thus when you play a game and want to hit a certain button, + you just hit the Ctrl key twice, mark the button, and from then on, + all mouse movements will be repeated relative to that button, even + if the button is somewhere else when you run the script the next + time. + + If you know Tcl Expect, you will recognize this approach. Only this + time, it is not text, but an image which is expected. + +How does it work? + + It acts as a VNC proxy: your Perl script starts its own VNC server. + The script now can intercept inputs and outputs, and act upon them. + In order to write a macro, start + + recorder.pl --script my-macro.pl --timing host:port + + connect with a vncviewer of your choice to :23, where + is the computer on which recorder.pl was started (not necessarily the + same as the VNC server!). Now your actions are recorded into + my_macro.pl, and the images you want to grep for will be saved as + my_macro-1.pnm, my_macro-2.pnm, ... + + In order to finish the script, hit Ctrl twice and say "q". + +Why did I do it? + + Because I could ;-) + + No really, I needed a way to write automated tests. While there + exist a lot of OpenSource programs for web testing, I found none + of them easy to use, and for GUI testing I found xautomation. + + Xautomation has this "visual grep" (or "graphical expect") feature: + given an image it tries to find it on the desktop and returns the + coordinates. Unfortunately, there is no easy way to record macros + with it, and it only works on X11. + + As I know VNC pretty well, and there are VNC servers for every OS + and gadget, I thought it might be cool to have this feature to + control a VNC server. + + Actually, it makes it even easier: with plain X11, for example, you + can not know where on the screen the action is if you don't check + the whole screen. This complex problem is beautifully addressed + in Karl Runge's x11vnc. + + My main purpose is to run regression tests on different browsers, + which I can easily do by starting Xvnc and using VisualNaCro. + +How did I do it? + + I wondered long about how to do it. I couldn't take the same approach + as xautomation: I cannot connect to the VNC server thousand times + per second. So I decided to create an interface of LibVNCServer/ + LibVNCClient for use in a script language. + + Fortunately, this task is made very, very easy by SWIG. As Perl + is one of my favorite script languages, I decided to use this. + But SWIG makes it easy to use the very same interface for other + popular languages, so you are welcome to port VisualNaCro to + the language of your choice! + +Isn't it pronounced "Visual Macro"? + + Yes. But I liked the Visual Na Cro play of acronyms. I'm sorry if + you don't find it funny. + +What's the license? + + GPL. It is based on LibVNCServer/LibVNCClient, so it has to be. + If you want to port this package to use vncreflector, which has a + BSD license, go ahead. + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/autogen.sh b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/autogen.sh new file mode 100755 index 0000000..2d1645d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/autogen.sh @@ -0,0 +1,55 @@ +#! /bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +AUTOMAKE=automake-1.4 +ACLOCAL=aclocal-1.4 + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + AUTOMAKE=automake + ACLOCAL=aclocal +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile VisualNaCro." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile VisualNaCro." + echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +(test -f $srcdir/nacro.h) || { + echo "You must run this script in the top-level VisualNaCro directory" + exit 1 +} + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +$ACLOCAL $ACLOCAL_FLAGS +#autoheader +$AUTOMAKE --add-missing --copy +autoconf + +echo "Running ./configure --enable-maintainer-mode" "$@" +$srcdir/configure --enable-maintainer-mode "$@" + +echo "Now type 'make' to compile VisualNaCro." diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/configure.ac b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/configure.ac new file mode 100755 index 0000000..1f78317 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/configure.ac @@ -0,0 +1,252 @@ +dnl Process this file with autoconf to produce a configure script. +dnl The macros which aren't shipped with the autotools are stored in the +dnl Tools/config directory in .m4 files. + +AC_INIT([VisualNaCro],[0.1],[http://libvncserver.sourceforge.net]) +AC_PREREQ(2.54) +AC_CANONICAL_HOST +AM_INIT_AUTOMAKE + +dnl Checks for programs. +AC_CHECK_PROG(SWIG,swig,swig) +AC_CHECK_PROG(LIBVNCSERVERCONFIG,libvncserver-config,yes,no) +if test "$LIBVNCSERVERCONFIG" != "yes"; then + AC_MSG_ERROR([Need to have libvncserver-config in PATH]) + exit 1 +fi +AC_PROG_CC +AC_PROG_RANLIB +AC_EXEEXT +AC_OBJEXT + +LIBVNCSERVERCFLAGS=`libvncserver-config --cflags` +LIBVNCSERVERLIBS=`libvncserver-config --libs` +AC_SUBST(LIBVNCSERVERCFLAGS) +AC_SUBST(LIBVNCSERVERLIBS) + +dnl Checks for header files. +AC_HEADER_STDC + +dnl How to specify include directories that may be system directories. +# -I should not be used on system directories (GCC) +if test "$GCC" = yes; then + ISYSTEM="-isystem " +else + ISYSTEM="-I" +fi + + +# Set info about shared libraries. +AC_SUBST(SO) +AC_SUBST(LDSHARED) +AC_SUBST(CCSHARED) +AC_SUBST(LINKFORSHARED) + +# SO is the extension of shared libraries `(including the dot!) +AC_MSG_CHECKING(SO) +if test -z "$SO" +then + case $host in + *-*-hp*) SO=.sl;; + *-*-darwin*) SO=.bundle;; + *-*-cygwin* | *-*-mingw*) SO=.dll;; + *) SO=.so;; + esac +fi +AC_MSG_RESULT($SO) + +# LDSHARED is the ld *command* used to create shared library +# -- "ld" on SunOS 4.x.x, "ld -G" on SunOS 5.x, "ld -shared" on IRIX 5 +# (Shared libraries in this instance are shared modules to be loaded into +# Python, as opposed to building Python itself as a shared library.) +AC_MSG_CHECKING(LDSHARED) +if test -z "$LDSHARED" +then + case $host in + *-*-aix*) LDSHARED="\$(srcdir)/ld_so_aix \$(CC)";; + *-*-cygwin* | *-*-mingw*) + if test "$GCC" = yes; then + LDSHARED="dllwrap --driver-name gcc --dlltool dlltool --export-all-symbols --as as --dllname \$(LIBPREFIX)\$(TARGET)\$(SO)" + else + if test "cl" = $CC ; then + # Microsoft Visual C++ (MSVC) + LDSHARED="$CC -nologo -LD" + else + # Unknown compiler try gcc approach + LDSHARED="$CC -shared" + fi + fi ;; + *-*-irix5*) LDSHARED="ld -shared";; + *-*-irix6*) LDSHARED="ld ${SGI_ABI} -shared -all";; + *-*-sunos4*) LDSHARED="ld";; + *-*-solaris*) LDSHARED="ld -G";; + *-*-hp*) LDSHARED="ld -b";; + *-*-osf*) LDSHARED="ld -shared -expect_unresolved \"*\"";; + *-sequent-sysv4) LDSHARED="ld -G";; + *-*-next*) + if test "$ns_dyld" + then LDSHARED='$(CC) $(LDFLAGS) -bundle -prebind' + else LDSHARED='$(CC) $(CFLAGS) -nostdlib -r'; + fi + if test "$with_next_framework" ; then + LDSHARED="$LDSHARED \$(LDLIBRARY)" + fi ;; + *-*-linux*) LDSHARED="gcc -shared";; + *-*-dgux*) LDSHARED="ld -G";; + *-*-freebsd3*) LDSHARED="gcc -shared";; + *-*-freebsd* | *-*-openbsd*) LDSHARED="ld -Bshareable";; + *-*-netbsd*) + if [[ "`$CC -dM -E - /dev/null` + if test "$PERL5DIR" != ""; then + dirs="$PERL5DIR $PERL5DIR/CORE" + PERL5EXT=none + for i in $dirs; do + if test -r $i/perl.h; then + AC_MSG_RESULT($i) + PERL5EXT="$i" + break; + fi + done + if test "$PERL5EXT" = none; then + PERL5EXT="$PERL5DIR/CORE" + AC_MSG_RESULT(could not locate perl.h...using $PERL5EXT) + fi + + AC_MSG_CHECKING(for Perl5 library) + PERL5LIB=`($PERL -e 'use Config; $_=$Config{libperl}; s/^lib//; s/$Config{_a}$//; print $_, "\n"') 2>/dev/null` + if test "$PERL5LIB" = "" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5LIB) + fi + AC_MSG_CHECKING(for Perl5 compiler options) + PERL5CCFLAGS=`($PERL -e 'use Config; print $Config{ccflags}, "\n"' | sed "s/-I/$ISYSTEM/") 2>/dev/null` + if test "$PERL5CCFLAGS" = "" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5CCFLAGS) + fi + else + AC_MSG_RESULT(unable to determine perl5 configuration) + PERL5EXT=$PERL5DIR + fi +else + AC_MSG_RESULT(could not figure out how to run perl5) +fi + +# Cygwin (Windows) needs the library for dynamic linking +case $host in +*-*-cygwin* | *-*-mingw*) PERL5DYNAMICLINKING="-L$PERL5EXT -l$PERL5LIB";; +*)PERL5DYNAMICLINKING="";; +esac + +AC_SUBST(PERL) +AC_SUBST(PERL5EXT) +AC_SUBST(PERL5DYNAMICLINKING) +AC_SUBST(PERL5LIB) +AC_SUBST(PERL5CCFLAGS) + +#---------------------------------------------------------------- +# Miscellaneous +#---------------------------------------------------------------- + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT + +dnl configure.in ends here diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/default8x16.h b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/default8x16.h new file mode 100755 index 0000000..252f411 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/default8x16.h @@ -0,0 +1,261 @@ +static unsigned char default8x16FontData[4096+1]={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00, +0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00, +0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, +0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00, +0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, +0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, +0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, +0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00, +0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00, +0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00, +0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, +0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, +0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, +0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, +0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00, +0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +static int default8x16FontMetaData[256*5+1]={ +0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,}; +static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData }; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.c b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.c new file mode 100755 index 0000000..2fc9e36 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.c @@ -0,0 +1,799 @@ +#include +#include +#include +#include + +#include "nacro.h" + +/* for visual grepping */ +typedef struct image_t { + int width,height; + char* buffer; +} image_t; + +/* this is a VNC connection */ +typedef struct private_resource_t { + int listen_port; + rfbScreenInfo* server; + rfbClient* client; + + uint32_t keysym; + rfbBool keydown; + + int x,y; + int buttons; + + char* text_client; + char* text_server; + + image_t* grep_image; + int x_origin,y_origin; + + enum { SLEEP,VISUALGREP,WAITFORUPDATE } state; + result_t result; +} private_resource_t; + +/* resource management */ + +#define MAX_RESOURCE_COUNT 20 + +static private_resource_t resource_pool[MAX_RESOURCE_COUNT]; +static int resource_count=0; + +static private_resource_t* get_resource(int resource) +{ + if(resource>=MAX_RESOURCE_COUNT || resource<0 || resource_pool[resource].client==0) + return NULL; + return resource_pool+resource; +} + +static private_resource_t* get_next_resource(void) +{ + if(resource_countclient=NULL; +} + +/* hooks */ + +static void got_key(rfbBool down,rfbKeySym keysym,rfbClientRec* cl) +{ + private_resource_t* res=(private_resource_t*)cl->screen->screenData; + + res->keydown=down; + res->keysym=keysym; + res->result|=RESULT_KEY; +} + +static void got_mouse(int buttons,int x,int y,rfbClientRec* cl) +{ + private_resource_t* res=(private_resource_t*)cl->screen->screenData; + + res->buttons=buttons; + res->x=x; + res->y=y; + res->result|=RESULT_MOUSE; +} + +static void got_text(char* str,int len,rfbClientRec* cl) +{ + private_resource_t* res=(private_resource_t*)cl->screen->screenData; + + if (res->text_client) + free(res->text_client); + res->text_client=strdup(str); + res->result|=RESULT_TEXT_CLIENT; +} + +static void got_text_from_server(rfbClient* cl, const char *str, int textlen) +{ + private_resource_t* res=(private_resource_t*)cl->clientData; + + if (res->text_server) + free(res->text_server); + res->text_server=strdup(str); + res->result|=RESULT_TEXT_SERVER; +} + +static rfbBool malloc_frame_buffer(rfbClient* cl) +{ + private_resource_t* res=(private_resource_t*)cl->clientData; + + if(!res->server) { + int w=cl->width,h=cl->height; + + res->client->frameBuffer=malloc(w*4*h); + + res->server=rfbGetScreen(NULL,NULL,w,h,8,3,4); + res->server->screenData=res; + res->server->port=res->listen_port; + res->server->frameBuffer=res->client->frameBuffer; + res->server->kbdAddEvent=got_key; + res->server->ptrAddEvent=got_mouse; + res->server->setXCutText=got_text; + rfbInitServer(res->server); + } else { + /* TODO: realloc if necessary */ + /* TODO: resolution change: send NewFBSize */ + /* TODO: if the origin is out of bounds, reset to 0 */ + } +} + +static bool_t do_visual_grep(private_resource_t* res,int x,int y,int w,int h) +{ + rfbClient* cl; + image_t* image; + int x_start,y_start,x_end=x+w-1,y_end=y+h-1; + bool_t found=0; + + if(res==0 || (cl=res->client)==0 || (image=res->grep_image)==0) + return 0; + + x_start=x-image->width; + y_start=y-image->height; + if(x_start<0) x_start=0; + if(y_start<0) y_start=0; + if(x_end+image->width>cl->width) x_end=cl->width-image->width; + if(y_end+image->height>cl->height) y_end=cl->height-image->height; + + /* find image and set x_origin,y_origin if found */ + for(y=y_start;yheight;j++) + for(i=0;matching && iwidth;i++) + if(memcmp(cl->frameBuffer+4*(x+i+cl->width*(y+j)),image->buffer+4*(i+image->width*j),3)) + matching=0; + if(matching) { + private_resource_t* res=(private_resource_t*)cl->clientData; + res->x_origin=x; + res->y_origin=y; + return -1; + } + } + return 0; +} + +static void got_frame_buffer(rfbClient* cl,int x,int y,int w,int h) +{ + private_resource_t* res=(private_resource_t*)cl->clientData; + + assert(res->server); + + if(res->grep_image && do_visual_grep(res,x,y,w,h)) { + res->result|=RESULT_FOUNDIMAGE; + } + if(res->server) { + rfbMarkRectAsModified(res->server,x,y,x+w,y+h); + } + + res->result|=RESULT_SCREEN; +} + +/* init/shutdown functions */ + +resource_t initvnc(const char* server,int server_port,int listen_port) +{ + private_resource_t* res=get_next_resource(); + int dummy=0; + + if(res==0) + return -1; + + /* remember for later */ + res->listen_port=listen_port; + + res->text_client = NULL; + res->text_server = NULL; + + res->client=rfbGetClient(8,3,4); + res->client->clientData=(void*)res; + res->client->GotFrameBufferUpdate=got_frame_buffer; + res->client->MallocFrameBuffer=malloc_frame_buffer; + res->client->GotXCutText=got_text_from_server; + res->client->serverHost=strdup(server); + res->client->serverPort=server_port; + res->client->appData.encodingsString="raw"; + if(!rfbInitClient(res->client,&dummy,NULL)) { + res->client=NULL; + return -1; + } + return res-resource_pool; +} + +void closevnc(resource_t resource) +{ + private_resource_t* res=get_resource(resource); + if(res==0) + return; + + if(res->server) + rfbScreenCleanup(res->server); + + assert(res->client); + + rfbClientCleanup(res->client); + + res->client=NULL; +} + +/* PNM (image) helpers */ + +bool_t savepnm(resource_t resource,const char* filename,int x1,int y1,int x2,int y2) +{ + private_resource_t* res=get_resource(resource); + int i,j,w,h; + uint32_t* buffer; + FILE* f; + + if(res==0 || res->client==0) + return 0; + assert(res->client->format.depth==24); + + w=res->client->width; + h=res->client->height; + buffer=(uint32_t*)res->client->frameBuffer; + + if(res==0 || x1>x2 || y1>y2 || x1<0 || x2>=w || y1<0 || y2>=h) + return FALSE; + + f=fopen(filename,"wb"); + + if(f==0) + return FALSE; + + fprintf(f,"P6\n%d %d\n255\n",1+x2-x1,1+y2-y1); + for(j=y1;j<=y2;j++) + for(i=x1;i<=x2;i++) { + fwrite(buffer+i+j*w,3,1,f); + } + if(fclose(f)) + return FALSE; + return TRUE; +} + +static image_t* loadpnm(const char* filename) +{ + FILE* f=fopen(filename,"rb"); + char buffer[1024]; + int i,j,w,h; + image_t* image; + + if(f==0) + return NULL; + + if(!fgets(buffer,1024,f) || strcmp("P6\n",buffer)) { + fclose(f); + return NULL; + } + + do { + fgets(buffer,1024,f); + if(feof(f)) { + fclose(f); + return NULL; + } + } while(buffer[0]=='#'); + + if( sscanf(buffer,"%d %d",&w,&h)!=2 + || !fgets(buffer,1024,f) || strcmp("255\n",buffer)) { + fclose(f); + return NULL; + } + + image=(image_t*)malloc(sizeof(image_t)); + image->width=w; + image->height=h; + image->buffer=malloc(w*4*h); + if(!image->buffer) { + fclose(f); + free(image); + return NULL; + } + + for(j=0;jbuffer+4*(i+w*j),3,1,f)!=1) { + fprintf(stderr,"Could not read 3 bytes at %d,%d\n",i,j); + fclose(f); + free(image->buffer); + free(image); + return NULL; + } + + fclose(f); + + return image; +} + +static void free_image(image_t* image) +{ + if(image->buffer) + free(image->buffer); + free(image); +} + +static void copy_line(rfbScreenInfo *dest, char *backup, + int x0, int y0, int x1, int y1, int color_offset) +{ + uint8_t *d = (uint8_t *)dest->frameBuffer, *s = (uint8_t *)backup; + int i; + int steps0 = x1 > x0 ? x1 - x0 : x0 - x1; + int steps1 = y1 > y0 ? y1 - y0 : y0 - y1; + + if (steps1 > steps0) + steps0 = steps1; + else if (steps0 == 0) + steps0 = 1; + + for (i = 0; i <= steps0; i++) { + int j, index = 4 * (x0 + i * (x1 - x0) / steps0 + + dest->width * (y0 + i * (y1 - y0) / steps0)); + for (j = 0; j < 4; j++) + d[index + j] = s[index + j] + color_offset; + } + + rfbMarkRectAsModified(dest, x0 - 5, y0 - 5, x1 + 1, y1 + 2); +} + +result_t displaypnm(resource_t resource, const char *filename, + coordinate_t x, coordinate_t y, bool_t border, + timeout_t timeout_in_seconds) +{ + private_resource_t* res = get_resource(resource); + image_t *image; + char* fake_frame_buffer; + char* backup; + int w, h, i, j, w2, h2; + result_t result; + + if (res == NULL || res->server == NULL || + (image = loadpnm(filename)) == NULL) + return 0; + + w = res->server->width; + h = res->server->height; + fake_frame_buffer = malloc(w * 4 * h); + if(!fake_frame_buffer) + return 0; + memcpy(fake_frame_buffer, res->server->frameBuffer, w * 4 * h); + + backup = res->server->frameBuffer; + res->server->frameBuffer = fake_frame_buffer; + + w2 = image->width; + if (x + w2 > w) + w2 = w - x; + h2 = image->height; + if (y + h2 > h) + h2 = h - y; + for (j = 0; j < h2; j++) + memcpy(fake_frame_buffer + 4 * (x + (y + j) * w), + image->buffer + j * 4 * image->width, 4 * w2); + free(image); + if (border) { + copy_line(res->server, backup, x, y, x + w2, y, 0x80); + copy_line(res->server, backup, x, y, x, y + h2, 0x80); + copy_line(res->server, backup, x + w2, y, x + w2, y + h2, 0x80); + copy_line(res->server, backup, x, y + h2, x + w2, y + h2, 0x80); + } + rfbMarkRectAsModified(res->server, + x - 1, y - 1, x + w2 + 1, y + h2 + 1); + + result = waitforinput(resource, timeout_in_seconds); + + res->server->frameBuffer=backup; + free(fake_frame_buffer); + rfbMarkRectAsModified(res->server, + x - 1, y - 1, x + w2 + 1, y + h2 + 1); + + return result; +} + +/* process() and friends */ + +/* this function returns only if res->result in return_mask */ +static result_t private_process(resource_t resource,timeout_t timeout_in_seconds,result_t return_mask) +{ + private_resource_t* res=get_resource(resource); + fd_set fds; + struct timeval tv,tv_start,tv_end; + unsigned long timeout=(unsigned long)(timeout_in_seconds*1000000UL); + int count,max_fd; + + if(res==0) + return 0; + + assert(res->client); + + gettimeofday(&tv_start,NULL); + res->result=0; + + do { + unsigned long timeout_done; + + if(res->server) { + rfbBool loop; + do { + loop=rfbProcessEvents(res->server,res->server->deferUpdateTime); + } while(loop && (res->result&return_mask)==0 + && rfbIsActive(res->server)); + + if(!rfbIsActive(res->server)) + return RESULT_SHUTDOWN; + + if((res->result&return_mask)!=0) + return res->result; + + memcpy((char*)&fds,(const char*)&(res->server->allFds),sizeof(fd_set)); + max_fd=res->server->maxFd; + } else { + FD_ZERO(&fds); + max_fd=0; + } + FD_SET(res->client->sock,&fds); + if(res->client->sock>max_fd) + max_fd=res->client->sock; + + gettimeofday(&tv_end,NULL); + timeout_done=tv_end.tv_usec-tv_start.tv_usec+ + 1000000L*(tv_end.tv_sec-tv_start.tv_sec); + if(timeout_done>=timeout) + return RESULT_TIMEOUT; + + tv.tv_usec=((timeout-timeout_done)%1000000); + tv.tv_sec=(timeout-timeout_done)/1000000; + + count=select(max_fd+1,&fds,NULL,NULL,&tv); + if(count<0) + return 0; + + if(count>0) { + if(FD_ISSET(res->client->sock,&fds)) { + if(!HandleRFBServerMessage(res->client)) { + closevnc(resource); + return 0; + } + if((res->result&return_mask)!=0) + return res->result; + } + } else { + res->result|=RESULT_TIMEOUT; + return res->result; + } + } while(1); + + return RESULT_TIMEOUT; +} + +result_t process(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,RESULT_TIMEOUT); +} + +result_t waitforanything(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,-1); +} + +result_t waitforinput(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,RESULT_KEY|RESULT_MOUSE|RESULT_TIMEOUT); +} + +result_t waitforupdate(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,RESULT_SCREEN|RESULT_TIMEOUT); +} + +result_t visualgrep(resource_t resource,const char* filename,timeout_t timeout) +{ + private_resource_t* res=get_resource(resource); + image_t* image; + result_t result; + + if(res==0 || res->client==0) + return 0; + + /* load filename and set res->grep_image to this image */ + image=loadpnm(filename); + if(image==0) + return 0; + if(res->grep_image) + free_image(res->grep_image); + res->grep_image=image; + + if(do_visual_grep(res,0,0,res->client->width,res->client->height)) + return RESULT_FOUNDIMAGE; + + result=private_process(resource,timeout,RESULT_FOUNDIMAGE|RESULT_TIMEOUT); + + /* free image */ + if(res->grep_image) { + free_image(res->grep_image); + res->grep_image=NULL; + } + + return result; +} + +/* auxiliary function for alert */ + +#include "default8x16.h" + +static void center_text(rfbScreenInfo* screen,const char* message,int* x,int* y,int* w,int* h) +{ + rfbFontData* font=&default8x16Font; + const char* pointer; + int j,x1,y1,x2,y2,line_count=0; + if(message==0 || screen==0) + return; + rfbWholeFontBBox(font,&x1,&y1,&x2,&y2); + for(line_count=1,pointer=message;*pointer;pointer++) + if(*pointer=='\n') + line_count++; + + *h=(y2-y1)*line_count; + assert(*h>0); + + if(*h>screen->height) + *h=screen->height; + + *x=0; *w=screen->width; *y=(screen->height-*h)/2; + + rfbFillRect(screen,*x,*y,*x+*w,*y+*h,0xff0000); + + for(pointer=message,j=0;jscreen->width) + width=screen->width; + + x_cur=(screen->width-width)/2; + for(;pointer!=eol;pointer++) + x_cur+=rfbDrawCharWithClip(screen,font, + x_cur,y_cur,*pointer, + 0,0,screen->width,screen->height, + 0xffffffff,0xffffffff); + pointer++; + } + rfbMarkRectAsModified(screen,*x,*y,*x+*w,*y+*h); +} + +/* this is an overlay which is shown for a certain time */ + +result_t alert(resource_t resource,const char* message,timeout_t timeout) +{ + private_resource_t* res=get_resource(resource); + char* fake_frame_buffer; + char* backup; + int x,y,w,h; + result_t result; + + if(res == NULL || res->server==NULL) + return -1; + + w=res->server->width; + h=res->server->height; + + fake_frame_buffer=malloc(w*4*h); + if(!fake_frame_buffer) + return -1; + memcpy(fake_frame_buffer,res->server->frameBuffer,w*4*h); + + backup=res->server->frameBuffer; + res->server->frameBuffer=fake_frame_buffer; + center_text(res->server,message,&x,&y,&w,&h); + fprintf(stderr,"%s\n",message); + + result=waitforinput(resource,timeout); + + res->server->frameBuffer=backup; + free(fake_frame_buffer); + rfbMarkRectAsModified(res->server,x,y,x+w,y+h); + + return result; +} +/* inspect last events */ + +keysym_t getkeysym(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->keysym; +} + +bool_t getkeydown(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->keydown; +} + +coordinate_t getx(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->x; +} + +coordinate_t gety(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->y; +} + +buttons_t getbuttons(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->buttons; +} + +const char *gettext_client(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->text_client; +} + +result_t rubberband(resource_t resource, coordinate_t x0, coordinate_t y0) +{ + private_resource_t* res=get_resource(resource); + char* fake_frame_buffer; + char* backup; + int w, h, x, y; + + if(res == NULL || res->server==NULL) + return -1; + + x = res->x; + y = res->y; + w = res->server->width; + h = res->server->height; + fake_frame_buffer = malloc(w * 4 * h); + if(!fake_frame_buffer) + return 0; + memcpy(fake_frame_buffer, res->server->frameBuffer, w * 4 * h); + + backup = res->server->frameBuffer; + res->server->frameBuffer = fake_frame_buffer; + + while (res->buttons) { + result_t r = waitforinput(resource, 1000000L); + if (x == res->x && y == res->y) + continue; + copy_line(res->server, backup, x0, y0, x, y0, 0); + copy_line(res->server, backup, x0, y0, x0, y, 0); + copy_line(res->server, backup, x, y0, x, y, 0); + copy_line(res->server, backup, x0, y, x, y, 0); + x = res->x; + y = res->y; + copy_line(res->server, backup, x0, y0, x, y0, 0x80); + copy_line(res->server, backup, x0, y0, x0, y, 0x80); + copy_line(res->server, backup, x, y0, x, y, 0x80); + copy_line(res->server, backup, x0, y, x, y, 0x80); + } + + copy_line(res->server, backup, x0, y0, x, y0, 0); + copy_line(res->server, backup, x0, y0, x0, y, 0); + copy_line(res->server, backup, x, y0, x, y, 0); + copy_line(res->server, backup, x0, y, x, y, 0); + + res->server->frameBuffer=backup; + free(fake_frame_buffer); + + return RESULT_MOUSE; +} + +const char *gettext_server(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->text_server; +} + +/* send events to the server */ + +bool_t sendkey(resource_t res,keysym_t keysym,bool_t keydown) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + return SendKeyEvent(r->client,keysym,keydown); +} + +bool_t sendascii(resource_t res,const char *string) +{ + timeout_t delay = 0.1; + private_resource_t* r=get_resource(res); + int i; + if(r==NULL) + return 0; + while (*string) { + int keysym = *string; + int need_shift = 0; + + if (keysym >= 8 && keysym < ' ') + keysym += 0xff00; + else if (keysym >= 'A' && keysym <= 'Z') + need_shift = 1; + else if (keysym > '~') { + fprintf(stderr, "String contains non-ASCII " + "character 0x%02x\n", *string); + return FALSE; + } + + if (need_shift) { + if (!SendKeyEvent(r->client,0xffe1,1)) + return FALSE; + waitforinput(r,delay); + } + for (i = 1; i >= 0; i--) { + if (!SendKeyEvent(r->client,keysym,i)) + return FALSE; + waitforinput(r,delay); + } + if (need_shift) { + if (!SendKeyEvent(r->client,0xffe1,0)) + return FALSE; + waitforinput(r,delay); + } + string++; + } + return TRUE; +} + +bool_t sendmouse(resource_t res,coordinate_t x,coordinate_t y,buttons_t buttons) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + return SendPointerEvent(r->client,x,y,buttons); +} + +bool_t sendtext(resource_t res, const char *string) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + return SendClientCutText(r->client, (char *)string, (int)strlen(string)); +} + +bool_t sendtext_to_server(resource_t res, const char *string) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + rfbSendServerCutText(r->server, (char *)string, (int)strlen(string)); + return 1; +} + +/* for visual grepping */ + +coordinate_t getxorigin(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->x_origin; +} + +coordinate_t getyorigin(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->y_origin; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.h b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.h new file mode 100755 index 0000000..abd0067 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.h @@ -0,0 +1,120 @@ +#ifndef NACRO_H +#define NACRO_H + +#ifdef SWIG +%module nacro + +%{ + +/* types used */ + +/* 0=false, every other value=true */ +typedef int bool_t; + +/* a keysym: identical with ASCII for values between 0-127 */ +typedef int keysym_t; + +/* this can be negative, because of a new origin set via visual grep */ +typedef int coordinate_t; + +/* left button is 1<<0, middle button is 1<<1, right button is 1<<2 */ +typedef unsigned char buttons_t; + +/* this is sort of a "file descriptor" for the proxy */ +typedef int resource_t; + +/* the timeout, specified in microseconds, for process() and friends */ +typedef double timeout_t; + +/* the return values of process() and friends */ +typedef int result_t; +/* +%constant int RESULT_TIMEOUT=1; +%constant int RESULT_KEY=2; +%constant int RESULT_MOUSE=4; +%constant int RESULT_TEXT_CLIENT=8; +%constant int RESULT_TEXT_CLIENT=16; +%constant int RESULT_SCREEN=32; +%constant int RESULT_FOUNDIMAGE=64; +%constant int RESULT_SHUTDOWN=128; +*/ + +%} + +#endif // SWIG + +typedef int bool_t; +typedef int keysym_t; +typedef int coordinate_t; +typedef unsigned char buttons_t; +typedef int resource_t; +typedef double timeout_t; +typedef int result_t; +#define RESULT_TIMEOUT 1 +#define RESULT_KEY 2 +#define RESULT_MOUSE 4 +#define RESULT_TEXT_CLIENT 8 +#define RESULT_TEXT_SERVER 16 +#define RESULT_SCREEN 32 +#define RESULT_FOUNDIMAGE 64 +#define RESULT_SHUTDOWN 128 + +/* init/shutdown */ + +resource_t initvnc(const char* server,int serverPort,int listenPort); +void closevnc(resource_t res); + +/* run the event loop for a while: process() and friends: + * process() returns only on timeout, + * waitforanything returns on any event (input, output or timeout), + * waitforupdate() returns only on timeout or screen update, + * waitforinput() returns only on timeout or user input, + * visualgrep() returns only on timeout or if the specified PNM was found + * (in that case, x_origin and y_origin are set to the upper left + * corner of the matched image). */ + +result_t process(resource_t res,timeout_t seconds); +result_t waitforanything(resource_t res,timeout_t seconds); +result_t waitforupdate(resource_t res,timeout_t seconds); +result_t waitforinput(resource_t res,timeout_t seconds); +result_t visualgrep(resource_t res,const char* filename,timeout_t seconds); + +/* inspect last events */ + +keysym_t getkeysym(resource_t res); +bool_t getkeydown(resource_t res); + +coordinate_t getx(resource_t res); +coordinate_t gety(resource_t res); +buttons_t getbuttons(resource_t res); + +const char *gettext_client(resource_t res); +const char *gettext_server(resource_t res); + +/* send events to the server */ + +bool_t sendkey(resource_t res,keysym_t keysym,bool_t keydown); +bool_t sendascii(resource_t res,const char *string); +bool_t sendmouse(resource_t res,coordinate_t x,coordinate_t y,buttons_t buttons); +bool_t sendtext(resource_t res, const char *string); +bool_t sendtext_to_server(resource_t res, const char *string); + +/* for visual grepping */ + +coordinate_t getxorigin(resource_t res); +coordinate_t getyorigin(resource_t res); + +bool_t savepnm(resource_t res,const char* filename,coordinate_t x1, coordinate_t y1, coordinate_t x2, coordinate_t y2); + +result_t displaypnm(resource_t res, const char *filename, coordinate_t x, coordinate_t y, bool_t border, timeout_t timeout); + +/* this displays an overlay which is shown for a certain time */ + +result_t alert(resource_t res,const char* message,timeout_t timeout); + +/* display a rectangular rubber band between (x0, y0) and the current + mouse pointer, as long as a button us pressed. */ + +result_t rubberband(resource_t res, coordinate_t x0, coordinate_t y0); + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/recorder.pl b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/recorder.pl new file mode 100755 index 0000000..01ab3f2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/recorder.pl @@ -0,0 +1,282 @@ +#!/usr/bin/perl + +use Getopt::Long; +use nacro; + +$output="my_script"; +$server="localhost"; +$port=5900; +$listen_port=5923; +$timing=0; +$symbolic=0; +$compact=0; +$compact_dragging=0; + +if(!GetOptions( + "script:s" => \$output, + "listen:i" => \$listen_port, + "timing" => \$timing, + "symbolic" => \$symbolic, + "compact" => \$compact, + "compact-dragging" => \$compact_dragging, +) || $#ARGV!=0) { + print STDERR "Usage: $ARGV0 [--script output_name] [--listen listen_port] [--timing]\n\t[--symbolic] [--compact] [--compact-dragging] server[:port]\n"; + exit 2; +} + +$output=~s/\.pl$//; + +if ($timing) { + eval 'use Time::HiRes'; + $timing=0 if $@; + $starttime=-1; +} + +if ($symbolic) { + eval 'use X11::Keysyms qw(%Keysyms)'; + $symbolic=0 if $@; + %sym_name = reverse %Keysyms; +} + +$server=$ARGV[0]; + +if($server=~/^(.*):(\d+)$/) { + $server=$1; + $port=$2; + if($2<100) { + $port+=5900; + } +} + +if($listen_port<100) { + $listen_port+=5900; +} + +# do not overwrite script + +if(stat("$output.pl")) { + print STDERR "Will not overwrite $output.pl\n"; + exit 2; +} + +# start connection +$vnc=nacro::initvnc($server,$port,$listen_port); + +if($vnc<0) { + print STDERR "Could not initialize $server:$port\n"; + exit 1; +} + +open OUT, ">$output.pl"; +print OUT "#!/usr/bin/perl\n"; +print OUT "\n"; +if ($symbolic) { + print OUT "use X11::Keysyms qw(\%sym);\n"; +} +print OUT "use nacro;\n"; +print OUT "\n"; +print OUT "\$x_origin=0; \$y_origin=0;\n"; +print OUT "\$vnc=nacro::initvnc(\"$server\",$port,$listen_port);\n"; + +$mode="passthru"; +$image_counter=1; +$magickey=0; +$x_origin=0; $y_origin=0; + +sub writetiming () { + if ($timing) { + $now=Time::HiRes::time(); + if ($starttime>0) { + print OUT "nacro::process(\$vnc," . ($now - $starttime) . ");\n"; + } + $starttime=$now; + } +} + +$last_button = -1; + +sub handle_mouse { + my $x = shift; + my $y = shift; + my $buttons = shift; + if(nacro::sendmouse($vnc,$x,$y,$buttons)) { + $x-=$x_origin; $y-=$y_origin; + writetiming(); + print OUT "nacro::sendmouse(\$vnc,\$x_origin" + . ($x>=0?"+":"")."$x,\$y_origin" + . ($y>=0?"+":"")."$y,$buttons);\n"; + } +} + +sub toggle_text { + my $text = shift; + if ($text eq "Timing") { + return $text . " is " . ($timing ? "on" : "off"); + } elsif ($text eq "Key presses") { + return $text . " are recorded " . ($symbolic ? "symbolically" + : "numerically"); + } elsif ($text eq "Mouse moves") { + return $text . " are recorded " . ($compact ? "compacted" + : "verbosely"); + } elsif ($text eq "Mouse drags") { + return $text . " are recorded " . ($compact ? "compacted" + : "verbosely"); + } + return $text . ": "; +} + +$menu_message = "VisualNaCro: press 'q' to quit,\n" + . "'i' to display current settings,\n" + . "'c', 'r' to toggle compact mouse movements or drags,\n" + . "'d' to display current reference image,\n" + . "or mark reference rectangle by dragging"; + +while(1) { + $result=nacro::waitforinput($vnc,999999); + if($result==0) { + # server went away + close OUT; + exit 0; + } + + if($mode eq "passthru") { + if($result&$nacro::RESULT_KEY) { + $keysym=nacro::getkeysym($vnc); + $keydown=nacro::getkeydown($vnc); + if(nacro::sendkey($vnc,$keysym,$keydown)) { + writetiming(); + if ($symbolic and exists $sym_name{$keysym}) { + print OUT 'nacro::sendkey($vnc,$sym{'.$sym_name{$keysym}."},$keydown);\n"; + } else { + print OUT "nacro::sendkey(\$vnc,$keysym,$keydown);\n"; + } + } + if($keysym==0xffe3 || $keysym==0xffe4) { + if (!$keydown) { + # Control pressed + $magickey++; + if ($magickey > 1) { + $magickey = 0; + $mode = "menu"; + nacro::alert($vnc, + $menu_message, 10); + } + } + } else { + $magickey=0; + } + } + if($result&$nacro::RESULT_MOUSE) { + $x=nacro::getx($vnc); + $y=nacro::gety($vnc); + $buttons=nacro::getbuttons($vnc); + if ($buttons != $last_buttons) { + if (!$buttons && $compact_dragging) { + handle_mouse($x, $y, $last_buttons); + } + $last_buttons = $buttons; + } else { + if (($buttons && $compact_dragging) || + (!$buttons && $compact)) { + next; + } + } + handle_mouse($x, $y, $buttons); + } + if ($result & $nacro::RESULT_TEXT_CLIENT) { + my $text = nacro::gettext_client($vnc); + if (nacro::sendtext($vnc,$text)) { + writetiming(); + print OUT "nacro::sendtext(\$vnc, q(\Q$text\E));\n"; + print "got text from client: $text\n"; + } + } + if ($result & $nacro::RESULT_TEXT_SERVER) { + my $text = nacro::gettext_server($vnc); + if (nacro::sendtext_to_server($vnc,$text)) { + writetiming(); + print OUT "nacro::sendtext_to_server(\$vnc, q(\Q$text\E));\n"; + print "got text from server: $text\n"; + } + } + } else { + if($result&$nacro::RESULT_KEY) { + $keysym=nacro::getkeysym($vnc); + $keydown=nacro::getkeydown($vnc); + if($keysym==ord('q')) { + # shutdown + close OUT; + nacro::closevnc($vnc); + exit 0; + } elsif ($keysym == ord('d')) { + $pnm=$output.($image_counter - 1).".pnm"; + $res = nacro::displaypnm($vnc, $pnm, + $x_origin, $y_origin, 1, 10); + #0, 0, 1, 10); + if ($res == 0) { + nacro::alert($vnc, "Error displaying " + . $pnm, 10); + } + } elsif ($keysym == ord('i')) { + nacro::alert($vnc, "Current settings:\n" + . "\n" + . "Script: $output\n" + . "Server: $server\n" + . "Listening on port: $port\n" + . toggle_text("Timing") . "\n" + . toggle_text("Key presses") . "\n" + . toggle_text("Mouse moves") . "\n" + . toggle_text("Mouse drags"), 10); + } elsif ($keysym == ord('c')) { + $compact = !$compact; + nacro::alert($vnc, + toggle_text("Mouse moves"), 10); + } elsif ($keysym == ord('r')) { + $compact_dragging = !$compact_dragging; + nacro::alert($vnc, + toggle_text("Mouse drags"), 10); + } else { + nacro::alert($vnc,"Unknown key",10); + } + $mode="passthru"; + } + if($result&$nacro::RESULT_MOUSE) { + $x=nacro::getx($vnc); + $y=nacro::gety($vnc); + $buttons=nacro::getbuttons($vnc); + if(($buttons&1)==1) { + print STDERR "start draggin: $x $y\n"; + $start_x=$x; + $start_y=$y; + nacro::rubberband($vnc, $x, $y); + $x=nacro::getx($vnc); + $y=nacro::gety($vnc); + if($start_x==$x && $start_y==$y) { + # reset + print OUT "\$x_origin=0; \$y_origin=0;\n"; + } else { + if($start_x>$x) { + $dummy=$x; $x=$start_x; $start_x=$dummy; + } + if($start_y>$y) { + $dummy=$y; $y=$start_y; $start_y=$dummy; + } + $pnm=$output.$image_counter.".pnm"; + $image_counter++; + if(!nacro::savepnm($vnc,$pnm,$start_x,$start_y,$x,$y)) { + nacro::alert($vnc,"Saving $pnm failed!",10); + } else { + $x_origin=$start_x; + $y_origin=$start_y; + nacro::alert($vnc,"Got new origin: $x_origin $y_origin",10); + print OUT "if(nacro::visualgrep(\$vnc,\"$pnm\",999999)) {\n" + . "\t\$x_origin=nacro::getxorigin(\$vnc);\n" + . "\t\$y_origin=nacro::getyorigin(\$vnc);\n}\n"; + } + } + $mode="passthru"; + } + } + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/acinclude.m4 b/droidvncgrab/vnc/libvncserver-kanaka/acinclude.m4 new file mode 100755 index 0000000..c69a38d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/acinclude.m4 @@ -0,0 +1,7001 @@ +AH_TEMPLATE(socklen_t, [The type for socklen]) +AC_DEFUN([AC_TYPE_SOCKLEN_T], +[AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t, +[ + AC_TRY_COMPILE( + [#include + #include ], + [socklen_t len = 42; return 0;], + ac_cv_type_socklen_t=yes, + ac_cv_type_socklen_t=no) +]) + if test $ac_cv_type_socklen_t != yes; then + AC_DEFINE(socklen_t, int) + fi +]) + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_compile_check_sizeof.html +dnl +AC_DEFUN([AC_COMPILE_CHECK_SIZEOF], +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl +dnl The cache variable name. +define(<>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $1) +AC_CACHE_VAL(AC_CV_NAME, +[for ac_size in 4 8 1 2 16 $2 ; do # List sizes in rough order of prevalence. + AC_TRY_COMPILE([#include "confdefs.h" +#include +$2 +], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size) + if test x$AC_CV_NAME != x ; then break; fi +done +]) +if test x$AC_CV_NAME = x ; then + AC_MSG_ERROR([cannot determine a size for $1]) +fi +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1]) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_create_stdint_h.html +dnl +AC_DEFUN([AC_CREATE_STDINT_H], +[# ------ AC CREATE STDINT H ------------------------------------- +AC_MSG_CHECKING([for stdint-types....]) +ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` +if test "$ac_stdint_h" = "stdint.h" ; then + AC_MSG_RESULT("(are you sure you want them in ./stdint.h?)") +elif test "$ac_stdint_h" = "inttypes.h" ; then + AC_MSG_RESULT("(are you sure you want them in ./inttypes.h?)") +else + AC_MSG_RESULT("(putting them into $ac_stdint_h)") +fi + +inttype_headers=`echo inttypes.h sys/inttypes.h sys/inttypes.h $2 \ +| sed -e 's/,/ /g'` + + ac_cv_header_stdint_x="no-file" + ac_cv_header_stdint_o="no-file" + ac_cv_header_stdint_u="no-file" + for i in stdint.h $inttype_headers ; do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uint64_t + _AC_CHECK_TYPE_NEW(uintptr_t,[ac_cv_header_stdint_x=$i],dnl + continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="(uint64_t too)"],[and64=""],[#include<$i>]) + AC_MSG_RESULT(... seen our uintptr_t in $i $and64) + break; + done + if test "$ac_cv_header_stdint_x" = "no-file" ; then + for i in stdint.h $inttype_headers ; do + unset ac_cv_type_uint32_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],dnl + continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="(uint64_t too)"],[and64=""],[#include<$i>]) + AC_MSG_RESULT(... seen our uint32_t in $i $and64) + break; + done + if test "$ac_cv_header_stdint_o" = "no-file" ; then + for i in sys/types.h $inttype_headers ; do + unset ac_cv_type_u_int32_t + unset ac_cv_type_u_int64_t + AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],dnl + continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="(u_int64_t too)"],[and64=""],[#include<$i>]) + AC_MSG_RESULT(... seen our u_int32_t in $i $and64) + break; + done + fi + fi + +# ----------------- DONE inttypes.h checks MAYBE C basic types -------- + +if test "$ac_cv_header_stdint_x" = "no-file" ; then + AC_COMPILE_CHECK_SIZEOF(char) + AC_COMPILE_CHECK_SIZEOF(short) + AC_COMPILE_CHECK_SIZEOF(int) + AC_COMPILE_CHECK_SIZEOF(long) + AC_COMPILE_CHECK_SIZEOF(void*) + ac_cv_header_stdint_test="yes" +else + ac_cv_header_stdint_test="no" +fi + +# ----------------- DONE inttypes.h checks START header ------------- +_ac_stdint_h=AS_TR_CPP(_$ac_stdint_h) +AC_MSG_RESULT(creating $ac_stdint_h : $_ac_stdint_h) +echo "#ifndef" $_ac_stdint_h >$ac_stdint_h +echo "#define" $_ac_stdint_h "1" >>$ac_stdint_h +echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint_h +echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint_h +if test "$GCC" = "yes" ; then + echo "/* generated using a gnu compiler version" `$CC --version` "*/" \ + >>$ac_stdint_h +else + echo "/* generated using $CC */" >>$ac_stdint_h +fi +echo "" >>$ac_stdint_h + +if test "$ac_cv_header_stdint_x" != "no-file" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_x" +elif test "$ac_cv_header_stdint_o" != "no-file" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_o" +elif test "$ac_cv_header_stdint_u" != "no-file" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_u" +else + ac_cv_header_stdint="stddef.h" +fi + +# ----------------- See if int_least and int_fast types are present +unset ac_cv_type_int_least32_t +unset ac_cv_type_int_fast32_t +AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) +AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) + +if test "$ac_cv_header_stdint" != "stddef.h" ; then +if test "$ac_cv_header_stdint" != "stdint.h" ; then +AC_MSG_RESULT(..adding include stddef.h) + echo "#include " >>$ac_stdint_h +fi ; fi +AC_MSG_RESULT(..adding include $ac_cv_header_stdint) + echo "#include <$ac_cv_header_stdint>" >>$ac_stdint_h +echo "" >>$ac_stdint_h + +# ----------------- DONE header START basic int types ------------- +if test "$ac_cv_header_stdint_x" = "no-file" ; then + AC_MSG_RESULT(... need to look at C basic types) +dnl ac_cv_header_stdint_test="yes" # moved up before creating the file +else + AC_MSG_RESULT(... seen good stdint.h inttypes) +dnl ac_cv_header_stdint_test="no" # moved up before creating the file +fi + +if test "$ac_cv_header_stdint_u" != "no-file" ; then + AC_MSG_RESULT(... seen bsd/sysv typedefs) + cat >>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h < 199901L + +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#elif !defined __STRICT_ANSI__ +#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ + +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#endif + +#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ +dnl /* note: all ELF-systems seem to have loff-support which needs 64-bit */ + +#if !defined _NO_LONGLONG +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif +#endif + +#elif defined __alpha || (defined __mips && defined _ABIN32) + +#if !defined _NO_LONGLONG +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef long int64_t; +typedef unsigned long uint64_t; +#endif +#endif + /* compiler/cpu type ... or just ISO C99 */ +#endif +#endif +EOF + +# plus a default 64-bit for systems that are likely to be 64-bit ready + case "$ac_cv_sizeof_x:$ac_cv_sizeof_voidp:$ac_cv_sizeof_long" in + 1:2:8:8) AC_MSG_RESULT(..adding uint64_t default, normal 64-bit system) +cat >>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <@/_/g"` +_PKG=`echo ifelse($2, , $PACKAGE, $2)` +_LOW=`echo _$_PKG | sed -e "y:m4_cr_LETTERS-:m4_cr_letters[]_:"` +_UPP=`echo $_PKG | sed -e "y:m4_cr_letters-:m4_cr_LETTERS[]_:" -e "/^@<:@m4_cr_digits@:>@/s/^/_/"` +_INP=`echo ifelse($3, , _, $3)` +if test "$ac_prefix_conf_INP" = "_"; then + for ac_file in : $CONFIG_HEADERS; do test "_$ac_file" = _: && continue + test -f "$ac_prefix_conf_INP" && continue + case $ac_file in + *.h) test -f $ac_file && _INP=$ac_file ;; + *) + esac + done +fi +if test "$_INP" = "_"; then + case "$_OUT" in + */*) _INP=`basename "$_OUT"` + ;; + *-*) _INP=`echo "$_OUT" | sed -e "s/@<:@_symbol@:>@*-//"` + ;; + *) _INP=config.h + ;; + esac +fi +if test -z "$_PKG" ; then + AC_MSG_ERROR([no prefix for _PREFIX_PKG_CONFIG_H]) +else + if test ! -f "$_INP" ; then if test -f "$srcdir/$_INP" ; then + _INP="$srcdir/$_INP" + fi fi + AC_MSG_NOTICE(creating $_OUT - prefix $_UPP for $_INP defines) + if test -f $_INP ; then + echo "s/@%:@undef *\\(@<:@m4_cr_LETTERS[]_@:>@\\)/@%:@undef $_UPP""_\\1/" > _script + # no! these are things like socklen_t, const, vfork + # echo "s/@%:@undef *\\(@<:@m4_cr_letters@:>@\\)/@%:@undef $_LOW""_\\1/" >> _script + echo "s/@%:@def[]ine *\\(@<:@m4_cr_LETTERS[]_@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_UPP""_\\1 \\" >> _script + echo "@%:@def[]ine $_UPP""_\\1 \\2 \\" >> _script + echo "@%:@endif/" >>_script + # no! these are things like socklen_t, const, vfork + # echo "s/@%:@def[]ine *\\(@<:@m4_cr_letters@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_LOW""_\\1 \\" >> _script + # echo "@%:@define $_LOW""_\\1 \\2 \\" >> _script + # echo "@%:@endif/" >> _script + # now executing _script on _DEF input to create _OUT output file + echo "@%:@ifndef $_DEF" >$tmp/pconfig.h + echo "@%:@def[]ine $_DEF 1" >>$tmp/pconfig.h + echo ' ' >>$tmp/pconfig.h + echo /'*' $_OUT. Generated automatically at end of configure. '*'/ >>$tmp/pconfig.h + + sed -f _script $_INP >>$tmp/pconfig.h + echo ' ' >>$tmp/pconfig.h + echo '/* once:' $_DEF '*/' >>$tmp/pconfig.h + echo "@%:@endif" >>$tmp/pconfig.h + if cmp -s $_OUT $tmp/pconfig.h 2>/dev/null; then + AC_MSG_NOTICE([$_OUT is unchanged]) + else + ac_dir=`AS_DIRNAME(["$_OUT"])` + AS_MKDIR_P(["$ac_dir"]) + rm -f "$_OUT" + mv $tmp/pconfig.h "$_OUT" + fi + cp _script _configs.sed + else + AC_MSG_ERROR([input file $_INP does not exist - skip generating $_OUT]) + fi + rm -f conftest.* +fi +m4_popdef([_symbol])dnl +m4_popdef([_script])dnl +AS_VAR_POPDEF([_INP])dnl +AS_VAR_POPDEF([_UPP])dnl +AS_VAR_POPDEF([_LOW])dnl +AS_VAR_POPDEF([_PKG])dnl +AS_VAR_POPDEF([_DEF])dnl +AS_VAR_POPDEF([_OUT])dnl +],[PACKAGE="$PACKAGE"])]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 48 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# 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; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/autogen.sh b/droidvncgrab/vnc/libvncserver-kanaka/autogen.sh new file mode 100755 index 0000000..2e809c6 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/autogen.sh @@ -0,0 +1,57 @@ +#! /bin/sh +# Run this to generate all the initial makefiles, etc. + +set -e + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +AUTOMAKE=automake-1.4 +ACLOCAL=aclocal-1.4 + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + AUTOMAKE=automake + ACLOCAL=aclocal +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile libvncserver." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile libvncserver." + echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +(test -f $srcdir/rfb/rfb.h) || { + echo "You must run this script in the top-level libvncserver directory" + exit 1 +} + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +$ACLOCAL $ACLOCAL_FLAGS +autoheader +$AUTOMAKE --add-missing --copy +autoconf + +echo "Running ./configure --enable-maintainer-mode" "$@" +$srcdir/configure --enable-maintainer-mode "$@" + +echo "Now type 'make' to compile libvncserver." diff --git a/droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl b/droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl new file mode 100755 index 0000000..fc43712 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl @@ -0,0 +1,60 @@ +#!/usr/bin/perl + +@encodings=(); +for($i=0;$i<256*5;$i++) { + $encodings[$i]="0"; +} + +$out=""; +$counter=0; +$fontname="default"; + +$i=0; +$searchfor=""; +$nullx="0x"; + +while(<>) { + if(/^FONT (.*)$/) { + $fontname=$1; + $fontname=~y/\"//d; + } elsif(/^ENCODING (.*)$/) { + $glyphindex=$1; + $searchfor="BBX"; + $dwidth=0; + } elsif(/^DWIDTH (.*) (.*)/) { + $dwidth=$1; + } elsif(/^BBX (.*) (.*) (.*) (.*)$/) { + ($width,$height,$x,$y)=($1,$2,$3,$4); + @encodings[$glyphindex*5..($glyphindex*5+4)]=($counter,$width,$height,$x,$y); + if($dwidth != 0) { + $encodings[$glyphindex*5+1]=$dwidth; + } else { + $dwidth=$width; + } + $searchfor="BITMAP"; + } elsif(/^BITMAP/) { + $i=1; + } elsif($i>0) { + if($i>$height) { + $i=0; + $out.=" /* $glyphindex */\n"; + } else { + if(int(($dwidth+7)/8) > int(($width+7)/8)) { + $_ .= "00"x(int(($dwidth+7)/8)-int(($width+7)/8)); + } + $_=substr($_,0,(int(($dwidth+7)/8)*2)); + $counter+=(int(($dwidth+7)/8)); + s/(..)/$nullx$1,/g; + $out.=$_; + $i++; + } + } +} + +print "unsigned char " . $fontname . "FontData[$counter]={\n" . $out; +print "};\nint " . $fontname . "FontMetaData[256*5]={\n"; +for($i=0;$i<256*5;$i++) { + print $encodings[$i] . ","; +} +print "};\nrfbFontData " . $fontname . "Font={" . + $fontname . "FontData, " . $fontname . "FontMetaData};\n"; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/classes/.cvsignore new file mode 100755 index 0000000..22a4e72 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/classes/Makefile.am new file mode 100755 index 0000000..c5497a8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/Makefile.am @@ -0,0 +1,5 @@ +EXTRA_DIST=VncViewer.jar index.vnc javaviewer.pseudo_proxy.patch + +SUBDIRS = ssl +DIST_SUBDIRS = ssl + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/VncViewer.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/VncViewer.jar new file mode 100755 index 0000000..602fdb9 Binary files /dev/null and b/droidvncgrab/vnc/libvncserver-kanaka/classes/VncViewer.jar differ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/index.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/index.vnc new file mode 100755 index 0000000..63b2f56 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/index.vnc @@ -0,0 +1,18 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + +
+www.TightVNC.com + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/javaviewer.pseudo_proxy.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/javaviewer.pseudo_proxy.patch new file mode 100755 index 0000000..4d2f36e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/javaviewer.pseudo_proxy.patch @@ -0,0 +1,141 @@ +diff -ru vnc_javasrc/OptionsFrame.java proxy_vnc_javasrc/OptionsFrame.java +--- vnc_javasrc/OptionsFrame.java Fri Jul 5 08:17:23 2002 ++++ proxy_vnc_javasrc/OptionsFrame.java Thu Aug 22 23:24:44 2002 +@@ -70,6 +70,12 @@ + + Label[] labels = new Label[names.length]; + Choice[] choices = new Choice[names.length]; ++ ++ Label proxyHostLabel; ++ TextField proxyHostEdit; ++ Label proxyPortLabel; ++ TextField proxyPortEdit; ++ + Button closeButton; + VncViewer viewer; + +@@ -93,6 +99,9 @@ + boolean shareDesktop; + boolean viewOnly; + ++ String proxyHost; ++ int proxyPort; ++ + // + // Constructor. Set up the labels and choices from the names and values + // arrays. +@@ -126,6 +135,32 @@ + } + } + ++ // TODO: find a way to set these to defaults from browser ++ proxyPort = viewer.readIntParameter("Use Proxy Port", -1); ++ if(proxyPort>-1) { ++ proxyHost = viewer.readParameter("Use Proxy Host", false); ++ if(proxyHost == null) ++ proxyHost = viewer.host; ++ ++ proxyHostLabel = new Label("Proxy Host"); ++ gbc.gridwidth = 1; ++ gridbag.setConstraints(proxyHostLabel,gbc); ++ add(proxyHostLabel); ++ proxyHostEdit = new TextField(); ++ gbc.gridwidth = GridBagConstraints.REMAINDER; ++ gridbag.setConstraints(proxyHostEdit,gbc); ++ add(proxyHostEdit); ++ ++ proxyPortLabel = new Label("Proxy Port"); ++ gbc.gridwidth = 1; ++ gridbag.setConstraints(proxyPortLabel,gbc); ++ add(proxyPortLabel); ++ proxyPortEdit = new TextField(); ++ gbc.gridwidth = GridBagConstraints.REMAINDER; ++ gridbag.setConstraints(proxyPortEdit,gbc); ++ add(proxyPortEdit); ++ } ++ + closeButton = new Button("Close"); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gridbag.setConstraints(closeButton, gbc); +@@ -161,6 +196,11 @@ + } + } + ++ if(proxyPort>-1) { ++ proxyPortEdit.setText(Integer.toString(proxyPort)); ++ proxyHostEdit.setText(proxyHost); ++ } ++ + // Make the booleans and encodings array correspond to the state of the GUI + + setEncodings(); +@@ -361,8 +401,12 @@ + // + + public void actionPerformed(ActionEvent evt) { +- if (evt.getSource() == closeButton) ++ if (evt.getSource() == closeButton) { + setVisible(false); ++ proxyHost = proxyHostEdit.getText(); ++ proxyPort = Integer.parseInt(proxyPortEdit.getText()); ++ System.err.println("proxy is " + proxyHost + ":" + proxyPort); ++ } + } + + // +diff -ru vnc_javasrc/RfbProto.java proxy_vnc_javasrc/RfbProto.java +--- vnc_javasrc/RfbProto.java Sun Aug 4 18:39:35 2002 ++++ proxy_vnc_javasrc/RfbProto.java Thu Aug 22 22:53:53 2002 +@@ -119,12 +119,51 @@ + viewer = v; + host = h; + port = p; +- sock = new Socket(host, port); ++ if(viewer.options.proxyPort>-1) ++ sock = new Socket(viewer.options.proxyHost, viewer.options.proxyPort); ++ else ++ sock = new Socket(host, port); + is = new DataInputStream(new BufferedInputStream(sock.getInputStream(), + 16384)); + os = sock.getOutputStream(); ++ if(viewer.options.proxyPort>-1) ++ negotiateProxy(host,port); + } + ++ // this is inefficient as hell, but only used once per connection ++ String readLine() { ++ byte[] ba = new byte[1]; ++ String s = new String(""); ++ ++ ba[0]=0; ++ try { ++ while(ba[0] != 0xa) { ++ ba[0] = (byte)is.readUnsignedByte(); ++ s += new String(ba); ++ } ++ } catch(Exception e) { ++ e.printStackTrace(); ++ } ++ return s; ++ } ++ ++ void negotiateProxy(String realHost,int realPort) throws IOException { ++ String line; ++ ++ // this would be the correct way, but we want to trick strict proxies. ++ // line = "CONNECT " + realHost + ":" + realPort + " HTTP/1.1\r\nHost: " + realHost + ":" + realPort + "\r\n\r\n"; ++ line = "GET " + realHost + ":" + realPort + "/proxied.connection HTTP/1.0\r\nPragma: No-Cache\r\nProxy-Connection: Keep-Alive\r\n\r\n"; ++ os.write(line.getBytes()); ++ ++ line = readLine(); ++ System.err.println("Proxy said: " + line); ++ if(!(line.substring(0,7)+line.substring(8,12)).equalsIgnoreCase("HTTP/1. 200")) { ++ IOException e = new IOException(line); ++ throw e; ++ } ++ while(!line.equals("\r\n") && !line.equals("\n")) ++ line = readLine(); ++ } + + void close() { + try { diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/Makefile.am new file mode 100755 index 0000000..fd1c201 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README ss_vncviewer onetimekey UltraViewerSSL.jar SignedUltraViewerSSL.jar ultra.vnc ultrasigned.vnc ultraproxy.vnc + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/README b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/README new file mode 100755 index 0000000..b244cf1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/README @@ -0,0 +1,338 @@ +This directory contains a patched Java applet VNC viewer that is SSL +enabled. + +The patches in the *.patch files are relative to the source tarball: + + tightvnc-1.3dev7_javasrc.tar.gz + +currently (4/06) available here: + + http://prdownloads.sourceforge.net/vnc-tight/tightvnc-1.3dev7_javasrc.tar.gz?download + +It also includes some simple patches to: + + - fix richcursor colors + + - make the Java Applet cursor (not the cursor drawn to the canvas + framebuffer) invisible when it is inside the canvas. + + - allow Tab (and some other) keystrokes to be sent to the vnc + server instead of doing widget traversal. + + +This SSL applet should work with any VNC viewer that has an SSL tunnel in +front of it. It has been tested on x11vnc and using the stunnel tunnel +to other VNC servers. + +By default this Vnc Viewer will only do SSL. To do unencrypted traffic +see the "DisableSSL" applet parameter (e.g. set it to Yes in index.vnc). + +Proxies: they are a general problem with java socket applets (a socket +connection does not go through the proxy). See the info in the proxy.vnc +file for a workaround. It uses SignedVncViewer.jar which is simply +a signed version of VncViewer.jar. The basic idea is the user clicks +"Yes" to trust the applet and then it can connect directly to the proxy +and issue a CONNECT request. + +This applet has been tested on versions 1.4.2 and 1.5.0 of the Sun +Java plugin. It may not work on older releases or different vendor VM's. +Send full Java Console output for failures. + +--------------------------------------------------------------- +Tips: + +When doing single-port proxy connections (e.g. both VNC and HTTPS +thru port 5900) it helps to move through the 'do you trust this site' +dialogs quickly. x11vnc has to wait to see if the traffic is VNC or +HTTP and this can cause timeouts if you don't move thru them quickly. + +You may have to restart your browser completely if it gets into a +weird state. For one case we saw the JVM requesting VncViewer.class +even when no such file exists. + + +--------------------------------------------------------------- +Extras: + +ss_vncviewer (not Java): + + Wrapper script for native VNC viewer to connect to x11vnc in + SSL mode. Script launches stunnel(8) and then connects to it + via localhost which in turn is then redirected to x11vnc via an + SSL tunnel. stunnel(8) must be installed and available in PATH. + + +Running Java SSL VncViewer from the command line: + + From this directory: + + java -cp ./VncViewer.jar VncViewer HOST PORT + + substitute and with the actual values. + You can add any other parameters, e.g.: ignoreProxy yes + +--------------------------------------------------------------- +UltraVNC: + +The UltraVNC java viewer has also been patched to support SSL. Various +bugs in the UltraVNC java viewer were also fixed. This viewer can be +useful because is support UltraVNC filetransfer, and so it works on +Unix, etc. + +UltraViewerSSL.jar +SignedUltraViewerSSL.jar +ultra.vnc +ultraproxy.vnc +ultravnc-102-JavaViewer-ssl-etc.patch + +--------------------------------------------------------------- +Applet Parameters: + +Some additional applet parameters can be set via the URL, e.g. + + http://host:5800/?param=value + http://host:5800/ultra.vnc?param=value + https://host:5900/ultra.vnc?param=value + +etc. If running java from command line as show above, it comes +in as java ... VncViewer param value ... + +There is a limitation with libvncserver that param and value can +only be alphanumeric, underscore, "+" (for space), or "." + +We have added some applet parameters to the stock VNC java +viewers. Here are the applet parameters: + +Both TightVNC and UltraVNC Java viewers: + + HOST + string, default: none. + The Hostname to connect to. + + PORT + number, default: 0 + The VNC server port to connect to. + + Open New Window + yes/no, default: no + Run applet in separate frame. + + Show Controls + yes/no, default: yes + Show Controls button panel. + + Show Offline Desktop + yes/no, default: no + Do we continue showing desktop on remote disconnect? + + Defer screen updates + number, default: 20 + Milliseconds delay + + Defer cursor updates + number, default: 10 + Milliseconds delay + + Defer update requests + number, default: 50 + Milliseconds delay + + PASSWORD + string, default: none + VNC session password in plain text. + + ENCPASSWORD + string, default: none + VNC session password in encrypted in DES with KNOWN FIXED + key. It is a hex string. This is like the ~/.vnc/passwd format. + + + The following are added by x11vnc and/or ssvnc project + + VNCSERVERPORT + number, default: 0 + Like PORT, but if there is a firewall this is the Actual VNC + server port. PORT might be a redir port on the firewall. + + DisableSSL + yes/no, default: no + Do unencrypted connection, no SSL. + + httpsPort + number, default: none + When checking for proxy, use this at the url port number. + + CONNECT + string, default: none + Sets to host:port for the CONNECT line to a Web proxy. + The Web proxy should connect us to it. + + GET + yes/no, default: no + Set to do a special HTTP GET (/request.https.vnc.connection) + to the vnc server that will cause it to switch to VNC instead. + This is to speedup/make more robust, the single port HTTPS and VNC + mode of x11vnc (e.g. both services thru port 5900, etc) + + urlPrefix + string, default: none + set to a string that will be prefixed to all URL's when contacting + the VNC server. Idea is a special proxy will use this to indicate + internal hostname, etc. + + oneTimeKey + string, default: none + set a special hex "key" to correspond to an SSL X.509 cert+key. + See the 'onetimekey' helper script. Can also be PROMPT to prompt + the user to paste the hex key string in. + + This provides a Client-Side cert+key that the client will use to + authenticate itself by SSL To the VNC Server. + + This is to try to work around the problem that the Java applet + cannot keep an SSL keystore on disk, etc. E.g. if they log + into an HTTPS website via password they are authenticated and + encrypted, then the website can safely put oneTimeKey=... on the + URL. The Vncviewer authenticates the VNC server with this key. + + Note that there is currently a problem in that if x11vnc requires + Client Certificates the user cannot download the index.vnc HTML + and VncViewer.jar from the same x11vnc. Those need to come from + a different x11vnc or from a web server. + + Note that the HTTPS website can also put the VNC Password + (e.g. a temporary/one-time one) in the parameter PASSWORD. + The Java Applet will automatically supply this VNC password + instead of prompting. + + serverCert + string, default: none + set a special hex "cert" to correspond to an SSL X.509 cert + See the 'onetimekey -certonly' helper script. + + This provides a Server-Side cert that the client will authenticate + the VNC Server against by SSL. + + This is to try to work around the problem that the Java applet + cannot keep an SSL keystore on disk, etc. E.g. if they log + into an HTTPS website via password they are authenticated and + encrypted, then the website can safely put serverCert=... on the + URL. + + Of course the VNC Server is sending this string to the Java + Applet, so this is only reasonable security if the VNC Viewer + already trusts the HTTPS retrieval of the URL + serverCert param + that it gets. This should be done over HTTPS not HTTP. + + proxyHost + string, default: none + Do not try to guess the proxy's hostname, use the value in + proxyHost. Does not imply forceProxy (below.) + + proxyPort + string, default: none + Do not try to guess the proxy's port number, use the value in + proxyPort. Does not imply forceProxy (below.) + + forceProxy + yes/no, default: no + Assume there is a proxy and force its use. + + If a string other than "yes" or "no" is given, it implies "yes" + and uses the string for proxyHost and proxyPort (see above). + In this case the string must be of the form "hostname+port". + Note that it is "+" and not ":" before the port number. + + ignoreProxy + yes/no, default: no + Don't check for a proxy, assume there is none. + + trustAllVncCerts + yes/no, default: no + Automatically trust any cert received from the VNC server + (obviously this could be dangerous and lead to man in the + middle attack). Do not ask the user to verify any of these + certs from the VNC server. + + trustUrlVncCert + yes/no, default: no + Automatically trust any cert that the web browsers has accepted. + E.g. the user said "Yes" or "Continue" to a web browser dialog + regarding a certificate. If we get the same cert (chain) from + the VNC server we trust it without prompting the user. + + debugCerts + yes/no, default: no + Print out every cert in the Server, TrustUrl, TrustAll chains. + + +TightVNC Java viewer only: + + Offer Relogin + yes/no, default: yes + "Offer Relogin" set to "No" disables "Login again" + + SocketFactory + string, default: none + set Java Socket class factory. + +UltraVNC Java viewer only: + + None. + + The following are added by x11vnc and/or ssvnc project + + ftpDropDown + string, default: none + Sets the file transfer "drives" dropdown to the "." separated + list. Use "+" for space. The default is + + My+Documents.Desktop.Home + + for 3 entries in the dropdown in addition to the "drives" + (e.g. C:\) These items should be expanded properly by the VNC + Server. x11vnc will prepend $HOME to them, which is normally + what one wants. To include a "/" use "_2F_". Another example: + + Home.Desktop.bin_2F_linux + + If an item is prefixed with "TOP_" then the item is inserted at + the top of the drop down rather than being appended to the end. + E.g. to try to initially load the user homedir instead of /: + + TOP_Home.My+Documents.Desktop + + If ftpDropDown is set to the empty string, "", then no special + locations, [Desktop] etc., are placed in the drop down. Only the + ultravnc "drives" will appear. + + ftpOnly + yes/no, default: no + The VNC viewer only shows the filetransfer panel, no desktop + is displayed. + + graftFtp + yes/no, default: no + As ftpOnly, the VNC viewer only shows the filetransfer panel, + no desktop is displayed, however it is "grafted" onto an existing + SSVNC unix vncviewer. The special SSVNC vncviewer merges the two + channels. + + dsmActive + yes/no, default: no + Special usage mode with the SSVNC unix vncviewer. The UltraVNC + DSM encryption is active. Foolishly, UltraVNC DSM encryption + *MODIFIES* the VNC protocol when active (it is not a pure tunnel). + This option indicates to modify the VNC protocol to make this work. + Usually only used with graftFtp and SSVNC unix vncviewer. + + delayAuthPanel + yes/no, default: no + This is another special usage mode with the SSVNC unix vncviewer. + A login panel is delayed (not shown at startup.) Could be useful + for non SSVNC usage too. + + ignoreMSLogonCheck + yes/no, default: no + Similar to delayAuthPanel, do not put up a popup asking for + Windows username, etc. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedUltraViewerSSL.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedUltraViewerSSL.jar new file mode 100755 index 0000000..7f1c312 Binary files /dev/null and b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedUltraViewerSSL.jar differ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedVncViewer.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedVncViewer.jar new file mode 100755 index 0000000..b5b0b7d Binary files /dev/null and b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedVncViewer.jar differ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/UltraViewerSSL.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/UltraViewerSSL.jar new file mode 100755 index 0000000..e90582a Binary files /dev/null and b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/UltraViewerSSL.jar differ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/VncViewer.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/VncViewer.jar new file mode 100755 index 0000000..a78bde3 Binary files /dev/null and b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/VncViewer.jar differ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/index.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/index.vnc new file mode 100755 index 0000000..ec520dc --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/index.vnc @@ -0,0 +1,26 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/onetimekey b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/onetimekey new file mode 100755 index 0000000..bf57c8f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/onetimekey @@ -0,0 +1,65 @@ +#!/bin/sh +# +# usage: onetimekey path/to/mycert.pem +# onetimekey -certonly path/to/mycert.pem +# +# Takes an openssl cert+key pem file and turns into a long string +# for the x11vnc SSL VNC Java Viewer. +# +# The Java applet URL parameter can be oneTimeKey= where str is +# the output of this program, or can be oneTimeKey=PROMPT in which +# case the applet will ask you to paste in the string. +# +# The problem trying to be solved here is it is difficult to get +# the Java applet to have or use a keystore with the key saved +# in it. Also, as the name implies, an HTTPS server can create +# a one time key to send to the applet (the user has already +# logged in via password to the HTTPS server). +# +# Note oneTimeKey is to provide a CLIENT Certificate for the viewer +# to authenticate itself to the VNC Server. +# +# There is also the serverCert= Applet parameter. This is +# a cert to authenticate the VNC server against. To create that +# string with this tool specify -certonly as the first argument. + +certonly="" +if [ "X$1" = "X-certonly" ]; then + shift + certonly=1 +fi + +in=$1 +der=/tmp/1time$$.der +touch $der +chmod 600 $der + +openssl pkcs8 -topk8 -nocrypt -in "$in" -out "$der" -outform der + +pbinhex=/tmp/pbinhex.$$ +cat > $pbinhex < + + + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ss_vncviewer b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ss_vncviewer new file mode 100755 index 0000000..63ddac5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ss_vncviewer @@ -0,0 +1,3513 @@ +#!/bin/sh +# +# ss_vncviewer: wrapper for vncviewer to use an stunnel SSL tunnel +# or an SSH tunnel. +# +# Copyright (c) 2006-2009 by Karl J. Runge +# +# ss_vncviewer 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. +# +# ss_vncviewer 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 ss_vncviewer; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +# or see . +# +# +# You must have stunnel(8) installed on the system and in your PATH +# (however, see the -ssh option below, in which case you will need ssh(1) +# installed) Note: stunnel is usually installed in an "sbin" subdirectory. +# +# You should have "x11vnc -ssl ..." or "x11vnc -stunnel ..." +# already running as the VNC server on the remote machine. +# (or use stunnel on the server side for any other VNC server) +# +# +# Usage: ss_vncviewer [cert-args] host:display +# +# e.g.: ss_vncviewer snoopy:0 +# ss_vncviewer snoopy:0 -encodings "copyrect tight zrle hextile" +# +# [cert-args] can be: +# +# -verify /path/to/cacert.pem +# -mycert /path/to/mycert.pem +# -crl /path/to/my_crl.pem (or directory) +# -proxy host:port +# +# -verify specifies a CA cert PEM file (or a self-signed one) for +# authenticating the VNC server. +# +# -mycert specifies this client's cert+key PEM file for the VNC server to +# authenticate this client. +# +# -proxy try host:port as a Web proxy to use the CONNECT method +# to reach the VNC server (e.g. your firewall requires a proxy). +# +# For the "double proxy" case use -proxy host1:port1,host2:port2 +# (the first CONNECT is done through host1:port1 to host2:port2 +# and then a 2nd CONNECT to the destination VNC server.) +# +# Use socks://host:port, socks4://host:port, or socks5://host,port +# to force usage of a SOCKS proxy. Also repeater://host:port and +# sslrepeater://host:port. +# +# -showcert Only fetch the certificate using the 'openssl s_client' +# command (openssl(1) must in installed). +# +# See http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca for details on +# SSL certificates with VNC. +# +# A few other args (not related to SSL and certs): +# +# -2nd Run the vncviewer a 2nd time if the first connections fails. +# +# -ssh Use ssh instead of stunnel SSL. ssh(1) must be installed and you +# must be able to log into the remote machine via ssh. +# +# In this case "host:display" may be of the form "user@host:display" +# where "user@host" is used for the ssh login (see ssh(1) manpage). +# +# If -proxy is supplied it can be of the forms: "gwhost" "gwhost:port" +# "user@gwhost" or "user@gwhost:port". "gwhost" is an incoming ssh +# gateway machine (the VNC server is not running there), an ssh -L +# redir is used to "host" in "host:display" from "gwhost". Any "user@" +# part must be in the -proxy string (not in "host:display"). +# +# Under -proxy use "gwhost:port" if connecting to any ssh port +# other than the default (22). (even for the non-gateway case, +# -proxy must be used to specify a non-standard ssh port) +# +# A "double ssh" can be specified via a -proxy string with the two +# hosts separated by a comma: +# +# [user1@]host1[:port1],[user2@]host2[:port2] +# +# in which case a ssh to host1 and thru it via a -L redir a 2nd +# ssh is established to host2. +# +# Examples: +# +# ss_vncviewer -ssh bob@bobs-home.net:0 +# ss_vncviewer -ssh -sshcmd 'x11vnc -localhost' bob@bobs-home.net:0 +# +# ss_vncviewer -ssh -proxy fred@mygate.com:2022 mymachine:0 +# ss_vncviewer -ssh -proxy bob@bobs-home.net:2222 localhost:0 +# +# ss_vncviewer -ssh -proxy fred@gw-host,fred@peecee localhost:0 +# +# -sshcmd cmd Run "cmd" via ssh instead of the default "sleep 15" +# e.g. -sshcmd 'x11vnc -display :0 -localhost -rfbport 5900' +# +# -sshargs "args" pass "args" to the ssh process, e.g. -L/-R port redirs. +# +# -sshssl Tunnel the SSL connection thru a SSH connection. The tunnel as +# under -ssh is set up and the SSL connection goes thru it. Use +# this if you want to have and end-to-end SSL connection but must +# go thru a SSH gateway host (e.g. not the vnc server). Or use +# this if you need to tunnel additional services via -R and -L +# (see -sshargs above). +# +# ss_vncviewer -sshssl -proxy fred@mygate.com mymachine:0 +# +# -listen (or -reverse) set up a reverse connection. +# +# -alpha turn on cursor alphablending hack if you are using the +# enhanced tightvnc vncviewer. +# +# -grab turn on XGrabServer hack if you are using the enhanced tightvnc +# vncviewer (e.g. for fullscreen mode in some windowmanagers like +# fvwm that do not otherwise work in fullscreen mode) +# +# +# set VNCVIEWERCMD to whatever vncviewer command you want to use. +# +VNCIPCMD=${VNCVIEWERCMD:-vncip} +VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer} +if [ "X$SSVNC_TURBOVNC" != "X" ]; then + if echo "$VNCVIEWERCMD" | grep '\.turbovnc' > /dev/null; then + : + else + if type "$VNCVIEWERCMD.turbovnc" > /dev/null 2>/dev/null; then + VNCVIEWERCMD="$VNCVIEWERCMD.turbovnc" + fi + fi +fi +# +# Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc. +# + +# turn on verbose debugging output +if [ "X$SS_DEBUG" != "X" -a "X$SS_DEBUG" != "X0" ]; then + set -xv +fi + +PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH + +localhost="localhost" +if uname | grep Darwin >/dev/null; then + localhost="127.0.0.1" +fi + +# work out which stunnel to use (debian installs as stunnel4) +stunnel_set_here="" +if [ "X$STUNNEL" = "X" ]; then + check_stunnel=1 + if [ "X$SSVNC_BASEDIRNAME" != "X" ]; then + if [ -x "$SSVNC_BASEDIRNAME/stunnel" ]; then + type stunnel > /dev/null 2>&1 + if [ $? = 0 ]; then + # found ours + STUNNEL=stunnel + check_stunnel=0 + fi + fi + fi + if [ "X$check_stunnel" = "X1" ]; then + type stunnel4 > /dev/null 2>&1 + if [ $? = 0 ]; then + STUNNEL=stunnel4 + else + STUNNEL=stunnel + fi + fi + stunnel_set_here=1 +fi + +help() { + tail -n +2 "$0" | sed -e '/^$/ q' +} + +secondtry="" +gotalpha="" +use_ssh="" +use_sshssl="" +direct_connect="" +ssh_sleep=15 + +# sleep longer in -listen mode: +if echo "$*" | grep '.*-listen' > /dev/null; then + ssh_sleep=1800 +fi + + +ssh_cmd="" +# env override of ssh_cmd: +if [ "X$SS_VNCVIEWER_SSH_CMD" != "X" ]; then + ssh_cmd="$SS_VNCVIEWER_SSH_CMD" +fi + +ssh_args="" +showcert="" +reverse="" + +ciphers="" +anondh="ALL:RC4+RSA:+SSLv2:@STRENGTH" +anondh_set="" +stunnel_debug="6" +if [ "X$SS_DEBUG" != "X" -o "X$SSVNC_VENCRYPT_DEBUG" != "X" -o "X$SSVNC_STUNNEL_DEBUG" != "X" ]; then + stunnel_debug="7" +fi + +if [ "X$1" = "X-viewerflavor" ]; then + # special case, try to guess which viewer: + # + if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then + echo "unknown" + exit 0 + fi + if echo "$VNCVIEWERCMD" | grep -i chicken.of > /dev/null; then + echo "cotvnc" + exit 0 + fi + if echo "$VNCVIEWERCMD" | grep -i ultra > /dev/null; then + echo "ultravnc" + exit 0 + fi + # OK, run it for help output... + str=`$VNCVIEWERCMD -h 2>&1 | head -n 5` + if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then + echo "tightvnc" + elif echo "$str" | grep -i 'VNC viewer version 3' > /dev/null; then + echo "realvnc3" + elif echo "$str" | grep -i 'VNC viewer .*Edition 4' > /dev/null; then + echo "realvnc4" + elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then + echo "realvnc4" + else + echo "unknown" + fi + exit 0 +fi +if [ "X$1" = "X-viewerhelp" ]; then + $VNCVIEWERCMD -h 2>&1 + exit 0 +fi + +# grab our cmdline options: +while [ "X$1" != "X" ] +do + case $1 in + "-verify") shift; verify="$1" + ;; + "-mycert") shift; mycert="$1" + ;; + "-crl") shift; crl="$1" + ;; + "-proxy") shift; proxy="$1" + ;; + "-ssh") use_ssh=1 + ;; + "-sshssl") use_ssh=1 + use_sshssl=1 + ;; + "-sshcmd") shift; ssh_cmd="$1" + ;; + "-sshargs") shift; ssh_args="$1" + ;; + "-anondh") ciphers="ciphers=$anondh" + anondh_set=1 + ;; + "-ciphers") shift; ciphers="ciphers=$1" + ;; + "-alpha") gotalpha=1 + ;; + "-showcert") showcert=1 + ;; + "-listen") reverse=1 + ;; + "-reverse") reverse=1 + ;; + "-2nd") secondtry=1 + ;; + "-grab") VNCVIEWER_GRAB_SERVER=1; export VNCVIEWER_GRAB_SERVER + ;; + "-x11cursor") VNCVIEWER_X11CURSOR=1; export VNCVIEWER_X11CURSOR + ;; + "-rawlocal") VNCVIEWER_RAWLOCAL=1; export VNCVIEWER_RAWLOCAL + ;; + "-scale") shift; SSVNC_SCALE="$1"; export SSVNC_SCALE + ;; + "-onelisten") SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE + ;; + "-sendclipboard") VNCVIEWER_SEND_CLIPBOARD=1; export VNCVIEWER_SEND_CLIPBOARD + ;; + "-sendalways") VNCVIEWER_SEND_ALWAYS=1; export VNCVIEWER_SEND_ALWAYS + ;; + "-recvtext") shift; VNCVIEWER_RECV_TEXT="$1"; export VNCVIEWER_RECV_TEXT + ;; + "-escape") shift; VNCVIEWER_ESCAPE="$1"; export VNCVIEWER_ESCAPE + ;; + "-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS + ;; + "-ssvnc_extra_opts") shift; VNCVIEWERCMD_EXTRA_OPTS="$1"; export VNCVIEWERCMD_EXTRA_OPTS + ;; + "-rfbversion") shift; VNCVIEWER_RFBVERSION="$1"; export VNCVIEWER_RFBVERSION + ;; + "-nobell") VNCVIEWER_NOBELL=1; export VNCVIEWER_NOBELL + ;; + "-popupfix") VNCVIEWER_POPUP_FIX=1; export VNCVIEWER_POPUP_FIX + ;; + "-realvnc4") VNCVIEWER_IS_REALVNC4=1; export VNCVIEWER_IS_REALVNC4 + ;; + "-h"*) help; exit 0 + ;; + "--h"*) help; exit 0 + ;; + *) break + ;; + esac + shift +done + +# maxconn is something we added to stunnel, this disables it: +if [ "X$SS_VNCVIEWER_NO_MAXCONN" != "X" ]; then + STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` +elif echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then + STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` +elif [ "X$reverse" != "X" ]; then + STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` +else + # new way (our patches). other than the above, we set these: + if [ "X$SKIP_STUNNEL_ONCE" = "X" ]; then + STUNNEL_ONCE=1; export STUNNEL_ONCE + fi + if [ "X$SKIP_STUNNEL_MAX_CLIENTS" = "X" ]; then + STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS + fi +fi +# always set this one: +if [ "X$SKIP_STUNNEL_NO_SYSLOG" = "X" ]; then + STUNNEL_NO_SYSLOG=1; export STUNNEL_NO_SYSLOG +fi + +# this is the -t ssh option (gives better keyboard response thru SSH tunnel) +targ="-t" +if [ "X$SS_VNCVIEWER_NO_T" != "X" ]; then + targ="" +fi + +# set the alpha blending env. hack: +if [ "X$gotalpha" = "X1" ]; then + VNCVIEWER_ALPHABLEND=1 + export VNCVIEWER_ALPHABLEND +else + NO_ALPHABLEND=1 + export NO_ALPHABLEND +fi + +if [ "X$reverse" != "X" ]; then + ssh_sleep=1800 + if [ "X$proxy" != "X" ]; then + # check proxy usage under reverse connection: + if [ "X$use_ssh" = "X" -a "X$use_sshssl" = "X" ]; then + echo "" + if echo "$proxy" | egrep -i "(repeater|vencrypt)://" > /dev/null; then + : + else + echo "*Warning*: SSL -listen and a Web proxy does not make sense." + sleep 2 + fi + elif echo "$proxy" | grep "," > /dev/null; then + : + else + echo "" + echo "*Warning*: -listen and a single proxy/gateway does not make sense." + sleep 2 + fi + + # we now try to PPROXY_LOOP_THYSELF, set this var to disable that. + #SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE + fi +fi +if [ "X$ssh_cmd" = "X" ]; then + # if no remote ssh cmd, sleep a bit: + ssh_cmd="sleep $ssh_sleep" +fi + +# this should be a host:display: +# +orig="$1" +shift + +dL="-L" +if uname -sr | egrep 'SunOS 5\.[5-8]' > /dev/null; then + dL="-h" +fi + +rchk() { + # a kludge to set $RANDOM if we are not bash: + if [ "X$BASH_VERSION" = "X" ]; then + RANDOM=`date +%S``sh -c 'echo $$'``ps -elf 2>&1 | sum 2>&1 | awk '{print $1}'` + fi +} +rchk + +# a portable, but not absolutely safe, tmp file creator +mytmp() { + tf=$1 + if type mktemp > /dev/null 2>&1; then + # if we have mktemp(1), use it: + tf2="$tf.XXXXXX" + tf2=`mktemp "$tf2"` + if [ "X$tf2" != "X" -a -f "$tf2" ]; then + if [ "X$DEBUG_MKTEMP" != "X" ]; then + echo "mytmp-mktemp: $tf2" 1>&2 + fi + echo "$tf2" + return + fi + fi + # fallback to multiple cmds: + rm -rf "$tf" || exit 1 + if [ -d "$tf" ]; then + echo "tmp file $tf still exists as a directory." + exit 1 + elif [ $dL "$tf" ]; then + echo "tmp file $tf still exists as a symlink." + exit 1 + elif [ -f "$tf" ]; then + echo "tmp file $tf still exists." + exit 1 + fi + touch "$tf" || exit 1 + chmod 600 "$tf" || exit 1 + rchk + if [ "X$DEBUG_MKTEMP" != "X" ]; then + echo "mytmp-touch: $tf" 1>&2 + fi + echo "$tf" +} + +# set up special case of ultravnc single click III mode: +if echo "$proxy" | egrep "^sslrepeater://" > /dev/null; then + pstr=`echo "$proxy" | sed -e 's,sslrepeater://,,'` + pstr1=`echo "$pstr" | sed -e 's/+.*$//'` + pstr2=`echo "$pstr" | sed -e 's/^[^+]*+//'` + SSVNC_REPEATER="SCIII=$pstr2"; export SSVNC_REPEATER + orig=$pstr1 + echo + echo "reset: SSVNC_REPEATER=$SSVNC_REPEATER orig=$orig proxy=''" + proxy="" +fi +if echo "$proxy" | egrep "vencrypt://" > /dev/null; then + vtmp="/tmp/ss_handshake${RANDOM}.$$.txt" + vtmp=`mytmp "$vtmp"` + SSVNC_PREDIGESTED_HANDSHAKE="$vtmp" + export SSVNC_PREDIGESTED_HANDSHAKE + if [ "X$SSVNC_USE_OURS" = "X" ]; then + NEED_VENCRYPT_VIEWER_BRIDGE=1 + fi +fi +if [ "X$SSVNC_USE_OURS" = "X" ]; then + VNCVIEWERCMD_EXTRA_OPTS="" +fi + + +# check -ssh and -mycert/-verify conflict: +if [ "X$use_ssh" = "X1" -a "X$use_sshssl" = "X" ]; then + if [ "X$mycert" != "X" -o "X$verify" != "X" ]; then + echo "-mycert and -verify cannot be used in -ssh mode" + exit 1 + fi +fi + +# direct mode Vnc:// means show no warnings. +# direct mode vnc:// will show warnings. +if echo "$orig" | grep '^V[Nn][Cc]://' > /dev/null; then + SSVNC_NO_ENC_WARN=1 + export SSVNC_NO_ENC_WARN + orig=`echo "$orig" | sed -e 's/^...:/vnc:/'` +fi + +# interprest the pseudo URL proto:// strings: +if echo "$orig" | grep '^vnc://' > /dev/null; then + orig=`echo "$orig" | sed -e 's,vnc://,,'` + verify="" + mycert="" + crl="" + use_ssh="" + use_sshssl="" + direct_connect=1 +elif echo "$orig" | grep '^vncs://' > /dev/null; then + orig=`echo "$orig" | sed -e 's,vncs://,,'` +elif echo "$orig" | grep '^vncssl://' > /dev/null; then + orig=`echo "$orig" | sed -e 's,vncssl://,,'` +elif echo "$orig" | grep '^vnc+ssl://' > /dev/null; then + orig=`echo "$orig" | sed -e 's,vnc.ssl://,,'` +elif echo "$orig" | grep '^vncssh://' > /dev/null; then + orig=`echo "$orig" | sed -e 's,vncssh://,,'` + use_ssh=1 +elif echo "$orig" | grep '^vnc+ssh://' > /dev/null; then + orig=`echo "$orig" | sed -e 's,vnc.ssh://,,'` + use_ssh=1 +fi + +if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then + verify="" + mycert="" + crl="" + use_ssh="" + use_sshssl="" + direct_connect=1 + if echo "$SSVNC_ULTRA_DSM" | grep 'noultra:' > /dev/null; then + SSVNC_NO_ULTRA_DSM=1; export SSVNC_NO_ULTRA_DSM + fi +fi + +# rsh mode is an internal/secret thing only I use. +rsh="" +if echo "$orig" | grep '^rsh://' > /dev/null; then + use_ssh=1 + rsh=1 + orig=`echo "$orig" | sed -e 's,rsh://,,'` +elif echo "$orig" | grep '^rsh:' > /dev/null; then + use_ssh=1 + rsh=1 + orig=`echo "$orig" | sed -e 's,rsh:,,'` +fi + +# play around with host:display port: +if echo "$orig" | grep ':' > /dev/null; then + : +else + # add or assume :0 if no ':' + if [ "X$reverse" = "X" ]; then + orig="$orig:0" + elif [ "X$orig" = "X" ]; then + orig=":0" + fi +fi + +# extract host and disp number: + +# try to see if it is ipv6 address: +ipv6=0 +if echo "$orig" | grep '\[' > /dev/null; then + # ipv6 [fe80::219:dbff:fee5:3f92%eth1]:5900 + host=`echo "$orig" | sed -e 's/\].*$//' -e 's/\[//'` + disp=`echo "$orig" | sed -e 's/^.*\]://'` + ipv6=1 +elif echo "$orig" | grep ':..*:' > /dev/null; then + # ipv6 fe80::219:dbff:fee5:3f92%eth1:5900 + host=`echo "$orig" | sed -e 's/:[^:]*$//'` + disp=`echo "$orig" | sed -e 's/^.*://'` + ipv6=1 +else + # regular host:port + host=`echo "$orig" | awk -F: '{print $1}'` + disp=`echo "$orig" | awk -F: '{print $2}'` +fi + +if [ "X$reverse" != "X" -a "X$STUNNEL_LISTEN" = "X" -a "X$host" != "X" ]; then + STUNNEL_LISTEN=$host + echo "set STUNNEL_LISTEN=$STUNNEL_LISTEN" +fi + +if [ "X$host" = "X" ]; then + host=$localhost +fi + +if [ "X$SSVNC_IPV6" = "X0" ]; then + # disable checking for it. + ipv6=0 +#elif [ "X$reverse" != "X" -a "X$ipv6" = "X1" ]; then +# ipv6=0 +elif [ "X$ipv6" = "X1" ]; then + : +elif echo "$host" | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; then + : +else + # regular hostname, can't be sure... + host "$host" >/dev/null 2>&1 + host "$host" >/dev/null 2>&1 + hout=`host "$host" 2>/dev/null` + if echo "$hout" | grep -i 'has ipv6 address' > /dev/null; then + if echo "$hout" | grep -i 'has address' > /dev/null; then + : + else + echo "ipv6: "`echo "$hout" | grep -i 'has ipv6 address' | head -n 1` + ipv6=1 + fi + fi + if [ "X$ipv6" = "X0" ]; then + dout=`dig -t any "$host" 2>/dev/null` + if echo "$dout" | grep -i "^$host" | grep '[ ]AAAA[ ]' > /dev/null; then + if echo "$dout" | grep -i "^$host" | grep '[ ]A[ ]' > /dev/null; then + : + else + echo "ipv6: "`echo "$dout" | grep -i '[ ]AAAA[ ]' | head -n 1` + ipv6=1 + fi + fi + fi + if [ "X$ipv6" = "X0" ]; then + sout=`env LOOKUP="$host" \ + perl -e ' eval {use Socket}; exit 0 if $@; + eval {use Socket6}; exit 0 if $@; + @res = getaddrinfo($ENV{LOOKUP}, "daytime", AF_UNSPEC, SOCK_STREAM); + $ipv4 = 0; + $ipv6 = 0; + $ip6 = ""; + while (scalar(@res) >= 5) { + ($family, $socktype, $proto, $saddr, $canon, @res) = @res; + $ipv4 = 1 if $family == AF_INET; + $ipv6 = 1 if $family == AF_INET6; + if ($family == AF_INET6 && $ip6 eq "") { + my ($host, $port) = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV); + $ip6 = $host; + } + } + if (! $ipv4 && $ipv6) { + print "AF_INET6_ONLY: $ENV{LOOKUP}: $ip6\n"; + } + exit 0; + ' 2>/dev/null` + if echo "$sout" | grep AF_INET6_ONLY > /dev/null; then + echo "$sout" + ipv6=1 + fi + fi +fi +if [ "X$ipv6" = "X1" ]; then + echo "ipv6: addr=$host disp=$disp" +fi +if [ "X$disp" = "X" ]; then + port="" # probably -listen mode. +elif [ $disp -lt 0 ]; then + # negative means use |n| without question: + port=`expr 0 - $disp` +elif [ $disp -lt 200 ]; then + # less than 200 means 5900+n + if [ "X$reverse" = "X" ]; then + port=`expr $disp + 5900` + else + port=`expr $disp + 5500` + fi +else + # otherwise use the number directly, e.g. 443, 2345 + port=$disp +fi + +if [ "X$ipv6" = "X1" -a "X$direct_connect" = "X1" ]; then + if [ "X$proxy" = "X" -a "X$reverse" = "X" ]; then + proxy="ipv6://$host:$port" + echo "direct connect: set proxy=$proxy" + fi +fi + +# (possibly) tell the vncviewer to only listen on lo: +if [ "X$reverse" != "X" ]; then + if [ "X$direct_connect" = "X" -o "X$proxy" != "X" -o "X$STUNNEL_LISTEN" != "X" ]; then + VNCVIEWER_LISTEN_LOCALHOST=1 + export VNCVIEWER_LISTEN_LOCALHOST + fi +fi + +# try to find an open listening port via netstat(1): +inuse="" +if uname | grep Linux > /dev/null; then + inuse=`netstat -ant | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*://'` +elif uname | grep SunOS > /dev/null; then + inuse=`netstat -an -f inet -P tcp | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $1}' | sed 's/^.*\.//'` +elif uname | egrep -i 'bsd|darwin' > /dev/null; then + inuse=`netstat -ant -f inet | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*\.//'` +# add others... +fi + +# this is a crude attempt for unique ports tags, etc. +date_sec=`date +%S` + +# these are special cases of no vnc, e.g. sleep or xmessage. +# these are for using ssvnc as a general port redirector. +if echo "$VNCVIEWERCMD" | grep '^sleep[ ][ ]*[0-9][0-9]*' > /dev/null; then + if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then + p=`echo "$VNCVIEWERCMD" | awk '{print $3}'` + if [ "X$p" != "X" ]; then + SS_VNCVIEWER_LISTEN_PORT=$p + fi + fi + p2=`echo "$VNCVIEWERCMD" | awk '{print $2}'` + VNCVIEWERCMD="eval sleep $p2; echo Local " +elif echo "$VNCVIEWERCMD" | grep '^xmessage[ ][ ]*[0-9][0-9]*' > /dev/null; then + if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then + p=`echo "$VNCVIEWERCMD" | awk '{print $2}'` + SS_VNCVIEWER_LISTEN_PORT=$p + fi +fi + +# utility to find a free port to listen on. +findfree() { + try0=$1 + try=$try0 + use0="" + + if [ "X$SS_VNCVIEWER_LISTEN_PORT" != "X" ]; then + echo "$SS_VNCVIEWER_LISTEN_PORT" + return + fi + if [ $try -ge 6000 ]; then + fmax=`expr $try + 1000` + else + fmax=6000 + fi + + while [ $try -lt $fmax ] + do + if [ "X$inuse" = "X" ]; then + break + fi + if echo "$inuse" | grep -w $try > /dev/null; then + : + else + use0=$try + break + fi + try=`expr $try + 1` + done + if [ "X$use0" = "X" ]; then + use0=`expr $date_sec + $try0` + fi + + echo $use0 +} + +# utility for exiting; kills some helper processes, +# removes files, etc. +final() { + echo "" + if [ "X$tmp_cfg" != "X" ]; then + rm -f $tmp_cfg + fi + if [ "X$SS_VNCVIEWER_RM" != "X" ]; then + rm -f $SS_VNCVIEWER_RM 2>/dev/null + fi + if [ "X$tcert" != "X" ]; then + rm -f $tcert + fi + if [ "X$pssh" != "X" ]; then + echo "Terminating background ssh process" + echo kill -TERM "$pssh" + kill -TERM "$pssh" 2>/dev/null + sleep 1 + kill -KILL "$pssh" 2>/dev/null + pssh="" + fi + if [ "X$stunnel_pid" != "X" ]; then + echo "Terminating background stunnel process" + echo kill -TERM "$stunnel_pid" + kill -TERM "$stunnel_pid" 2>/dev/null + sleep 1 + kill -KILL "$stunnel_pid" 2>/dev/null + stunnel_pid="" + fi + if [ "X$dsm_pid" != "X" ]; then + echo "Terminating background ultravnc_dsm_helper process" + echo kill -TERM "$dsm_pid" + kill -TERM "$dsm_pid" 2>/dev/null + sleep 1 + kill -KILL "$dsm_pid" 2>/dev/null + stunnel_pid="" + fi + if [ "X$tail_pid" != "X" ]; then + kill -TERM $tail_pid + fi + if [ "X$tail_pid2" != "X" ]; then + kill -TERM $tail_pid2 + fi +} + +if [ "X$reverse" = "X" ]; then + # normal connections try 5930-5999: + if [ "X$showcert" = "X" ]; then + use=`findfree 5930` + else + # move away from normal place for (possibly many) -showcert + pstart=`date +%S` + pstart=`expr 6130 + $pstart + $pstart` + use=`findfree $pstart` + fi + if [ $use -ge 5900 ]; then + N=`expr $use - 5900` + else + N=$use + fi +else + # reverse connections: + p2=`expr $port + 30` + use=`findfree $p2` + if [ $use -ge 5500 ]; then + N=`expr $use - 5500` + else + N=$use + fi +fi + +# this is for my special use of ss_vncip -> vncip viewer. +if echo "$0" | grep vncip > /dev/null; then + VNCVIEWERCMD="$VNCIPCMD" +fi + +if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then + : +elif [ "X$VNCVIEWERCMD_EXTRA_OPTS" != "X" ]; then + VNCVIEWERCMD="$VNCVIEWERCMD $VNCVIEWERCMD_EXTRA_OPTS" +fi + +# trick for the undocumented rsh://host:port method. +rsh_setup() { + if echo "$ssh_host" | grep '@' > /dev/null; then + ul=`echo "$ssh_host" | awk -F@ '{print $1}'` + ul="-l $ul" + ssh_host=`echo "$ssh_host" | awk -F@ '{print $2}'` + else + ul="" + fi + ssh_cmd=`echo "$ssh_cmd" | sed -e 's/ -localhost/ /g'` +} + +# trick for the undocumented rsh://host:port method. +rsh_viewer() { + trap "final" 0 2 15 + if [ "X$PORT" = "X" ]; then + exit 1 + elif [ $PORT -ge 5900 ]; then + vdpy=`expr $PORT - 5900` + else + vdpy=":$PORT" + fi + stty sane + echo "$VNCVIEWERCMD" "$@" $ssh_host:$vdpy + echo "" + $VNCVIEWERCMD "$@" $ssh_host:$vdpy + if [ $? != 0 ]; then + sleep 2 + $VNCVIEWERCMD "$@" $ssh_host:$vdpy + fi +} + +check_perl() { + if type "$1" > /dev/null 2>&1; then + : + elif [ ! -x "$1" ]; then + echo "" + echo "*******************************************************" + echo "** Problem finding the Perl command '$1': **" + echo "" + type "perl" + echo "" + echo "** Perhaps you need to install the Perl package. **" + echo "*******************************************************" + echo "" + sleep 5 + fi +} + +# this is the PPROXY tool. used only here for now... +pcode() { + tf=$1 + PPROXY_PROXY=$proxy; export PPROXY_PROXY + PPROXY_DEST="$host:$port"; export PPROXY_DEST + check_perl /usr/bin/perl + + cod='#!/usr/bin/perl + +# A hack to glue stunnel to a Web or SOCKS proxy, UltraVNC repeater for +# client connections. +# Also acts as a VeNCrypt bridge (by redirecting to stunnel.) + +use IO::Socket::INET; + +my $have_inet6 = ""; +eval "use IO::Socket::INET6;"; +$have_inet6 = 1 if $@ eq ""; + +#my $have_sock6 = ""; +#eval "use Socket; use Socket6;"; +#$have_sock6 = 1 if $@ eq ""; + +if (exists $ENV{PPROXY_LOOP_THYSELF}) { + # used for reverse vnc, run a repeating outer loop. + print STDERR "PPROXY_LOOP: $ENV{PPROXY_LOOP_THYSELF}\n"; + my $rm = $ENV{PPROXY_REMOVE}; + my $lp = $ENV{PPROXY_LOOP_THYSELF}; + delete $ENV{PPROXY_REMOVE}; + delete $ENV{PPROXY_LOOP_THYSELF}; + $ENV{PPROXY_LOOP_THYSELF_MASTER} = $$; + my $pid = $$; + my $dbg = 0; + my $c = 0; + use POSIX ":sys_wait_h"; + while (1) { + $pid = fork(); + last if ! defined $pid; + if ($pid eq "0") { + last; + } + $c++; + print STDERR "\nPPROXY_LOOP: pid=$$ child=$pid count=$c\n"; + while (1) { + waitpid(-1, WNOHANG); + fsleep(0.25); + if (! kill 0, $pid) { + print STDERR "PPROXY_LOOP: child=$pid gone.\n"; + last; + } + print STDERR "PPROXY_LOOP: child=$pid alive.\n" if $dbg; + if (! -f $lp) { + print STDERR "PPROXY_LOOP: flag file $lp gone, killing $pid\n"; + kill TERM, $pid; + fsleep(0.1); + wait; + last; + } + print STDERR "PPROXY_LOOP: file exists $lp\n" if $dbg; + } + last if ! -f $lp; + fsleep(0.25); + } + if ($pid ne "0") { + unlink($0) if $rm; + exit 0; + } +} + +if (exists $ENV{PPROXY_SLEEP} && $ENV{PPROXY_SLEEP} > 0) { + print STDERR "PPROXY_PID: $$\n"; + sleep $ENV{PPROXY_SLEEP}; +} + +foreach my $var (qw( + PPROXY_DEST + PPROXY_KILLPID + PPROXY_LISTEN + PPROXY_PROXY + PPROXY_REMOVE + PPROXY_REPEATER + PPROXY_REVERSE + PPROXY_SLEEP + PPROXY_SOCKS + PPROXY_VENCRYPT + PPROXY_VENCRYPT_VIEWER_BRIDGE + )) { + if (0 || $ENV{SS_DEBUG} || $ENV{SSVNC_VENCRYPT_DEBUG}) { + print STDERR "$var: $ENV{$var}\n"; + } +} + +if ($ENV{PPROXY_SOCKS} ne "" && $ENV{PPROXY_PROXY} !~ m,^socks5?://,i) { + if ($ENV{PPROXY_SOCKS} eq "5") { + $ENV{PPROXY_PROXY} = "socks5://$ENV{PPROXY_PROXY}"; + } else { + $ENV{PPROXY_PROXY} = "socks://$ENV{PPROXY_PROXY}"; + } +} + +my $rfbSecTypeAnonTls = 18; +my $rfbSecTypeVencrypt = 19; + +my $rfbVencryptPlain = 256; +my $rfbVencryptTlsNone = 257; +my $rfbVencryptTlsVnc = 258; +my $rfbVencryptTlsPlain = 259; +my $rfbVencryptX509None = 260; +my $rfbVencryptX509Vnc = 261; +my $rfbVencryptX509Plain = 262; + +my $handshake_file = ""; +if (exists $ENV{SSVNC_PREDIGESTED_HANDSHAKE}) { + $handshake_file = $ENV{SSVNC_PREDIGESTED_HANDSHAKE}; +} + +my $have_gettimeofday = 0; +eval "use Time::HiRes;"; +if ($@ eq "") { + $have_gettimeofday = 1; +} +sub gettime { + my $t = "0.0"; + if ($have_gettimeofday) { + $t = Time::HiRes::gettimeofday(); + } + return $t; +} + +my $listen_handle = ""; +my $sock = ""; +my $parent = $$; + +if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { + my ($from, $to) = split(/,/, $ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}); + do_vencrypt_viewer_bridge($from, $to); + exit 0; +} + +my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3); +my ($mode_1st, $mode_2nd, $mode_3rd) = ("", "", ""); + +($first, $mode_1st) = url_parse($first); + +my ($proxy_host, $proxy_port) = ($first, ""); +if ($proxy_host =~ /^(.*):(\d+)$/) { + $proxy_host = $1; + $proxy_port = $2; +} +my $connect = $ENV{PPROXY_DEST}; + +if ($second ne "") { + ($second, $mode_2nd) = url_parse($second); +} + +if ($third ne "") { + ($third, $mode_3rd) = url_parse($third); +} + + +print STDERR "\n"; +print STDERR "PPROXY v0.4: a tool for Web, SOCKS, and UltraVNC proxies and for\n"; +print STDERR "PPROXY v0.4: IPv6 and VNC VeNCrypt bridging.\n"; +print STDERR "proxy_host: $proxy_host\n"; +print STDERR "proxy_port: $proxy_port\n"; +print STDERR "proxy_connect: $connect\n"; +print STDERR "pproxy_params: $ENV{PPROXY_PROXY}\n"; +print STDERR "pproxy_listen: $ENV{PPROXY_LISTEN}\n"; +print STDERR "pproxy_reverse: $ENV{PPROXY_REVERSE}\n"; +print STDERR "io_socket_inet6: $have_inet6\n"; +print STDERR "\n"; +if (1) { + print STDERR "pproxy 1st: $first\t- $mode_1st\n"; + print STDERR "pproxy 2nd: $second\t- $mode_2nd\n"; + print STDERR "pproxy 3rd: $third\t- $mode_3rd\n"; + print STDERR "\n"; +} + +sub pdie { + my $msg = shift; + kill_proxy_pids(); + die "$msg"; +} + +if ($ENV{PPROXY_REVERSE} ne "") { + my ($rhost, $rport) = ($ENV{PPROXY_REVERSE}, ""); + if ($rhost =~ /^(.*):(\d+)$/) { + $rhost = $1; + $rport = $2; + } + $rport = 5900 unless $rport; + my $emsg = ""; + $listen_handle = IO::Socket::INET->new( + PeerAddr => $rhost, + PeerPort => $rport, + Proto => "tcp" + ); + $emsg = $!; + if (! $listen_handle && $have_inet6) { + eval {$listen_handle = IO::Socket::INET6->new( + PeerAddr => $rhost, + PeerPort => $rport, + Proto => "tcp" + );}; + $emsg .= " / $!"; + } + if (! $listen_handle) { + pdie "pproxy: $emsg -- PPROXY_REVERSE\n"; + } + print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n"; + +} elsif ($ENV{PPROXY_LISTEN} ne "") { + my $listen_sock = ""; + my $maxtry = 12; + my $sleep = 5; + my $p2 = ""; + my $emsg = ""; + for (my $i=0; $i < $maxtry; $i++) { + my ($if, $p) = ("", $ENV{PPROXY_LISTEN}); + if ($p =~ /^(.*):(\d+)$/) { + $if = $1; + $p = $2; + } + $p2 = "*:$p"; + if ($if eq "") { + $if = "localhost"; + } + print STDERR "pproxy interface: $if\n"; + + $emsg = ""; + if (($if eq "INADDR_ANY6" || $if eq "::") && $have_inet6) { + eval {$listen_sock = IO::Socket::INET6->new( + Listen => 2, + ReuseAddr => 1, + Domain => AF_INET6, + LocalAddr => "::", + LocalPort => $p, + Proto => "tcp" + );}; + $p2 = ":::$p"; + } elsif ($if =~ /^INADDR_ANY/) { + $listen_sock = IO::Socket::INET->new( + Listen => 2, + ReuseAddr => 1, + LocalPort => $p, + Proto => "tcp" + ); + } elsif (($if eq "INADDR_LOOPBACK6" || $if eq "::1") && $have_inet6) { + $p2 = "::1:$p"; + eval {$listen_sock = IO::Socket::INET6->new( + Listen => 2, + ReuseAddr => 1, + Domain => AF_INET6, + LocalAddr => "::1", + LocalPort => $p, + Proto => "tcp" + );}; + $p2 = "::1:$p"; + } else { + $p2 = "$if:$p"; + $listen_sock = IO::Socket::INET->new( + Listen => 2, + ReuseAddr => 1, + LocalAddr => $if, + LocalPort => $p, + Proto => "tcp" + ); + $emsg = $!; + + if (! $listen_sock && $have_inet6) { + print STDERR "PPROXY_LISTEN: retry with INET6\n"; + eval {$listen_sock = IO::Socket::INET6->new( + Listen => 2, + ReuseAddr => 1, + Domain => AF_INET6, + LocalAddr => $if, + LocalPort => $p, + Proto => "tcp" + );}; + $emsg .= " / $!"; + } + } + if (! $listen_sock) { + if ($i < $maxtry - 1) { + warn "pproxy: $emsg $!\n"; + warn "Could not listen on port $p2, retrying in $sleep seconds... (Ctrl-C to quit)\n"; + sleep $sleep; + } + } else { + last; + } + } + if (! $listen_sock) { + pdie "pproxy: $emsg -- PPROXY_LISTEN\n"; + } + print STDERR "pproxy: listening on $p2\n"; + my $ip; + ($listen_handle, $ip) = $listen_sock->accept(); + my $err = $!; + close $listen_sock; + if (! $listen_handle) { + pdie "pproxy: $err\n"; + } + + if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) { + my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; + if ($sml ne "" && $sml ne "0") { + setpgrp(0, 0); + if (fork()) { + close $viewer_sock; + wait; + exit 0; + } + if (fork()) { + close $viewer_sock; + exit 0; + } + setpgrp(0, 0); + $parent = $$; + } + } +} + +$sock = IO::Socket::INET->new( + PeerAddr => $proxy_host, + PeerPort => $proxy_port, + Proto => "tcp" +); + +my $err = ""; + +if (! $sock && $have_inet6) { + $err = $!; + + eval {$sock = IO::Socket::INET6->new( + PeerAddr => $proxy_host, + PeerPort => $proxy_port, + Proto => "tcp" + );}; + $err .= " / $!"; +} + +if (! $sock) { + unlink($0) if $ENV{PPROXY_REMOVE}; + pdie "pproxy: $err\n"; +} + +unlink($0) if $ENV{PPROXY_REMOVE}; + +if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_VENCRYPT_REVERSE}) { + print STDERR "\nPPROXY: vencrypt+reverse: swapping listen socket with connect socket.\n"; + my $tmp_swap = $sock; + $sock = $listen_handle; + $listen_handle = $tmp_swap; +} + +$cur_proxy = $first; +setmode($mode_1st); + +if ($second ne "") { + connection($second, 1); + + setmode($mode_2nd); + $cur_proxy = $second; + + if ($third ne "") { + connection($third, 2); + setmode($mode_3rd); + $cur_proxy = $third; + connection($connect, 3); + } else { + connection($connect, 2); + } +} else { + connection($connect, 1); +} + +sub kill_proxy_pids() { + if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { + return; + } + if ($ENV{PPROXY_KILLPID}) { + foreach my $p (split(/,/, $ENV{PPROXY_KILLPID})) { + if ($p =~ /^(\+|-)/) { + $p = $parent + $p; + } + print STDERR "kill TERM, $p (PPROXY_KILLPID)\n"; + kill "TERM", $p; + } + } +} + +sub xfer { + my($in, $out) = @_; + $RIN = $WIN = $EIN = ""; + $ROUT = ""; + vec($RIN, fileno($in), 1) = 1; + vec($WIN, fileno($in), 1) = 1; + $EIN = $RIN | $WIN; + + while (1) { + my $nf = 0; + while (! $nf) { + $nf = select($ROUT=$RIN, undef, undef, undef); + } + my $len = sysread($in, $buf, 8192); + if (! defined($len)) { + next if $! =~ /^Interrupted/; + print STDERR "pproxy[$$]: $!\n"; + last; + } elsif ($len == 0) { + print STDERR "pproxy[$$]: Input is EOF.\n"; + last; + } + my $offset = 0; + my $quit = 0; + while ($len) { + my $written = syswrite($out, $buf, $len, $offset); + if (! defined $written) { + print STDERR "pproxy[$$]: Output is EOF. $!\n"; + $quit = 1; + last; + } + $len -= $written; + $offset += $written; + } + last if $quit; + } + close($out); + close($in); + print STDERR "pproxy[$$]: finished xfer.\n"; +} + +sub handler { + print STDERR "pproxy[$$]: got SIGTERM.\n"; + close $listen_handle if $listen_handle; + close $sock if $sock; + exit; +} + +sub xfer_both { + $child = fork; + + if (! defined $child) { + kill_proxy_pids(); + exit 1; + } + + $SIG{TERM} = "handler"; + + if ($child) { + if ($listen_handle) { + print STDERR "pproxy parent[$$] listen_handle -> socket\n"; + xfer($listen_handle, $sock); + } else { + print STDERR "pproxy parent[$$] STDIN -> socket\n"; + xfer(STDIN, $sock); + } + select(undef, undef, undef, 0.25); + if (kill 0, $child) { + select(undef, undef, undef, 0.9); + if (kill 0, $child) { + print STDERR "pproxy[$$]: kill TERM child $child\n"; + kill "TERM", $child; + } else { + print STDERR "pproxy[$$]: child $child gone.\n"; + } + } + } else { + select(undef, undef, undef, 0.05); + if ($listen_handle) { + print STDERR "pproxy child [$$] socket -> listen_handle\n\n"; + xfer($sock, $listen_handle); + } else { + print STDERR "pproxy child [$$] socket -> STDOUT\n\n"; + xfer($sock, STDOUT); + } + select(undef, undef, undef, 0.25); + if (kill 0, $parent) { + select(undef, undef, undef, 0.8); + if (kill 0, $parent) { + print STDERR "pproxy[$$]: kill TERM parent $parent\n"; + kill "TERM", $parent; + } else { + print STDERR "pproxy[$$]: parent $parent gone.\n"; + } + } + } + + kill_proxy_pids(); +} + +xfer_both(); + +exit; + +sub fsleep { + select(undef, undef, undef, shift); +} + +sub url_parse { + my $hostport = shift; + my $mode = "http"; + if ($hostport =~ m,^socks4?://(\S*)$,i) { + $mode = "socks4"; + $hostport = $1; + } elsif ($hostport =~ m,^socks5://(\S*)$,i) { + $mode = "socks5"; + $hostport = $1; + } elsif ($hostport =~ m,^https?://(\S*)$,i) { + $mode = "http"; + $hostport = $1; + } elsif ($hostport =~ m,^ipv6://(\S*)$,i) { + $mode = "ipv6"; + $hostport = $1; + } elsif ($hostport =~ m,^repeater://(\S*)\+(\S*)$,i) { + # ultravnc repeater proxy. + $hostport = $1; + $mode = "repeater:$2"; + if ($hostport !~ /:\d+$/) { + $hostport .= ":5900"; + } + } elsif ($hostport =~ m,^vencrypt://(\S*)$,i) { + # vencrypt handshake. + $hostport = $1; + my $m = "connect"; + if ($hostpost =~ /^(\S+)\+(\S+)$/) { + $hostport = $1; + $mode = $2; + } + $mode = "vencrypt:$m"; + if ($hostport !~ /:\d+$/) { + $hostport .= ":5900"; + } + } + return ($hostport, $mode); +} + +sub setmode { + my $mode = shift; + $ENV{PPROXY_REPEATER} = ""; + $ENV{PPROXY_VENCRYPT} = ""; + if ($mode =~ /^socks/) { + if ($mode =~ /^socks5/) { + $ENV{PPROXY_SOCKS} = 5; + } else { + $ENV{PPROXY_SOCKS} = 1; + } + } elsif ($mode =~ /^ipv6/i) { + $ENV{PPROXY_SOCKS} = 0; + } elsif ($mode =~ /^repeater:(.*)/) { + $ENV{PPROXY_REPEATER} = $1; + $ENV{PPROXY_SOCKS} = ""; + } elsif ($mode =~ /^vencrypt:(.*)/) { + $ENV{PPROXY_VENCRYPT} = $1; + $ENV{PPROXY_SOCKS} = ""; + } else { + $ENV{PPROXY_SOCKS} = ""; + } +} + +sub connection { + my ($CONNECT, $w) = @_; + + my $con = ""; + my $msg = ""; + + if ($ENV{PPROXY_SOCKS} eq "5") { + # SOCKS5 + my ($h, $p) = ($CONNECT, ""); + if ($h =~ /^(.*):(\d+)$/) { + $h = $1; + $p = $2; + } + $con .= pack("C", 0x05); + $con .= pack("C", 0x01); + $con .= pack("C", 0x00); + + $msg = "SOCKS5 via $cur_proxy to $h:$p\n\n"; + print STDERR "proxy_request$w: $msg"; + + syswrite($sock, $con, length($con)); + + my ($n1, $n2, $n3, $n4, $n5, $n6); + my ($r1, $r2, $r3, $r4, $r5, $r6); + my ($s1, $s2, $s3, $s4, $s5, $s6); + + $n1 = sysread($sock, $r1, 1); + $n2 = sysread($sock, $r2, 1); + + $s1 = unpack("C", $r1); + $s2 = unpack("C", $r2); + if ($s1 != 0x05 || $s2 != 0x00) { + print STDERR "SOCKS5 fail s1=$s1 s2=$s2 n1=$n1 n2=$n2\n"; + close $sock; + exit(1); + } + + $con = ""; + $con .= pack("C", 0x05); + $con .= pack("C", 0x01); + $con .= pack("C", 0x00); + $con .= pack("C", 0x03); + $con .= pack("C", length($h)); + $con .= $h; + $con .= pack("C", $p >> 8); + $con .= pack("C", $p & 0xff); + + syswrite($sock, $con, length($con)); + + $n1 = sysread($sock, $r1, 1); + $n2 = sysread($sock, $r2, 1); + $n3 = sysread($sock, $r3, 1); + $n4 = sysread($sock, $r4, 1); + $s1 = unpack("C", $r1); + $s2 = unpack("C", $r2); + $s3 = unpack("C", $r3); + $s4 = unpack("C", $r4); + + if ($s4 == 0x1) { + sysread($sock, $r5, 4 + 2); + } elsif ($s4 == 0x3) { + sysread($sock, $r5, 1); + $s5 = unpack("C", $r5); + sysread($sock, $r6, $s5 + 2); + } elsif ($s4 == 0x4) { + sysread($sock, $r5, 16 + 2); + } + + if ($s1 != 0x5 || $s2 != 0x0 || $s3 != 0x0) { + print STDERR "SOCKS5 failed: s1=$s1 s2=$s2 s3=$s3 s4=$s4 n1=$n1 n2=$n2 n3=$n3 n4=$n4\n"; + close $sock; + exit(1); + } + + } elsif ($ENV{PPROXY_SOCKS} eq "1") { + # SOCKS4 SOCKS4a + my ($h, $p) = ($CONNECT, ""); + if ($h =~ /^(.*):(\d+)$/) { + $h = $1; + $p = $2; + } + $con .= pack("C", 0x04); + $con .= pack("C", 0x01); + $con .= pack("n", $p); + + my $SOCKS_4a = 0; + if ($h eq "localhost" || $h eq "127.0.0.1") { + $con .= pack("C", 127); + $con .= pack("C", 0); + $con .= pack("C", 0); + $con .= pack("C", 1); + } elsif ($h =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { + $con .= pack("C", $1); + $con .= pack("C", $2); + $con .= pack("C", $3); + $con .= pack("C", $4); + } else { + $con .= pack("C", 0); + $con .= pack("C", 0); + $con .= pack("C", 0); + $con .= pack("C", 3); + $SOCKS_4a = 1; + } + + $con .= "nobody"; + $con .= pack("C", 0); + + $msg = "SOCKS4 via $cur_proxy to $h:$p\n\n"; + if ($SOCKS_4a) { + $con .= $h; + $con .= pack("C", 0); + $msg =~ s/SOCKS4/SOCKS4a/; + } + print STDERR "proxy_request$w: $msg"; + syswrite($sock, $con, length($con)); + + my $ok = 1; + for (my $i = 0; $i < 8; $i++) { + my $c; + sysread($sock, $c, 1); + my $s = unpack("C", $c); + if ($i == 0) { + $ok = 0 if $s != 0x0; + } elsif ($i == 1) { + $ok = 0 if $s != 0x5a; + } + } + if (! $ok) { + print STDERR "SOCKS4 failed.\n"; + close $sock; + exit(1); + } + } elsif ($ENV{PPROXY_SOCKS} eq "0") { + # hack for ipv6 "proxy", nothing to do, assume INET6 call worked. + ; + } elsif ($ENV{PPROXY_REPEATER} ne "") { + my $rep = $ENV{PPROXY_REPEATER}; + print STDERR "repeater: $rep\n"; + $rep .= pack("x") x 250; + syswrite($sock, $rep, 250); + + my $ok = 1; + for (my $i = 0; $i < 12; $i++) { + my $c; + sysread($sock, $c, 1); + print STDERR $c; + } + } elsif ($ENV{PPROXY_VENCRYPT} ne "") { + my $vencrypt = $ENV{PPROXY_VENCRYPT}; + vencrypt_dialog($vencrypt); + + } else { + # Web Proxy: + $con = "CONNECT $CONNECT HTTP/1.1\r\n"; + $con .= "Host: $CONNECT\r\n"; + $con .= "Connection: close\r\n\r\n"; + $msg = $con; + + print STDERR "proxy_request$w: via $cur_proxy:\n$msg"; + syswrite($sock, $con, length($con)); + + my $rep = ""; + my $n = 0; + while ($rep !~ /\r\n\r\n/ && $n < 30000) { + my $c; + sysread($sock, $c, 1); + print STDERR $c; + $rep .= $c; + $n++; + } + if ($rep !~ m,HTTP/.* 200,) { + print STDERR "HTTP CONNECT failed.\n"; + close $sock; + exit(1); + } + } +} + +sub vdie { + append_handshake("done\n"); + close $sock; + kill_proxy_pids(); + exit(1); +} + +sub anontls_handshake { + my ($vmode, $db) = @_; + + print STDERR "\nPPROXY: Doing ANONTLS Handshake\n"; + + my $psec = pack("C", $rfbSecTypeAnonTls); + syswrite($sock, $psec, 1); + + append_handshake("done\n"); +} + +sub vencrypt_handshake { + + my ($vmode, $db) = @_; + + print STDERR "\nPPROXY: Doing VeNCrypt Handshake\n"; + + my $psec = pack("C", $rfbSecTypeVencrypt); + + if (exists $ENV{SSVNC_TEST_SEC_TYPE}) { + my $fake = $ENV{SSVNC_TEST_SEC_TYPE}; + print STDERR "PPROXY: sending sec-type: $fake\n"; + $psec = pack("C", $fake); + } + + syswrite($sock, $psec, 1); + + my $vmajor; + my $vminor; + sysread($sock, $vmajor, 1); + sysread($sock, $vminor, 1); + + vdie if $vmajor eq "" || $vminor eq ""; + + $vmajor = unpack("C", $vmajor); + $vminor = unpack("C", $vminor); + print STDERR "server vencrypt version $vmajor.$vminor\n" if $db; + + if (exists $ENV{SSVNC_TEST_SEC_TYPE}) { + print STDERR "PPROXY: continuing on in test mode.\n"; + } else { + vdie if $vmajor ne 0; + vdie if $vminor < 2; + } + + $vmajor = pack("C", 0); + $vminor = pack("C", 2); + append_handshake("subversion=0.2\n"); + + syswrite($sock, $vmajor, 1); + syswrite($sock, $vminor, 1); + + my $result; + sysread($sock, $result, 1); + print STDERR "result empty\n" if $db && $result eq ""; + + vdie if $result eq ""; + $result = unpack("C", $result); + print STDERR "result=$result\n" if $db; + + vdie if $result ne 0; + + my $nsubtypes; + sysread($sock, $nsubtypes, 1); + + vdie if $nsubtypes eq ""; + $nsubtypes = unpack("C", $nsubtypes); + print STDERR "nsubtypes=$nsubtypes\n" if $db; + + my %subtypes; + + for (my $i = 0; $i < $nsubtypes; $i++) { + my $subtype = ""; + sysread($sock, $subtype, 4); + vdie if length($subtype) != 4; + + # XXX fix 64bit. + $subtype = unpack("N", $subtype); + print STDERR "subtype: $subtype\n" if $db; + $subtypes{$subtype} = 1; + append_handshake("sst$i=$subtype\n"); + } + + my $subtype = 0; + if (exists $subtypes{$rfbVencryptX509None}) { + $subtype = $rfbVencryptX509None; + print STDERR "selected rfbVencryptX509None\n" if $db; + } elsif (exists $subtypes{$rfbVencryptX509Vnc}) { + $subtype = $rfbVencryptX509Vnc; + print STDERR "selected rfbVencryptX509Vnc\n" if $db; + } elsif (exists $subtypes{$rfbVencryptX509Plain}) { + $subtype = $rfbVencryptX509Plain; + print STDERR "selected rfbVencryptX509Plain\n" if $db; + } elsif (exists $subtypes{$rfbVencryptTlsNone}) { + $subtype = $rfbVencryptTlsNone; + print STDERR "selected rfbVencryptTlsNone\n" if $db; + } elsif (exists $subtypes{$rfbVencryptTlsVnc}) { + $subtype = $rfbVencryptTlsVnc; + print STDERR "selected rfbVencryptTlsVnc\n" if $db; + } elsif (exists $subtypes{$rfbVencryptTlsPlain}) { + $subtype = $rfbVencryptTlsPlain; + print STDERR "selected rfbVencryptTlsPlain\n" if $db; + } + + if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) { + my $fake = $ENV{SSVNC_TEST_SEC_SUBTYPE}; + print STDERR "PPROXY: sending sec-subtype: $fake\n"; + $subtype = $fake; + } + + append_handshake("subtype=$subtype\n"); + + my $pst = pack("N", $subtype); + syswrite($sock, $pst, 4); + + if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) { + print STDERR "PPROXY: continuing on in test mode.\n"; + } else { + vdie if $subtype == 0; + } + + my $ok; + sysread($sock, $ok, 1); + $ok = unpack("C", $ok); + print STDERR "ok=$ok\n" if $db; + + append_handshake("done\n"); + + vdie if $ok == 0; +} + +sub vencrypt_dialog { + my $vmode = shift; + my $db = 0; + + $db = 1 if exists $ENV{SS_DEBUG}; + $db = 1 if exists $ENV{SSVNC_VENCRYPT_DEBUG}; + + append_handshake("mode=$vmode\n"); + + my $server_rfb = ""; + #syswrite($sock, $rep, 250); + for (my $i = 0; $i < 12; $i++) { + my $c; + sysread($sock, $c, 1); + $server_rfb .= $c; + print STDERR $c; + } + print STDERR "server_rfb: $server_rfb\n" if $db; + append_handshake("server=$server_rfb"); + + my $minor = ""; + if ($server_rfb =~ /^RFB 003\.(\d+)/) { + $minor = $1; + } else { + vdie; + } + my $viewer_rfb = "RFB 003.008\n"; + if ($minor < 7) { + vdie; + } elsif ($minor == 7) { + $viewer_rfb = "RFB 003.007\n"; + } + my $nsec; + my $t1 = gettime(); + my $t0 = gettime(); + + syswrite($sock, $viewer_rfb, 12); + sysread($sock, $nsec, 1); + + $t1 = gettime(); + $t1 = sprintf("%.6f", $t1 - $t0); + + append_handshake("viewer=$viewer_rfb"); + append_handshake("latency=$t1\n"); + + vdie if $nsec eq ""; + + $nsec = unpack("C", $nsec); + + print STDERR "nsec: $nsec\n" if $db; + vdie if $nsec eq 0 || $nsec > 100; + + my %sectypes = (); + + for (my $i = 0; $i < $nsec; $i++) { + my $sec; + sysread($sock, $sec, 1); + vdie if $sec eq ""; + $sec = unpack("C", $sec); + print STDERR "sec: $sec\n" if $db; + $sectypes{$sec} = 1; + } + + if (exists $sectypes{$rfbSecTypeVencrypt}) { + print STDERR "found rfbSecTypeVencrypt\n" if $db; + append_handshake("sectype=$rfbSecTypeVencrypt\n"); + vencrypt_handshake($vmode, $db); + } elsif (exists $sectypes{$rfbSecTypeAnonTls}) { + print STDERR "found rfbSecTypeAnonTls\n" if $db; + append_handshake("sectype=$rfbSecTypeAnonTls\n"); + anontls_handshake($vmode, $db); + } else { + print STDERR "No supported sec-type found\n" if $db; + vdie; + } +} + +sub append_handshake { + my $str = shift; + if ($handshake_file) { + if (open(HSF, ">>$handshake_file")) { + print HSF $str; + close HSF; + } + } +} + +sub do_vencrypt_viewer_bridge { + my ($listen, $connect) = @_; + print STDERR "\npproxy: starting vencrypt_viewer_bridge[$$]: $listen \-> $connect\n"; + my $db = 0; + my $backwards = 0; + if ($listen < 0) { + $backwards = 1; + $listen = -$listen; + } + if ($handshake_file eq "") { + die "pproxy: vencrypt_viewer_bridge[$$]: no SSVNC_PREDIGESTED_HANDSHAKE\n"; + } + my $listen_sock; + my $maxtry = 12; + my $sleep = 5; + for (my $i=0; $i < $maxtry; $i++) { + $listen_sock = IO::Socket::INET->new( + Listen => 2, + ReuseAddr => 1, + LocalAddr => "127.0.0.1", + LocalPort => $listen, + Proto => "tcp" + ); + if (! $listen_sock) { + if ($i < $maxtry - 1) { + warn "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; + warn "Could not listen on port $listen, retrying in $sleep seconds... (Ctrl-C to quit)\n"; + sleep $sleep; + } + } else { + last; + } + } + if (! $listen_sock) { + die "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; + } + print STDERR "pproxy: vencrypt_viewer_bridge[$$]: listening on port $listen\n\n"; + my ($viewer_sock, $ip) = $listen_sock->accept(); + my $err = $!; + close $listen_sock; + if (! $viewer_sock) { + die "pproxy: vencrypt_viewer_bridge[$$]: $err\n"; + } + if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) { + my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; + if ($sml ne "" && $sml ne "0") { + setpgrp(0, 0); + if (fork()) { + close $viewer_sock; + wait; + exit 0; + } + if (fork()) { + close $viewer_sock; + exit 0; + } + setpgrp(0, 0); + $parent = $$; + } + } + print STDERR "vencrypt_viewer_bridge[$$]: viewer_sock $viewer_sock\n" if $db; + + print STDERR "pproxy: vencrypt_viewer_bridge[$$]: connecting to 127.0.0.1:$connect\n"; + my $server_sock = IO::Socket::INET->new( + PeerAddr => "127.0.0.1", + PeerPort => $connect, + Proto => "tcp" + ); + print STDERR "vencrypt_viewer_bridge[$$]: server_sock $server_sock\n" if $db; + if (! $server_sock) { + my $err = $!; + die "pproxy: vencrypt_viewer_bridge[$$]: $err\n"; + } + + if ($backwards) { + print STDERR "vencrypt_viewer_bridge[$$]: reversing roles of viewer and server.\n"; + my $t = $viewer_sock; + $viewer_sock = $server_sock; + $server_sock = $t; + } + + my %hs = (); + my $dt = 0.2; + my $slept = 0.0; + while ($slept < 20.0) { + select(undef, undef, undef, $dt); + $slept += $dt; + if (-f $handshake_file && open(HSF, "<$handshake_file")) { + my $done = 0; + %hs = (); + my $str = ""; + while () { + print STDERR "vencrypt_viewer_bridge[$$]: $_" if $ENV{VENCRYPT_VIEWER_BRIDGE_DEBUG}; + $str .= "vencrypt_viewer_bridge[$$]: $_"; + chomp; + if ($_ eq "done") { + $done = 1; + } else { + my ($k, $v) = split(/=/, $_, 2); + if ($k ne "" && $v ne "") { + $hs{$k} = $v; + } + } + } + close HSF; + if ($done) { + print STDERR "\n" . $str; + last; + } + } + } + if (! exists $hs{server}) { + $hs{server} = "RFB 003.008"; + } + if (! exists $hs{sectype}) { + unlink($handshake_file); + die "pproxy: vencrypt_viewer_bridge[$$]: no sectype.\n"; + } + syswrite($viewer_sock, "$hs{server}\n", length($hs{server}) + 1); + my $viewer_rfb = ""; + for (my $i = 0; $i < 12; $i++) { + my $c; + sysread($viewer_sock, $c, 1); + $viewer_rfb .= $c; + print STDERR $c; + } + my $viewer_major = 3; + my $viewer_minor = 8; + if ($viewer_rfb =~ /RFB (\d+)\.(\d+)/) { + $viewer_major = $1; + $viewer_minor = $2; + } + my $u0 = pack("C", 0); + my $u1 = pack("C", 1); + my $u2 = pack("C", 2); + if ($hs{sectype} == $rfbSecTypeAnonTls) { + unlink($handshake_file); + print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeAnonTls\n"; + if ($viewer_major > 3 || $viewer_minor >= 7) { + ; # setup ok, proceed to xfer. + } else { + print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; + my $n; + sysread($server_sock, $n, 1); + $n = unpack("C", $n); + if ($n == 0) { + die "pproxy: vencrypt_viewer_bridge[$$]: nsectypes == $n.\n"; + } + my %types; + for (my $i = 0; $i < $n; $i++) { + my $t; + sysread($server_sock, $t, 1); + $t = unpack("C", $t); + $types{$t} = 1; + } + my $use = 1; # None + if (exists $types{1}) { + $use = 1; # None + } elsif (exists $types{2}) { + $use = 2; # VncAuth + } else { + die "pproxy: vencrypt_viewer_bridge[$$]: no valid sectypes" . join(",", keys %types) . "\n"; + } + + # send 4 bytes sectype to viewer: + # (note this should be MSB, network byte order...) + my $up = pack("C", $use); + syswrite($viewer_sock, $u0, 1); + syswrite($viewer_sock, $u0, 1); + syswrite($viewer_sock, $u0, 1); + syswrite($viewer_sock, $up, 1); + # and tell server the one we selected: + syswrite($server_sock, $up, 1); + if ($use == 1) { + # even None has security result, so read it here and discard it. + my $sr = ""; + sysread($server_sock, $sr, 4); + } + } + } elsif ($hs{sectype} == $rfbSecTypeVencrypt) { + print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeVencrypt\n"; + if (! exists $hs{subtype}) { + unlink($handshake_file); + die "pproxy: vencrypt_viewer_bridge[$$]: no subtype.\n"; + } + my $fake_type = "None"; + my $plain = 0; + my $sub_type = $hs{subtype}; + if ($sub_type == $rfbVencryptTlsNone) { + $fake_type = "None"; + } elsif ($sub_type == $rfbVencryptTlsVnc) { + $fake_type = "VncAuth"; + } elsif ($sub_type == $rfbVencryptTlsPlain) { + $fake_type = "None"; + $plain = 1; + } elsif ($sub_type == $rfbVencryptX509None) { + $fake_type = "None"; + } elsif ($sub_type == $rfbVencryptX509Vnc) { + $fake_type = "VncAuth"; + } elsif ($sub_type == $rfbVencryptX509Plain) { + $fake_type = "None"; + $plain = 1; + } + if ($plain) { + if (!open(W, ">$handshake_file")) { + unlink($handshake_file); + die "pproxy: vencrypt_viewer_bridge[$$]: $handshake_file $!\n"; + } + print W <<"END"; + + proc print_out {} { + global user pass env + + if [info exists env(SSVNC_UP_DEBUG)] { + toplevel .b + button .b.b -text "user=\$user pass=\$pass" -command {destroy .b} + pack .b.b + update + tkwait window .b + } + + if [info exists env(SSVNC_UP_FILE)] { + set fh "" + catch {set fh [open \$env(SSVNC_UP_FILE) w]} + if {\$fh != ""} { + puts \$fh user=\$user\\npass=\$pass + flush \$fh + close \$fh + return + } + } + puts stdout user=\$user\\npass=\$pass + flush stdout + } + + proc center_win {w} { + update + set W [winfo screenwidth \$w] + set W [expr \$W + 1] + wm geometry \$w +\$W+0 + update + set x [expr [winfo screenwidth \$w]/2 - [winfo width \$w]/2] + set y [expr [winfo screenheight \$w]/2 - [winfo height \$w]/2] + + wm geometry \$w +\$x+\$y + wm deiconify \$w + update + } + + wm withdraw . + + global env + set up {} + if [info exists env(SSVNC_UNIXPW)] { + set rm 0 + set up \$env(SSVNC_UNIXPW) + if [regexp {^rm:} \$up] { + set rm 1 + regsub {^rm:} \$up {} up + } + if [file exists \$up] { + set fh "" + set f \$up + catch {set fh [open \$up r]} + if {\$fh != ""} { + gets \$fh u + gets \$fh p + close \$fh + set up "\$u@\$p" + } + if {\$rm} { + catch {file delete \$f} + } + } + } elseif [info exists env(SSVNC_VENCRYPT_USERPASS)] { + set up \$env(SSVNC_VENCRYPT_USERPASS) + } + #puts stderr up=\$up + if {\$up != ""} { + if [regexp {@} \$up] { + global user pass + set user \$up + set pass \$up + regsub {@.*\$} \$user "" user + regsub {^[^@]*@} \$pass "" pass + print_out + exit + } + } + + wm title . {VeNCrypt Viewer Bridge User/Pass} + + set user {} + set pass {} + + label .l -text {SSVNC VeNCrypt Viewer Bridge} + + frame .f0 + frame .f0.fL + label .f0.fL.la -text {Username: } + label .f0.fL.lb -text {Password: } + + pack .f0.fL.la .f0.fL.lb -side top + + frame .f0.fR + entry .f0.fR.ea -width 24 -textvariable user + entry .f0.fR.eb -width 24 -textvariable pass -show * + + pack .f0.fR.ea .f0.fR.eb -side top -fill x + + pack .f0.fL -side left + pack .f0.fR -side right -expand 1 -fill x + + button .no -text Cancel -command {destroy .} + button .ok -text Done -command {print_out; destroy .} + + center_win . + pack .l .f0 .no .ok -side top -fill x + update + wm deiconify . + + bind .f0.fR.ea {focus .f0.fR.eb} + bind .f0.fR.eb {print_out; destroy .} + focus .f0.fR.ea + + wm resizable . 1 0 + wm minsize . [winfo reqwidth .] [winfo reqheight .] +END + close W; + + #system("cat $handshake_file"); + my $w = "wish"; + if ($ENV{WISH}) { + $w = $ENV{WISH}; + } + print STDERR "pproxy: vencrypt_viewer_bridge[$$]: prompt VencryptPlain user and passwd.\n"; + my $res = ""; + if (`uname` =~ /Darwin/) { + my $mtmp = `mktemp /tmp/hsup.XXXXXX`; + chomp $mtmp; + system("env SSVNC_UP_FILE=$mtmp $w $handshake_file"); + $res = `cat $mtmp`; + unlink $mtmp; + } else { + $res = `$w $handshake_file`; + } + my $user = ""; + my $pass = ""; + if ($res =~ /user=(\S*)/) { + $user = $1; + } + if ($res =~ /pass=(\S*)/) { + $pass = $1; + } + print STDERR "pproxy: vencrypt_viewer_bridge[$$]: sending VencryptPlain user and passwd.\n"; + my $ulen = pack("C", length($user)); + my $plen = pack("C", length($pass)); + # (note this should be MSB, network byte order...) + syswrite($server_sock, $u0, 1); + syswrite($server_sock, $u0, 1); + syswrite($server_sock, $u0, 1); + syswrite($server_sock, $ulen, 1); + syswrite($server_sock, $u0, 1); + syswrite($server_sock, $u0, 1); + syswrite($server_sock, $u0, 1); + syswrite($server_sock, $plen, 1); + syswrite($server_sock, $user, length($user)); + syswrite($server_sock, $pass, length($pass)); + } + unlink($handshake_file); + + my $ft = 0; + if ($fake_type eq "None") { + $ft = 1; + } elsif ($fake_type eq "VncAuth") { + $ft = 2; + } else { + die "pproxy: vencrypt_viewer_bridge[$$]: unknown fake type: $fake_type\n"; + } + my $fp = pack("C", $ft); + if ($viewer_major > 3 || $viewer_minor >= 7) { + syswrite($viewer_sock, $u1, 1); + syswrite($viewer_sock, $fp, 1); + my $cr; + sysread($viewer_sock, $cr, 1); + $cr = unpack("C", $cr); + if ($cr != $ft) { + die "pproxy: vencrypt_viewer_bridge[$$]: client selected wrong type: $cr / $ft\n"; + } + } else { + print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; + # send 4 bytes sect type to viewer: + # (note this should be MSB, network byte order...) + syswrite($viewer_sock, $u0, 1); + syswrite($viewer_sock, $u0, 1); + syswrite($viewer_sock, $u0, 1); + syswrite($viewer_sock, $fp, 1); + if ($ft == 1) { + # even None has security result, so read it here and discard it. + my $sr = ""; + sysread($server_sock, $sr, 4); + } + } + } + + $listen_handle = $viewer_sock; + $sock = $server_sock; + + xfer_both(); +} +' + # ' + # xpg_echo will expand \n \r, etc. + # try to unset and then test for it. + if type shopt > /dev/null 2>&1; then + shopt -u xpg_echo >/dev/null 2>&1 + fi + v='print STDOUT "abc\n";' + echo "$v" > $tf + chmod 700 $tf + + lc=`wc -l $tf | awk '{print $1}'` + if [ "X$lc" = "X1" ]; then + echo "$cod" > $tf + else + printf "%s" "$cod" > $tf + echo "" >> $tf + fi + # prime perl + perl -e 'use IO::Socket::INET; select(undef, undef, undef, 0.01)' >/dev/null 2>&1 +} + +# make_tcert is no longer invoked via the ssvnc gui (Listen mode). +# make_tcert is for testing only now via -mycert BUILTIN +make_tcert() { + tcert="/tmp/ss_vnc_viewer_tcert${RANDOM}.$$" + tcert=`mytmp "$tcert"` + cat > $tcert < Advanced -> Private SSH KnownHosts file' (or set" + echo "** Warning: SSVNC_KNOWN_HOSTS_FILE directly) to a per-connection known hosts" + echo "** Warning: file. That file holds the 'localhost' cert for this specific" + echo "** Warning: connection. This yields a both secure and convenient solution." + echo "" +} + +# handle ssh case: +# +if [ "X$use_ssh" = "X1" ]; then + # + # USING SSH + # + ssh_port="22" + ssh_host="$host" + vnc_host="$localhost" + ssh_UKHF="" + localhost_extra="" + # let user override ssh via $SSH + ssh=${SSH:-"ssh -x"} + + sshword=`echo "$ssh" | awk '{print $1}'` + if [ "X$sshword" != "X" ]; then + if [ -x "$sshword" ]; then + : + elif type "$sshword" > /dev/null 2>&1; then + : + else + echo "" + echo "*********************************************************" + echo "** Problem finding the SSH command '$sshword': **" + echo "" + type "$sshword" + echo "" + echo "** Perhaps you need to install the SSH client package. **" + echo "*********************************************************" + echo "" + sleep 5 + fi + fi + + ssh_NHAFL="-o NoHostAuthenticationForLocalhost=yes" + if [ "X$SSVNC_SSH_LOCALHOST_AUTH" = "X1" ]; then + ssh_NHAFL="" + fi + if [ "X$SSVNC_KNOWN_HOSTS_FILE" != "X" ]; then + ssh_NHAFL="" + + ssh_UKHF="-o UserKnownHostsFile=$SSVNC_KNOWN_HOSTS_FILE" + ssh_args="$ssh_args $ssh_UKHF" + if [ ! -f "$SSVNC_KNOWN_HOSTS_FILE" ]; then + touch "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 + fi + chmod 600 "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 + fi + did_ssh_NHAFL="" + + if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then + SSVNC_LIM_ACCEPT_PRELOAD="$SSVNC_BASEDIR/$SSVNC_UNAME/$SSVNC_LIM_ACCEPT_PRELOAD" + fi + if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then + echo "" + echo "SSVNC_LIM_ACCEPT_PRELOAD=$SSVNC_LIM_ACCEPT_PRELOAD" + fi + + if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" -a -f "$SSVNC_LIM_ACCEPT_PRELOAD" ]; then + plvar=LD_PRELOAD + if uname | grep Darwin >/dev/null; then + plvar="DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES" + fi + ssh="env $plvar=$SSVNC_LIM_ACCEPT_PRELOAD $ssh" + else + SSVNC_LIM_ACCEPT_PRELOAD="" + fi + + ssh_vencrypt_proxy="" + # We handle vencrypt for SSH+SSL mode. + if echo "$proxy" | grep 'vencrypt://' > /dev/null; then + proxynew="" + for part in `echo "$proxy" | tr ',' ' '` + do + if echo "$part" | egrep -i '^vencrypt://' > /dev/null; then + ssh_vencrypt_proxy=$part + else + if [ "X$proxynew" = "X" ]; then + proxynew="$part" + else + proxynew="$proxynew,$part" + fi + fi + done + proxy=$proxynew + fi + Kecho ssh_vencrypt_proxy=$ssh_vencrypt_proxy + + # note that user must supply http:// for web proxy in SSH and SSH+SSL. + # No xxxx:// implies ssh server+port. + # + if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then + # Handle Web or SOCKS proxy(ies) for the initial connect. + Kecho host=$host + Kecho port=$port + pproxy="" + sproxy1="" + sproxy_rest="" + for part in `echo "$proxy" | tr ',' ' '` + do + Kecho proxy_part=$part + if [ "X$part" = "X" ]; then + continue + elif echo "$part" | egrep -i '^(http|https|socks|socks4|socks5)://' > /dev/null; then + pproxy="$pproxy,$part" + else + if [ "X$sproxy1" = "X" ]; then + sproxy1="$part" + else + sproxy_rest="$sproxy_rest,$part" + fi + fi + done + pproxy=`echo "$pproxy" | sed -e 's/^,,*//' -e 's/,,*/,/g'` + sproxy_rest=`echo "$sproxy_rest" | sed -e 's/^,,*//' -e 's/,,*/,/g'` + + Kecho pproxy=$pproxy + Kecho sproxy1=$sproxy1 + Kecho sproxy_rest=$sproxy_rest + + sproxy1_host="" + sproxy1_port="" + sproxy1_user="" + + if [ "X$sproxy1" != "X" ]; then + sproxy1_host=`echo "$sproxy1" | awk -F: '{print $1}'` + sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'` + sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'` + if [ "X$sproxy1_host" = "X" ]; then + sproxy1_host=$sproxy1_user + sproxy1_user="" + else + sproxy1_user="${sproxy1_user}@" + fi + sproxy1_port=`echo "$sproxy1" | awk -F: '{print $2}'` + if [ "X$sproxy1_port" = "X" ]; then + sproxy1_port="22" + fi + else + sproxy1_host=`echo "$host" | awk -F: '{print $1}'` + sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'` + sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'` + if [ "X$sproxy1_host" = "X" ]; then + sproxy1_host=$sproxy1_user + sproxy1_user="" + else + sproxy1_user="${sproxy1_user}@" + fi + sproxy1_port=`echo "$host" | awk -F: '{print $2}'` + if [ "X$sproxy1_port" = "X" ]; then + sproxy1_port="22" + fi + fi + + Kecho sproxy1_host=$sproxy1_host + Kecho sproxy1_port=$sproxy1_port + Kecho sproxy1_user=$sproxy1_user + + ptmp="/tmp/ss_vncviewer_ssh${RANDOM}.$$.pl" + ptmp=`mytmp "$ptmp"` + PPROXY_REMOVE=1; export PPROXY_REMOVE + proxy=$pproxy + port_save=$port + host_save=$host + if [ "X$sproxy1_host" != "X" ]; then + host=$sproxy1_host + fi + if [ "X$sproxy1_port" != "X" ]; then + port=$sproxy1_port + fi + host=`echo "$host" | sed -e 's/^.*@//'` + port=`echo "$port" | sed -e 's/^.*://'` + pcode "$ptmp" + port=$port_save + host=$host_save + + nd=`findfree 6600` + PPROXY_LISTEN=$nd; export PPROXY_LISTEN + # XXX no reverse forever PPROXY_LOOP_THYSELF ... + $ptmp & + sleep 1 + if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then + NHAFL_warning + ssh_args="$ssh_args $ssh_NHAFL" + did_ssh_NHAFL=1 + fi + sleep 1 + if [ "X$sproxy1" = "X" ]; then + u="" + if echo "$host" | grep '@' > /dev/null; then + u=`echo "$host" | sed -e 's/@.*$/@/'` + fi + + proxy="${u}$localhost:$nd" + else + proxy="${sproxy1_user}$localhost:$nd" + fi + localhost_extra=".2" + if [ "X$sproxy_rest" != "X" ]; then + proxy="$proxy,$sproxy_rest" + fi + Kecho proxy=$proxy + fi + + if echo "$proxy" | grep "," > /dev/null; then + + proxy1=`echo "$proxy" | awk -F, '{print $1}'` + proxy2=`echo "$proxy" | awk -F, '{print $2}'` + + # user1@gw1.com:port1,user2@ws2:port2 + ssh_host1=`echo "$proxy1" | awk -F: '{print $1}'` + ssh_port1=`echo "$proxy1" | awk -F: '{print $2}'` + if [ "X$ssh_port1" != "X" ]; then + ssh_port1="-p $ssh_port1" + fi + ssh_host2=`echo "$proxy2" | awk -F: '{print $1}'` + ssh_user2=`echo "$ssh_host2" | awk -F@ '{print $1}'` + ssh_host2=`echo "$ssh_host2" | awk -F@ '{print $2}'` + if [ "X$ssh_host2" = "X" ]; then + ssh_host2=$ssh_user2 + ssh_user2="" + else + ssh_user2="${ssh_user2}@" + fi + ssh_port2=`echo "$proxy2" | awk -F: '{print $2}'` + if [ "X$ssh_port2" = "X" ]; then + ssh_port2="22" + fi + proxport=`findfree 3500` + if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then + NHAFL_warning + did_ssh_NHAFL=1 + sleep 1 + fi + echo + echo "Running 1st ssh proxy:" + ukhf="" + if [ "X$ssh_UKHF" != "X" ]; then + ukhf="$ssh_UKHF$localhost_extra" + fi + echo "$ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 \"sleep 30\"" + echo "" + $ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 "sleep 30" + ssh_args="$ssh_args $ssh_NHAFL" + sleep 1 + stty sane + proxy="${ssh_user2}$localhost:$proxport" + fi + + if [ "X$proxy" != "X" ]; then + ssh_port=`echo "$proxy" | awk -F: '{print $2}'` + if [ "X$ssh_port" = "X" ]; then + ssh_port="22" + fi + ssh_host=`echo "$proxy" | awk -F: '{print $1}'` + vnc_host="$host" + fi + + echo "" + echo "Running ssh:" + sz=`echo "$ssh_cmd" | wc -c` + if [ "$sz" -gt 300 ]; then + info="..." + else + info="$ssh_cmd" + fi + + C="" + if [ "X$SS_VNCVIEWER_USE_C" != "X" ]; then + C="-C" + fi + + getport="" + teeport="" + if echo "$ssh_cmd" | egrep "(PORT=|P=) " > /dev/null; then + getport=1 + if echo "$ssh_cmd" | egrep "P= " > /dev/null; then + teeport=1 + fi + + PORT="" + ssh_cmd=`echo "$ssh_cmd" | sed -e 's/PORT=[ ]*//' -e 's/P=//'` + SSVNC_NO_ENC_WARN=1 + if [ "X$use_sshssl" = "X" ]; then + direct_connect=1 + fi + fi + if [ "X$getport" != "X" ]; then + ssh_redir="-D ${use}" + elif [ "X$reverse" = "X" ]; then + ssh_redir="-L ${use}:${vnc_host}:${port}" + else + ssh_redir="-R ${port}:${vnc_host}:${use}" + fi + pmark=`sh -c 'echo $$'` + + # the -t option actually speeds up typing response via VNC!! + if [ "X$ssh_port" = "X22" ]; then + ssh_port="" + else + ssh_port="-p $ssh_port" + fi + + if [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then + echo "$ssh -x $ssh_port $targ $C $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x $ssh_port $targ $C $ssh_args $ssh_host "$ssh_cmd" + exit $? + + elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then + echo "$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd" + rc=$? + + elif [ "X$getport" != "X" ]; then + tport=/tmp/ss_vncviewer_tport${RANDOM}.$$ + tport=`mytmp "$tport"` + tport2=/tmp/ss_vncviewer_tport2${RANDOM}.$$ + tport2=`mytmp "$tport2"` + + if [ "X$rsh" != "X1" ]; then + if echo "$ssh_cmd" | grep "sudo " > /dev/null; then + echo "" + echo "Initial ssh with 'sudo id' to prime sudo so hopefully the next one" + echo "will require no password..." + echo "" + targ="-t" + $ssh -x $ssh_port $targ $ssh_args $ssh_host "sudo id; tty" + echo "" + fi + echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd" > $tport 2> $tport2 + if [ "X$teeport" = "X1" ]; then + tail -f $tport 1>&2 & + tail_pid=$! + tail -f $tport2 1>&2 & + tail_pid2=$! + fi + rc=$? + else + rsh_setup + echo "rsh $ul $ssh_host \"$ssh_cmd\"" + echo "" + rsh $ul $ssh_host "$ssh_cmd" > $tport & + sleep 1 + rc=0 + fi + + if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then + echo "sleep $SSVNC_EXTRA_SLEEP" + sleep $SSVNC_EXTRA_SLEEP + fi + + stty sane + i=0 + if type perl > /dev/null 2>&1; then + imax=50 + sleepit="perl -e 'select(undef, undef, undef, 0.20)'" + else + imax=10 + sleepit="sleep 1" + fi + while [ $i -lt $imax ]; do + #echo $sleepit + eval $sleepit + PORT=`grep "^PORT=" $tport | tr '\r' ' ' | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g' -e 's/ *$//'` + if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then + break + fi + vnss=`sed -e 's/\r//g' $tport $tport2 | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'` + if [ "X$vnss" != "X" ]; then + PORT=`echo "$vnss" | awk -F: '{print $2}'` + if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then + if [ $PORT -lt 100 ]; then + PORT=`expr $PORT + 5900` + fi + fi + if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then + vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1` + echo "vncserver string: $vnss" 1>&2 + break + fi + fi + i=`expr $i + 1` + done + + echo "found: PORT='$PORT'" 1>&2 + rm -f $tport $tport2 + if [ "X$rsh" = "X1" ]; then + rsh_viewer "$@" + exit $? + fi + PPROXY_SOCKS=1 + if [ "X$SSVNC_SOCKS5" != "X" ]; then + PPROXY_SOCKS=5 + fi + export PPROXY_SOCKS + host="$localhost" + port="$PORT" + proxy="$localhost:$use" + + else + if [ "X$rsh" != "X1" ]; then + echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd" + rc=$? + else + rsh_setup + echo "rsh $ul $ssh_host \"$ssh_cmd\"" + echo "" + rsh $ul $ssh_host "$ssh_cmd" & + sleep 1 + PORT=$port + rsh_viewer "$@" + exit $? + fi + fi + + if [ "$rc" != "0" ]; then + echo "" + echo "ssh to $ssh_host failed." + exit 1 + fi + stty sane + + c=0 + pssh="" + while [ $c -lt 40 ] + do + p=`expr $pmark + $c` + pout=`ps -p "$p" 2>/dev/null | grep -v '^[ ]*PID' | sed -e 's/-L.*$//' -e 's/-x .*$//'` + if echo "$pout" | grep "ssh" > /dev/null; then + if echo "$pout" | egrep -i 'ssh.*(-add|-agent|-ask|-keygen|-argv0|vnc)' >/dev/null; then + : + elif echo "$pout" | egrep -i 'scp|sshd' >/dev/null; then + : + else + pssh=$p + break + fi + fi + c=`expr $c + 1` + done + if [ "X$getport" != "X" ]; then + : + elif [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ] ; then + sleep 2 + elif [ "X$ssh_cmd" = "Xsleep $ssh_sleep" ] ; then + #echo T sleep 1 + sleep 1 + elif echo "$ssh_cmd" | grep '^sleep ' >/dev/null; then + #echo T sleep 2 + sleep 2 + else + # let any command get started a bit. + #echo T sleep 5 + sleep 5 + fi + echo "" + #reset + stty sane + if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then + echo "sleep $SSVNC_EXTRA_SLEEP" + sleep $SSVNC_EXTRA_SLEEP + fi + echo "ssh_pid='$pssh'"; echo + if [ "X$use_sshssl" = "X" -a "X$getport" = "X" ]; then + echo "Running viewer:" + + trap "final" 0 2 15 + if [ "X$reverse" = "X" ]; then + echo "$VNCVIEWERCMD" "$@" $localhost:$N + echo "" + $VNCVIEWERCMD "$@" $localhost:$N + if [ $? != 0 ]; then + echo "vncviewer command failed: $?" + if [ "X$secondtry" = "X1" ]; then + sleep 2 + $VNCVIEWERCMD "$@" $localhost:$N + fi + fi + else + echo "" + echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." + echo "" + N2=$N + if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then + N2=`echo "$N2" | sed -e 's/://g'` + if [ $N2 -le 200 ]; then + N2=`expr $N2 + 5500` + fi + fi + echo "$VNCVIEWERCMD" "$@" -listen $N2 + echo "" + $VNCVIEWERCMD "$@" -listen $N2 + fi + + exit $? + else + use2=`findfree 5960` + host0=$host + port0=$port + host=$localhost + port=$use + use=$use2 + N=`expr $use - 5900` + if [ "X$getport" != "X" ]; then + host="$host0" + port="$port0" + else + proxy="" + fi + if [ "X$ssh_vencrypt_proxy" != "X" ]; then + ssh_vencrypt_proxy="vencrypt://$host:$port" + if [ "X$proxy" = "X" ]; then + proxy=$ssh_vencrypt_proxy + else + proxy="$proxy,$ssh_vencrypt_proxy" + fi + Kecho "proxy_now=$proxy" + unset PPROXY_LISTEN + fi + fi +fi + +if [ "X$stunnel_set_here" = "X1" -a "X$showcert" = "X" ]; then + if type $STUNNEL > /dev/null 2>&1; then + : + else + echo "" + echo "***************************************************************" + echo "** Problem finding the Stunnel command '$STUNNEL': **" + echo "" + type $STUNNEL + echo "" + echo "** Perhaps you need to install the stunnel/stunnel4 package. **" + echo "***************************************************************" + echo "" + sleep 5 + fi +fi + +# create the stunnel config file: +if [ "X$verify" != "X" ]; then + if [ -d $verify ]; then + verify="CApath = $verify" + else + verify="CAfile = $verify" + fi + verify="$verify +verify = 2" +fi +if [ "X$SSVNC_STUNNEL_VERIFY3" != "X" ]; then + verify=`echo "$verify" | sed -e 's/verify = 2/verify = 3/'` +fi +if [ "X$mycert" != "X" ]; then + cert="cert = $mycert" +fi +if [ "X$crl" != "X" ]; then + if [ -d $crl ]; then + crl="CRLpath = $crl" + else + crl="CRLfile = $crl" + fi +fi + +if [ "X$showcert" = "X1" ]; then + if [ "X$ipv6" = "X1" -a "X$proxy" = "X" ]; then + proxy="ipv6://$host:$port" + fi +fi + +if [ "X$direct_connect" != "X" -a "X$STUNNEL_LISTEN" != "X" ]; then + proxy=reverse_direct +fi + +ptmp="" +if [ "X$proxy" != "X" ]; then + ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl" + ptmp=`mytmp "$ptmp"` + PPROXY_REMOVE=1; export PPROXY_REMOVE + pcode "$ptmp" + if [ "X$showcert" != "X1" -a "X$direct_connect" = "X" ]; then + if uname | egrep 'Darwin|SunOS' >/dev/null; then + vout=`echo "$proxy" | grep -i vencrypt` + if [ "X$vout" != "X" -a "X$reverse" = "X1" ]; then + # need to exec for reverse vencrypt + connect="exec = $ptmp" + else + # on mac and solaris we need to listen on socket instead of stdio: + nd=`findfree 6700` + PPROXY_LISTEN=$nd + export PPROXY_LISTEN + if [ "X$reverse" = "X" ]; then + $ptmp & + fi + sleep 2 + host="$localhost" + port="$nd" + connect="connect = $localhost:$nd" + fi + else + # otherwise on unix we can exec it: + connect="exec = $ptmp" + fi + else + connect="exec = $ptmp" + fi +else + connect="connect = $host:$port" +fi + +# handle showcert case: +# +if [ "X$showcert" = "X1" ]; then + if [ "X$proxy" != "X" ]; then + PPROXY_LISTEN=$use + export PPROXY_LISTEN + if [ "X$SS_DEBUG" != "X" ]; then + $ptmp & + else + $ptmp 2>/dev/null & + fi + sleep 1 + more_sleep=1 + if uname | grep Linux > /dev/null; then + if netstat -ant | grep LISTEN | grep "127.0.0.1:$use" > /dev/null; then + more_sleep="" + fi + elif uname | grep SunOS > /dev/null; then + if netstat -an -f inet -P tcp | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then + more_sleep="" + fi + elif uname | egrep -i 'bsd|darwin' > /dev/null; then + if netstat -ant -f inet | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then + more_sleep="" + fi + fi + if [ "X$more_sleep" = "X1" ]; then + sleep 1 + fi + host="$localhost" + port="$use" + fi + cipher_args="" + if [ "X$ciphers" != "X" ]; then + cipher_args=`echo "$ciphers" | sed -e 's/ciphers=/-cipher /'` + fi + if type openssl > /dev/null 2>&1; then + : + else + echo "" + echo "********************************************************" + echo "** Problem finding the OpenSSL command 'openssl': **" + echo "" + type openssl 2>&1 + echo "" + echo "** Perhaps you need to install the 'openssl' package. **" + echo "********************************************************" + echo "" + fi + #echo "openssl s_client $cipher_args -connect $host:$port" + if [ "X$reverse" = "X" ]; then + host $host >/dev/null 2>&1 + host $host >/dev/null 2>&1 + timeout=15 + if [ "X$SSVNC_FETCH_TIMEOUT" != "X" ]; then + timeout=$SSVNC_FETCH_TIMEOUT + fi + if type pkill >/dev/null 2>&1; then + (sleep $timeout; if kill -0 $$; then pkill -TERM -f "openssl.*s_client.*$host.*$port"; fi) >/dev/null 2>&1 & + fi + openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null + rc=$? + else + tcert="" + if [ "X$mycert" = "X" ]; then + tcert=`make_tcert` + cert_args="-cert $tcert -CAfile $tcert" + else + cert_args="-cert $mycert -CAfile $mycert" + fi + tmp_out=/tmp/showcert_out${RANDOM}.$$ + tmp_out=`mytmp "$tmp_out"` + tmp_err=/tmp/showcert_err${RANDOM}.$$ + tmp_err=`mytmp "$tmp_err"` + + #echo "openssl s_server $cipher_args $cert_args -accept $port -verify 2 > $tmp_out 2> $tmp_err" 1>&2 + + # assume we have perl: + check_perl perl + + perl -e " + \$p = open(O, \"|openssl s_server $cipher_args $cert_args -accept $port -verify 2 1>$tmp_out 2> $tmp_err\"); + exit 1 unless \$p; + while (1) { + sleep 1; + if (!open(F, \"<$tmp_out\")) { + kill \$p; + exit 1; + } + while () { + if (/RFB 00/) { + fsleep(0.25); + print O \"RFB 000.000\\n\"; + fsleep(1.00); + kill \$p; + fsleep(0.25); + exit 0; + } + } + close F; + } + sub fsleep { + select(undef, undef, undef, shift); + } + "; + + echo "" + cat $tmp_out + echo "" + echo "----2----" + cat $tmp_err + if grep BEGIN.CERTIFICATE $tmp_out >/dev/null; then + rc=0 + else + rc=1 + fi + + rm -f $tmp_out $tmp_err + fi + if [ "X$SSVNC_PREDIGESTED_HANDSHAKE" != "X" ]; then + rm -f $SSVNC_PREDIGESTED_HANDSHAKE + fi + if [ "X$SSVNC_SHOWCERT_EXIT_0" = "X1" ]; then + exit 0 + else + exit $rc + fi +fi + +# handle direct connect case: +# +if [ "X$direct_connect" != "X" ]; then + if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then + SSVNC_NO_ENC_WARN=1 + echo "" + echo "Using UltraVNC DSM Plugin key for encryption:" + echo "" + ustr=`echo "$SSVNC_ULTRA_DSM" | sed -e 's/pw=[^ ]*/pw=******/g'` + echo " $ustr PORT HOST:PORT" + echo "" + elif [ "X$getport" = "X" ]; then + echo "" + echo "Running viewer for direct connection:" + if echo X"$@" | grep chatonly > /dev/null; then + : + else + echo "" + echo "** WARNING: THERE WILL BE NO SSL OR SSH ENCRYPTION **" + echo "" + fi + fi + x="" + if [ "X$SSVNC_NO_ENC_WARN" != "X" ]; then + if [ "X$getport" = "X" ]; then + sleep 1 + fi + elif type printf > /dev/null 2>&1; then + printf "Are you sure you want to continue? [y]/n " + read x + else + echo -n "Are you sure you want to continue? [y]/n " + read x + fi + if [ "X$x" = "Xn" ]; then + exit 1 + fi + echo "" + if [ "X$ptmp" != "X" ]; then + if [ "X$reverse" = "X" ]; then + PPROXY_LISTEN=$use + export PPROXY_LISTEN + else + if [ "X$proxy" = "Xreverse_direct" ]; then + PPROXY_LISTEN="$STUNNEL_LISTEN:`expr 5500 + $disp`" + PPROXY_DEST="$localhost:$use" + PPROXY_PROXY="ipv6://$localhost:$use" # not always ipv6.. + export PPROXY_LISTEN PPROXY_DEST PPROXY_PROXY + pps=1 + else + PPROXY_REVERSE="$localhost:$use" + export PPROXY_LISTEN + pps=3 + fi + if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then + PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself.${RANDOM}.$$"` + export PPROXY_LOOP_THYSELF + pps=2 + fi + if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then + pps=`expr $pps + $SSVNC_EXTRA_SLEEP` + fi + PPROXY_SLEEP=$pps; export PPROXY_SLEEP; + PPROXY_KILLPID=+1; export PPROXY_KILLPID; + fi + + $ptmp & + + if [ "X$reverse" = "X" ]; then + #sleep 2 + #echo T sleep 1 + sleep 1 + fi + host="$localhost" + disp="$N" + port=`expr $disp + 5900` + fi + if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then + echo "T sleep $SSVNC_EXTRA_SLEEP" + sleep $SSVNC_EXTRA_SLEEP + fi + if [ "X$reverse" = "X" ]; then + hostdisp="$host:$disp" + if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then + if [ "X$SSVNC_USE_OURS" = "X1" ]; then + hostdisp="exec=$SSVNC_ULTRA_DSM 0 $host:$port" + else + pf=`findfree 5970` + cmd="$SSVNC_ULTRA_DSM -$pf $host:$port" + pf=`expr $pf - 5900` + hostdisp="$localhost:$pf" + ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'` + echo "Running:" + echo + echo "$ustr &" + echo + $cmd & + dsm_pid=$! + sleep 2 + fi + fi + hostdisp2=`echo "$hostdisp" | sed -e 's/pw=[^ ]*/pw=******/g'` + echo "$VNCVIEWERCMD" "$@" "$hostdisp2" + trap "final" 0 2 15 + echo "" + $VNCVIEWERCMD "$@" "$hostdisp" + if [ $? != 0 ]; then + echo "vncviewer command failed: $?" + if [ "X$secondtry" = "X1" ]; then + sleep 2 + $VNCVIEWERCMD "$@" "$hostdisp" + fi + fi + else + echo "" + echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." + echo "" + trap "final" 0 2 15 + if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then + if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then + echo "NOTE: The ultravnc_dsm_helper only runs once. So after the first LISTEN" + echo " ends you must restart the Listening mode. You may also need to" + echo " Press Ctrl-C to stop the viewer and restart for another connection." + echo "" + fi + #SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE + VNCVIEWER_LISTEN_LOCALHOST=1 + export VNCVIEWER_LISTEN_LOCALHOST + dport=`expr 5500 + $disp` + cmd="$SSVNC_ULTRA_DSM $dport $localhost:$use" + ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'` + echo "Running:" + echo + echo "$ustr &" + echo + if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then + $cmd & + dsm_pid=$! + else + while [ 1 ]; do $cmd; sleep 1; done & + dsm_pid=$! + fi + sleep 2 + disp=$use + if [ $disp -ge 5500 ]; then + disp=`expr $disp - 5500` + fi + fi + disp2=$disp + if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then + disp2=`echo "$disp2" | sed -e 's/://g'` + if [ $disp2 -le 200 ]; then + disp2=`expr $disp2 + 5500` + fi + fi + echo "$VNCVIEWERCMD" "$@" -listen $disp2 + echo "" + $VNCVIEWERCMD "$@" -listen $disp2 + if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then + rm -f $PPROXY_LOOP_THYSELF + fi + fi + exit $? +fi + +tmp_cfg=/tmp/ss_vncviewer${RANDOM}.$$ +tmp_cfg=`mytmp "$tmp_cfg"` + +stunnel_exec="" +if [ "X$SSVNC_USE_OURS" != "X1" ]; then + : +elif echo $STUNNEL_EXTRA_SVC_OPTS | grep '#stunnel-exec' > /dev/null; then + stunnel_exec="#" +fi + +if [ "X$reverse" = "X" ]; then + + if echo "$proxy" | grep "^repeater://" > /dev/null; then + if [ "X$cert" = "XBUILTIN" ]; then + ttcert=`make_tcert` + cert="cert = $ttcert" + fi + # Note for listen mode, an empty cert will cause stunnel to fail. + # The ssvnc gui will have already taken care of this. + fi + + cat > "$tmp_cfg" < /dev/null; then + hloc="$localhost:" + pv=`findfree 5570` + proxy="vencrypt:$pv:$port" + port=$pv + if [ "X$anondh_set" = "X1" ]; then + # not needed for ANONDH in this mode + #ciphers="ciphers = ADH:@STRENGTH" + : + fi + fi + cat > "$tmp_cfg" < /dev/null 2>&1 + $STUNNEL "$tmp_cfg" < /dev/tty > /dev/tty & + stunnel_pid=$! + echo "" + + # pause here to let the user supply a possible passphrase for the + # mycert key: + if [ "X$mycert" != "X" ]; then + nsl=10 + dsl=0 + if [ ! -f $mycert ]; then + dsl=0 + elif grep -i 'Proc-Type.*ENCRYPTED' "$mycert" > /dev/null 2>/dev/null; then + dsl=1 + fi + if [ "X$dsl" = "X1" ]; then + echo "" + echo "(** pausing $nsl secs for possible certificate passphrase dialog **)" + echo "" + sleep $nsl + echo "(** done pausing for passphrase **)" + echo "" + fi + fi + #echo T sleep 1 + sleep 1 + rm -f "$tmp_cfg" +fi + + +echo "" +if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then + echo "sleep $SSVNC_EXTRA_SLEEP" + sleep $SSVNC_EXTRA_SLEEP +fi + +if [ "X$reverse" = "X" ]; then + if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then + port1=`expr 5900 + $N` # stunnel port + port2=`findfree 5970` # bridge port (viewer connects to it.) + N=`expr $port2 - 5900` + env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="$port2,$port1" $ptmp & + sleep 1 + fi + echo "Running viewer:" + vnc_hp=$localhost:$N + if [ "X$stunnel_exec" != "X" ]; then + vnc_hp="exec=$STUNNEL $tmp_cfg" + fi + echo "$VNCVIEWERCMD" "$@" "$vnc_hp" + trap "final" 0 2 15 + echo "" + $VNCVIEWERCMD "$@" "$vnc_hp" + if [ $? != 0 ]; then + echo "vncviewer command failed: $?" + if [ "X$secondtry" = "X1" ]; then + sleep 2 + $VNCVIEWERCMD "$@" "$vnc_hp" + fi + fi +else + echo "Running viewer:" + echo "" + echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." + echo "" + trap "final" 0 2 15 + N2=$N + N2_trim=`echo "$N2" | sed -e 's/://g'` + if [ $N2_trim -le 200 ]; then + N2_trim=`expr $N2_trim + 5500` + fi + if [ "X$proxy" != "X" ]; then + if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then + pstunnel=`echo "$proxy" | awk -F: '{print $2}'` + plisten=`echo "$proxy" | awk -F: '{print $3}'` + IF=INADDR_ANY + if [ "X$STUNNEL_LISTEN" != "X" ]; then + IF=$STUNNEL_LISTEN + fi + PPROXY_VENCRYPT_REVERSE=1; export PPROXY_VENCRYPT_REVERSE + PPROXY_LISTEN="$IF:$plisten"; export PPROXY_LISTEN + PPROXY_PROXY="vencrypt://$localhost:$pstunnel"; export PPROXY_PROXY + PPROXY_DEST="$localhost:$pstunnel"; export PPROXY_DEST + STUNNEL_ONCE=1; export STUNNEL_ONCE + STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS + if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then + port1=`expr 5500 + $N2` + port2=`findfree 5580` + N2=`expr $port2 - 5500` + N2_trim=`echo "$N2" | sed -e 's/://g'` + if [ $N2_trim -le 200 ]; then + N2_trim=`expr $N2_trim + 5500` + fi + if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then + PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself1.${RANDOM}.$$"` + export PPROXY_LOOP_THYSELF + PPROXY_LOOP_THYSELF0=$PPROXY_LOOP_THYSELF + fi + env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="-$port1,$port2" $ptmp & + sleep 1 + fi + else + PPROXY_REVERSE="$localhost:$port"; export PPROXY_REVERSE + PPROXY_SLEEP=1; export PPROXY_SLEEP; + fi + PPROXY_KILLPID=+1; export PPROXY_KILLPID; + if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then + PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself2.${RANDOM}.$$"` + export PPROXY_LOOP_THYSELF + fi + $ptmp & + # Important to have no extra pids generated between here and VNCVIEWERCMD + fi + if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then + N2=$N2_trim + fi + echo "$VNCVIEWERCMD" "$@" -listen $N2 + echo "" + $VNCVIEWERCMD "$@" -listen $N2 + + if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then + rm -f $PPROXY_LOOP_THYSELF + fi + if [ "X$PPROXY_LOOP_THYSELF0" != "X" ]; then + rm -f $PPROXY_LOOP_THYSELF0 + fi +fi + +sleep 1 diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch new file mode 100755 index 0000000..db611af --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch @@ -0,0 +1,57 @@ +--- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400 ++++ vnc_javasrc/VncCanvas.java 2006-03-27 22:34:02.000000000 -0500 +@@ -28,6 +28,7 @@ + import java.lang.*; + import java.util.zip.*; + ++import java.util.Collections; + + // + // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. +@@ -81,6 +82,20 @@ + cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); + cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); + ++ // kludge to not show any Java cursor in the canvas since we are ++ // showing the soft cursor (should be a user setting...) ++ Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( ++ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), ++ "dot"); ++ this.setCursor(dot); ++ ++ // while we are at it... get rid of the keyboard traversals that ++ // make it so we can't type a Tab character: ++ this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, ++ Collections.EMPTY_SET); ++ this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, ++ Collections.EMPTY_SET); ++ + colors = new Color[256]; + for (int i = 0; i < 256; i++) + colors[i] = new Color(cm8.getRGB(i)); +@@ -1387,9 +1402,9 @@ + result = cm8.getRGB(pixBuf[i]); + } else { + result = 0xFF000000 | +- (pixBuf[i * 4 + 1] & 0xFF) << 16 | +- (pixBuf[i * 4 + 2] & 0xFF) << 8 | +- (pixBuf[i * 4 + 3] & 0xFF); ++ (pixBuf[i * 4 + 2] & 0xFF) << 16 | ++ (pixBuf[i * 4 + 1] & 0xFF) << 8 | ++ (pixBuf[i * 4 + 0] & 0xFF); + } + } else { + result = 0; // Transparent pixel +@@ -1403,9 +1418,9 @@ + result = cm8.getRGB(pixBuf[i]); + } else { + result = 0xFF000000 | +- (pixBuf[i * 4 + 1] & 0xFF) << 16 | +- (pixBuf[i * 4 + 2] & 0xFF) << 8 | +- (pixBuf[i * 4 + 3] & 0xFF); ++ (pixBuf[i * 4 + 2] & 0xFF) << 16 | ++ (pixBuf[i * 4 + 1] & 0xFF) << 8 | ++ (pixBuf[i * 4 + 0] & 0xFF); + } + } else { + result = 0; // Transparent pixel diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch new file mode 100755 index 0000000..550cc17 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch @@ -0,0 +1,2429 @@ +diff -x VncCanvas.java -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile +--- vnc_javasrc.orig/Makefile 2004-03-04 08:34:25.000000000 -0500 ++++ vnc_javasrc/Makefile 2006-03-26 17:29:25.000000000 -0500 +@@ -15,25 +15,29 @@ + DesCipher.class CapabilityInfo.class CapsContainer.class \ + RecordingFrame.class SessionRecorder.class AuthUnixLoginPanel.class \ + SocketFactory.class HTTPConnectSocketFactory.class \ +- HTTPConnectSocket.class ReloginPanel.class ++ HTTPConnectSocket.class ReloginPanel.class \ ++ SSLSocketToMe.class ++ ++SSL_CLASSES = SSLSocketToMe*.class TrustDialog.class + + SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \ + OptionsFrame.java ClipboardFrame.java ButtonPanel.java \ + DesCipher.java CapabilityInfo.java CapsContainer.java \ + RecordingFrame.java SessionRecorder.java AuthUnixLoginPanel.java \ + SocketFactory.java HTTPConnectSocketFactory.java \ +- HTTPConnectSocket.java ReloginPanel.java ++ HTTPConnectSocket.java ReloginPanel.java \ ++ SSLSocketToMe.java + + all: $(CLASSES) $(ARCHIVE) + + $(CLASSES): $(SOURCES) +- $(JC) -target 1.1 -O $(SOURCES) ++ $(JC) -target 1.4 -O $(SOURCES) + + $(ARCHIVE): $(CLASSES) $(MANIFEST) +- $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) ++ $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) $(SSL_CLASSES) + + install: $(CLASSES) $(ARCHIVE) +- $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) ++ $(CP) $(CLASSES) $(SSL_CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) + + export:: $(CLASSES) $(ARCHIVE) $(PAGES) + @$(ExportJavaClasses) +diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto.java +--- vnc_javasrc.orig/RfbProto.java 2004-03-04 08:34:25.000000000 -0500 ++++ vnc_javasrc/RfbProto.java 2010-03-27 17:58:37.000000000 -0400 +@@ -199,7 +199,21 @@ + host = h; + port = p; + +- if (viewer.socketFactory == null) { ++ if (! viewer.disableSSL) { ++ System.out.println("new SSLSocketToMe"); ++ SSLSocketToMe ssl; ++ try { ++ ssl = new SSLSocketToMe(host, port, v); ++ } catch (Exception e) { ++ throw new IOException(e.getMessage()); ++ } ++ ++ try { ++ sock = ssl.connectSock(); ++ } catch (Exception es) { ++ throw new IOException(es.getMessage()); ++ } ++ } else if (viewer.socketFactory == null) { + sock = new Socket(host, port); + } else { + try { +@@ -255,7 +269,7 @@ + || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) + { + throw new Exception("Host " + host + " port " + port + +- " is not an RFB server"); ++ " is not an RFB server: " + b); + } + + serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); +@@ -992,6 +1006,19 @@ + boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); + + int key; ++ if (viewer.debugKeyboard) { ++ System.out.println("----------------------------------------"); ++ System.out.println("evt.getKeyChar: " + evt.getKeyChar()); ++ System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); ++ System.out.println("evt.getKeyCode: " + evt.getKeyCode()); ++ System.out.println("evt.getID: " + evt.getID()); ++ System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); ++ System.out.println("evt.isActionKey: " + evt.isActionKey()); ++ System.out.println("evt.isControlDown: " + evt.isControlDown()); ++ System.out.println("evt.getModifiers: " + evt.getModifiers()); ++ System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); ++ System.out.println("evt.paramString: " + evt.paramString()); ++ } + if (evt.isActionKey()) { + + // +@@ -1025,6 +1052,13 @@ + return; + } + ++ if(key == 0xffc2 && viewer.mapF5_to_atsign) { ++ if (viewer.debugKeyboard) { ++ System.out.println("Mapping: F5 -> AT "); ++ } ++ key = 0x40; ++ } ++ + } else { + + // +@@ -1036,6 +1070,7 @@ + + key = keyChar; + ++ + if (key < 0x20) { + if (evt.isControlDown()) { + key += 0x60; +@@ -1121,6 +1156,16 @@ + int oldModifiers = 0; + + void writeModifierKeyEvents(int newModifiers) { ++ if(viewer.forbid_Ctrl_Alt) { ++ if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { ++ int orig = newModifiers; ++ newModifiers &= ~ALT_MASK; ++ newModifiers &= ~CTRL_MASK; ++ if (viewer.debugKeyboard) { ++ System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); ++ } ++ } ++ } + if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) + writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); + +diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java +--- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_javasrc/SSLSocketToMe.java 2010-03-21 12:53:24.000000000 -0400 +@@ -0,0 +1,2055 @@ ++/* ++ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. ++ * ++ * Copyright (c) 2006 Karl J. Runge ++ * 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; 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. ++ * ++ */ ++ ++import java.net.*; ++import java.io.*; ++import javax.net.ssl.*; ++import java.util.*; ++ ++import java.security.*; ++import java.security.cert.*; ++import java.security.spec.*; ++import java.security.cert.Certificate; ++import java.security.cert.CertificateFactory; ++ ++import java.awt.*; ++import java.awt.event.*; ++ ++public class SSLSocketToMe { ++ ++ /* basic member data: */ ++ String host; ++ int port; ++ VncViewer viewer; ++ ++ boolean debug = true; ++ boolean debug_certs = false; ++ ++ /* sockets */ ++ SSLSocket socket = null; ++ SSLSocketFactory factory; ++ ++ /* fallback for Proxy connection */ ++ boolean proxy_in_use = false; ++ boolean proxy_failure = false; ++ public DataInputStream is = null; ++ public OutputStream os = null; ++ ++ /* strings from user WRT proxy: */ ++ String proxy_auth_string = null; ++ String proxy_dialog_host = null; ++ int proxy_dialog_port = 0; ++ ++ Socket proxySock; ++ DataInputStream proxy_is; ++ OutputStream proxy_os; ++ ++ /* trust contexts */ ++ SSLContext trustloc_ctx; ++ SSLContext trustall_ctx; ++ SSLContext trustsrv_ctx; ++ SSLContext trusturl_ctx; ++ SSLContext trustone_ctx; ++ ++ /* corresponding trust managers */ ++ TrustManager[] trustAllCerts; ++ TrustManager[] trustSrvCert; ++ TrustManager[] trustUrlCert; ++ TrustManager[] trustOneCert; ++ ++ /* client-side SSL auth key (oneTimeKey=...) */ ++ KeyManager[] mykey = null; ++ ++ boolean user_wants_to_see_cert = true; ++ String cert_fail = null; ++ ++ /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ ++ java.security.cert.Certificate[] trustallCerts = null; ++ java.security.cert.Certificate[] trustsrvCerts = null; ++ java.security.cert.Certificate[] trusturlCerts = null; ++ ++ /* utility to decode hex oneTimeKey=... and serverCert=... */ ++ byte[] hex2bytes(String s) { ++ byte[] bytes = new byte[s.length()/2]; ++ for (int i=0; i 127) { ++ val -= 256; ++ } ++ Integer I = new Integer(val); ++ bytes[i] = Byte.decode(I.toString()).byteValue(); ++ ++ } catch (Exception e) { ++ ; ++ } ++ } ++ return bytes; ++ } ++ ++ SSLSocketToMe(String h, int p, VncViewer v) throws Exception { ++ host = h; ++ port = p; ++ viewer = v; ++ ++ debug_certs = v.debugCerts; ++ ++ /* we will first try default factory for certification: */ ++ ++ factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); ++ ++ dbg("SSL startup: " + host + " " + port); ++ ++ ++ /* create trust managers to be used if initial handshake fails: */ ++ ++ trustAllCerts = new TrustManager[] { ++ /* ++ * this one accepts everything. Only used if user ++ * has disabled checking (trustAllVncCerts=yes) ++ * or when we grab the cert to show it to them in ++ * a dialog and ask them to manually verify/accept it. ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) { ++ /* empty */ ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) { ++ /* empty */ ++ dbg("ALL: an untrusted connect to grab cert."); ++ } ++ } ++ }; ++ ++ trustUrlCert = new TrustManager[] { ++ /* ++ * this one accepts only the retrieved server ++ * cert by SSLSocket by this applet and stored in ++ * trusturlCerts. ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ throw new CertificateException("No Clients (URL)"); ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ /* we want to check 'certs' against 'trusturlCerts' */ ++ if (trusturlCerts == null) { ++ throw new CertificateException( ++ "No Trust url Certs array."); ++ } ++ if (trusturlCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust url Certs."); ++ } ++ if (certs == null) { ++ throw new CertificateException( ++ "No this-certs array."); ++ } ++ if (certs.length < 1) { ++ throw new CertificateException( ++ "No this-certs Certs."); ++ } ++ if (certs.length != trusturlCerts.length) { ++ throw new CertificateException( ++ "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); ++ } ++ boolean ok = true; ++ for (int i = 0; i < certs.length; i++) { ++ if (! trusturlCerts[i].equals(certs[i])) { ++ ok = false; ++ dbg("URL: cert mismatch at i=" + i); ++ dbg("URL: cert mismatch cert" + certs[i]); ++ dbg("URL: cert mismatch url" + trusturlCerts[i]); ++ if (cert_fail == null) { ++ cert_fail = "cert-mismatch"; ++ } ++ } ++ if (debug_certs) { ++ dbg("\n***********************************************"); ++ dbg("URL: cert info at i=" + i); ++ dbg("URL: cert info cert" + certs[i]); ++ dbg("==============================================="); ++ dbg("URL: cert info url" + trusturlCerts[i]); ++ dbg("***********************************************"); ++ } ++ } ++ if (!ok) { ++ throw new CertificateException( ++ "Server Cert Chain != URL Cert Chain."); ++ } ++ dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); ++ } ++ } ++ }; ++ ++ trustSrvCert = new TrustManager[] { ++ /* ++ * this one accepts cert given to us in the serverCert ++ * Applet Parameter we were started with. It is ++ * currently a fatal error if the VNC Server's cert ++ * doesn't match it. ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ throw new CertificateException("No Clients (SRV)"); ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ /* we want to check 'certs' against 'trustsrvCerts' */ ++ if (trustsrvCerts == null) { ++ throw new CertificateException( ++ "No Trust srv Certs array."); ++ } ++ if (trustsrvCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust srv Certs."); ++ } ++ if (certs == null) { ++ throw new CertificateException( ++ "No this-certs array."); ++ } ++ if (certs.length < 1) { ++ throw new CertificateException( ++ "No this-certs Certs."); ++ } ++ if (certs.length != trustsrvCerts.length) { ++ throw new CertificateException( ++ "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); ++ } ++ boolean ok = true; ++ for (int i = 0; i < certs.length; i++) { ++ if (! trustsrvCerts[i].equals(certs[i])) { ++ ok = false; ++ dbg("SRV: cert mismatch at i=" + i); ++ dbg("SRV: cert mismatch cert" + certs[i]); ++ dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); ++ if (cert_fail == null) { ++ cert_fail = "server-cert-mismatch"; ++ } ++ } ++ if (debug_certs) { ++ dbg("\n***********************************************"); ++ dbg("SRV: cert info at i=" + i); ++ dbg("SRV: cert info cert" + certs[i]); ++ dbg("==============================================="); ++ dbg("SRV: cert info srv" + trustsrvCerts[i]); ++ dbg("***********************************************"); ++ } ++ } ++ if (!ok) { ++ throw new CertificateException( ++ "Server Cert Chain != serverCert Applet Parameter Cert Chain."); ++ } ++ dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); ++ } ++ } ++ }; ++ ++ trustOneCert = new TrustManager[] { ++ /* ++ * this one accepts only the retrieved server ++ * cert by SSLSocket by this applet we stored in ++ * trustallCerts that user has accepted or applet ++ * parameter trustAllVncCerts=yes is set. This is ++ * for when we reconnect after the user has manually ++ * accepted the trustall cert in the dialog (or set ++ * trustAllVncCerts=yes applet param.) ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ throw new CertificateException("No Clients (ONE)"); ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ /* we want to check 'certs' against 'trustallCerts' */ ++ if (trustallCerts == null) { ++ throw new CertificateException( ++ "No Trust All Server Certs array."); ++ } ++ if (trustallCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust All Server Certs."); ++ } ++ if (certs == null) { ++ throw new CertificateException( ++ "No this-certs array."); ++ } ++ if (certs.length < 1) { ++ throw new CertificateException( ++ "No this-certs Certs."); ++ } ++ if (certs.length != trustallCerts.length) { ++ throw new CertificateException( ++ "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); ++ } ++ boolean ok = true; ++ for (int i = 0; i < certs.length; i++) { ++ if (! trustallCerts[i].equals(certs[i])) { ++ ok = false; ++ dbg("ONE: cert mismatch at i=" + i); ++ dbg("ONE: cert mismatch cert" + certs[i]); ++ dbg("ONE: cert mismatch all" + trustallCerts[i]); ++ } ++ if (debug_certs) { ++ dbg("\n***********************************************"); ++ dbg("ONE: cert info at i=" + i); ++ dbg("ONE: cert info cert" + certs[i]); ++ dbg("==============================================="); ++ dbg("ONE: cert info all" + trustallCerts[i]); ++ dbg("***********************************************"); ++ } ++ } ++ if (!ok) { ++ throw new CertificateException( ++ "Server Cert Chain != TRUSTALL Cert Chain."); ++ } ++ dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); ++ } ++ } ++ }; ++ ++ /* ++ * The above TrustManagers are used: ++ * ++ * 1) to retrieve the server cert in case of failure to ++ * display it to the user in a dialog. ++ * 2) to subsequently connect to the server if user agrees. ++ */ ++ ++ /* ++ * build oneTimeKey cert+key if supplied in applet parameter: ++ */ ++ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { ++ ClientCertDialog d = new ClientCertDialog(); ++ viewer.oneTimeKey = d.queryUser(); ++ } ++ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { ++ int idx = viewer.oneTimeKey.indexOf(","); ++ ++ String onetimekey = viewer.oneTimeKey.substring(0, idx); ++ byte[] key = hex2bytes(onetimekey); ++ String onetimecert = viewer.oneTimeKey.substring(idx+1); ++ byte[] cert = hex2bytes(onetimecert); ++ ++ KeyFactory kf = KeyFactory.getInstance("RSA"); ++ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); ++ PrivateKey ff = kf.generatePrivate (keysp); ++ if (debug_certs) { ++ dbg("one time key " + ff); ++ } ++ ++ CertificateFactory cf = CertificateFactory.getInstance("X.509"); ++ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); ++ Certificate[] certs = new Certificate[c.toArray().length]; ++ if (c.size() == 1) { ++ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); ++ if (debug_certs) { ++ dbg("one time cert" + tmpcert); ++ } ++ certs[0] = tmpcert; ++ } else { ++ certs = (Certificate[]) c.toArray(); ++ } ++ ++ KeyStore ks = KeyStore.getInstance("JKS"); ++ ks.load(null, null); ++ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); ++ String da = KeyManagerFactory.getDefaultAlgorithm(); ++ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); ++ kmf.init(ks, "".toCharArray()); ++ ++ mykey = kmf.getKeyManagers(); ++ } ++ ++ /* ++ * build serverCert cert if supplied in applet parameter: ++ */ ++ if (viewer.serverCert != null) { ++ CertificateFactory cf = CertificateFactory.getInstance("X.509"); ++ byte[] cert = hex2bytes(viewer.serverCert); ++ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); ++ trustsrvCerts = new Certificate[c.toArray().length]; ++ if (c.size() == 1) { ++ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); ++ trustsrvCerts[0] = tmpcert; ++ } else { ++ trustsrvCerts = (Certificate[]) c.toArray(); ++ } ++ } ++ ++ /* the trust loc certs context: */ ++ try { ++ trustloc_ctx = SSLContext.getInstance("SSL"); ++ ++ /* ++ * below is a failed attempt to get jvm's default ++ * trust manager using null (below) makes it so ++ * for HttpsURLConnection the server cannot be ++ * verified (no prompting.) ++ */ ++ if (false) { ++ boolean didit = false; ++ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); ++ tmf.init((KeyStore) null); ++ TrustManager [] tml = tmf.getTrustManagers(); ++ for (int i = 0; i < tml.length; i++) { ++ TrustManager tm = tml[i]; ++ if (tm instanceof X509TrustManager) { ++ TrustManager tm1[] = new TrustManager[1]; ++ tm1[0] = tm; ++ trustloc_ctx.init(mykey, tm1, null); ++ didit = true; ++ break; ++ } ++ } ++ if (!didit) { ++ trustloc_ctx.init(mykey, null, null); ++ } ++ } else { ++ /* we have to set trust manager to null */ ++ trustloc_ctx.init(mykey, null, null); ++ } ++ ++ } catch (Exception e) { ++ String msg = "SSL trustloc_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust all certs context: */ ++ try { ++ trustall_ctx = SSLContext.getInstance("SSL"); ++ trustall_ctx.init(mykey, trustAllCerts, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trustall_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust url certs context: */ ++ try { ++ trusturl_ctx = SSLContext.getInstance("SSL"); ++ trusturl_ctx.init(mykey, trustUrlCert, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trusturl_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust srv certs context: */ ++ try { ++ trustsrv_ctx = SSLContext.getInstance("SSL"); ++ trustsrv_ctx.init(mykey, trustSrvCert, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trustsrv_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust the one cert from server context: */ ++ try { ++ trustone_ctx = SSLContext.getInstance("SSL"); ++ trustone_ctx.init(mykey, trustOneCert, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trustone_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ } ++ ++ /* ++ * we call this early on to 1) check for a proxy, 2) grab ++ * Browser/JVM accepted HTTPS cert. ++ */ ++ public void check_for_proxy_and_grab_vnc_server_cert() { ++ ++ trusturlCerts = null; ++ proxy_in_use = false; ++ ++ if (viewer.ignoreProxy) { ++ /* applet param says skip it. */ ++ /* the downside is we do not set trusturlCerts for comparison later... */ ++ /* nor do we autodetect x11vnc for GET=1. */ ++ return; ++ } ++ ++ dbg("------------------------------------------------"); ++ dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); ++ ++ dbg("TRYING HTTPS:"); ++ String ustr = "https://" + host + ":"; ++ if (viewer.httpsPort != null) { ++ ustr += viewer.httpsPort; ++ } else { ++ ustr += port; ++ } ++ ustr += viewer.urlPrefix + "/check.https.proxy.connection"; ++ dbg("ustr is: " + ustr); ++ ++ try { ++ /* prepare for an HTTPS URL connection to host:port */ ++ URL url = new URL(ustr); ++ HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); ++ ++ if (mykey != null) { ++ /* with oneTimeKey (mykey) we can't use the default SSL context */ ++ if (trustsrvCerts != null) { ++ dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); ++ https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); ++ } else if (trustloc_ctx != null) { ++ dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); ++ https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); ++ } ++ } ++ ++ https.setUseCaches(false); ++ https.setRequestMethod("GET"); ++ https.setRequestProperty("Pragma", "No-Cache"); ++ https.setRequestProperty("Proxy-Connection", "Keep-Alive"); ++ https.setDoInput(true); ++ ++ dbg("trying https.connect()"); ++ https.connect(); ++ ++ dbg("trying https.getServerCertificates()"); ++ trusturlCerts = https.getServerCertificates(); ++ ++ if (trusturlCerts == null) { ++ dbg("set trusturlCerts to null!"); ++ } else { ++ dbg("set trusturlCerts to non-null"); ++ } ++ ++ if (https.usingProxy()) { ++ proxy_in_use = true; ++ dbg("An HTTPS proxy is in use. There may be connection problems."); ++ } ++ ++ dbg("trying https.getContent()"); ++ Object output = https.getContent(); ++ dbg("trying https.disconnect()"); ++ https.disconnect(); ++ if (! viewer.GET) { ++ String header = https.getHeaderField("VNC-Server"); ++ if (header != null && header.startsWith("x11vnc")) { ++ dbg("detected x11vnc server (1), setting GET=1"); ++ viewer.GET = true; ++ } ++ } ++ ++ } catch(Exception e) { ++ dbg("HttpsURLConnection: " + e.getMessage()); ++ } ++ ++ if (proxy_in_use) { ++ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); ++ dbg("------------------------------------------------"); ++ return; ++ } else if (trusturlCerts != null && !viewer.forceProxy) { ++ /* Allow user to require HTTP check? use forceProxy for now. */ ++ dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); ++ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); ++ dbg("------------------------------------------------"); ++ return; ++ } ++ ++ /* ++ * XXX need to remember scenario where this extra check ++ * gives useful info. User's Browser proxy settings? ++ */ ++ dbg("TRYING HTTP:"); ++ ustr = "http://" + host + ":" + port; ++ ustr += viewer.urlPrefix + "/index.vnc"; ++ dbg("ustr is: " + ustr); ++ ++ try { ++ /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ ++ URL url = new URL(ustr); ++ HttpURLConnection http = (HttpURLConnection) ++ url.openConnection(); ++ ++ http.setUseCaches(false); ++ http.setRequestMethod("GET"); ++ http.setRequestProperty("Pragma", "No-Cache"); ++ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); ++ http.setDoInput(true); ++ ++ dbg("trying http.connect()"); ++ http.connect(); ++ ++ if (http.usingProxy()) { ++ proxy_in_use = true; ++ dbg("An HTTP proxy is in use. There may be connection problems."); ++ } ++ dbg("trying http.getContent()"); ++ Object output = http.getContent(); ++ dbg("trying http.disconnect()"); ++ http.disconnect(); ++ if (! viewer.GET) { ++ String header = http.getHeaderField("VNC-Server"); ++ if (header != null && header.startsWith("x11vnc")) { ++ dbg("detected x11vnc server (2), setting GET=1"); ++ viewer.GET = true; ++ } ++ } ++ } catch(Exception e) { ++ dbg("HttpURLConnection: " + e.getMessage()); ++ } ++ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); ++ dbg("------------------------------------------------"); ++ } ++ ++ public Socket connectSock() throws IOException { ++ /* ++ * first try a https connection to detect a proxy, and ++ * grab the VNC server cert at the same time: ++ */ ++ check_for_proxy_and_grab_vnc_server_cert(); ++ ++ boolean srv_cert = false; ++ ++ if (trustsrvCerts != null) { ++ /* applet parameter suppled serverCert */ ++ dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); ++ factory = trustsrv_ctx.getSocketFactory(); ++ srv_cert = true; ++ } else if (viewer.trustAllVncCerts) { ++ /* trust all certs (no checking) */ ++ dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); ++ factory = trustall_ctx.getSocketFactory(); ++ } else if (trusturlCerts != null) { ++ /* trust certs the Browser/JVM accepted in check_for_proxy... */ ++ dbg("using trusturl_ctx"); ++ factory = trusturl_ctx.getSocketFactory(); ++ } else { ++ /* trust the local defaults */ ++ dbg("using trustloc_ctx"); ++ factory = trustloc_ctx.getSocketFactory(); ++ } ++ ++ socket = null; ++ ++ try { ++ if (proxy_in_use && viewer.forceProxy) { ++ throw new Exception("forcing proxy (forceProxy)"); ++ } else if (viewer.CONNECT != null) { ++ throw new Exception("forcing CONNECT"); ++ } ++ ++ int timeout = 6; ++ if (timeout > 0) { ++ socket = (SSLSocket) factory.createSocket(); ++ InetSocketAddress inetaddr = new InetSocketAddress(host, port); ++ dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); ++ socket.connect(inetaddr, timeout * 1000); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } ++ ++ } catch (Exception esock) { ++ dbg("socket error: " + esock.getMessage()); ++ if (proxy_in_use || viewer.CONNECT != null) { ++ proxy_failure = true; ++ if (proxy_in_use) { ++ dbg("HTTPS proxy in use. Trying to go with it."); ++ } else { ++ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); ++ } ++ try { ++ socket = proxy_socket(factory); ++ } catch (Exception e) { ++ dbg("proxy_socket error: " + e.getMessage()); ++ } ++ } else { ++ /* n.b. socket is left in error state to cause ex. below. */ ++ } ++ } ++ ++ try { ++ socket.startHandshake(); ++ ++ dbg("The Server Connection Verified OK on 1st try."); ++ ++ java.security.cert.Certificate[] currentTrustedCerts; ++ BrowserCertsDialog bcd; ++ ++ SSLSession sess = socket.getSession(); ++ currentTrustedCerts = sess.getPeerCertificates(); ++ ++ if (viewer.trustAllVncCerts) { ++ dbg("viewer.trustAllVncCerts-1 keeping socket."); ++ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { ++ try { ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy."); ++ } ++ socket = null; ++ throw new SSLHandshakeException("no current certs"); ++ } ++ ++ String serv = ""; ++ try { ++ CertInfo ci = new CertInfo(currentTrustedCerts[0]); ++ serv = ci.get_certinfo("CN"); ++ } catch (Exception e) { ++ ; ++ } ++ ++ if (viewer.trustAllVncCerts) { ++ dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); ++ user_wants_to_see_cert = false; ++ } else if (viewer.serverCert != null && trustsrvCerts != null) { ++ dbg("viewer.serverCert-1 skipping browser certs dialog"); ++ user_wants_to_see_cert = false; ++ } else if (viewer.trustUrlVncCert) { ++ dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); ++ user_wants_to_see_cert = false; ++ } else { ++ /* have a dialog with the user: */ ++ bcd = new BrowserCertsDialog(serv, host + ":" + port); ++ dbg("browser certs dialog begin."); ++ bcd.queryUser(); ++ dbg("browser certs dialog finished."); ++ ++ if (bcd.showCertDialog) { ++ String msg = "user wants to see cert"; ++ dbg(msg); ++ user_wants_to_see_cert = true; ++ if (cert_fail == null) { ++ cert_fail = "user-view"; ++ } ++ throw new SSLHandshakeException(msg); ++ } else { ++ user_wants_to_see_cert = false; ++ dbg("browser certs dialog: user said yes, accept it"); ++ } ++ } ++ ++ } catch (SSLHandshakeException eh) { ++ dbg("SSLHandshakeException: could not automatically verify Server."); ++ dbg("msg: " + eh.getMessage()); ++ ++ ++ /* send a cleanup string just in case: */ ++ String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; ++ ++ try { ++ OutputStream os = socket.getOutputStream(); ++ os.write(getoutstr.getBytes()); ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy!"); ++ } ++ ++ /* reload */ ++ ++ socket = null; ++ ++ String reason = null; ++ ++ if (srv_cert) { ++ /* for serverCert usage we make this a fatal error. */ ++ throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); ++ /* see below in TrustDialog were we describe this case to user anyway */ ++ } ++ ++ /* ++ * Reconnect, trusting any cert, so we can grab ++ * the cert to show it to the user in a dialog ++ * for him to manually accept. This connection ++ * is not used for anything else. ++ */ ++ factory = trustall_ctx.getSocketFactory(); ++ if (proxy_failure) { ++ socket = proxy_socket(factory); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } ++ ++ if (debug_certs) { ++ dbg("trusturlCerts: " + trusturlCerts); ++ dbg("trustsrvCerts: " + trustsrvCerts); ++ } ++ if (trusturlCerts == null && cert_fail == null) { ++ cert_fail = "missing-certs"; ++ } ++ ++ try { ++ socket.startHandshake(); ++ ++ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); ++ ++ /* grab the cert: */ ++ try { ++ SSLSession sess = socket.getSession(); ++ trustallCerts = sess.getPeerCertificates(); ++ } catch (Exception e) { ++ throw new Exception("Could not get " + ++ "Peer Certificate"); ++ } ++ if (debug_certs) { ++ dbg("trustallCerts: " + trustallCerts); ++ } ++ ++ if (viewer.trustAllVncCerts) { ++ dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); ++ } else if (! browser_cert_match()) { ++ /* ++ * close socket now, we will reopen after ++ * dialog if user agrees to use the cert. ++ */ ++ try { ++ OutputStream os = socket.getOutputStream(); ++ os.write(getoutstr.getBytes()); ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy!!"); ++ } ++ socket = null; ++ ++ /* dialog with user to accept cert or not: */ ++ ++ TrustDialog td= new TrustDialog(host, port, ++ trustallCerts); ++ ++ if (cert_fail == null) { ++ ; ++ } else if (cert_fail.equals("user-view")) { ++ reason = "Reason for this Dialog:\n\n" ++ + " You Asked to View the Certificate."; ++ } else if (cert_fail.equals("server-cert-mismatch")) { ++ /* this is now fatal error, see above. */ ++ reason = "Reason for this Dialog:\n\n" ++ + " The VNC Server's Certificate does not match the Certificate\n" ++ + " specified in the supplied 'serverCert' Applet Parameter."; ++ } else if (cert_fail.equals("cert-mismatch")) { ++ reason = "Reason for this Dialog:\n\n" ++ + " The VNC Server's Certificate does not match the Website's\n" ++ + " HTTPS Certificate (that you previously accepted; either\n" ++ + " manually or automatically via Certificate Authority.)"; ++ } else if (cert_fail.equals("missing-certs")) { ++ reason = "Reason for this Dialog:\n\n" ++ + " Not all Certificates could be obtained to check."; ++ } ++ ++ if (! td.queryUser(reason)) { ++ String msg = "User decided against it."; ++ dbg(msg); ++ throw new IOException(msg); ++ } ++ } ++ ++ } catch (Exception ehand2) { ++ dbg("** Could not TrustAll Verify Server!"); ++ ++ throw new IOException(ehand2.getMessage()); ++ } ++ ++ /* reload again: */ ++ ++ if (socket != null) { ++ try { ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy!!!"); ++ } ++ socket = null; ++ } ++ ++ /* ++ * Now connect a 3rd time, using the cert ++ * retrieved during connection 2 (sadly, that ++ * the user likely blindly agreed to...) ++ */ ++ ++ factory = trustone_ctx.getSocketFactory(); ++ if (proxy_failure) { ++ socket = proxy_socket(factory); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } ++ ++ try { ++ socket.startHandshake(); ++ dbg("TrustAll/TrustOne Server Connection Verified #3."); ++ ++ } catch (Exception ehand3) { ++ dbg("** Could not TrustAll/TrustOne Verify Server #3."); ++ ++ throw new IOException(ehand3.getMessage()); ++ } ++ } ++ ++ /* we have socket (possibly null) at this point, so proceed: */ ++ ++ /* handle x11vnc GET=1, if applicable: */ ++ if (socket != null && viewer.GET) { ++ String str = "GET "; ++ str += viewer.urlPrefix; ++ str += "/request.https.vnc.connection"; ++ str += " HTTP/1.0\r\n"; ++ str += "Pragma: No-Cache\r\n"; ++ str += "\r\n"; ++ ++ System.out.println("sending: " + str); ++ OutputStream os = socket.getOutputStream(); ++ String type = "os"; ++ ++ if (type == "os") { ++ os.write(str.getBytes()); ++ os.flush(); ++ System.out.println("used OutputStream"); ++ } else if (type == "bs") { ++ BufferedOutputStream bs = new BufferedOutputStream(os); ++ bs.write(str.getBytes()); ++ bs.flush(); ++ System.out.println("used BufferedOutputStream"); ++ } else if (type == "ds") { ++ DataOutputStream ds = new DataOutputStream(os); ++ ds.write(str.getBytes()); ++ ds.flush(); ++ System.out.println("used DataOutputStream"); ++ } ++ if (false) { ++ String rep = ""; ++ DataInputStream is = new DataInputStream( ++ new BufferedInputStream(socket.getInputStream(), 16384)); ++ while (true) { ++ rep += readline(is); ++ if (rep.indexOf("\r\n\r\n") >= 0) { ++ break; ++ } ++ } ++ System.out.println("rep: " + rep); ++ } ++ } ++ ++ dbg("SSL returning socket to caller."); ++ dbg(""); ++ ++ /* could be null, let caller handle that. */ ++ return (Socket) socket; ++ } ++ ++ boolean browser_cert_match() { ++ String msg = "Browser URL accept previously accepted cert"; ++ ++ if (user_wants_to_see_cert) { ++ return false; ++ } ++ ++ if (viewer.serverCert != null || trustsrvCerts != null) { ++ if (cert_fail == null) { ++ cert_fail = "server-cert-mismatch"; ++ } ++ } ++ if (trustallCerts != null && trusturlCerts != null) { ++ if (trustallCerts.length == trusturlCerts.length) { ++ boolean ok = true; ++ /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ ++ for (int i = 0; i < trusturlCerts.length; i++) { ++ if (! trustallCerts[i].equals(trusturlCerts[i])) { ++ dbg("BCM: cert mismatch at i=" + i); ++ dbg("BCM: cert mismatch url" + trusturlCerts[i]); ++ dbg("BCM: cert mismatch all" + trustallCerts[i]); ++ ok = false; ++ } ++ } ++ if (ok) { ++ System.out.println(msg); ++ if (cert_fail == null) { ++ cert_fail = "did-not-fail"; ++ } ++ return true; ++ } else { ++ if (cert_fail == null) { ++ cert_fail = "cert-mismatch"; ++ } ++ return false; ++ } ++ } ++ } ++ if (cert_fail == null) { ++ cert_fail = "missing-certs"; ++ } ++ return false; ++ } ++ ++ private void dbg(String s) { ++ if (debug) { ++ System.out.println(s); ++ } ++ } ++ ++ private int gint(String s) { ++ int n = -1; ++ try { ++ Integer I = new Integer(s); ++ n = I.intValue(); ++ } catch (Exception ex) { ++ return -1; ++ } ++ return n; ++ } ++ ++ /* this will do the proxy CONNECT negotiation and hook us up. */ ++ ++ private void proxy_helper(String proxyHost, int proxyPort) { ++ ++ boolean proxy_auth = false; ++ String proxy_auth_basic_realm = ""; ++ String hp = host + ":" + port; ++ dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp); ++ ++ /* we loop here a few times trying for the password case */ ++ for (int k=0; k < 2; k++) { ++ dbg("proxy_in_use psocket: " + k); ++ ++ if (proxySock != null) { ++ try { ++ proxySock.close(); ++ } catch (Exception e) { ++ dbg("proxy socket is grumpy."); ++ } ++ } ++ ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("1-a sadly, returning a null socket"); ++ return; ++ } ++ ++ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" ++ + "Host: " + hp + "\r\n"; ++ ++ dbg("requesting via proxy: " + req1); ++ ++ if (proxy_auth) { ++ if (proxy_auth_string == null) { ++ ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm); ++ pp.queryUser(); ++ proxy_auth_string = pp.getAuth(); ++ } ++ //dbg("auth1: " + proxy_auth_string); ++ ++ String auth2 = Base64Coder.encodeString(proxy_auth_string); ++ //dbg("auth2: " + auth2); ++ ++ req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n"; ++ //dbg("req1: " + req1); ++ ++ dbg("added Proxy-Authorization: Basic ... to request"); ++ } ++ req1 += "\r\n"; ++ ++ try { ++ proxy_os.write(req1.getBytes()); ++ String reply = readline(proxy_is); ++ ++ dbg("proxy replied: " + reply.trim()); ++ ++ if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) { ++ proxy_auth = true; ++ proxySock.close(); ++ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { ++ proxySock.close(); ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("2-a sadly, returning a null socket"); ++ return; ++ } ++ } ++ } catch(Exception e) { ++ dbg("some proxy socket problem: " + e.getMessage()); ++ } ++ ++ /* read the rest of the HTTP headers */ ++ while (true) { ++ String line = readline(proxy_is); ++ dbg("proxy line: " + line.trim()); ++ if (proxy_auth) { ++ String uc = line.toLowerCase(); ++ if (uc.indexOf("proxy-authenticate:") == 0) { ++ if (uc.indexOf(" basic ") >= 0) { ++ int idx = uc.indexOf(" realm"); ++ if (idx >= 0) { ++ proxy_auth_basic_realm = uc.substring(idx+1); ++ } ++ } ++ } ++ } ++ if (line.equals("\r\n") || line.equals("\n")) { ++ break; ++ } ++ } ++ if (!proxy_auth || proxy_auth_basic_realm.equals("")) { ++ /* we only try once for the non-password case: */ ++ break; ++ } ++ } ++ } ++ ++ public SSLSocket proxy_socket(SSLSocketFactory factory) { ++ Properties props = null; ++ String proxyHost = null; ++ int proxyPort = 0; ++ String proxyHost_nossl = null; ++ int proxyPort_nossl = 0; ++ String str; ++ ++ /* see if we can guess the proxy info from Properties: */ ++ try { ++ props = System.getProperties(); ++ } catch (Exception e) { ++ /* sandboxed applet might not be able to read it. */ ++ dbg("props failed: " + e.getMessage()); ++ } ++ if (viewer.proxyHost != null) { ++ dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); ++ proxyHost = viewer.proxyHost; ++ if (viewer.proxyPort != null) { ++ proxyPort = gint(viewer.proxyPort); ++ } else { ++ proxyPort = 8080; ++ } ++ ++ } else if (props != null) { ++ dbg("\n---------------\nAll props:"); ++ props.list(System.out); ++ dbg("\n---------------\n\n"); ++ ++ /* scrape throught properties looking for proxy info: */ ++ ++ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { ++ String s = (String) e.nextElement(); ++ String v = System.getProperty(s); ++ String s2 = s.toLowerCase(); ++ String v2 = v.toLowerCase(); ++ ++ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { ++ continue; ++ } ++ if (v2.indexOf("http") < 0) { ++ continue; ++ } ++ ++ if (s2.indexOf("proxy.https.host") >= 0) { ++ proxyHost = v2; ++ continue; ++ } ++ if (s2.indexOf("proxy.https.port") >= 0) { ++ proxyPort = gint(v2); ++ continue; ++ } ++ if (s2.indexOf("proxy.http.host") >= 0) { ++ proxyHost_nossl = v2; ++ continue; ++ } ++ if (s2.indexOf("proxy.http.port") >= 0) { ++ proxyPort_nossl = gint(v2); ++ continue; ++ } ++ ++ String[] pieces = v.split("[,;]"); ++ for (int i = 0; i < pieces.length; i++) { ++ String p = pieces[i]; ++ int j = p.indexOf("https"); ++ if (j < 0) { ++ j = p.indexOf("http"); ++ if (j < 0) { ++ continue; ++ } ++ } ++ j = p.indexOf("=", j); ++ if (j < 0) { ++ continue; ++ } ++ p = p.substring(j+1); ++ String [] hp = p.split(":"); ++ if (hp.length != 2) { ++ continue; ++ } ++ if (hp[0].length() > 1 && hp[1].length() > 1) { ++ ++ proxyPort = gint(hp[1]); ++ if (proxyPort < 0) { ++ continue; ++ } ++ proxyHost = new String(hp[0]); ++ break; ++ } ++ } ++ } ++ } ++ if (proxyHost != null) { ++ if (proxyHost_nossl != null && proxyPort_nossl > 0) { ++ dbg("Using http proxy info instead of https."); ++ proxyHost = proxyHost_nossl; ++ proxyPort = proxyPort_nossl; ++ } ++ } ++ ++ if (proxy_in_use) { ++ if (proxy_dialog_host != null && proxy_dialog_port > 0) { ++ proxyHost = proxy_dialog_host; ++ proxyPort = proxy_dialog_port; ++ } ++ if (proxyHost != null) { ++ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); ++ } else { ++ /* ask user to help us: */ ++ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); ++ pd.queryUser(); ++ proxyHost = pd.getHost(); ++ proxyPort = pd.getPort(); ++ proxy_dialog_host = new String(proxyHost); ++ proxy_dialog_port = proxyPort; ++ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); ++ } ++ ++ proxy_helper(proxyHost, proxyPort); ++ if (proxySock == null) { ++ return null; ++ } ++ } else if (viewer.CONNECT != null) { ++ dbg("viewer.CONNECT psocket:"); ++ proxySock = psocket(host, port); ++ if (proxySock == null) { ++ dbg("1-b sadly, returning a null socket"); ++ return null; ++ } ++ } ++ ++ if (viewer.CONNECT != null) { ++ String hp = viewer.CONNECT; ++ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" ++ + "Host: " + hp + "\r\n\r\n"; ++ ++ dbg("requesting2: " + req2); ++ ++ try { ++ proxy_os.write(req2.getBytes()); ++ String reply = readline(proxy_is); ++ ++ dbg("proxy replied2: " + reply.trim()); ++ ++ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { ++ proxySock.close(); ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("2-b sadly, returning a null socket"); ++ return null; ++ } ++ } ++ } catch(Exception e) { ++ dbg("proxy socket problem-2: " + e.getMessage()); ++ } ++ ++ while (true) { ++ String line = readline(proxy_is); ++ dbg("proxy line2: " + line.trim()); ++ if (line.equals("\r\n") || line.equals("\n")) { ++ break; ++ } ++ } ++ } ++ ++ Socket sslsock = null; ++ try { ++ sslsock = factory.createSocket(proxySock, host, port, true); ++ } catch(Exception e) { ++ dbg("sslsock prob: " + e.getMessage()); ++ dbg("3 sadly, returning a null socket"); ++ } ++ ++ return (SSLSocket) sslsock; ++ } ++ ++ Socket psocket(String h, int p) { ++ Socket psock = null; ++ try { ++ psock = new Socket(h, p); ++ proxy_is = new DataInputStream(new BufferedInputStream( ++ psock.getInputStream(), 16384)); ++ proxy_os = psock.getOutputStream(); ++ } catch(Exception e) { ++ dbg("psocket prob: " + e.getMessage()); ++ return null; ++ } ++ ++ return psock; ++ } ++ ++ String readline(DataInputStream i) { ++ byte[] ba = new byte[1]; ++ String s = new String(""); ++ ba[0] = 0; ++ try { ++ while (ba[0] != 0xa) { ++ ba[0] = (byte) i.readUnsignedByte(); ++ s += new String(ba); ++ } ++ } catch (Exception e) { ++ ; ++ } ++ return s; ++ } ++} ++ ++class TrustDialog implements ActionListener { ++ String msg, host, text; ++ int port; ++ java.security.cert.Certificate[] trustallCerts = null; ++ boolean viewing_cert = false; ++ boolean trust_this_session = false; ++ ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok, cancel, viewcert; ++ TextArea textarea; ++ Checkbox accept, deny; ++ Dialog dialog; ++ ++ String s1 = "Accept this certificate temporarily for this session"; ++ String s2 = "Do not accept this certificate and do not connect to" ++ + " this VNC server"; ++ String ln = "\n---------------------------------------------------\n\n"; ++ ++ TrustDialog (String h, int p, java.security.cert.Certificate[] s) { ++ host = h; ++ port = p; ++ trustallCerts = s; ++ ++ msg = "VNC Server " + host + ":" + port + " Not Verified"; ++ } ++ ++ public boolean queryUser(String reason) { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame(msg); ++ ++ dialog = new Dialog(frame, true); ++ ++ String infostr = ""; ++ if (trustallCerts.length == 1) { ++ CertInfo ci = new CertInfo(trustallCerts[0]); ++ infostr = ci.get_certinfo("all"); ++ } ++ if (reason != null) { ++ reason += "\n\n"; ++ } ++ ++ text = "\n" +++ "Unable to verify the identity of\n" +++ "\n" +++ " " + host + ":" + port + "\n" +++ "\n" +++ infostr +++ "\n" +++ "as a trusted VNC server.\n" +++ "\n" +++ reason +++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" +++ "is due to one of the following:\n" +++ "\n" +++ " - Your requesting to View the Certificate before accepting.\n" +++ "\n" +++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" +++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" +++ "\n" +++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" +++ " the Apache Web server has a certificate *different* from the VNC server's.\n" +++ "\n" +++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" +++ " obtained by this applet to compare the VNC Server Certificate against.\n" +++ "\n" +++ " - The VNC Server's Certificate does not match the one specified in the\n" +++ " supplied 'serverCert' Java Applet Parameter.\n" +++ "\n" +++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" +++ " to connect to. (Wouldn't that be exciting!!)\n" +++ "\n" +++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" +++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" +++ "automatically authenticate this VNC Server.\n" +++ "\n" +++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" +++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" +++ "certificate (except for the Apache portal case above where they don't match.)\n" +++ "\n" +++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" +++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" +++ "and thereby see no dialog from this VNC Viewer applet.\n" ++; ++ ++ /* the accept / do-not-accept radio buttons: */ ++ CheckboxGroup checkbox = new CheckboxGroup(); ++ accept = new Checkbox(s1, true, checkbox); ++ deny = new Checkbox(s2, false, checkbox); ++ ++ /* put the checkboxes in a panel: */ ++ Panel check = new Panel(); ++ check.setLayout(new GridLayout(2, 1)); ++ ++ check.add(accept); ++ check.add(deny); ++ ++ /* make the 3 buttons: */ ++ ok = new Button("OK"); ++ cancel = new Button("Cancel"); ++ viewcert = new Button("View Certificate"); ++ ++ ok.addActionListener(this); ++ cancel.addActionListener(this); ++ viewcert.addActionListener(this); ++ ++ /* put the buttons in their own panel: */ ++ Panel buttonrow = new Panel(); ++ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); ++ buttonrow.add(viewcert); ++ buttonrow.add(ok); ++ buttonrow.add(cancel); ++ ++ /* label at the top: */ ++ Label label = new Label(msg, Label.CENTER); ++ label.setFont(new Font("Helvetica", Font.BOLD, 16)); ++ ++ /* textarea in the middle */ ++ textarea = new TextArea(text, 38, 64, ++ TextArea.SCROLLBARS_VERTICAL_ONLY); ++ textarea.setEditable(false); ++ ++ /* put the two panels in their own panel at bottom: */ ++ Panel bot = new Panel(); ++ bot.setLayout(new GridLayout(2, 1)); ++ bot.add(check); ++ bot.add(buttonrow); ++ ++ /* now arrange things inside the dialog: */ ++ dialog.setLayout(new BorderLayout()); ++ ++ dialog.add("North", label); ++ dialog.add("South", bot); ++ dialog.add("Center", textarea); ++ ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ ++ return trust_this_session; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ ++ if (evt.getSource() == viewcert) { ++ /* View Certificate button clicked */ ++ if (viewing_cert) { ++ /* show the original info text: */ ++ textarea.setText(text); ++ viewcert.setLabel("View Certificate"); ++ viewing_cert = false; ++ } else { ++ int i; ++ /* show all (likely just one) certs: */ ++ textarea.setText(""); ++ for (i=0; i < trustallCerts.length; i++) { ++ int j = i + 1; ++ textarea.append("Certificate[" + ++ j + "]\n\n"); ++ textarea.append( ++ trustallCerts[i].toString()); ++ textarea.append(ln); ++ } ++ viewcert.setLabel("View Info"); ++ viewing_cert = true; ++ ++ textarea.setCaretPosition(0); ++ } ++ ++ } else if (evt.getSource() == ok) { ++ /* OK button clicked */ ++ if (accept.getState()) { ++ trust_this_session = true; ++ } else { ++ trust_this_session = false; ++ } ++ //dialog.dispose(); ++ dialog.hide(); ++ ++ } else if (evt.getSource() == cancel) { ++ /* Cancel button clicked */ ++ trust_this_session = false; ++ ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++ ++ String get_certinfo() { ++ String all = ""; ++ String fields[] = {"CN", "OU", "O", "L", "C"}; ++ int i; ++ if (trustallCerts.length < 1) { ++ all = ""; ++ return all; ++ } ++ String cert = trustallCerts[0].toString(); ++ ++ /* ++ * For now we simply scrape the cert string, there must ++ * be an API for this... perhaps optionValue? ++ */ ++ ++ for (i=0; i < fields.length; i++) { ++ int f, t, t1, t2; ++ String sub, mat = fields[i] + "="; ++ ++ f = cert.indexOf(mat, 0); ++ if (f > 0) { ++ t1 = cert.indexOf(", ", f); ++ t2 = cert.indexOf("\n", f); ++ if (t1 < 0 && t2 < 0) { ++ continue; ++ } else if (t1 < 0) { ++ t = t2; ++ } else if (t2 < 0) { ++ t = t1; ++ } else if (t1 < t2) { ++ t = t1; ++ } else { ++ t = t2; ++ } ++ if (t > f) { ++ sub = cert.substring(f, t); ++ all = all + " " + sub + "\n"; ++ } ++ } ++ } ++ return all; ++ } ++} ++ ++class ProxyDialog implements ActionListener { ++ String guessedHost = null; ++ String guessedPort = null; ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry; ++ String reply = ""; ++ ++ ProxyDialog (String h, int p) { ++ guessedHost = h; ++ try { ++ guessedPort = Integer.toString(p); ++ } catch (Exception e) { ++ guessedPort = "8080"; ++ } ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Need Proxy host:port"); ++ ++ dialog = new Dialog(frame, true); ++ ++ ++ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); ++ //label.setFont(new Font("Helvetica", Font.BOLD, 16)); ++ entry = new TextField(30); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ String guess = ""; ++ if (guessedHost != null) { ++ guess = guessedHost + ":" + guessedPort; ++ } ++ entry.setText(guess); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry); ++ dialog.add("South", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return; ++ } ++ ++ public String getHost() { ++ int i = reply.indexOf(":"); ++ if (i < 0) { ++ return "unknown"; ++ } ++ String h = reply.substring(0, i); ++ return h; ++ } ++ ++ public int getPort() { ++ int i = reply.indexOf(":"); ++ int p = 8080; ++ if (i < 0) { ++ return p; ++ } ++ i++; ++ String ps = reply.substring(i); ++ try { ++ Integer I = new Integer(ps); ++ p = I.intValue(); ++ } catch (Exception e) { ++ ; ++ } ++ return p; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply = entry.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ ++class ProxyPasswdDialog implements ActionListener { ++ String guessedHost = null; ++ String guessedPort = null; ++ String guessedUser = null; ++ String guessedPasswd = null; ++ String realm = null; ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry1; ++ TextField entry2; ++ String reply1 = ""; ++ String reply2 = ""; ++ ++ ProxyPasswdDialog (String h, int p, String realm) { ++ guessedHost = h; ++ try { ++ guessedPort = Integer.toString(p); ++ } catch (Exception e) { ++ guessedPort = "8080"; ++ } ++ this.realm = realm; ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Proxy Requires Username and Password"); ++ ++ dialog = new Dialog(frame, true); ++ ++ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); ++ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); ++ entry1 = new TextField(30); ++ entry2 = new TextField(30); ++ entry2.setEchoChar('*'); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry1); ++ dialog.add("South", entry2); ++ dialog.add("East", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return; ++ } ++ ++ public String getAuth() { ++ return reply1 + ":" + reply2; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply1 = entry1.getText(); ++ reply2 = entry2.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ ++class ClientCertDialog implements ActionListener { ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry; ++ String reply = ""; ++ ++ ClientCertDialog() { ++ ; ++ } ++ ++ public String queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Enter SSL Client Cert+Key String"); ++ ++ dialog = new Dialog(frame, true); ++ ++ ++ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); ++ entry = new TextField(30); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry); ++ dialog.add("South", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return reply; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply = entry.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ ++class BrowserCertsDialog implements ActionListener { ++ Button yes, no; ++ Dialog dialog; ++ String vncServer; ++ String hostport; ++ public boolean showCertDialog = true; ++ ++ BrowserCertsDialog(String serv, String hp) { ++ vncServer = serv; ++ hostport = hp; ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Use Browser/JVM Certs?"); ++ ++ dialog = new Dialog(frame, true); ++ ++ String m = ""; ++m += "\n"; ++m += "This VNC Viewer applet does not have its own keystore to track\n"; ++m += "SSL certificates, and so cannot authenticate the certificate\n"; ++m += "of the VNC Server:\n"; ++m += "\n"; ++m += " " + hostport + "\n\n " + vncServer + "\n"; ++m += "\n"; ++m += "on its own.\n"; ++m += "\n"; ++m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; ++m += "has previously accepted the same certificate. You may have set\n"; ++m += "this up permanently or just for this session, or the server\n"; ++m += "certificate was signed by a CA cert that your Web Browser or\n"; ++m += "Java VM Plugin has.\n"; ++m += "\n"; ++m += "If the VNC Server connection times out while you are reading this\n"; ++m += "dialog, then restart the connection and try again.\n"; ++m += "\n"; ++m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; ++m += "\n"; ++ ++ TextArea textarea = new TextArea(m, 22, 64, ++ TextArea.SCROLLBARS_VERTICAL_ONLY); ++ textarea.setEditable(false); ++ yes = new Button("Yes"); ++ yes.addActionListener(this); ++ no = new Button("No, Let Me See the Certificate."); ++ no.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", textarea); ++ dialog.add("Center", yes); ++ dialog.add("South", no); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til Yes or No pressed. */ ++ System.out.println("done show()"); ++ return; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == yes) { ++ showCertDialog = false; ++ //dialog.dispose(); ++ dialog.hide(); ++ } else if (evt.getSource() == no) { ++ showCertDialog = true; ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ System.out.println("done actionPerformed()"); ++ } ++} ++ ++class CertInfo { ++ String fields[] = {"CN", "OU", "O", "L", "C"}; ++ java.security.cert.Certificate cert; ++ String certString = ""; ++ ++ CertInfo(java.security.cert.Certificate c) { ++ cert = c; ++ certString = cert.toString(); ++ } ++ ++ String get_certinfo(String which) { ++ int i; ++ String cs = new String(certString); ++ String all = ""; ++ ++ /* ++ * For now we simply scrape the cert string, there must ++ * be an API for this... perhaps optionValue? ++ */ ++ for (i=0; i < fields.length; i++) { ++ int f, t, t1, t2; ++ String sub, mat = fields[i] + "="; ++ ++ f = cs.indexOf(mat, 0); ++ if (f > 0) { ++ t1 = cs.indexOf(", ", f); ++ t2 = cs.indexOf("\n", f); ++ if (t1 < 0 && t2 < 0) { ++ continue; ++ } else if (t1 < 0) { ++ t = t2; ++ } else if (t2 < 0) { ++ t = t1; ++ } else if (t1 < t2) { ++ t = t1; ++ } else { ++ t = t2; ++ } ++ if (t > f) { ++ sub = cs.substring(f, t); ++ all = all + " " + sub + "\n"; ++ if (which.equals(fields[i])) { ++ return sub; ++ } ++ } ++ } ++ } ++ if (which.equals("all")) { ++ return all; ++ } else { ++ return ""; ++ } ++ } ++} ++ ++class Base64Coder { ++ ++ // Mapping table from 6-bit nibbles to Base64 characters. ++ private static char[] map1 = new char[64]; ++ static { ++ int i=0; ++ for (char c='A'; c<='Z'; c++) map1[i++] = c; ++ for (char c='a'; c<='z'; c++) map1[i++] = c; ++ for (char c='0'; c<='9'; c++) map1[i++] = c; ++ map1[i++] = '+'; map1[i++] = '/'; } ++ ++ // Mapping table from Base64 characters to 6-bit nibbles. ++ private static byte[] map2 = new byte[128]; ++ static { ++ for (int i=0; iin. ++ * @return A character array with the Base64 encoded data. ++ */ ++ public static char[] encode (byte[] in, int iLen) { ++ int oDataLen = (iLen*4+2)/3; // output length without padding ++ int oLen = ((iLen+2)/3)*4; // output length including padding ++ char[] out = new char[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++] & 0xff; ++ int i1 = ip < iLen ? in[ip++] & 0xff : 0; ++ int i2 = ip < iLen ? in[ip++] & 0xff : 0; ++ int o0 = i0 >>> 2; ++ int o1 = ((i0 & 3) << 4) | (i1 >>> 4); ++ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); ++ int o3 = i2 & 0x3F; ++ out[op++] = map1[o0]; ++ out[op++] = map1[o1]; ++ out[op] = op < oDataLen ? map1[o2] : '='; op++; ++ out[op] = op < oDataLen ? map1[o3] : '='; op++; } ++ return out; } ++ ++ /** ++ * Decodes a string from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return A String containing the decoded data. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static String decodeString (String s) { ++ return new String(decode(s)); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (String s) { ++ return decode(s.toCharArray()); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * No blanks or line breaks are allowed within the Base64 encoded data. ++ * @param in a character array containing the Base64 encoded data. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (char[] in) { ++ int iLen = in.length; ++ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); ++ while (iLen > 0 && in[iLen-1] == '=') iLen--; ++ int oLen = (iLen*3) / 4; ++ byte[] out = new byte[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++]; ++ int i1 = in[ip++]; ++ int i2 = ip < iLen ? in[ip++] : 'A'; ++ int i3 = ip < iLen ? in[ip++] : 'A'; ++ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int b0 = map2[i0]; ++ int b1 = map2[i1]; ++ int b2 = map2[i2]; ++ int b3 = map2[i3]; ++ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int o0 = ( b0 <<2) | (b1>>>4); ++ int o1 = ((b1 & 0xf)<<4) | (b2>>>2); ++ int o2 = ((b2 & 3)<<6) | b3; ++ out[op++] = (byte)o0; ++ if (op= 2) { ++ proxyPort = new String(pieces[1]); ++ } else { ++ proxyPort = new String("8080"); ++ } ++ } ++ } ++ str = readParameter("proxyHost", false); ++ if (str != null) { ++ proxyHost = new String(str); ++ } ++ str = readParameter("proxyPort", false); ++ if (str != null) { ++ proxyPort = new String(str); ++ } ++ if (proxyHost != null && proxyPort == null) { ++ proxyPort = new String("8080"); ++ } ++ ++ ignoreProxy = false; ++ str = readParameter("ignoreProxy", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ ignoreProxy = true; ++ } ++ ++ trustAllVncCerts = false; ++ str = readParameter("trustAllVncCerts", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ trustAllVncCerts = true; ++ } ++ trustUrlVncCert = false; ++ str = readParameter("trustUrlVncCert", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ trustUrlVncCert = true; ++ } ++ debugCerts = false; ++ str = readParameter("debugCerts", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ debugCerts = true; ++ } ++ debugKeyboard = false; ++ str = readParameter("debugKeyboard", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ debugKeyboard = true; ++ } ++ mapF5_to_atsign = false; ++ str = readParameter("mapF5_to_atsign", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ mapF5_to_atsign = true; ++ } ++ forbid_Ctrl_Alt = false; ++ str = readParameter("forbid_Ctrl_Alt", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ forbid_Ctrl_Alt = true; ++ } + } + + public String readParameter(String name, boolean required) { diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultra.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultra.vnc new file mode 100755 index 0000000..3c57445 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultra.vnc @@ -0,0 +1,28 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultraproxy.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultraproxy.vnc new file mode 100755 index 0000000..fd842c4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultraproxy.vnc @@ -0,0 +1,28 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultrasigned.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultrasigned.vnc new file mode 100755 index 0000000..a711655 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultrasigned.vnc @@ -0,0 +1,28 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch new file mode 100755 index 0000000..4dbffaf --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch @@ -0,0 +1,5365 @@ +diff -Naur JavaViewer.orig/ButtonPanel.java JavaViewer/ButtonPanel.java +--- JavaViewer.orig/ButtonPanel.java 2004-12-12 20:51:02.000000000 -0500 ++++ JavaViewer/ButtonPanel.java 2007-05-31 15:40:45.000000000 -0400 +@@ -43,30 +43,36 @@ + viewer = v; + + setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); +- disconnectButton = new Button("Disconnect"); ++ if (v.ftpOnly) { ++ disconnectButton = new Button("Quit"); ++ } else { ++ disconnectButton = new Button("Close"); ++ } + disconnectButton.setEnabled(false); + add(disconnectButton); + disconnectButton.addActionListener(this); +- optionsButton = new Button("Options"); +- add(optionsButton); +- optionsButton.addActionListener(this); +- clipboardButton = new Button("Clipboard"); +- clipboardButton.setEnabled(false); +- add(clipboardButton); +- clipboardButton.addActionListener(this); +- if (viewer.rec != null) { +- recordButton = new Button("Record"); +- add(recordButton); +- recordButton.addActionListener(this); +- } +- ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); +- ctrlAltDelButton.setEnabled(false); +- add(ctrlAltDelButton); +- ctrlAltDelButton.addActionListener(this); +- refreshButton = new Button("Refresh"); +- refreshButton.setEnabled(false); +- add(refreshButton); +- refreshButton.addActionListener(this); ++ if (!v.ftpOnly) { ++ optionsButton = new Button("Options"); ++ add(optionsButton); ++ optionsButton.addActionListener(this); ++ clipboardButton = new Button("Clipboard"); ++ clipboardButton.setEnabled(false); ++ add(clipboardButton); ++ clipboardButton.addActionListener(this); ++ if (viewer.rec != null) { ++ recordButton = new Button("Record"); ++ add(recordButton); ++ recordButton.addActionListener(this); ++ } ++ ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); ++ ctrlAltDelButton.setEnabled(false); ++ add(ctrlAltDelButton); ++ ctrlAltDelButton.addActionListener(this); ++ refreshButton = new Button("Refresh"); ++ refreshButton.setEnabled(false); ++ add(refreshButton); ++ refreshButton.addActionListener(this); ++ } + ftpButton = new Button("File Transfer"); + ftpButton.setEnabled(false); + add(ftpButton); +@@ -79,9 +85,10 @@ + + public void enableButtons() { + disconnectButton.setEnabled(true); ++ ftpButton.setEnabled(true); ++ if (viewer.ftpOnly) {return;} + clipboardButton.setEnabled(true); + refreshButton.setEnabled(true); +- ftpButton.setEnabled(true); + } + + // +@@ -89,6 +96,9 @@ + // + + public void disableButtonsOnDisconnect() { ++ ftpButton.setEnabled(false); ++ if (viewer.ftpOnly) {return;} ++ + remove(disconnectButton); + disconnectButton = new Button("Hide desktop"); + disconnectButton.setEnabled(true); +@@ -99,7 +109,6 @@ + clipboardButton.setEnabled(false); + ctrlAltDelButton.setEnabled(false); + refreshButton.setEnabled(false); +- ftpButton.setEnabled(false); + + validate(); + } +@@ -110,6 +119,7 @@ + // + + public void enableRemoteAccessControls(boolean enable) { ++ if (viewer.ftpOnly) {return;} + ctrlAltDelButton.setEnabled(enable); + } + +@@ -163,9 +173,19 @@ + } + else if (evt.getSource() == ftpButton) + { +- viewer.ftp.setVisible(!viewer.ftp.isVisible()); ++// begin runge/x11vnc ++ if (viewer.ftpOnly) { ++ viewer.vncFrame.setVisible(false); ++ } ++ viewer.ftp.setSavedLocations(); ++ if (viewer.ftp.isVisible()) { ++ viewer.ftp.doClose(); ++ } else { ++ viewer.ftp.doOpen(); ++ } ++// end runge/x11vnc + viewer.rfb.readServerDriveList(); +- ++ + } + } + } +diff -Naur JavaViewer.orig/FTPFrame.java JavaViewer/FTPFrame.java +--- JavaViewer.orig/FTPFrame.java 2005-03-15 23:53:14.000000000 -0500 ++++ JavaViewer/FTPFrame.java 2009-01-13 09:48:30.000000000 -0500 +@@ -24,8 +24,17 @@ + import java.io.*; + import java.util.ArrayList; + import java.util.Vector; ++import java.util.Date; + import javax.swing.*; + ++import java.nio.ByteBuffer; ++import java.nio.CharBuffer; ++import java.nio.charset.*; ++ ++// begin runge/x11vnc ++import java.util.Arrays; ++// end runge/x11vnc ++ + + /* + * Created on Feb 25, 2004 +@@ -74,12 +83,31 @@ + public javax.swing.JTextField connectionStatus = null; + public boolean updateDriveList; + private Vector remoteList = null; ++ private Vector remoteListInfo = null; + private Vector localList = null; ++ private Vector localListInfo = null; + private File currentLocalDirectory = null; // Holds the current local Directory + private File currentRemoteDirectory = null; // Holds the current remote Directory + private File localSelection = null; // Holds the currently selected local file + private String remoteSelection = null; // Holds the currently selected remote file + public String selectedTable = null; ++ ++// begin runge/x11vnc ++ private javax.swing.JButton viewButton = null; ++ private javax.swing.JButton refreshButton = null; ++ public File saveLocalDirectory = null; ++ public long saveLocalDirectoryTime = 0; ++ public int saveLocalDirectoryCount = 0; ++ public String saveRemoteDirectory = null; ++ public long saveRemoteDirectoryTime = 0; ++ public int saveRemoteDirectoryCount = 0; ++ private boolean localCurrentIsDir = true; ++ private int lastRemoteIndex = -1; ++ private int lastLocalIndex = -1; ++ private boolean doingShortcutDir = false; ++ private boolean gotShortcutDir = false; ++ private boolean ignore_events = false; ++// end runge/x11vnc + + // sf@2004 - Separate directories and files for better lisibility + private ArrayList DirsList; +@@ -125,11 +153,61 @@ + + void refreshRemoteLocation() + { ++ ++//System.out.println("refreshRemoteLocation1"); + remoteList.clear(); ++ remoteListInfo.clear(); + remoteFileTable.setListData(remoteList); ++System.out.println("refreshRemoteLocation '" + remoteLocation.getText() + "'"); // runge/x11vnc + viewer.rfb.readServerDirectory(remoteLocation.getText()); + } + ++// begin runge/x11vnc ++ public void setSavedLocations() { ++ saveLocalDirectory = currentLocalDirectory; ++ saveLocalDirectoryTime = System.currentTimeMillis(); ++ saveLocalDirectoryCount = 0; ++ ++ if (remoteLocation != null) { ++ saveRemoteDirectory = remoteLocation.getText(); ++System.out.println("RemoteSave '" + saveRemoteDirectory + "'"); ++ } ++ saveRemoteDirectoryTime = System.currentTimeMillis(); ++ saveRemoteDirectoryCount = 0; ++ } ++ ++ private File saveLocalHack(File dir) { ++ saveLocalDirectoryCount++; ++//System.out.println("L " + saveLocalDirectoryCount + " dt: " + (System.currentTimeMillis() - saveLocalDirectoryTime) + " - " + saveLocalDirectory); ++ if (System.currentTimeMillis() > saveLocalDirectoryTime + 2000 || saveLocalDirectoryCount > 2) { ++ saveLocalDirectory = null; ++ } ++ if (saveLocalDirectory != null) { ++ currentLocalDirectory = saveLocalDirectory; ++ localLocation.setText(saveLocalDirectory.toString()); ++ return saveLocalDirectory; ++ } else { ++ return dir; ++ } ++ } ++ ++ private String saveRemoteHack(String indrive) { ++ saveRemoteDirectoryCount++; ++//System.out.println("R " + saveRemoteDirectoryCount + " - " + saveRemoteDirectory); ++ if (saveRemoteDirectory != null && saveRemoteDirectoryCount > 1) { ++ saveRemoteDirectory = null; ++ } ++ if (saveRemoteDirectory != null) { ++ if (! saveRemoteDirectory.equals("")) { ++System.out.println("saveRemoteHack setText + refreshRemoteLocation '" + saveRemoteDirectory + "'"); ++ return saveRemoteDirectory; ++ } ++ } ++ return indrive; ++ } ++// end runge/x11vnc ++ ++ + /* + * Prints the list of drives on the remote directory and returns a String[]. + * str takes as string like A:fC:lD:lE:lF:lG:cH:c +@@ -143,6 +221,9 @@ + int size = str.length(); + String driveType = null; + String[] drive = new String[str.length() / 3]; ++ int idx = 0, C_drive = -1, O_drive = -1; ++ ++System.out.println("ComboBox: Str '" + str + "'"); + + // Loop through the string to create a String[] + for (int i = 0; i < size; i = i + 3) { +@@ -150,26 +231,68 @@ + driveType = str.substring(i + 2, i + 3); + if (driveType.compareTo("f") == 0) + drive[i / 3] += "\\ Floppy"; +- if (driveType.compareTo("l") == 0) ++ if (driveType.compareTo("l") == 0) { + drive[i / 3] += "\\ Local Disk"; ++ if (drive[i/3].substring(0,1).toUpperCase().equals("C")) { ++ C_drive = idx; ++ } else if (O_drive < 0) { ++ O_drive = idx; ++ } ++ } + if (driveType.compareTo("c") == 0) + drive[i / 3] += "\\ CD-ROM"; + if (driveType.compareTo("n") == 0) + drive[i / 3] += "\\ Network"; + + remoteDrivesComboBox.addItem(drive[i / 3]); ++System.out.println("ComboBox: Add " + idx + " '" + drive[i/3] + "'"); ++ idx++; ++ } ++ ++ // runge ++ if (viewer.ftpDropDown != null) { ++ String[] dd = viewer.ftpDropDown.split("\\."); ++ for (int i=0; i < dd.length; i++) { ++ if (!dd[i].equals("")) { ++ String s = dd[i]; ++ if (s.startsWith("TOP_")) { ++ s = s.substring(4); ++ remoteDrivesComboBox.insertItemAt(" [" + s + "]", 0); ++ } else { ++ remoteDrivesComboBox.addItem(" [" + s + "]"); ++ } ++ } ++ } ++ } else { ++ remoteDrivesComboBox.addItem(" [My Documents]"); ++ remoteDrivesComboBox.addItem(" [Desktop]"); ++ remoteDrivesComboBox.addItem(" [Home]"); + } ++ + //sf@ - Select Drive C:as default if possible + boolean bFound = false; +- for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) +- { +- if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) +- { +- remoteDrivesComboBox.setSelectedIndex(i); ++ ++ if (false) { ++ for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) { ++ if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) { ++ remoteDrivesComboBox.setSelectedIndex(i); ++ bFound = true; ++ } ++ } ++ } else { ++ if (C_drive >= 0) { ++ remoteDrivesComboBox.setSelectedIndex(C_drive); ++ bFound = true; ++System.out.println("ComboBox: C_drive index: " + C_drive); ++ } else if (O_drive >= 0) { ++ remoteDrivesComboBox.setSelectedIndex(O_drive); + bFound = true; ++System.out.println("ComboBox: Other_drive index: " + O_drive); + } + } ++ + if (!bFound) remoteDrivesComboBox.setSelectedIndex(0); ++ + updateDriveList = false; + return drive; + } +@@ -185,6 +308,8 @@ + stopButton.setVisible(true); + stopButton.setEnabled(true); + receiveButton.setEnabled(false); ++ viewButton.setEnabled(false); // runge/x11vnc ++ refreshButton.setEnabled(false); + remoteTopButton.setEnabled(false); + sendButton.setEnabled(false); + remoteFileTable.setEnabled(false); +@@ -207,6 +332,8 @@ + stopButton.setVisible(false); + stopButton.setEnabled(false); + receiveButton.setEnabled(true); ++ viewButton.setEnabled(true); // runge/x11vnc ++ refreshButton.setEnabled(true); + remoteTopButton.setEnabled(true); + sendButton.setEnabled(true); + remoteFileTable.setEnabled(true); +@@ -221,10 +348,11 @@ + /* + * Print Directory prints out all the contents of a directory + */ +- void printDirectory(ArrayList a) { ++ void printDirectory(ArrayList a, ArrayList b) { + + for (int i = 0; i < a.size(); i++) { + remoteList.addElement(a.get(i)); ++ remoteListInfo.addElement(b.get(i)); + } + remoteFileTable.setListData(remoteList); + } +@@ -235,10 +363,12 @@ + * @return void + */ + private void initialize() { ++ ignore_events = true; + this.setSize(794, 500); + this.setContentPane(getJContentPane()); ++ ignore_events = false; + updateDriveList = true; +- } ++ } + /** + * This method initializes jContentPane. This is the main content pane + * +@@ -253,6 +383,33 @@ + jContentPane.add(getRemotePanel(), java.awt.BorderLayout.EAST); + jContentPane.add(getLocalPanel(), java.awt.BorderLayout.WEST); + jContentPane.add(getButtonPanel(), java.awt.BorderLayout.CENTER); ++ ++ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); ++ AbstractAction escapeAction = new AbstractAction() { ++ public void actionPerformed(ActionEvent actionEvent) { ++ System.out.println("Escape Pressed"); ++ if (viewer.ftpOnly) { ++ System.out.println("exiting..."); ++ System.exit(0); ++ } else { ++ doClose(); ++ } ++ } ++ }; ++ jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); ++ jContentPane.getInputMap().put(stroke, "escapeAction"); ++ jContentPane.getActionMap().put("escapeAction", escapeAction); ++ ++ stroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK); ++ AbstractAction resetAction = new AbstractAction() { ++ public void actionPerformed(ActionEvent actionEvent) { ++ System.out.println("Ctrl-R Pressed"); ++ doReset(); ++ } ++ }; ++ jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "resetAction"); ++ jContentPane.getInputMap().put(stroke, "resetAction"); ++ jContentPane.getActionMap().put("resetAction", resetAction); + } + return jContentPane; + } +@@ -270,6 +427,7 @@ + topPanelLocal.add(getLocalMachineLabel(), java.awt.BorderLayout.CENTER); + topPanelLocal.add(getLocalTopButton(), java.awt.BorderLayout.EAST); + topPanelLocal.setBackground(java.awt.Color.lightGray); ++//System.out.println("getTopPanelLocal"); + } + return topPanelLocal; + } +@@ -288,6 +446,7 @@ + topPanelRemote.add(getRemoteMachineLabel(), java.awt.BorderLayout.CENTER); + topPanelRemote.add(getRemoteTopButton(), java.awt.BorderLayout.EAST); + topPanelRemote.setBackground(java.awt.Color.lightGray); ++//System.out.println("getTopPanelRemote"); + } + return topPanelRemote; + } +@@ -301,6 +460,7 @@ + if (topPanelCenter == null) { + topPanelCenter = new javax.swing.JPanel(); + topPanelCenter.add(getDummyButton(), null); ++//System.out.println("getTopPanelCenter"); + } + return topPanelCenter; + } +@@ -328,6 +488,7 @@ + topPanel.add(getRemoteTopButton(), null); + topPanel.setBackground(java.awt.Color.lightGray); + */ ++//System.out.println("getTopPanel"); + } + return topPanel; + } +@@ -348,6 +509,7 @@ + statusPanel.add(getJProgressBar(), null); + statusPanel.add(getConnectionStatus(), null); + statusPanel.setBackground(java.awt.Color.lightGray); ++//System.out.println("getStatusPanel"); + + } + return statusPanel; +@@ -368,6 +530,7 @@ + remotePanel.add(getRemoteScrollPane(), null); + remotePanel.add(getRemoteStatus(), null); + remotePanel.setBackground(java.awt.Color.lightGray); ++//System.out.println("getRemotePanel"); + } + return remotePanel; + } +@@ -390,6 +553,7 @@ + localPanel.setComponentOrientation( + java.awt.ComponentOrientation.UNKNOWN); + localPanel.setName("localPanel"); ++//System.out.println("getLocalPanel"); + } + return localPanel; + } +@@ -405,12 +569,15 @@ + buttonPanel = new javax.swing.JPanel(); + buttonPanel.setLayout(null); + buttonPanel.add(getReceiveButton(), null); ++ buttonPanel.add(getRefreshButton(), null); // runge/x11vnc ++ buttonPanel.add(getViewButton(), null); // runge/x11vnc + buttonPanel.add(getNewFolderButton(), null); + buttonPanel.add(getCloseButton(), null); + buttonPanel.add(getDeleteButton(), null); + buttonPanel.add(getSendButton(), null); + buttonPanel.add(getStopButton(), null); + buttonPanel.setBackground(java.awt.Color.lightGray); ++//System.out.println("getButtonPanel"); + } + return buttonPanel; + } +@@ -422,10 +589,11 @@ + private javax.swing.JButton getSendButton() { + if (sendButton == null) { + sendButton = new javax.swing.JButton(); +- sendButton.setBounds(20, 30, 97, 25); ++ sendButton.setBounds(15, 30, 107, 25); // runge/x11vnc + sendButton.setText("Send >>"); + sendButton.setName("sendButton"); + sendButton.addActionListener(this); ++//System.out.println("getSendButton"); + + } + return sendButton; +@@ -438,7 +606,7 @@ + private javax.swing.JButton getReceiveButton() { + if (receiveButton == null) { + receiveButton = new javax.swing.JButton(); +- receiveButton.setBounds(20, 60, 97, 25); ++ receiveButton.setBounds(15, 60, 107, 25); // runge/x11vnc + receiveButton.setText("<< Receive"); + receiveButton.setName("receiveButton"); + receiveButton.addActionListener(this); +@@ -453,7 +621,7 @@ + private javax.swing.JButton getDeleteButton() { + if (deleteButton == null) { + deleteButton = new javax.swing.JButton(); +- deleteButton.setBounds(20, 110, 97, 25); ++ deleteButton.setBounds(15, 110, 107, 25); // runge/x11vnc + deleteButton.setText("Delete File"); + deleteButton.setName("deleteButton"); + deleteButton.addActionListener(this); +@@ -468,7 +636,7 @@ + private javax.swing.JButton getNewFolderButton() { + if (newFolderButton == null) { + newFolderButton = new javax.swing.JButton(); +- newFolderButton.setBounds(20, 140, 97, 25); ++ newFolderButton.setBounds(15, 140, 107, 25); // runge/x11vnc + newFolderButton.setText("New Folder"); + newFolderButton.setName("newFolderButton"); + newFolderButton.addActionListener(this); +@@ -476,6 +644,39 @@ + return newFolderButton; + } + ++// begin runge/x11vnc ++ /** ++ * This method initializes refreshButton ++ * ++ * @return javax.swing.JButton ++ */ ++ private javax.swing.JButton getRefreshButton() { ++ if (refreshButton == null) { ++ refreshButton = new javax.swing.JButton(); ++ refreshButton.setBounds(15, 170, 107, 25); ++ refreshButton.setText("Refresh"); ++ refreshButton.setName("refreshButton"); ++ refreshButton.addActionListener(this); ++ } ++ return refreshButton; ++ } ++ /** ++ * This method initializes viewButton ++ * ++ * @return javax.swing.JButton ++ */ ++ private javax.swing.JButton getViewButton() { ++ if (viewButton == null) { ++ viewButton = new javax.swing.JButton(); ++ viewButton.setBounds(15, 200, 107, 25); ++ viewButton.setText("View File"); ++ viewButton.setName("viewButton"); ++ viewButton.addActionListener(this); ++ } ++ return viewButton; ++ } ++// end runge/x11vnc ++ + /** + * This method initializes stopButton + * +@@ -486,7 +687,7 @@ + if (stopButton == null) + { + stopButton = new javax.swing.JButton(); +- stopButton.setBounds(20, 200, 97, 25); ++ stopButton.setBounds(15, 230, 107, 25); // runge/x11vnc + stopButton.setText("Stop"); + stopButton.setName("stopButton"); + stopButton.addActionListener(this); +@@ -503,8 +704,12 @@ + private javax.swing.JButton getCloseButton() { + if (closeButton == null) { + closeButton = new javax.swing.JButton(); +- closeButton.setBounds(20, 325, 97, 25); +- closeButton.setText("Close"); ++ closeButton.setBounds(15, 325, 107, 25); // runge/x11vnc ++ if (viewer.ftpOnly) { ++ closeButton.setText("Quit"); ++ } else { ++ closeButton.setText("Close"); ++ } + closeButton.setName("closeButton"); + closeButton.addActionListener(this); + } +@@ -551,6 +756,7 @@ + //Select the second entry (e.g. C:\) + // localDrivesComboBox.setSelectedIndex(1); + localDrivesComboBox.addActionListener(this); ++//System.out.println("getLocalDrivesComboBox"); + } + updateDriveList = false; + return localDrivesComboBox; +@@ -567,6 +773,7 @@ + remoteDrivesComboBox.setFont( + new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); + remoteDrivesComboBox.addActionListener(this); ++//System.out.println("getRemoteDrivesComboBox"); + + } + return remoteDrivesComboBox; +@@ -587,6 +794,7 @@ + localMachineLabel.setFont( + new java.awt.Font("Dialog", java.awt.Font.BOLD, 11)); + localMachineLabel.setEditable(false); ++//System.out.println("getLocalMachineLabel"); + } + return localMachineLabel; + } +@@ -622,6 +830,7 @@ + localTopButton.setFont( + new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); + localTopButton.addActionListener(this); ++//System.out.println("getLocalTopButton"); + } + return localTopButton; + } +@@ -638,6 +847,7 @@ + remoteTopButton.setFont( + new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); + remoteTopButton.addActionListener(this); ++//System.out.println("getRemoteTopButton"); + } + return remoteTopButton; + } +@@ -650,9 +860,24 @@ + private javax.swing.JList getLocalFileTable() { + if (localFileTable == null) { + localList = new Vector(0); ++ localListInfo = new Vector(0); + localFileTable = new JList(localList); ++ MouseMotionListener mlisten = new MouseMotionAdapter() { ++ public void mouseMoved(MouseEvent e) { ++ int index = localFileTable.locationToIndex(e.getPoint()); ++ if (index == lastLocalIndex) { ++ return; ++ } else if (index < 0) { ++ return; ++ } ++ lastLocalIndex = index; ++ connectionStatus.setText((String) localListInfo.get(index)); ++ } ++ }; + localFileTable.addMouseListener(this); ++ localFileTable.addMouseMotionListener(mlisten); + localFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++//System.out.println("getLocalFileTable"); + } + return localFileTable; + } +@@ -669,6 +894,7 @@ + localScrollPane.setFont( + new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); + localScrollPane.setName("localFileList"); ++//System.out.println("getLocalScrollPane"); + } + return localScrollPane; + } +@@ -680,10 +906,25 @@ + private javax.swing.JList getRemoteFileTable() { + if (remoteFileTable == null) { + remoteList = new Vector(0); ++ remoteListInfo = new Vector(0); + remoteFileTable = new JList(remoteList); ++ MouseMotionListener mlisten = new MouseMotionAdapter() { ++ public void mouseMoved(MouseEvent e) { ++ int index = remoteFileTable.locationToIndex(e.getPoint()); ++ if (index == lastRemoteIndex) { ++ return; ++ } else if (index < 0) { ++ return; ++ } ++ lastRemoteIndex = index; ++ connectionStatus.setText((String) remoteListInfo.get(index)); ++ } ++ }; + remoteFileTable.addMouseListener(this); ++ remoteFileTable.addMouseMotionListener(mlisten); + remoteFileTable.setSelectedValue("C:\\", false); + remoteFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ++//System.out.println("getRemoteFileTable"); + + } + return remoteFileTable; +@@ -698,6 +939,7 @@ + remoteScrollPane = new javax.swing.JScrollPane(); + remoteScrollPane.setViewportView(getRemoteFileTable()); + remoteScrollPane.setPreferredSize(new java.awt.Dimension(325, 418)); ++//System.out.println("getRemoteScrollPane"); + } + return remoteScrollPane; + } +@@ -716,6 +958,7 @@ + remoteLocation.setBackground(new Color(255,255,238)); + remoteLocation.setFont( + new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); ++//System.out.println("getRemoteLocation"); + } + return remoteLocation; + } +@@ -732,6 +975,7 @@ + localLocation.setBackground( new Color(255,255,238)); + localLocation.setFont( + new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); ++//System.out.println("getLocalLocation"); + } + return localLocation; + } +@@ -748,6 +992,7 @@ + localStatus.setFont( + new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); + localStatus.setEditable(false); ++//System.out.println("getLocalStatus"); + } + return localStatus; + } +@@ -764,6 +1009,7 @@ + remoteStatus.setFont( + new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); + remoteStatus.setEditable(false); ++//System.out.println("getRemoteStatus"); + } + return remoteStatus; + } +@@ -777,9 +1023,10 @@ + historyComboBox = new javax.swing.JComboBox(); + historyComboBox.setFont( + new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); +- historyComboBox.insertItemAt(new String("Pulldown to view history ..."),0); ++ historyComboBox.insertItemAt(new String("Pulldown to view history; Press Escape to Close/Quit; Press Ctrl-R to Reset Panel."),0); + historyComboBox.setSelectedIndex(0); + historyComboBox.addActionListener(this); ++//System.out.println("getHistoryComboBox"); + } + return historyComboBox; + } +@@ -791,6 +1038,7 @@ + private javax.swing.JProgressBar getJProgressBar() { + if (jProgressBar == null) { + jProgressBar = new javax.swing.JProgressBar(); ++//System.out.println("getJProgressBar"); + } + return jProgressBar; + } +@@ -806,6 +1054,7 @@ + connectionStatus.setBackground(java.awt.Color.lightGray); + connectionStatus.setFont( + new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); ++//System.out.println("getConnectionStatus"); + } + connectionStatus.setEditable(false); + return connectionStatus; +@@ -815,7 +1064,12 @@ + * Implements Action listener. + */ + public void actionPerformed(ActionEvent evt) { +- System.out.println(evt.getSource()); ++// System.out.println(evt.getSource()); ++ ++ if (ignore_events) { ++ System.out.println("ignore_events: " + evt.getSource()); ++ return; ++ } + + if (evt.getSource() == closeButton) + { // Close Button +@@ -829,15 +1083,27 @@ + { + doReceive(); + } ++// begin runge/x11vnc ++ else if (evt.getSource() == viewButton) ++ { ++ doView(); ++ } ++// end runge/x11vnc + else if (evt.getSource() == localDrivesComboBox) + { + changeLocalDrive(); + } + else if (evt.getSource() == remoteDrivesComboBox) + { ++//System.out.println("remoteDrivesComboBox"); // runge/x11vnc + changeRemoteDrive(); +- remoteList.clear(); +- remoteFileTable.setListData(remoteList); ++ ++ // are these really needed? changeRemoteDrive() does them at the end. ++ if (false) { ++ remoteList.clear(); ++ remoteListInfo.clear(); ++ remoteFileTable.setListData(remoteList); ++ } + } + else if (evt.getSource() == localTopButton) + { +@@ -845,12 +1111,17 @@ + } + else if (evt.getSource() == remoteTopButton) + { ++//System.out.println("remoteTopButton"); // runge/x11vnc + changeRemoteDrive(); + } + else if(evt.getSource() == deleteButton) + { + doDelete(); + } ++ else if(evt.getSource() == refreshButton) ++ { ++ doRefresh(); ++ } + else if(evt.getSource()==newFolderButton) + { + doNewFolder(); +@@ -864,7 +1135,7 @@ + + private void doNewFolder() + { +- String name = JOptionPane.showInputDialog(null,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); ++ String name = JOptionPane.showInputDialog(jContentPane,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); + if(selectedTable.equals("remote")) + { + name = remoteLocation.getText()+name; +@@ -880,34 +1151,106 @@ + historyComboBox.setSelectedIndex(0); + } + } +- private void doClose() ++ public void doClose() + { ++ if (viewer.ftpOnly) { ++ viewer.disconnect(); ++ return; ++ } + try { + this.setVisible(false); +- viewer.rfb.writeFramebufferUpdateRequest( +- 0, +- 0, +- viewer.rfb.framebufferWidth, +- viewer.rfb.framebufferHeight, +- true); ++ viewer.rfb.writeFramebufferUpdateRequest(0, 0, viewer.rfb.framebufferWidth, ++ viewer.rfb.framebufferHeight, true); ++ ++ if (false) { ++ this.dispose(); ++ jContentPane = null; ++ } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } ++ private void unSwing() { ++ jContentPane = null; ++ topPanel = null; ++ topPanelLocal = null; ++ topPanelRemote = null; ++ topPanelCenter = null; ++ statusPanel = null; ++ remotePanel = null; ++ localPanel = null; ++ buttonPanel = null; ++ sendButton = null; ++ receiveButton = null; ++ deleteButton = null; ++ newFolderButton = null; ++ stopButton = null; ++ closeButton = null; ++ dummyButton = null; ++ localDrivesComboBox = null; ++ remoteDrivesComboBox = null; ++ localMachineLabel = null; ++ remoteMachineLabel = null; ++ localTopButton = null; ++ remoteTopButton = null; ++ localScrollPane = null; ++ localFileTable = null; ++ remoteScrollPane = null; ++ remoteFileTable = null; ++ remoteLocation = null; ++ localLocation = null; ++ localStatus = null; ++ remoteStatus = null; ++ historyComboBox = null; ++ jProgressBar = null; ++ connectionStatus = null; ++ viewButton = null; ++ refreshButton = null; ++ } ++ ++ public void doReset() ++ { ++ try { ++ this.setVisible(false); ++ this.dispose(); ++ jContentPane = null; ++ try {Thread.sleep(500);} catch (InterruptedException e) {} ++ viewer.ftp_init(); ++ } catch (Exception e) { ++ // TODO Auto-generated catch block ++ e.printStackTrace(); ++ } ++ } + ++ public void doOpen() ++ { ++ try { ++ this.setVisible(true); ++ if (false) { ++ this.initialize(); ++ } ++ } catch (Exception e) { ++ // TODO Auto-generated catch block ++ e.printStackTrace(); ++ } ++ } + private void doDelete() + { +- System.out.println("Delete Button Pressed"); ++// System.out.println("Delete Button Pressed"); + //Call this method to delete a file at server + if(selectedTable.equals("remote")) + { +- String sFileName = ((String) this.remoteFileTable.getSelectedValue()); ++ Object selected = this.remoteFileTable.getSelectedValue(); ++ if (selected == null) { ++ return; ++ } ++ String sFileName = ((String) selected); + + // sf@2004 - Directory can't be deleted + if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) + { +- JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); ++ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); + return; + } + +@@ -916,7 +1259,7 @@ + // sf@2004 - Delete prompt + if (remoteList.contains(sFileName)) + { +- int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); ++ int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); + if (r == JOptionPane.NO_OPTION) + return; + } +@@ -926,18 +1269,22 @@ + } + else + { +- String sFileName = ((String) this.localFileTable.getSelectedValue()); ++ Object selected = this.localFileTable.getSelectedValue(); ++ if (selected == null) { ++ return; ++ } ++ String sFileName = ((String) selected); + + // sf@2004 - Directory can't be deleted + if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) + { +- JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); ++ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); + return; + } + // sf@2004 - Delete prompt + if (localList.contains(sFileName)) + { +- int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); ++ int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); + if (r == JOptionPane.NO_OPTION) + return; + } +@@ -952,21 +1299,25 @@ + + private void doReceive() + { +- System.out.println("Received Button Pressed"); ++// System.out.println("Received Button Pressed"); + +- String sFileName = ((String) this.remoteFileTable.getSelectedValue()); ++ Object selected = this.remoteFileTable.getSelectedValue(); ++ if (selected == null) { ++ return; ++ } ++ String sFileName = ((String) selected); + + // sf@2004 - Directory can't be transfered + if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) + { +- JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); ++ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); + return; + } + + // sf@2004 - Overwrite prompt + if (localList.contains(sFileName)) + { +- int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); ++ int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); + if (r == JOptionPane.NO_OPTION) + return; + } +@@ -979,23 +1330,101 @@ + viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); + } + ++// begin runge/x11vnc ++ private void doRefresh() ++ { ++ System.out.println("Refreshing Local and Remote."); ++ refreshLocalLocation(); ++ refreshRemoteLocation(); ++ } ++ ++ private void doView() ++ { ++// System.out.println("View Button Pressed"); ++ ++ if (selectedTable == null) { ++ return; ++ } ++ if (selectedTable.equals("remote")) { ++ viewRemote(); ++ } else if (selectedTable.equals("local")) { ++ viewLocal(); ++ } ++ } ++ ++ private File doReceiveTmp() ++ { ++ ++ if (remoteFileTable == null) { ++ return null; ++ } ++ Object selected = this.remoteFileTable.getSelectedValue(); ++ if (selected == null) { ++ return null; ++ } ++ String sFileName = ((String) selected); ++ ++ if (sFileName == null) { ++ return null; ++ } ++ ++ // sf@2004 - Directory can't be transfered ++ if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) ++ { ++ return null; ++ } ++ ++ File tmp = null; ++ try { ++ tmp = File.createTempFile("ULTRAFTP", ".txt"); ++ } catch (Exception e) { ++ return null; ++ } ++ ++ //updateHistory("Downloaded " + localSelection.toString()); ++ String remoteFileName = this.remoteLocation.getText(); ++ remoteFileName+= ((String) this.remoteFileTable.getSelectedValue()).substring(1); ++ System.out.println("remoteFileName: " + remoteFileName); ++if (false) { ++ char[] b = remoteFileName.toCharArray(); ++ for (int n = 0; n < b.length; n++) { ++ System.out.print(Integer.toHexString(b[n]) + " "); ++ } ++ System.out.println(""); ++ for (int n = 0; n < b.length; n++) { ++ System.out.print(b[n]); ++ } ++ System.out.println(""); ++} ++ ++ String localDestinationPath = tmp.getAbsolutePath(); ++ viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); ++ System.out.println("ReceiveTmp: " + localDestinationPath); ++ return tmp; ++ } ++// end runge/x11vnc ++ + private void doSend() + { +- System.out.println("Send Button Pressed"); ++// System.out.println("Send Button Pressed"); + +- String sFileName = ((String) this.localFileTable.getSelectedValue()); ++ Object selected = this.localFileTable.getSelectedValue(); ++ if (selected == null) { ++ return; ++ } ++ String sFileName = ((String) selected); + + // sf@2004 - Directory can't be transfered + if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) + { +- JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); ++ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); + return; + } + + // sf@2004 - Overwrite prompt + if (remoteList.contains(sFileName)) + { +- int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); ++ int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); + if (r == JOptionPane.NO_OPTION) + return; + } +@@ -1013,6 +1442,7 @@ + // + private void doStop() + { ++ System.out.println("** Current Transfer Aborted **"); + viewer.rfb.fAbort = true; + } + /** +@@ -1024,6 +1454,14 @@ + System.out.println("History: " + message); + historyComboBox.insertItemAt(new String(message), 0); + } ++ ++ public void receivedRemoteDirectoryName(String str) { ++ if (doingShortcutDir) { ++ if (str.length() > 1) { ++ remoteLocation.setText(str); ++ } ++ } ++ } + + /** + * This method updates the file table to the current selection of the remoteComboBox +@@ -1034,11 +1472,44 @@ + remoteSelection = null; + + if (!updateDriveList) { +- String drive = remoteDrivesComboBox.getSelectedItem().toString().substring(0,1)+ ":\\"; +- viewer.rfb.readServerDirectory(drive); +- remoteLocation.setText(drive); ++//System.out.println("changeRemoteDrive-A " + drive); // begin runge/x11vnc ++ Object selected = remoteDrivesComboBox.getSelectedItem(); ++ if (selected != null) { ++ String instr = selected.toString(); ++ if (instr != null) { ++System.out.println("changeRemoteDrive: instr='" + instr + "'"); ++ String drive = instr.substring(0,1)+ ":\\"; ++ if (instr.startsWith(" [")) { ++ int idx = instr.lastIndexOf(']'); ++ if (idx > 2) { ++ drive = instr.substring(2, idx); ++ } else { ++ drive = instr.substring(2); ++ } ++ if (drive.equals("Home")) { ++ drive = ""; ++ } ++ drive += "\\"; ++ doingShortcutDir = true; ++ } else { ++ doingShortcutDir = false; ++ drive = saveRemoteHack(drive); ++ } ++ gotShortcutDir = false; ++ viewer.rfb.readServerDirectory(drive); ++ if (!gotShortcutDir) { ++ remoteLocation.setText(drive); ++ } ++ } else { ++System.out.println("changeRemoteDrive: instr null"); ++ } ++ } else { ++System.out.println("changeRemoteDrive: selection null"); ++ } ++//System.out.println("changeRemoteDrive-B " + drive); // end runge/x11vnc + } + remoteList.clear(); ++ remoteListInfo.clear(); + remoteFileTable.setListData(remoteList); + } + /** +@@ -1048,6 +1519,7 @@ + private void changeLocalDrive() + { + File currentDrive = new File(localDrivesComboBox.getSelectedItem().toString()); ++System.out.println("changeLocalDrive " + currentDrive.toString()); // runge/x11vnc + if(currentDrive.canRead()) + { + localSelection = null; +@@ -1057,9 +1529,11 @@ + else + { + localList.clear(); ++ localListInfo.clear(); + localStatus.setText("WARNING: Drive " + localDrivesComboBox.getSelectedItem().toString()); + connectionStatus.setText(" > WARNING - Local Drive unavailable (possibly restricted access or media not present)"); + } ++ + } + /** + * Determines which FileTable was double-clicked and updates the table +@@ -1098,10 +1572,18 @@ + selectedTable = "remote"; + localFileTable.setBackground(new Color(238, 238, 238)); + remoteFileTable.setBackground(new Color(255, 255, 255)); +- String name = (remoteFileTable.getSelectedValue().toString()).substring(1); ++ Object selected = remoteFileTable.getSelectedValue(); ++ if (selected == null) { ++ return; ++ } ++ String selstr = selected.toString(); ++ if (selstr == null) { ++ return; ++ } ++ String name = selstr.substring(1); + if( !name.substring(0, 2).equals(" [")) + remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); +- ++ + } + + /* +@@ -1115,10 +1597,38 @@ + localFileTable.setBackground(new Color(255, 255, 255)); + File currentSelection = new File(currentLocalDirectory, getTrimmedSelection()); + +- if(currentSelection.isFile()) ++// begin runge/x11vnc ++ // localSelection = currentSelection.getAbsoluteFile(); ++ if(currentSelection.isFile()) { + localSelection = currentSelection.getAbsoluteFile(); ++ localCurrentIsDir = false; ++ } else { ++ localCurrentIsDir = true; ++ } ++// end runge/x11vnc + + } ++ ++// begin runge/x11vnc ++ private void viewRemote() { ++ File tmp = doReceiveTmp(); ++ if (tmp == null) { ++ return; ++ } ++ TextViewer tv = new TextViewer("Remote: " + remoteSelection, tmp, true); ++ } ++ private void viewLocal() { ++ if (localSelection == null) { ++ return; ++ } ++ if (localCurrentIsDir) { ++ return; ++ } ++ File loc = new File(localSelection.toString()); ++ TextViewer tv = new TextViewer("Local: " + localSelection.toString(), loc, false); ++ } ++// end runge/x11vnc ++ + /** + * Updates the Remote File Table based on selection. Called from mouseClicked handler + */ +@@ -1126,20 +1636,29 @@ + String name = null; + String action = null; + String drive = null; +- name = (remoteFileTable.getSelectedValue().toString()).substring(1); ++ Object selected = remoteFileTable.getSelectedValue(); ++ if (selected == null) { ++ return; ++ } ++ String sname = selected.toString(); ++ if (sname == null) { ++ return; ++ } ++ name = sname.substring(1); + + if (name.equals("[..]")) + { + action = "up"; + remoteSelection = null; + drive = remoteLocation.getText().substring(0, remoteLocation.getText().length() - 1); +- // JOptionPane.showMessageDialog(null, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); ++ // JOptionPane.showMessageDialog(jContentPane, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); + int index = drive.lastIndexOf("\\"); + drive = drive.substring(0, index + 1); + + remoteLocation.setText(drive); + viewer.rfb.readServerDirectory(drive); + remoteList.clear(); ++ remoteListInfo.clear(); + remoteFileTable.setListData(remoteList); + } + else if (!name.substring(0, 2).equals(" [") && !name.substring((name.length() - 1), name.length()).equals("]")) +@@ -1149,6 +1668,7 @@ + remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); + drive = remoteLocation.getText(); + // ?? ++ viewRemote(); // runge/x11vnc + } + else + { +@@ -1159,10 +1679,12 @@ + remoteLocation.setText(drive); + viewer.rfb.readServerDirectory(drive); + remoteList.clear(); ++ remoteListInfo.clear(); + remoteFileTable.setListData(remoteList); + } + //remoteLocation.setText(drive); + } ++ + /** + * Updates the Local File Table based on selection. Called from MouseClicked handler + */ +@@ -1188,6 +1710,7 @@ + else if (currentSelection.isFile()) + { + localSelection = currentSelection.getAbsoluteFile(); ++ viewLocal(); // runge/x11vnc + } + else if (currentSelection.isDirectory()) + { +@@ -1201,13 +1724,22 @@ + * + */ + private String getTrimmedSelection(){ +- String currentSelection = (localFileTable.getSelectedValue().toString()).substring(1); +- if(currentSelection.substring(0,1).equals("[") && +- currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ +- return currentSelection.substring(1,currentSelection.length()-1); +- } else { +- return currentSelection; +- } ++ String currentSelection = ""; ++ Object selected = localFileTable.getSelectedValue(); ++ if (selected == null) { ++ return currentSelection; ++ } ++ String selstr = selected.toString(); ++ if (selstr == null) { ++ return currentSelection; ++ } ++ currentSelection = selstr.substring(1); ++ if(currentSelection.substring(0,1).equals("[") && ++ currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ ++ return currentSelection.substring(1,currentSelection.length()-1); ++ } else { ++ return currentSelection; ++ } + } + + /* +@@ -1241,36 +1773,148 @@ + return null; + } + ++ String timeStr(long t) { ++ Date date = new Date(t); ++ return date.toString(); ++ } ++ String dotPast(double f, int n) { ++ String fs = "" + f; ++ int i = fs.lastIndexOf(".") + n; ++ if (i >= 0) { ++ int len = fs.length(); ++ if (i >= len) { ++ i = len-1; ++ } ++ fs = fs.substring(0, i); ++ } ++ return fs; ++ } ++ String sizeStr(int s) { ++ if (s < 0) { ++ return s + "? B"; ++ } else if (s < 1024) { ++ return s + " B"; ++ } else if (s < 1024 * 1024) { ++ double k = s / 1024.0; ++ String ks = dotPast(k, 3); ++ ++ return s + " (" + ks + " KB)"; ++ } else { ++ double m = s / (1024.0*1024.0); ++ String ms = dotPast(m, 3); ++ return s + " (" + ms + " MB)"; ++ } ++ } ++ ++ int max_char(String text) { ++ int maxc = 0; ++ char chars[] = text.toCharArray(); ++ for (int n = 0; n < chars.length; n++) { ++ if ((int) chars[n] > maxc) { ++ maxc = (int) chars[n]; ++ } ++ } ++ return maxc; ++ } + + /* + * Navigates the local file structure up or down one directory + */ + public void changeLocalDirectory(File dir) + { +- currentLocalDirectory = dir; // Updates Global ++ dir = saveLocalHack(dir); // runge/x11vnc ++ ++ if (dir == null) { ++ connectionStatus.setText("Error changing local directory."); ++ historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); ++ historyComboBox.setSelectedIndex(0); ++ return; ++ } ++ + File allFiles[] = dir.listFiles(); // Reads files + String[] contents = dir.list(); + ++ if (contents == null || allFiles == null) { ++ connectionStatus.setText("Error changing local directory."); ++ historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); ++ historyComboBox.setSelectedIndex(0); ++ return; ++ } ++ ++ currentLocalDirectory = dir; // Updates Global ++// begin runge/x11vnc ++System.out.println("changeLocalDirectory: " + dir.toString()); ++ if (contents != null) { ++ java.util.Arrays.sort(contents, String.CASE_INSENSITIVE_ORDER); ++ for (int i = 0; i < contents.length; i++) { ++ allFiles[i] = new File(dir, contents[i]); ++ } ++ } else { ++ return; ++ } ++// end runge/x11vnc ++ + localList.clear(); ++ localListInfo.clear(); + localList.addElement(" [..]"); ++ localListInfo.addElement(" [..]"); ++ ++ ArrayList DirInfo = new ArrayList(); ++ ArrayList FilInfo = new ArrayList(); ++ ++ Charset charset = Charset.forName("ISO-8859-1"); ++ CharsetDecoder decoder = charset.newDecoder(); ++ CharsetEncoder encoder = charset.newEncoder(); + + // Populate the Lists + for (int i = 0; i < contents.length; i++) + { +- if (allFiles[i].isDirectory()) ++ String f1 = contents[i]; ++ ++if (false) { ++ ++System.out.println("max_char: " + max_char(f1) + " " + f1); ++ if (max_char(f1) > 255) { ++ try { ++System.out.println("bbuf1"); ++ ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(f1.toCharArray())); ++System.out.println("bbuf2"); ++ CharBuffer cbuf = decoder.decode(bbuf); ++System.out.println("bbuf3"); ++ f1 = cbuf.toString(); ++System.out.println("did bbuf: " + f1); ++ } catch (Exception e) { ++ ; ++ } ++ } ++} ++ ++ String f2 = f1; ++ if (f2.length() < 24) { ++ for (int ik = f2.length(); ik < 24; ik++) { ++ f2 = f2 + " "; ++ } ++ } ++ String s = f2 + " \tLastmod: " + timeStr(allFiles[i].lastModified()) + " \t\tSize: " + sizeStr((int) allFiles[i].length()); ++ if (allFiles[i].isDirectory()) { + // localList.addElement("[" + contents[i] + "]"); +- DirsList.add(" [" + contents[i] + "]"); // sf@2004 +- else +- { ++ DirsList.add(" [" + f1 + "]"); // sf@2004 ++ DirInfo.add(s); ++ } else { + // localList.addElement(contents[i]); +- FilesList.add(" " + contents[i]); // sf@2004 ++ FilesList.add(" " + f1); // sf@2004 ++ FilInfo.add(s); + } + } + // sf@2004 +- for (int i = 0; i < DirsList.size(); i++) ++ for (int i = 0; i < DirsList.size(); i++) { + localList.addElement(DirsList.get(i)); +- for (int i = 0; i < FilesList.size(); i++) ++ localListInfo.addElement(DirInfo.get(i)); ++ } ++ for (int i = 0; i < FilesList.size(); i++) { + localList.addElement(FilesList.get(i)); ++ localListInfo.addElement(FilInfo.get(i)); ++ } + + FilesList.clear(); + DirsList.clear(); +@@ -1296,3 +1940,147 @@ + } + + } // @jve:visual-info decl-index=0 visual-constraint="10,10" ++ ++// begin runge/x11vnc ++class TextViewer extends JFrame implements ActionListener { ++ ++ JTextArea textArea = new JTextArea(35, 80); ++ File file = null; ++ JButton refreshButton; ++ JButton dismissButton; ++ Timer tim = null; ++ int rcnt = 0; ++ int tms = 250; ++ boolean delete_it = false; ++ TextViewer me; ++ ++ public TextViewer(String s, File f, boolean d) { ++ ++ delete_it = d; ++ file = f; ++ me = this; ++ ++ JScrollPane scrollPane = new JScrollPane(textArea, ++ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, ++ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); ++ ++ textArea.setEditable(false); ++ textArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); ++ ++ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, InputEvent.SHIFT_MASK); ++ AbstractAction escapeAction = new AbstractAction() { ++ public void actionPerformed(ActionEvent actionEvent) { ++ cleanse(); ++ me.dispose(); ++ } ++ }; ++ textArea.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); ++ textArea.getInputMap().put(stroke, "escapeAction"); ++ textArea.getActionMap().put("escapeAction", escapeAction); ++ ++ refreshButton = new JButton(); ++ refreshButton.setText("Reload"); ++ refreshButton.setName("refreshButton"); ++ refreshButton.addActionListener(this); ++ ++ dismissButton = new JButton(); ++ dismissButton.setText("Dismiss"); ++ dismissButton.setName("dismissButton"); ++ dismissButton.addActionListener(this); ++ ++ JPanel buttons = new JPanel(); ++ buttons.setLayout(new BorderLayout()); ++ buttons.add(refreshButton, BorderLayout.WEST); ++ buttons.add(dismissButton, BorderLayout.EAST); ++ ++ JPanel content = new JPanel(); ++ content.setLayout(new BorderLayout()); ++ content.add(scrollPane, BorderLayout.CENTER); ++ content.add(buttons, BorderLayout.SOUTH); ++ ++ ActionListener tsk = new ActionListener() { ++ public void actionPerformed(ActionEvent evt) { ++ // System.out.println("tsk"); ++ refresh(); ++ } ++ }; ++ tim = new Timer(tms, tsk); ++ tim.start(); ++ ++ this.setContentPane(content); ++ this.setTitle("TextViewer - " + s); ++ this.pack(); ++ this.setVisible(true); ++ } ++ ++ private void refresh() { ++ ++ rcnt++; ++ if (rcnt * tms > 3000 && tim != null) { ++ tim.stop(); ++ tim = null; ++ } ++ BufferedReader input = null; ++ StringBuffer contents = new StringBuffer(); ++ try { ++ if (input == null) { ++ input = new BufferedReader(new FileReader(file)); ++ } ++ String line = null; ++ int i = 0; ++ while (( line = input.readLine()) != null) { ++ if (i == 0) { ++ // System.out.println("read"); ++ } ++ i++; ++ contents.append(line); ++ contents.append(System.getProperty("line.separator")); ++ } ++ } catch (Exception e) { ++ ; ++ } finally { ++ try { ++ if (input != null) { ++ input.close(); ++ input = null; ++ } ++ } catch (Exception e) { ++ ; ++ } ++ } ++ ++ textArea.setText(contents.toString()); ++ textArea.setCaretPosition(0); ++ } ++ ++ public void actionPerformed(ActionEvent evt) { ++ ++ if (evt.getSource() == refreshButton) { ++ refresh(); ++ } ++ if (evt.getSource() == dismissButton) { ++ cleanse(); ++ this.dispose(); ++ } ++ } ++ ++ private void cleanse() { ++ if (delete_it && file != null) { ++ try { ++ file.delete(); ++ file = null; ++ } catch (Exception e) { ++ ; ++ } ++ } ++ } ++ ++ protected void finalize() throws Throwable { ++ try { ++ cleanse(); ++ } finally { ++ super.finalize(); ++ } ++ } ++} ++// end runge/x11vnc +diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java +--- JavaViewer.orig/OptionsFrame.java 2005-11-21 18:50:16.000000000 -0500 ++++ JavaViewer/OptionsFrame.java 2007-05-13 22:18:30.000000000 -0400 +@@ -144,7 +144,10 @@ + choices[jpegQualityIndex].select("6"); + choices[cursorUpdatesIndex].select("Enable"); + choices[useCopyRectIndex].select("Yes"); +- choices[eightBitColorsIndex].select("64"); ++// begin runge/x11vnc ++// choices[eightBitColorsIndex].select("64"); ++ choices[eightBitColorsIndex].select("Full"); ++// end runge/x11vnc + choices[mouseButtonIndex].select("Normal"); + choices[viewOnlyIndex].select("No"); + choices[shareDesktopIndex].select("Yes"); +diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java +--- JavaViewer.orig/RfbProto.java 2006-05-24 15:14:40.000000000 -0400 ++++ JavaViewer/RfbProto.java 2010-03-27 17:59:56.000000000 -0400 +@@ -31,6 +31,7 @@ + import java.net.Socket; + import java.util.*; + import java.util.zip.*; ++import java.text.DateFormat; + + + class RfbProto { +@@ -86,8 +87,11 @@ + + // sf@2004 - FileTransfer part + ArrayList remoteDirsList; ++ ArrayList remoteDirsListInfo; + ArrayList remoteFilesList; ++ ArrayList remoteFilesListInfo; + ArrayList a; ++ ArrayList b; + boolean fFTInit = true; // sf@2004 + boolean fFTAllowed = true; + boolean fAbort = false; +@@ -199,6 +203,10 @@ + // playback. + int numUpdatesInSession; + ++// begin runge/x11vnc ++ int readServerDriveListCnt = -1; ++ long readServerDriveListTime = 0; ++// end runge/x11vnc + // + // Constructor. Make TCP connection to RFB server. + // +@@ -207,7 +215,27 @@ + viewer = v; + host = h; + port = p; +- sock = new Socket(host, port); ++// begin runge/x11vnc ++// sock = new Socket(host, port); ++ if (! viewer.disableSSL) { ++ System.out.println("new SSLSocketToMe"); ++ SSLSocketToMe ssl; ++ try { ++ ssl = new SSLSocketToMe(host, port, v); ++ } catch (Exception e) { ++ throw new IOException(e.getMessage()); ++ } ++ ++ try { ++ sock = ssl.connectSock(); ++ } catch (Exception es) { ++ throw new IOException(es.getMessage()); ++ } ++ } else { ++ sock = new Socket(host, port); ++ } ++// end runge/x11vnc ++ + is = + new DataInputStream( + new BufferedInputStream(sock.getInputStream(), 16384)); +@@ -215,9 +243,12 @@ + osw = new OutputStreamWriter(sock.getOutputStream()); + inDirectory2 = false; + a = new ArrayList(); ++ b = new ArrayList(); + // sf@2004 + remoteDirsList = new ArrayList(); ++ remoteDirsListInfo = new ArrayList(); + remoteFilesList = new ArrayList(); ++ remoteFilesListInfo = new ArrayList(); + + sendFileSource = ""; + } +@@ -420,7 +451,13 @@ + // + + int readServerMessageType() throws IOException { +- int msgType = is.readUnsignedByte(); ++ int msgType; ++ try { ++ msgType = is.readUnsignedByte(); ++ } catch (Exception e) { ++ viewer.disconnect(); ++ return -1; ++ } + + // If the session is being recorded: + if (rec != null) { +@@ -600,6 +637,7 @@ + contentParamT = is.readUnsignedByte(); + contentParamT = contentParamT << 8; + contentParam = contentParam | contentParamT; ++//System.out.println("FTM: contentType " + contentType + " contentParam " + contentParam); + if (contentType == rfbRDrivesList || contentType == rfbDirPacket) + { + readDriveOrDirectory(contentParam); +@@ -610,7 +648,7 @@ + } + else if (contentType == rfbFilePacket) + { +- receiveFileChunk(); ++ receiveFileChunk(); + } + else if (contentType == rfbEndOfFile) + { +@@ -618,6 +656,10 @@ + } + else if (contentType == rfbAbortFileTransfer) + { ++ System.out.println("rfbAbortFileTransfer: fFileReceptionRunning=" ++ + fFileReceptionRunning + " fAbort=" ++ + fAbort + " fFileReceptionError=" ++ + fFileReceptionError); + if (fFileReceptionRunning) + { + endOfReceiveFile(false); // Error +@@ -626,6 +668,11 @@ + { + // sf@2004 - Todo: Add TestPermission + // System.out.println("File Transfer Aborted!"); ++ ++ // runge: seems like we must at least read the remaining ++ // 8 bytes of the header, right? ++ int size = is.readInt(); ++ int length = is.readInt(); + } + + } +@@ -645,6 +692,7 @@ + { + System.out.println("ContentType: " + contentType); + } ++//System.out.println("FTM: done"); + } + + //Refactored from readRfbFileTransferMsg() +@@ -662,6 +710,7 @@ + + //Refactored from readRfbFileTransferMsg() + public void readDriveOrDirectory(int contentParam) throws IOException { ++//System.out.println("RDOD: " + contentParam + " " + inDirectory2); + if (contentParam == rfbADrivesList) + { + readFTPMsgDriveList(); +@@ -688,13 +737,21 @@ + + // Internally used. Write an Rfb message to the server + void writeRfbFileTransferMsg( +- int contentType, +- int contentParam, +- long size, // 0 : compression not supported - 1 : compression supported +- long length, +- String text) throws IOException ++ int contentType, ++ int contentParam, ++ long size, // 0 : compression not supported - 1 : compression supported ++ long length, ++ String text) throws IOException + { + byte b[] = new byte[12]; ++ byte byteArray[]; ++ ++ if (viewer.dsmActive) { ++ // need to send the rfbFileTransfer msg type twice for the plugin... ++ byte b2[] = new byte[1]; ++ b2[0] = (byte) rfbFileTransfer; ++ os.write(b2); ++ } + + b[0] = (byte) rfbFileTransfer; + b[1] = (byte) contentType; +@@ -702,7 +759,7 @@ + + byte by = 0; + long c = 0; +- length++; ++ + c = size & 0xFF000000; + by = (byte) (c >>> 24); + b[4] = by; +@@ -716,6 +773,32 @@ + by = (byte) c; + b[7] = by; + ++ if (text != null) { ++ byte byteArray0[] = text.getBytes(); ++ int maxc = max_char(text); ++ if (maxc > 255) { ++ System.out.println("writeRfbFileTransferMsg: using getBytes(\"UTF-8\")"); ++ byteArray0 = text.getBytes("UTF-8"); ++ } else if (maxc > 127) { ++ System.out.println("writeRfbFileTransferMsg: using getBytes(\"ISO-8859-1\")"); ++ byteArray0 = text.getBytes("ISO-8859-1"); ++ } ++ byteArray = new byte[byteArray0.length + 1]; ++ for (int i = 0; i < byteArray0.length; i++) { ++ byteArray[i] = byteArray0[i]; ++ } ++ byteArray[byteArray.length - 1] = 0; ++System.out.println("writeRfbFileTransferMsg: length: " + length + " -> byteArray.length: " + byteArray.length); ++ ++ // will equal length for ascii, ISO-8859-1, more for UTF-8 ++ length = byteArray.length; ++ ++ //length++; // used to not include null byte at end. ++ } else { ++ String moo = "moo"; ++ byteArray = moo.getBytes(); ++ } ++ + c = length & 0xFF000000; + by = (byte) (c >>> 24); + b[8] = by; +@@ -729,29 +812,91 @@ + by = (byte) c; + b[11] = by; + os.write(b); ++ ++//System.out.println("size: " + size + " length: " + length + " text: " + text); + + + if (text != null) + { +- byte byteArray[] = text.getBytes(); +- byte byteArray2[] = new byte[byteArray.length + 1]; +- for (int i = 0; i < byteArray.length; i++) { +- byteArray2[i] = byteArray[i]; ++ os.write(byteArray); ++ } ++ } ++ ++ int max_char(String text) { ++ int maxc = 0; ++ char chars[] = text.toCharArray(); ++ for (int n = 0; n < chars.length; n++) { ++ if ((int) chars[n] > maxc) { ++ maxc = (int) chars[n]; + } +- byteArray2[byteArray2.length - 1] = 0; +- os.write(byteArray2); + } +- ++ return maxc; + } + ++ String guess_encoding(char[] chars) { ++ boolean saw_high_char = false; ++ ++ for (int i = 0; i < chars.length; i++) { ++ if (chars[i] == '\0') { ++ break; ++ } ++ if (chars[i] >= 128) { ++ saw_high_char = true; ++ break; ++ } ++ } ++ if (!saw_high_char) { ++ return "ASCII"; ++ } ++ char prev = 1; ++ boolean valid_utf8 = true; ++ int n = 0; ++ for (int i = 0; i < chars.length; i++) { ++ if (chars[i] == '\0') { ++ break; ++ } ++ char c = chars[i]; ++ if (prev < 128 && c >= 128) { ++ if (c >> 5 == 0x6) { ++ n = 1; ++ } else if (c >> 4 == 0xe) { ++ n = 2; ++ } else if (c >> 3 == 0x1e) { ++ n = 3; ++ } else if (c >> 2 == 0x3e) { ++ n = 4; ++ } else { ++ valid_utf8 = false; ++ break; ++ } ++ } else { ++ if (n > 0) { ++ if (c < 128) { ++ valid_utf8 = false; ++ break; ++ } ++ n--; ++ } ++ } ++ ++ prev = c; ++ } ++ if (valid_utf8) { ++ return "UTF-8"; ++ } else { ++ return "ISO-8859-1"; ++ } ++ } ++ ++ + //Internally used. Write an rfb message to the server for sending files ONLY + int writeRfbFileTransferMsgForSendFile( +- int contentType, +- int contentParam, +- long size, +- long length, +- String source +- ) throws IOException ++ int contentType, ++ int contentParam, ++ long size, ++ long length, ++ String source ++ ) throws IOException + { + File f = new File(source); + fis = new FileInputStream(f); +@@ -768,50 +913,47 @@ + + while (bytesRead!=-1) + { +- counter += bytesRead; +- myDeflater.setInput(byteBuffer, 0, bytesRead); +- myDeflater.finish(); +- compressedSize = myDeflater.deflate(CompressionBuffer); +- myDeflater.reset(); +- // If the compressed data is larger than the original one, we're dealing with +- // already compressed data +- if (compressedSize > bytesRead) +- fCompress = false; +- this.writeRfbFileTransferMsg( +- contentType, +- contentParam, +- (fCompress ? 1 : 0), +- (fCompress ? compressedSize-1 : bytesRead-1), +- null +- ); +- // Todo: Test write error ! +- os.write( +- fCompress ? CompressionBuffer : byteBuffer, +- 0, +- fCompress ? compressedSize : bytesRead +- ); +- +- // Todo: test read error ! +- bytesRead = fis.read(byteBuffer); +- +- // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); +- viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); +- viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); +- +- if (fAbort == true) +- { +- fAbort = false; +- fError = true; +- break; +- } +- try +- { +- Thread.sleep(5); +- } +- catch(InterruptedException e) +- { +- System.err.println("Interrupted"); +- } ++ counter += bytesRead; ++ myDeflater.setInput(byteBuffer, 0, bytesRead); ++ myDeflater.finish(); ++ compressedSize = myDeflater.deflate(CompressionBuffer); ++ myDeflater.reset(); ++ // If the compressed data is larger than the original one, we're dealing with ++ // already compressed data ++ if (compressedSize > bytesRead) ++ fCompress = false; ++ this.writeRfbFileTransferMsg( ++ contentType, ++ contentParam, ++ (fCompress ? 1 : 0), ++// RUNGE (fCompress ? compressedSize-1 : bytesRead-1), ++ (fCompress ? compressedSize : bytesRead), ++ null ++ ); ++ // Todo: Test write error ! ++ os.write(fCompress ? CompressionBuffer : byteBuffer, 0, fCompress ? compressedSize : bytesRead); ++ ++ // Todo: test read error ! ++ bytesRead = fis.read(byteBuffer); ++ ++ // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); ++ viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); ++ viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); ++ ++ if (fAbort == true) ++ { ++ fAbort = false; ++ fError = true; ++ break; ++ } ++ try ++ { ++ Thread.sleep(5); ++ } ++ catch(InterruptedException e) ++ { ++ System.err.println("Interrupted"); ++ } + } + + writeRfbFileTransferMsg(fError ? rfbAbortFileTransfer : rfbEndOfFile, 0, 0, 0, null); +@@ -831,24 +973,30 @@ + { + System.out.print((char) is.readUnsignedByte()); + } ++ System.out.println(""); ++ ++ if (size == rfbRErrorCmd || size == -1) { ++ viewer.ftp.enableButtons(); ++ viewer.ftp.connectionStatus.setText("Remote file not available for writing."); ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for writing."), 0); ++ viewer.ftp.historyComboBox.setSelectedIndex(0); ++ return; ++ } + +- int ret = writeRfbFileTransferMsgForSendFile( +- rfbFilePacket, +- 0, +- 0, +- 0, +- sendFileSource); ++ int ret = writeRfbFileTransferMsgForSendFile(rfbFilePacket, 0, 0, 0, sendFileSource); + + viewer.ftp.refreshRemoteLocation(); + if (ret != 1) + { + viewer.ftp.connectionStatus.setText(" > Error - File NOT sent"); +- viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) + "> was not correctly sent (aborted by user or error)",0); ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) ++ + "> was not correctly sent (aborted or error). Data may still be buffered/in transit. Wait for remote listing...",0); + } + else + { + viewer.ftp.connectionStatus.setText(" > File sent"); +- viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) + "> was sent to Remote Machine",0); ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) ++ + "> was sent to Remote Machine. Note: data may still be buffered/in transit. Wait for remote listing...",0); + } + viewer.ftp.historyComboBox.setSelectedIndex(0); + viewer.ftp.enableButtons(); +@@ -907,7 +1055,7 @@ + //Handles acknowledgement that the file has been deleted on the server + void deleteRemoteFileFeedback() throws IOException + { +- is.readInt(); ++ int ret = is.readInt(); + int length = is.readInt(); + String f = ""; + for (int i = 0; i < length; i++) +@@ -916,7 +1064,11 @@ + } + + viewer.ftp.refreshRemoteLocation(); +- viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); ++ if (ret == -1) { ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Delete File On Remote Machine: "),0); ++ } else { ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); ++ } + viewer.ftp.historyComboBox.setSelectedIndex(0); + } + +@@ -926,12 +1078,7 @@ + try + { + String temp = text; +- writeRfbFileTransferMsg( +- rfbCommand, +- rfbCFileDelete, +- 0, +- temp.length(), +- temp); ++ writeRfbFileTransferMsg(rfbCommand, rfbCFileDelete, 0, temp.length(), temp); + } + catch (IOException e) + { +@@ -943,7 +1090,7 @@ + // Handles acknowledgement that the directory has been created on the server + void createRemoteDirectoryFeedback() throws IOException + { +- is.readInt(); ++ int ret = is.readInt(); + int length = is.readInt(); + String f=""; + for (int i = 0; i < length; i++) +@@ -951,7 +1098,11 @@ + f += (char)is.readUnsignedByte(); + } + viewer.ftp.refreshRemoteLocation(); +- viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); ++ if (ret == -1) { ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Create Directory on Remote Machine."),0); ++ } else { ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); ++ } + viewer.ftp.historyComboBox.setSelectedIndex(0); + } + +@@ -961,12 +1112,7 @@ + try + { + String temp = text; +- writeRfbFileTransferMsg( +- rfbCommand, +- rfbCDirCreate, +- 0, +- temp.length(), +- temp); ++ writeRfbFileTransferMsg(rfbCommand, rfbCDirCreate, 0, temp.length(), temp); + } + catch (IOException e) + { +@@ -979,15 +1125,13 @@ + { + try + { ++//System.out.println("requestRemoteFile text: " + text); ++//System.out.println("requestRemoteFile leng: " + text.length()); + String temp = text; + receivePath = localPath; + +- writeRfbFileTransferMsg( +- rfbFileTransferRequest, +- 0, +- 1, // 0 : compression not supported - 1 : compression supported +- temp.length(), +- temp); ++ // 0 : compression not supported - 1 : compression supported ++ writeRfbFileTransferMsg(rfbFileTransferRequest, 0, 1, temp.length(), temp); + } + catch (IOException e) + { +@@ -1004,6 +1148,9 @@ + viewer.ftp.disableButtons(); + int size = is.readInt(); + int length = is.readInt(); ++ ++//System.out.println("receiveFileHeader size: " + size); ++//System.out.println("receiveFileHeader leng: " + length); + + String tempName = ""; + for (int i = 0; i < length; i++) +@@ -1011,6 +1158,15 @@ + tempName += (char) is.readUnsignedByte(); + } + ++ if (size == rfbRErrorCmd || size == -1) { ++ fFileReceptionRunning = false; ++ viewer.ftp.enableButtons(); ++ viewer.ftp.connectionStatus.setText("Remote file not available for reading."); ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for reading."), 0); ++ viewer.ftp.historyComboBox.setSelectedIndex(0); ++ return; ++ } ++ + // sf@2004 - Read the high part of file size (not yet in rfbFileTransferMsg for + // backward compatibility reasons...) + int sizeH = is.readInt(); +@@ -1021,7 +1177,16 @@ + fileSize=0; + fileChunkCounter = 0; + String fileName = receivePath; +- fos = new FileOutputStream(fileName); ++ try { ++ fos = new FileOutputStream(fileName); ++ } catch (Exception e) { ++ fFileReceptionRunning = false; ++ writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR opening Local File: <" + fileName ),0); ++ viewer.ftp.historyComboBox.setSelectedIndex(0); ++ viewer.ftp.enableButtons(); ++ return; ++ } + writeRfbFileTransferMsg(rfbFileHeader, 0, 0, 0, null); + } + +@@ -1085,7 +1250,13 @@ + fAbort = false; + fFileReceptionError = true; + writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); +- ++ ++ //runge for use with x11vnc/libvncserver, no rfbAbortFileTransfer reply sent. ++ try {Thread.sleep(500);} catch (InterruptedException e) {} ++ viewer.ftp.enableButtons(); ++ viewer.ftp.refreshLocalLocation(); ++ viewer.ftp.connectionStatus.setText(" > Error - File NOT received"); ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + receivePath + "> not correctly received from Remote Machine (aborted by user or error)") ,0); + } + // sf@2004 - For old FT protocole only + /* +@@ -1104,7 +1275,7 @@ + int length = is.readInt(); + fileSize=0; + fos.close(); +- ++ + viewer.ftp.refreshLocalLocation(); + if (fReceptionOk && !fFileReceptionError) + { +@@ -1132,12 +1303,7 @@ + try + { + String temp = text; +- writeRfbFileTransferMsg( +- rfbDirContentRequest, +- rfbRDirContent, +- 0, +- temp.length(), +- temp); ++ writeRfbFileTransferMsg(rfbDirContentRequest, rfbRDirContent, 0, temp.length(), temp); + } + catch (IOException e) + { +@@ -1197,11 +1363,80 @@ + str += temp; + } + } ++ // runge ++ viewer.ftp.receivedRemoteDirectoryName(str); + // viewer.ftp.changeRemoteDirectory(str); + + } + } + ++ int zogswap(int n) { ++ long l = n; ++ if (l < 0) { ++ l += 0x100000000L; ++ } ++ l = l & 0xFFFFFFFF; ++ l = (l >> 24) | ((l & 0x00ff0000) >> 8) | ((l & 0x0000ff00) << 8) | (l << 24); ++ return (int) l; ++ } ++ ++ int windozeToUnix(int L, int H) { ++ long L2 = zogswap(L); ++ long H2 = zogswap(H); ++ long unix = (H2 << 32) + L2; ++ unix -= 11644473600L * 10000000L; ++ unix /= 10000000L; ++ //System.out.println("unix time: " + unix + " H2: " + H2 + " L2: " + L2); ++ return (int) unix; ++ } ++ ++ String timeStr(int t, int h) { ++ if (h == 0) { ++ // x11vnc/libvncserver unix ++ t = zogswap(t); ++ } else { ++ // ultra (except if h==0 by chance) ++ t = windozeToUnix(t, h); ++ } ++ long tl = (long) t; ++ Date date = new Date(tl * 1000); ++ if (true) { ++ return date.toString(); ++ } else { ++ return DateFormat.getDateTimeInstance().format(date); ++ } ++ } ++ ++ String dotPast(double f, int n) { ++ String fs = "" + f; ++ int i = fs.lastIndexOf(".") + n; ++ if (i >= 0) { ++ int len = fs.length(); ++ if (i >= len) { ++ i = len-1; ++ } ++ fs = fs.substring(0, i); ++ } ++ return fs; ++ } ++ String sizeStr(int s) { ++ s = zogswap(s); ++ if (s < 0) { ++ return s + "? B"; ++ } else if (s < 1024) { ++ return s + " B"; ++ } else if (s < 1024 * 1024) { ++ double k = s / 1024.0; ++ String ks = dotPast(k, 3); ++ ++ return s + " (" + ks + " KB)"; ++ } else { ++ double m = s / (1024.0*1024.0); ++ String ms = dotPast(m, 3); ++ return s + " (" + ms + " MB)"; ++ } ++ } ++ + //Internally used to receive directory content from server + //Here, the server sends one file/directory with it's attributes + void readFTPMsgDirectoryListContent() throws IOException +@@ -1217,17 +1452,32 @@ + dwReserved0, + dwReserved1; + long ftCreationTime, ftLastAccessTime, ftLastWriteTime; ++ int ftCreationTimeL, ftLastAccessTimeL, ftLastWriteTimeL; ++ int ftCreationTimeH, ftLastAccessTimeH, ftLastWriteTimeH; + char cFileName, cAlternateFileName; + int length = 0; + is.readInt(); + length = is.readInt(); ++ ++ char[] chars = new char[4*length]; ++ int char_cnt = 0; ++ for (int i = 0; i < chars.length; i++) { ++ chars[i] = '\0'; ++ } ++ + dwFileAttributes = is.readInt(); + length -= 4; +- ftCreationTime = is.readLong(); ++ //ftCreationTime = is.readLong(); ++ ftCreationTimeL = is.readInt(); ++ ftCreationTimeH = is.readInt(); + length -= 8; +- ftLastAccessTime = is.readLong(); ++ //ftLastAccessTime = is.readLong(); ++ ftLastAccessTimeL = is.readInt(); ++ ftLastAccessTimeH = is.readInt(); + length -= 8; +- ftLastWriteTime = is.readLong(); ++ //ftLastWriteTime = is.readLong(); ++ ftLastWriteTimeL = is.readInt(); ++ ftLastWriteTimeH = is.readInt(); + length -= 8; + nFileSizeHigh = is.readInt(); + length -= 4; +@@ -1239,10 +1489,12 @@ + length -= 4; + cFileName = (char) is.readUnsignedByte(); + length--; ++ chars[char_cnt++] = cFileName; + while (cFileName != '\0') + { + fileName += cFileName; + cFileName = (char) is.readUnsignedByte(); ++ chars[char_cnt++] = cFileName; + length--; + } + cAlternateFileName = (char) is.readByte(); +@@ -1253,7 +1505,28 @@ + cAlternateFileName = (char) is.readUnsignedByte(); + length--; + } +- if (dwFileAttributes == 268435456 ++ String guessed = guess_encoding(chars); ++ if (!guessed.equals("ASCII")) { ++ System.out.println("guess: " + guessed + "\t" + fileName); ++ } ++ if (guessed.equals("UTF-8")) { ++ try { ++ byte[] bytes = new byte[char_cnt-1]; ++ for (int i=0; i < char_cnt-1; i++) { ++ bytes[i] = (byte) chars[i]; ++ } ++ String newstr = new String(bytes, "UTF-8"); ++ fileName = newstr; ++ } catch (Exception e) { ++ System.out.println("failed to convert bytes to UTF-8 based string"); ++ } ++ } ++ for (int i = 0; i < char_cnt; i++) { ++ //System.out.println("char[" + i + "]\t" + (int) chars[i]); ++ } ++ if (fileName.length() <= 0) { ++ ; ++ } else if (dwFileAttributes == 268435456 + || dwFileAttributes == 369098752 + || dwFileAttributes == 285212672 + || dwFileAttributes == 271056896 +@@ -1263,11 +1536,74 @@ + || dwFileAttributes == 369623040) + { + fileName = " [" + fileName + "]"; +- remoteDirsList.add(fileName); // sf@2004 +- } +- else +- { +- remoteFilesList.add(" " + fileName); // sf@2004 ++// begin runge/x11vnc ++// remoteDirsList.add(fileName); // sf@2004 ++ int i = -1; ++ String t1 = fileName.toLowerCase(); ++ for (int j = 0; j < remoteDirsList.size(); j++) { ++ String t = (String) remoteDirsList.get(j); ++ String t2 = t.toLowerCase(); ++ if (t1.compareTo(t2) < 0) { ++ i = j; ++ break; ++ } ++ } ++ //String s = "Lastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " " + fileName; ++ String f2 = fileName; ++ if (f2.length() < 24) { ++ for (int ik = f2.length(); ik < 24; ik++) { ++ f2 = f2 + " "; ++ } ++ } ++ String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); ++ //s = fileName + " Lastmod: " + zogswap(ftLastWriteTimeL); ++ if (i >= 0) { ++ remoteDirsList.add(i, fileName); ++ remoteDirsListInfo.add(i, s); ++ } else { ++ remoteDirsList.add(fileName); ++ remoteDirsListInfo.add(s); ++ } ++// end runge/x11vnc ++ } else { ++// begin runge/x11vnc ++// remoteFilesList.add(" " + fileName); // sf@2004 ++ ++ fileName = " " + fileName; ++ int i = -1; ++ String t1 = fileName.toLowerCase(); ++ for (int j = 0; j < remoteFilesList.size(); j++) { ++ String t = (String) remoteFilesList.get(j); ++ String t2 = t.toLowerCase(); ++ if (t1.compareTo(t2) < 0) { ++ i = j; ++ break; ++ } ++ } ++ String f2 = fileName; ++ if (f2.length() < 24) { ++ for (int ik = f2.length(); ik < 24; ik++) { ++ f2 = f2 + " "; ++ } ++ } ++ ++if (false) { ++System.out.println("fileName: " + f2); ++System.out.println("ftLastWriteTimeL: " + ftLastWriteTimeL); ++System.out.println("ftLastWriteTimeH: " + ftLastWriteTimeH); ++System.out.println("nFileSizeLow: " + nFileSizeLow); ++} ++ ++ String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); ++ //s = fileName + " Lastmod: " + ftLastWriteTimeL + "/" + zogswap(ftLastWriteTimeL) + " Size: " + nFileSizeLow + "/" + zogswap(nFileSizeLow); ++ if (i >= 0) { ++ remoteFilesList.add(i, fileName); ++ remoteFilesListInfo.add(i, s); ++ } else { ++ remoteFilesList.add(fileName); ++ remoteFilesListInfo.add(s); ++ } ++// end runge/x11vnc + } + + // a.add(fileName); +@@ -1282,14 +1618,32 @@ + + // sf@2004 + a.clear(); +- for (int i = 0; i < remoteDirsList.size(); i++) ++ b.clear(); ++ for (int i = 0; i < remoteDirsList.size(); i++) { + a.add(remoteDirsList.get(i)); +- for (int i = 0; i < remoteFilesList.size(); i++) ++ b.add(remoteDirsListInfo.get(i)); ++ } ++ for (int i = 0; i < remoteFilesList.size(); i++) { + a.add(remoteFilesList.get(i)); ++ ++ b.add(remoteFilesListInfo.get(i)); ++ } + remoteDirsList.clear(); ++ remoteDirsListInfo.clear(); + remoteFilesList.clear(); ++ remoteFilesListInfo.clear(); + +- viewer.ftp.printDirectory(a); ++// begin runge/x11vnc ++ // Hack for double listing at startup... probably libvncserver bug.. ++ readServerDriveListCnt++; ++ if (readServerDriveListCnt == 2) { ++ if (System.currentTimeMillis() - readServerDriveListTime < 2000) { ++//System.out.println("readServerDriveListCnt skip " + readServerDriveListCnt); ++ return; ++ } ++ } ++// end runge/x11vnc ++ viewer.ftp.printDirectory(a, b); + } + + //Internally used to signify the drive requested is not ready +@@ -1299,6 +1653,8 @@ + System.out.println("Remote Drive unavailable"); + viewer.ftp.connectionStatus.setText(" > WARNING - Remote Drive unavailable (possibly restricted access or media not present)"); + viewer.ftp.remoteStatus.setText("WARNING: Remote Drive unavailable"); ++ viewer.ftp.historyComboBox.insertItemAt(new String(" > WARNING: Remote Drive unavailable."), 0); ++ viewer.ftp.historyComboBox.setSelectedIndex(0); + } + + //Call this method to request the list of drives on the server. +@@ -1306,12 +1662,11 @@ + { + try + { +- viewer.rfb.writeRfbFileTransferMsg( +- RfbProto.rfbDirContentRequest, +- RfbProto.rfbRDrivesList, +- 0, +- 0, +- null); ++ viewer.rfb.writeRfbFileTransferMsg(RfbProto.rfbDirContentRequest, RfbProto.rfbRDrivesList, 0, 0, null); ++// begin runge/x11vnc ++ readServerDriveListCnt = 0; ++ readServerDriveListTime = System.currentTimeMillis(); ++// end runge/x11vnc + } + catch (IOException e) + { +@@ -1355,21 +1710,21 @@ + int h, + boolean incremental) + throws IOException { +- if (!viewer.ftp.isVisible()) { +- byte[] b = new byte[10]; ++ if (!viewer.ftp.isVisible()) { ++ byte[] b = new byte[10]; + +- b[0] = (byte) FramebufferUpdateRequest; +- b[1] = (byte) (incremental ? 1 : 0); +- b[2] = (byte) ((x >> 8) & 0xff); +- b[3] = (byte) (x & 0xff); +- b[4] = (byte) ((y >> 8) & 0xff); +- b[5] = (byte) (y & 0xff); +- b[6] = (byte) ((w >> 8) & 0xff); +- b[7] = (byte) (w & 0xff); +- b[8] = (byte) ((h >> 8) & 0xff); +- b[9] = (byte) (h & 0xff); ++ b[0] = (byte) FramebufferUpdateRequest; ++ b[1] = (byte) (incremental ? 1 : 0); ++ b[2] = (byte) ((x >> 8) & 0xff); ++ b[3] = (byte) (x & 0xff); ++ b[4] = (byte) ((y >> 8) & 0xff); ++ b[5] = (byte) (y & 0xff); ++ b[6] = (byte) ((w >> 8) & 0xff); ++ b[7] = (byte) (w & 0xff); ++ b[8] = (byte) ((h >> 8) & 0xff); ++ b[9] = (byte) (h & 0xff); + +- os.write(b); ++ os.write(b); + } + } + +@@ -1482,7 +1837,13 @@ + b[6] = (byte) ((text.length() >> 8) & 0xff); + b[7] = (byte) (text.length() & 0xff); + +- System.arraycopy(text.getBytes(), 0, b, 8, text.length()); ++ if (false && max_char(text) > 255) { ++ System.arraycopy(text.getBytes("UTF-8"), 0, b, 8, text.length()); ++ } else if (max_char(text) > 127) { ++ System.arraycopy(text.getBytes("ISO-8859-1"), 0, b, 8, text.length()); ++ } else { ++ System.arraycopy(text.getBytes(), 0, b, 8, text.length()); ++ } + + os.write(b); + // } +@@ -1610,6 +1971,21 @@ + + boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); + ++ if (viewer.debugKeyboard) { ++ System.out.println("----------------------------------------"); ++ System.out.println("evt.getKeyChar: " + evt.getKeyChar()); ++ System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); ++ System.out.println("evt.getKeyCode: " + evt.getKeyCode()); ++ System.out.println("evt.getID: " + evt.getID()); ++ System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); ++ System.out.println("evt.isActionKey: " + evt.isActionKey()); ++ System.out.println("evt.isControlDown: " + evt.isControlDown()); ++ System.out.println("evt.getModifiers: " + evt.getModifiers()); ++ System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); ++ System.out.println("evt.paramString: " + evt.paramString()); ++ } ++ ++ + int key; + if (evt.isActionKey()) { + +@@ -1685,6 +2061,9 @@ + default : + return; + } ++ if (key == 0xffc2 && viewer.mapF5_to_atsign) { ++ key = 0x40; ++ } + + } else { + +@@ -1794,6 +2173,16 @@ + int oldModifiers = 0; + + void writeModifierKeyEvents(int newModifiers) { ++ if(viewer.forbid_Ctrl_Alt) { ++ if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { ++ int orig = newModifiers; ++ newModifiers &= ~ALT_MASK; ++ newModifiers &= ~CTRL_MASK; ++ if (viewer.debugKeyboard) { ++ System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); ++ } ++ } ++ } + if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) + writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); + +diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java +--- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 ++++ JavaViewer/SSLSocketToMe.java 2010-03-21 12:53:24.000000000 -0400 +@@ -0,0 +1,2055 @@ ++/* ++ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. ++ * ++ * Copyright (c) 2006 Karl J. Runge ++ * 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; 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. ++ * ++ */ ++ ++import java.net.*; ++import java.io.*; ++import javax.net.ssl.*; ++import java.util.*; ++ ++import java.security.*; ++import java.security.cert.*; ++import java.security.spec.*; ++import java.security.cert.Certificate; ++import java.security.cert.CertificateFactory; ++ ++import java.awt.*; ++import java.awt.event.*; ++ ++public class SSLSocketToMe { ++ ++ /* basic member data: */ ++ String host; ++ int port; ++ VncViewer viewer; ++ ++ boolean debug = true; ++ boolean debug_certs = false; ++ ++ /* sockets */ ++ SSLSocket socket = null; ++ SSLSocketFactory factory; ++ ++ /* fallback for Proxy connection */ ++ boolean proxy_in_use = false; ++ boolean proxy_failure = false; ++ public DataInputStream is = null; ++ public OutputStream os = null; ++ ++ /* strings from user WRT proxy: */ ++ String proxy_auth_string = null; ++ String proxy_dialog_host = null; ++ int proxy_dialog_port = 0; ++ ++ Socket proxySock; ++ DataInputStream proxy_is; ++ OutputStream proxy_os; ++ ++ /* trust contexts */ ++ SSLContext trustloc_ctx; ++ SSLContext trustall_ctx; ++ SSLContext trustsrv_ctx; ++ SSLContext trusturl_ctx; ++ SSLContext trustone_ctx; ++ ++ /* corresponding trust managers */ ++ TrustManager[] trustAllCerts; ++ TrustManager[] trustSrvCert; ++ TrustManager[] trustUrlCert; ++ TrustManager[] trustOneCert; ++ ++ /* client-side SSL auth key (oneTimeKey=...) */ ++ KeyManager[] mykey = null; ++ ++ boolean user_wants_to_see_cert = true; ++ String cert_fail = null; ++ ++ /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ ++ java.security.cert.Certificate[] trustallCerts = null; ++ java.security.cert.Certificate[] trustsrvCerts = null; ++ java.security.cert.Certificate[] trusturlCerts = null; ++ ++ /* utility to decode hex oneTimeKey=... and serverCert=... */ ++ byte[] hex2bytes(String s) { ++ byte[] bytes = new byte[s.length()/2]; ++ for (int i=0; i 127) { ++ val -= 256; ++ } ++ Integer I = new Integer(val); ++ bytes[i] = Byte.decode(I.toString()).byteValue(); ++ ++ } catch (Exception e) { ++ ; ++ } ++ } ++ return bytes; ++ } ++ ++ SSLSocketToMe(String h, int p, VncViewer v) throws Exception { ++ host = h; ++ port = p; ++ viewer = v; ++ ++ debug_certs = v.debugCerts; ++ ++ /* we will first try default factory for certification: */ ++ ++ factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); ++ ++ dbg("SSL startup: " + host + " " + port); ++ ++ ++ /* create trust managers to be used if initial handshake fails: */ ++ ++ trustAllCerts = new TrustManager[] { ++ /* ++ * this one accepts everything. Only used if user ++ * has disabled checking (trustAllVncCerts=yes) ++ * or when we grab the cert to show it to them in ++ * a dialog and ask them to manually verify/accept it. ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) { ++ /* empty */ ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) { ++ /* empty */ ++ dbg("ALL: an untrusted connect to grab cert."); ++ } ++ } ++ }; ++ ++ trustUrlCert = new TrustManager[] { ++ /* ++ * this one accepts only the retrieved server ++ * cert by SSLSocket by this applet and stored in ++ * trusturlCerts. ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ throw new CertificateException("No Clients (URL)"); ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ /* we want to check 'certs' against 'trusturlCerts' */ ++ if (trusturlCerts == null) { ++ throw new CertificateException( ++ "No Trust url Certs array."); ++ } ++ if (trusturlCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust url Certs."); ++ } ++ if (certs == null) { ++ throw new CertificateException( ++ "No this-certs array."); ++ } ++ if (certs.length < 1) { ++ throw new CertificateException( ++ "No this-certs Certs."); ++ } ++ if (certs.length != trusturlCerts.length) { ++ throw new CertificateException( ++ "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); ++ } ++ boolean ok = true; ++ for (int i = 0; i < certs.length; i++) { ++ if (! trusturlCerts[i].equals(certs[i])) { ++ ok = false; ++ dbg("URL: cert mismatch at i=" + i); ++ dbg("URL: cert mismatch cert" + certs[i]); ++ dbg("URL: cert mismatch url" + trusturlCerts[i]); ++ if (cert_fail == null) { ++ cert_fail = "cert-mismatch"; ++ } ++ } ++ if (debug_certs) { ++ dbg("\n***********************************************"); ++ dbg("URL: cert info at i=" + i); ++ dbg("URL: cert info cert" + certs[i]); ++ dbg("==============================================="); ++ dbg("URL: cert info url" + trusturlCerts[i]); ++ dbg("***********************************************"); ++ } ++ } ++ if (!ok) { ++ throw new CertificateException( ++ "Server Cert Chain != URL Cert Chain."); ++ } ++ dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); ++ } ++ } ++ }; ++ ++ trustSrvCert = new TrustManager[] { ++ /* ++ * this one accepts cert given to us in the serverCert ++ * Applet Parameter we were started with. It is ++ * currently a fatal error if the VNC Server's cert ++ * doesn't match it. ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ throw new CertificateException("No Clients (SRV)"); ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ /* we want to check 'certs' against 'trustsrvCerts' */ ++ if (trustsrvCerts == null) { ++ throw new CertificateException( ++ "No Trust srv Certs array."); ++ } ++ if (trustsrvCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust srv Certs."); ++ } ++ if (certs == null) { ++ throw new CertificateException( ++ "No this-certs array."); ++ } ++ if (certs.length < 1) { ++ throw new CertificateException( ++ "No this-certs Certs."); ++ } ++ if (certs.length != trustsrvCerts.length) { ++ throw new CertificateException( ++ "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); ++ } ++ boolean ok = true; ++ for (int i = 0; i < certs.length; i++) { ++ if (! trustsrvCerts[i].equals(certs[i])) { ++ ok = false; ++ dbg("SRV: cert mismatch at i=" + i); ++ dbg("SRV: cert mismatch cert" + certs[i]); ++ dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); ++ if (cert_fail == null) { ++ cert_fail = "server-cert-mismatch"; ++ } ++ } ++ if (debug_certs) { ++ dbg("\n***********************************************"); ++ dbg("SRV: cert info at i=" + i); ++ dbg("SRV: cert info cert" + certs[i]); ++ dbg("==============================================="); ++ dbg("SRV: cert info srv" + trustsrvCerts[i]); ++ dbg("***********************************************"); ++ } ++ } ++ if (!ok) { ++ throw new CertificateException( ++ "Server Cert Chain != serverCert Applet Parameter Cert Chain."); ++ } ++ dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); ++ } ++ } ++ }; ++ ++ trustOneCert = new TrustManager[] { ++ /* ++ * this one accepts only the retrieved server ++ * cert by SSLSocket by this applet we stored in ++ * trustallCerts that user has accepted or applet ++ * parameter trustAllVncCerts=yes is set. This is ++ * for when we reconnect after the user has manually ++ * accepted the trustall cert in the dialog (or set ++ * trustAllVncCerts=yes applet param.) ++ */ ++ new X509TrustManager() { ++ public java.security.cert.X509Certificate[] ++ getAcceptedIssuers() { ++ return null; ++ } ++ public void checkClientTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ throw new CertificateException("No Clients (ONE)"); ++ } ++ public void checkServerTrusted( ++ java.security.cert.X509Certificate[] certs, ++ String authType) throws CertificateException { ++ /* we want to check 'certs' against 'trustallCerts' */ ++ if (trustallCerts == null) { ++ throw new CertificateException( ++ "No Trust All Server Certs array."); ++ } ++ if (trustallCerts.length < 1) { ++ throw new CertificateException( ++ "No Trust All Server Certs."); ++ } ++ if (certs == null) { ++ throw new CertificateException( ++ "No this-certs array."); ++ } ++ if (certs.length < 1) { ++ throw new CertificateException( ++ "No this-certs Certs."); ++ } ++ if (certs.length != trustallCerts.length) { ++ throw new CertificateException( ++ "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); ++ } ++ boolean ok = true; ++ for (int i = 0; i < certs.length; i++) { ++ if (! trustallCerts[i].equals(certs[i])) { ++ ok = false; ++ dbg("ONE: cert mismatch at i=" + i); ++ dbg("ONE: cert mismatch cert" + certs[i]); ++ dbg("ONE: cert mismatch all" + trustallCerts[i]); ++ } ++ if (debug_certs) { ++ dbg("\n***********************************************"); ++ dbg("ONE: cert info at i=" + i); ++ dbg("ONE: cert info cert" + certs[i]); ++ dbg("==============================================="); ++ dbg("ONE: cert info all" + trustallCerts[i]); ++ dbg("***********************************************"); ++ } ++ } ++ if (!ok) { ++ throw new CertificateException( ++ "Server Cert Chain != TRUSTALL Cert Chain."); ++ } ++ dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); ++ } ++ } ++ }; ++ ++ /* ++ * The above TrustManagers are used: ++ * ++ * 1) to retrieve the server cert in case of failure to ++ * display it to the user in a dialog. ++ * 2) to subsequently connect to the server if user agrees. ++ */ ++ ++ /* ++ * build oneTimeKey cert+key if supplied in applet parameter: ++ */ ++ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { ++ ClientCertDialog d = new ClientCertDialog(); ++ viewer.oneTimeKey = d.queryUser(); ++ } ++ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { ++ int idx = viewer.oneTimeKey.indexOf(","); ++ ++ String onetimekey = viewer.oneTimeKey.substring(0, idx); ++ byte[] key = hex2bytes(onetimekey); ++ String onetimecert = viewer.oneTimeKey.substring(idx+1); ++ byte[] cert = hex2bytes(onetimecert); ++ ++ KeyFactory kf = KeyFactory.getInstance("RSA"); ++ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); ++ PrivateKey ff = kf.generatePrivate (keysp); ++ if (debug_certs) { ++ dbg("one time key " + ff); ++ } ++ ++ CertificateFactory cf = CertificateFactory.getInstance("X.509"); ++ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); ++ Certificate[] certs = new Certificate[c.toArray().length]; ++ if (c.size() == 1) { ++ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); ++ if (debug_certs) { ++ dbg("one time cert" + tmpcert); ++ } ++ certs[0] = tmpcert; ++ } else { ++ certs = (Certificate[]) c.toArray(); ++ } ++ ++ KeyStore ks = KeyStore.getInstance("JKS"); ++ ks.load(null, null); ++ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); ++ String da = KeyManagerFactory.getDefaultAlgorithm(); ++ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); ++ kmf.init(ks, "".toCharArray()); ++ ++ mykey = kmf.getKeyManagers(); ++ } ++ ++ /* ++ * build serverCert cert if supplied in applet parameter: ++ */ ++ if (viewer.serverCert != null) { ++ CertificateFactory cf = CertificateFactory.getInstance("X.509"); ++ byte[] cert = hex2bytes(viewer.serverCert); ++ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); ++ trustsrvCerts = new Certificate[c.toArray().length]; ++ if (c.size() == 1) { ++ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); ++ trustsrvCerts[0] = tmpcert; ++ } else { ++ trustsrvCerts = (Certificate[]) c.toArray(); ++ } ++ } ++ ++ /* the trust loc certs context: */ ++ try { ++ trustloc_ctx = SSLContext.getInstance("SSL"); ++ ++ /* ++ * below is a failed attempt to get jvm's default ++ * trust manager using null (below) makes it so ++ * for HttpsURLConnection the server cannot be ++ * verified (no prompting.) ++ */ ++ if (false) { ++ boolean didit = false; ++ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); ++ tmf.init((KeyStore) null); ++ TrustManager [] tml = tmf.getTrustManagers(); ++ for (int i = 0; i < tml.length; i++) { ++ TrustManager tm = tml[i]; ++ if (tm instanceof X509TrustManager) { ++ TrustManager tm1[] = new TrustManager[1]; ++ tm1[0] = tm; ++ trustloc_ctx.init(mykey, tm1, null); ++ didit = true; ++ break; ++ } ++ } ++ if (!didit) { ++ trustloc_ctx.init(mykey, null, null); ++ } ++ } else { ++ /* we have to set trust manager to null */ ++ trustloc_ctx.init(mykey, null, null); ++ } ++ ++ } catch (Exception e) { ++ String msg = "SSL trustloc_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust all certs context: */ ++ try { ++ trustall_ctx = SSLContext.getInstance("SSL"); ++ trustall_ctx.init(mykey, trustAllCerts, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trustall_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust url certs context: */ ++ try { ++ trusturl_ctx = SSLContext.getInstance("SSL"); ++ trusturl_ctx.init(mykey, trustUrlCert, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trusturl_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust srv certs context: */ ++ try { ++ trustsrv_ctx = SSLContext.getInstance("SSL"); ++ trustsrv_ctx.init(mykey, trustSrvCert, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trustsrv_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ ++ /* the trust the one cert from server context: */ ++ try { ++ trustone_ctx = SSLContext.getInstance("SSL"); ++ trustone_ctx.init(mykey, trustOneCert, new ++ java.security.SecureRandom()); ++ ++ } catch (Exception e) { ++ String msg = "SSL trustone_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); ++ } ++ } ++ ++ /* ++ * we call this early on to 1) check for a proxy, 2) grab ++ * Browser/JVM accepted HTTPS cert. ++ */ ++ public void check_for_proxy_and_grab_vnc_server_cert() { ++ ++ trusturlCerts = null; ++ proxy_in_use = false; ++ ++ if (viewer.ignoreProxy) { ++ /* applet param says skip it. */ ++ /* the downside is we do not set trusturlCerts for comparison later... */ ++ /* nor do we autodetect x11vnc for GET=1. */ ++ return; ++ } ++ ++ dbg("------------------------------------------------"); ++ dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); ++ ++ dbg("TRYING HTTPS:"); ++ String ustr = "https://" + host + ":"; ++ if (viewer.httpsPort != null) { ++ ustr += viewer.httpsPort; ++ } else { ++ ustr += port; ++ } ++ ustr += viewer.urlPrefix + "/check.https.proxy.connection"; ++ dbg("ustr is: " + ustr); ++ ++ try { ++ /* prepare for an HTTPS URL connection to host:port */ ++ URL url = new URL(ustr); ++ HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); ++ ++ if (mykey != null) { ++ /* with oneTimeKey (mykey) we can't use the default SSL context */ ++ if (trustsrvCerts != null) { ++ dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); ++ https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); ++ } else if (trustloc_ctx != null) { ++ dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); ++ https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); ++ } ++ } ++ ++ https.setUseCaches(false); ++ https.setRequestMethod("GET"); ++ https.setRequestProperty("Pragma", "No-Cache"); ++ https.setRequestProperty("Proxy-Connection", "Keep-Alive"); ++ https.setDoInput(true); ++ ++ dbg("trying https.connect()"); ++ https.connect(); ++ ++ dbg("trying https.getServerCertificates()"); ++ trusturlCerts = https.getServerCertificates(); ++ ++ if (trusturlCerts == null) { ++ dbg("set trusturlCerts to null!"); ++ } else { ++ dbg("set trusturlCerts to non-null"); ++ } ++ ++ if (https.usingProxy()) { ++ proxy_in_use = true; ++ dbg("An HTTPS proxy is in use. There may be connection problems."); ++ } ++ ++ dbg("trying https.getContent()"); ++ Object output = https.getContent(); ++ dbg("trying https.disconnect()"); ++ https.disconnect(); ++ if (! viewer.GET) { ++ String header = https.getHeaderField("VNC-Server"); ++ if (header != null && header.startsWith("x11vnc")) { ++ dbg("detected x11vnc server (1), setting GET=1"); ++ viewer.GET = true; ++ } ++ } ++ ++ } catch(Exception e) { ++ dbg("HttpsURLConnection: " + e.getMessage()); ++ } ++ ++ if (proxy_in_use) { ++ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); ++ dbg("------------------------------------------------"); ++ return; ++ } else if (trusturlCerts != null && !viewer.forceProxy) { ++ /* Allow user to require HTTP check? use forceProxy for now. */ ++ dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); ++ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); ++ dbg("------------------------------------------------"); ++ return; ++ } ++ ++ /* ++ * XXX need to remember scenario where this extra check ++ * gives useful info. User's Browser proxy settings? ++ */ ++ dbg("TRYING HTTP:"); ++ ustr = "http://" + host + ":" + port; ++ ustr += viewer.urlPrefix + "/index.vnc"; ++ dbg("ustr is: " + ustr); ++ ++ try { ++ /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ ++ URL url = new URL(ustr); ++ HttpURLConnection http = (HttpURLConnection) ++ url.openConnection(); ++ ++ http.setUseCaches(false); ++ http.setRequestMethod("GET"); ++ http.setRequestProperty("Pragma", "No-Cache"); ++ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); ++ http.setDoInput(true); ++ ++ dbg("trying http.connect()"); ++ http.connect(); ++ ++ if (http.usingProxy()) { ++ proxy_in_use = true; ++ dbg("An HTTP proxy is in use. There may be connection problems."); ++ } ++ dbg("trying http.getContent()"); ++ Object output = http.getContent(); ++ dbg("trying http.disconnect()"); ++ http.disconnect(); ++ if (! viewer.GET) { ++ String header = http.getHeaderField("VNC-Server"); ++ if (header != null && header.startsWith("x11vnc")) { ++ dbg("detected x11vnc server (2), setting GET=1"); ++ viewer.GET = true; ++ } ++ } ++ } catch(Exception e) { ++ dbg("HttpURLConnection: " + e.getMessage()); ++ } ++ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); ++ dbg("------------------------------------------------"); ++ } ++ ++ public Socket connectSock() throws IOException { ++ /* ++ * first try a https connection to detect a proxy, and ++ * grab the VNC server cert at the same time: ++ */ ++ check_for_proxy_and_grab_vnc_server_cert(); ++ ++ boolean srv_cert = false; ++ ++ if (trustsrvCerts != null) { ++ /* applet parameter suppled serverCert */ ++ dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); ++ factory = trustsrv_ctx.getSocketFactory(); ++ srv_cert = true; ++ } else if (viewer.trustAllVncCerts) { ++ /* trust all certs (no checking) */ ++ dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); ++ factory = trustall_ctx.getSocketFactory(); ++ } else if (trusturlCerts != null) { ++ /* trust certs the Browser/JVM accepted in check_for_proxy... */ ++ dbg("using trusturl_ctx"); ++ factory = trusturl_ctx.getSocketFactory(); ++ } else { ++ /* trust the local defaults */ ++ dbg("using trustloc_ctx"); ++ factory = trustloc_ctx.getSocketFactory(); ++ } ++ ++ socket = null; ++ ++ try { ++ if (proxy_in_use && viewer.forceProxy) { ++ throw new Exception("forcing proxy (forceProxy)"); ++ } else if (viewer.CONNECT != null) { ++ throw new Exception("forcing CONNECT"); ++ } ++ ++ int timeout = 6; ++ if (timeout > 0) { ++ socket = (SSLSocket) factory.createSocket(); ++ InetSocketAddress inetaddr = new InetSocketAddress(host, port); ++ dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); ++ socket.connect(inetaddr, timeout * 1000); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } ++ ++ } catch (Exception esock) { ++ dbg("socket error: " + esock.getMessage()); ++ if (proxy_in_use || viewer.CONNECT != null) { ++ proxy_failure = true; ++ if (proxy_in_use) { ++ dbg("HTTPS proxy in use. Trying to go with it."); ++ } else { ++ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); ++ } ++ try { ++ socket = proxy_socket(factory); ++ } catch (Exception e) { ++ dbg("proxy_socket error: " + e.getMessage()); ++ } ++ } else { ++ /* n.b. socket is left in error state to cause ex. below. */ ++ } ++ } ++ ++ try { ++ socket.startHandshake(); ++ ++ dbg("The Server Connection Verified OK on 1st try."); ++ ++ java.security.cert.Certificate[] currentTrustedCerts; ++ BrowserCertsDialog bcd; ++ ++ SSLSession sess = socket.getSession(); ++ currentTrustedCerts = sess.getPeerCertificates(); ++ ++ if (viewer.trustAllVncCerts) { ++ dbg("viewer.trustAllVncCerts-1 keeping socket."); ++ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { ++ try { ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy."); ++ } ++ socket = null; ++ throw new SSLHandshakeException("no current certs"); ++ } ++ ++ String serv = ""; ++ try { ++ CertInfo ci = new CertInfo(currentTrustedCerts[0]); ++ serv = ci.get_certinfo("CN"); ++ } catch (Exception e) { ++ ; ++ } ++ ++ if (viewer.trustAllVncCerts) { ++ dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); ++ user_wants_to_see_cert = false; ++ } else if (viewer.serverCert != null && trustsrvCerts != null) { ++ dbg("viewer.serverCert-1 skipping browser certs dialog"); ++ user_wants_to_see_cert = false; ++ } else if (viewer.trustUrlVncCert) { ++ dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); ++ user_wants_to_see_cert = false; ++ } else { ++ /* have a dialog with the user: */ ++ bcd = new BrowserCertsDialog(serv, host + ":" + port); ++ dbg("browser certs dialog begin."); ++ bcd.queryUser(); ++ dbg("browser certs dialog finished."); ++ ++ if (bcd.showCertDialog) { ++ String msg = "user wants to see cert"; ++ dbg(msg); ++ user_wants_to_see_cert = true; ++ if (cert_fail == null) { ++ cert_fail = "user-view"; ++ } ++ throw new SSLHandshakeException(msg); ++ } else { ++ user_wants_to_see_cert = false; ++ dbg("browser certs dialog: user said yes, accept it"); ++ } ++ } ++ ++ } catch (SSLHandshakeException eh) { ++ dbg("SSLHandshakeException: could not automatically verify Server."); ++ dbg("msg: " + eh.getMessage()); ++ ++ ++ /* send a cleanup string just in case: */ ++ String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; ++ ++ try { ++ OutputStream os = socket.getOutputStream(); ++ os.write(getoutstr.getBytes()); ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy!"); ++ } ++ ++ /* reload */ ++ ++ socket = null; ++ ++ String reason = null; ++ ++ if (srv_cert) { ++ /* for serverCert usage we make this a fatal error. */ ++ throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); ++ /* see below in TrustDialog were we describe this case to user anyway */ ++ } ++ ++ /* ++ * Reconnect, trusting any cert, so we can grab ++ * the cert to show it to the user in a dialog ++ * for him to manually accept. This connection ++ * is not used for anything else. ++ */ ++ factory = trustall_ctx.getSocketFactory(); ++ if (proxy_failure) { ++ socket = proxy_socket(factory); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } ++ ++ if (debug_certs) { ++ dbg("trusturlCerts: " + trusturlCerts); ++ dbg("trustsrvCerts: " + trustsrvCerts); ++ } ++ if (trusturlCerts == null && cert_fail == null) { ++ cert_fail = "missing-certs"; ++ } ++ ++ try { ++ socket.startHandshake(); ++ ++ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); ++ ++ /* grab the cert: */ ++ try { ++ SSLSession sess = socket.getSession(); ++ trustallCerts = sess.getPeerCertificates(); ++ } catch (Exception e) { ++ throw new Exception("Could not get " + ++ "Peer Certificate"); ++ } ++ if (debug_certs) { ++ dbg("trustallCerts: " + trustallCerts); ++ } ++ ++ if (viewer.trustAllVncCerts) { ++ dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); ++ } else if (! browser_cert_match()) { ++ /* ++ * close socket now, we will reopen after ++ * dialog if user agrees to use the cert. ++ */ ++ try { ++ OutputStream os = socket.getOutputStream(); ++ os.write(getoutstr.getBytes()); ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy!!"); ++ } ++ socket = null; ++ ++ /* dialog with user to accept cert or not: */ ++ ++ TrustDialog td= new TrustDialog(host, port, ++ trustallCerts); ++ ++ if (cert_fail == null) { ++ ; ++ } else if (cert_fail.equals("user-view")) { ++ reason = "Reason for this Dialog:\n\n" ++ + " You Asked to View the Certificate."; ++ } else if (cert_fail.equals("server-cert-mismatch")) { ++ /* this is now fatal error, see above. */ ++ reason = "Reason for this Dialog:\n\n" ++ + " The VNC Server's Certificate does not match the Certificate\n" ++ + " specified in the supplied 'serverCert' Applet Parameter."; ++ } else if (cert_fail.equals("cert-mismatch")) { ++ reason = "Reason for this Dialog:\n\n" ++ + " The VNC Server's Certificate does not match the Website's\n" ++ + " HTTPS Certificate (that you previously accepted; either\n" ++ + " manually or automatically via Certificate Authority.)"; ++ } else if (cert_fail.equals("missing-certs")) { ++ reason = "Reason for this Dialog:\n\n" ++ + " Not all Certificates could be obtained to check."; ++ } ++ ++ if (! td.queryUser(reason)) { ++ String msg = "User decided against it."; ++ dbg(msg); ++ throw new IOException(msg); ++ } ++ } ++ ++ } catch (Exception ehand2) { ++ dbg("** Could not TrustAll Verify Server!"); ++ ++ throw new IOException(ehand2.getMessage()); ++ } ++ ++ /* reload again: */ ++ ++ if (socket != null) { ++ try { ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy!!!"); ++ } ++ socket = null; ++ } ++ ++ /* ++ * Now connect a 3rd time, using the cert ++ * retrieved during connection 2 (sadly, that ++ * the user likely blindly agreed to...) ++ */ ++ ++ factory = trustone_ctx.getSocketFactory(); ++ if (proxy_failure) { ++ socket = proxy_socket(factory); ++ } else { ++ socket = (SSLSocket) factory.createSocket(host, port); ++ } ++ ++ try { ++ socket.startHandshake(); ++ dbg("TrustAll/TrustOne Server Connection Verified #3."); ++ ++ } catch (Exception ehand3) { ++ dbg("** Could not TrustAll/TrustOne Verify Server #3."); ++ ++ throw new IOException(ehand3.getMessage()); ++ } ++ } ++ ++ /* we have socket (possibly null) at this point, so proceed: */ ++ ++ /* handle x11vnc GET=1, if applicable: */ ++ if (socket != null && viewer.GET) { ++ String str = "GET "; ++ str += viewer.urlPrefix; ++ str += "/request.https.vnc.connection"; ++ str += " HTTP/1.0\r\n"; ++ str += "Pragma: No-Cache\r\n"; ++ str += "\r\n"; ++ ++ System.out.println("sending: " + str); ++ OutputStream os = socket.getOutputStream(); ++ String type = "os"; ++ ++ if (type == "os") { ++ os.write(str.getBytes()); ++ os.flush(); ++ System.out.println("used OutputStream"); ++ } else if (type == "bs") { ++ BufferedOutputStream bs = new BufferedOutputStream(os); ++ bs.write(str.getBytes()); ++ bs.flush(); ++ System.out.println("used BufferedOutputStream"); ++ } else if (type == "ds") { ++ DataOutputStream ds = new DataOutputStream(os); ++ ds.write(str.getBytes()); ++ ds.flush(); ++ System.out.println("used DataOutputStream"); ++ } ++ if (false) { ++ String rep = ""; ++ DataInputStream is = new DataInputStream( ++ new BufferedInputStream(socket.getInputStream(), 16384)); ++ while (true) { ++ rep += readline(is); ++ if (rep.indexOf("\r\n\r\n") >= 0) { ++ break; ++ } ++ } ++ System.out.println("rep: " + rep); ++ } ++ } ++ ++ dbg("SSL returning socket to caller."); ++ dbg(""); ++ ++ /* could be null, let caller handle that. */ ++ return (Socket) socket; ++ } ++ ++ boolean browser_cert_match() { ++ String msg = "Browser URL accept previously accepted cert"; ++ ++ if (user_wants_to_see_cert) { ++ return false; ++ } ++ ++ if (viewer.serverCert != null || trustsrvCerts != null) { ++ if (cert_fail == null) { ++ cert_fail = "server-cert-mismatch"; ++ } ++ } ++ if (trustallCerts != null && trusturlCerts != null) { ++ if (trustallCerts.length == trusturlCerts.length) { ++ boolean ok = true; ++ /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ ++ for (int i = 0; i < trusturlCerts.length; i++) { ++ if (! trustallCerts[i].equals(trusturlCerts[i])) { ++ dbg("BCM: cert mismatch at i=" + i); ++ dbg("BCM: cert mismatch url" + trusturlCerts[i]); ++ dbg("BCM: cert mismatch all" + trustallCerts[i]); ++ ok = false; ++ } ++ } ++ if (ok) { ++ System.out.println(msg); ++ if (cert_fail == null) { ++ cert_fail = "did-not-fail"; ++ } ++ return true; ++ } else { ++ if (cert_fail == null) { ++ cert_fail = "cert-mismatch"; ++ } ++ return false; ++ } ++ } ++ } ++ if (cert_fail == null) { ++ cert_fail = "missing-certs"; ++ } ++ return false; ++ } ++ ++ private void dbg(String s) { ++ if (debug) { ++ System.out.println(s); ++ } ++ } ++ ++ private int gint(String s) { ++ int n = -1; ++ try { ++ Integer I = new Integer(s); ++ n = I.intValue(); ++ } catch (Exception ex) { ++ return -1; ++ } ++ return n; ++ } ++ ++ /* this will do the proxy CONNECT negotiation and hook us up. */ ++ ++ private void proxy_helper(String proxyHost, int proxyPort) { ++ ++ boolean proxy_auth = false; ++ String proxy_auth_basic_realm = ""; ++ String hp = host + ":" + port; ++ dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp); ++ ++ /* we loop here a few times trying for the password case */ ++ for (int k=0; k < 2; k++) { ++ dbg("proxy_in_use psocket: " + k); ++ ++ if (proxySock != null) { ++ try { ++ proxySock.close(); ++ } catch (Exception e) { ++ dbg("proxy socket is grumpy."); ++ } ++ } ++ ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("1-a sadly, returning a null socket"); ++ return; ++ } ++ ++ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" ++ + "Host: " + hp + "\r\n"; ++ ++ dbg("requesting via proxy: " + req1); ++ ++ if (proxy_auth) { ++ if (proxy_auth_string == null) { ++ ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm); ++ pp.queryUser(); ++ proxy_auth_string = pp.getAuth(); ++ } ++ //dbg("auth1: " + proxy_auth_string); ++ ++ String auth2 = Base64Coder.encodeString(proxy_auth_string); ++ //dbg("auth2: " + auth2); ++ ++ req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n"; ++ //dbg("req1: " + req1); ++ ++ dbg("added Proxy-Authorization: Basic ... to request"); ++ } ++ req1 += "\r\n"; ++ ++ try { ++ proxy_os.write(req1.getBytes()); ++ String reply = readline(proxy_is); ++ ++ dbg("proxy replied: " + reply.trim()); ++ ++ if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) { ++ proxy_auth = true; ++ proxySock.close(); ++ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { ++ proxySock.close(); ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("2-a sadly, returning a null socket"); ++ return; ++ } ++ } ++ } catch(Exception e) { ++ dbg("some proxy socket problem: " + e.getMessage()); ++ } ++ ++ /* read the rest of the HTTP headers */ ++ while (true) { ++ String line = readline(proxy_is); ++ dbg("proxy line: " + line.trim()); ++ if (proxy_auth) { ++ String uc = line.toLowerCase(); ++ if (uc.indexOf("proxy-authenticate:") == 0) { ++ if (uc.indexOf(" basic ") >= 0) { ++ int idx = uc.indexOf(" realm"); ++ if (idx >= 0) { ++ proxy_auth_basic_realm = uc.substring(idx+1); ++ } ++ } ++ } ++ } ++ if (line.equals("\r\n") || line.equals("\n")) { ++ break; ++ } ++ } ++ if (!proxy_auth || proxy_auth_basic_realm.equals("")) { ++ /* we only try once for the non-password case: */ ++ break; ++ } ++ } ++ } ++ ++ public SSLSocket proxy_socket(SSLSocketFactory factory) { ++ Properties props = null; ++ String proxyHost = null; ++ int proxyPort = 0; ++ String proxyHost_nossl = null; ++ int proxyPort_nossl = 0; ++ String str; ++ ++ /* see if we can guess the proxy info from Properties: */ ++ try { ++ props = System.getProperties(); ++ } catch (Exception e) { ++ /* sandboxed applet might not be able to read it. */ ++ dbg("props failed: " + e.getMessage()); ++ } ++ if (viewer.proxyHost != null) { ++ dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); ++ proxyHost = viewer.proxyHost; ++ if (viewer.proxyPort != null) { ++ proxyPort = gint(viewer.proxyPort); ++ } else { ++ proxyPort = 8080; ++ } ++ ++ } else if (props != null) { ++ dbg("\n---------------\nAll props:"); ++ props.list(System.out); ++ dbg("\n---------------\n\n"); ++ ++ /* scrape throught properties looking for proxy info: */ ++ ++ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { ++ String s = (String) e.nextElement(); ++ String v = System.getProperty(s); ++ String s2 = s.toLowerCase(); ++ String v2 = v.toLowerCase(); ++ ++ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { ++ continue; ++ } ++ if (v2.indexOf("http") < 0) { ++ continue; ++ } ++ ++ if (s2.indexOf("proxy.https.host") >= 0) { ++ proxyHost = v2; ++ continue; ++ } ++ if (s2.indexOf("proxy.https.port") >= 0) { ++ proxyPort = gint(v2); ++ continue; ++ } ++ if (s2.indexOf("proxy.http.host") >= 0) { ++ proxyHost_nossl = v2; ++ continue; ++ } ++ if (s2.indexOf("proxy.http.port") >= 0) { ++ proxyPort_nossl = gint(v2); ++ continue; ++ } ++ ++ String[] pieces = v.split("[,;]"); ++ for (int i = 0; i < pieces.length; i++) { ++ String p = pieces[i]; ++ int j = p.indexOf("https"); ++ if (j < 0) { ++ j = p.indexOf("http"); ++ if (j < 0) { ++ continue; ++ } ++ } ++ j = p.indexOf("=", j); ++ if (j < 0) { ++ continue; ++ } ++ p = p.substring(j+1); ++ String [] hp = p.split(":"); ++ if (hp.length != 2) { ++ continue; ++ } ++ if (hp[0].length() > 1 && hp[1].length() > 1) { ++ ++ proxyPort = gint(hp[1]); ++ if (proxyPort < 0) { ++ continue; ++ } ++ proxyHost = new String(hp[0]); ++ break; ++ } ++ } ++ } ++ } ++ if (proxyHost != null) { ++ if (proxyHost_nossl != null && proxyPort_nossl > 0) { ++ dbg("Using http proxy info instead of https."); ++ proxyHost = proxyHost_nossl; ++ proxyPort = proxyPort_nossl; ++ } ++ } ++ ++ if (proxy_in_use) { ++ if (proxy_dialog_host != null && proxy_dialog_port > 0) { ++ proxyHost = proxy_dialog_host; ++ proxyPort = proxy_dialog_port; ++ } ++ if (proxyHost != null) { ++ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); ++ } else { ++ /* ask user to help us: */ ++ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); ++ pd.queryUser(); ++ proxyHost = pd.getHost(); ++ proxyPort = pd.getPort(); ++ proxy_dialog_host = new String(proxyHost); ++ proxy_dialog_port = proxyPort; ++ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); ++ } ++ ++ proxy_helper(proxyHost, proxyPort); ++ if (proxySock == null) { ++ return null; ++ } ++ } else if (viewer.CONNECT != null) { ++ dbg("viewer.CONNECT psocket:"); ++ proxySock = psocket(host, port); ++ if (proxySock == null) { ++ dbg("1-b sadly, returning a null socket"); ++ return null; ++ } ++ } ++ ++ if (viewer.CONNECT != null) { ++ String hp = viewer.CONNECT; ++ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" ++ + "Host: " + hp + "\r\n\r\n"; ++ ++ dbg("requesting2: " + req2); ++ ++ try { ++ proxy_os.write(req2.getBytes()); ++ String reply = readline(proxy_is); ++ ++ dbg("proxy replied2: " + reply.trim()); ++ ++ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { ++ proxySock.close(); ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("2-b sadly, returning a null socket"); ++ return null; ++ } ++ } ++ } catch(Exception e) { ++ dbg("proxy socket problem-2: " + e.getMessage()); ++ } ++ ++ while (true) { ++ String line = readline(proxy_is); ++ dbg("proxy line2: " + line.trim()); ++ if (line.equals("\r\n") || line.equals("\n")) { ++ break; ++ } ++ } ++ } ++ ++ Socket sslsock = null; ++ try { ++ sslsock = factory.createSocket(proxySock, host, port, true); ++ } catch(Exception e) { ++ dbg("sslsock prob: " + e.getMessage()); ++ dbg("3 sadly, returning a null socket"); ++ } ++ ++ return (SSLSocket) sslsock; ++ } ++ ++ Socket psocket(String h, int p) { ++ Socket psock = null; ++ try { ++ psock = new Socket(h, p); ++ proxy_is = new DataInputStream(new BufferedInputStream( ++ psock.getInputStream(), 16384)); ++ proxy_os = psock.getOutputStream(); ++ } catch(Exception e) { ++ dbg("psocket prob: " + e.getMessage()); ++ return null; ++ } ++ ++ return psock; ++ } ++ ++ String readline(DataInputStream i) { ++ byte[] ba = new byte[1]; ++ String s = new String(""); ++ ba[0] = 0; ++ try { ++ while (ba[0] != 0xa) { ++ ba[0] = (byte) i.readUnsignedByte(); ++ s += new String(ba); ++ } ++ } catch (Exception e) { ++ ; ++ } ++ return s; ++ } ++} ++ ++class TrustDialog implements ActionListener { ++ String msg, host, text; ++ int port; ++ java.security.cert.Certificate[] trustallCerts = null; ++ boolean viewing_cert = false; ++ boolean trust_this_session = false; ++ ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok, cancel, viewcert; ++ TextArea textarea; ++ Checkbox accept, deny; ++ Dialog dialog; ++ ++ String s1 = "Accept this certificate temporarily for this session"; ++ String s2 = "Do not accept this certificate and do not connect to" ++ + " this VNC server"; ++ String ln = "\n---------------------------------------------------\n\n"; ++ ++ TrustDialog (String h, int p, java.security.cert.Certificate[] s) { ++ host = h; ++ port = p; ++ trustallCerts = s; ++ ++ msg = "VNC Server " + host + ":" + port + " Not Verified"; ++ } ++ ++ public boolean queryUser(String reason) { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame(msg); ++ ++ dialog = new Dialog(frame, true); ++ ++ String infostr = ""; ++ if (trustallCerts.length == 1) { ++ CertInfo ci = new CertInfo(trustallCerts[0]); ++ infostr = ci.get_certinfo("all"); ++ } ++ if (reason != null) { ++ reason += "\n\n"; ++ } ++ ++ text = "\n" +++ "Unable to verify the identity of\n" +++ "\n" +++ " " + host + ":" + port + "\n" +++ "\n" +++ infostr +++ "\n" +++ "as a trusted VNC server.\n" +++ "\n" +++ reason +++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" +++ "is due to one of the following:\n" +++ "\n" +++ " - Your requesting to View the Certificate before accepting.\n" +++ "\n" +++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" +++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" +++ "\n" +++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" +++ " the Apache Web server has a certificate *different* from the VNC server's.\n" +++ "\n" +++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" +++ " obtained by this applet to compare the VNC Server Certificate against.\n" +++ "\n" +++ " - The VNC Server's Certificate does not match the one specified in the\n" +++ " supplied 'serverCert' Java Applet Parameter.\n" +++ "\n" +++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" +++ " to connect to. (Wouldn't that be exciting!!)\n" +++ "\n" +++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" +++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" +++ "automatically authenticate this VNC Server.\n" +++ "\n" +++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" +++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" +++ "certificate (except for the Apache portal case above where they don't match.)\n" +++ "\n" +++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" +++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" +++ "and thereby see no dialog from this VNC Viewer applet.\n" ++; ++ ++ /* the accept / do-not-accept radio buttons: */ ++ CheckboxGroup checkbox = new CheckboxGroup(); ++ accept = new Checkbox(s1, true, checkbox); ++ deny = new Checkbox(s2, false, checkbox); ++ ++ /* put the checkboxes in a panel: */ ++ Panel check = new Panel(); ++ check.setLayout(new GridLayout(2, 1)); ++ ++ check.add(accept); ++ check.add(deny); ++ ++ /* make the 3 buttons: */ ++ ok = new Button("OK"); ++ cancel = new Button("Cancel"); ++ viewcert = new Button("View Certificate"); ++ ++ ok.addActionListener(this); ++ cancel.addActionListener(this); ++ viewcert.addActionListener(this); ++ ++ /* put the buttons in their own panel: */ ++ Panel buttonrow = new Panel(); ++ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); ++ buttonrow.add(viewcert); ++ buttonrow.add(ok); ++ buttonrow.add(cancel); ++ ++ /* label at the top: */ ++ Label label = new Label(msg, Label.CENTER); ++ label.setFont(new Font("Helvetica", Font.BOLD, 16)); ++ ++ /* textarea in the middle */ ++ textarea = new TextArea(text, 38, 64, ++ TextArea.SCROLLBARS_VERTICAL_ONLY); ++ textarea.setEditable(false); ++ ++ /* put the two panels in their own panel at bottom: */ ++ Panel bot = new Panel(); ++ bot.setLayout(new GridLayout(2, 1)); ++ bot.add(check); ++ bot.add(buttonrow); ++ ++ /* now arrange things inside the dialog: */ ++ dialog.setLayout(new BorderLayout()); ++ ++ dialog.add("North", label); ++ dialog.add("South", bot); ++ dialog.add("Center", textarea); ++ ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ ++ return trust_this_session; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ ++ if (evt.getSource() == viewcert) { ++ /* View Certificate button clicked */ ++ if (viewing_cert) { ++ /* show the original info text: */ ++ textarea.setText(text); ++ viewcert.setLabel("View Certificate"); ++ viewing_cert = false; ++ } else { ++ int i; ++ /* show all (likely just one) certs: */ ++ textarea.setText(""); ++ for (i=0; i < trustallCerts.length; i++) { ++ int j = i + 1; ++ textarea.append("Certificate[" + ++ j + "]\n\n"); ++ textarea.append( ++ trustallCerts[i].toString()); ++ textarea.append(ln); ++ } ++ viewcert.setLabel("View Info"); ++ viewing_cert = true; ++ ++ textarea.setCaretPosition(0); ++ } ++ ++ } else if (evt.getSource() == ok) { ++ /* OK button clicked */ ++ if (accept.getState()) { ++ trust_this_session = true; ++ } else { ++ trust_this_session = false; ++ } ++ //dialog.dispose(); ++ dialog.hide(); ++ ++ } else if (evt.getSource() == cancel) { ++ /* Cancel button clicked */ ++ trust_this_session = false; ++ ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++ ++ String get_certinfo() { ++ String all = ""; ++ String fields[] = {"CN", "OU", "O", "L", "C"}; ++ int i; ++ if (trustallCerts.length < 1) { ++ all = ""; ++ return all; ++ } ++ String cert = trustallCerts[0].toString(); ++ ++ /* ++ * For now we simply scrape the cert string, there must ++ * be an API for this... perhaps optionValue? ++ */ ++ ++ for (i=0; i < fields.length; i++) { ++ int f, t, t1, t2; ++ String sub, mat = fields[i] + "="; ++ ++ f = cert.indexOf(mat, 0); ++ if (f > 0) { ++ t1 = cert.indexOf(", ", f); ++ t2 = cert.indexOf("\n", f); ++ if (t1 < 0 && t2 < 0) { ++ continue; ++ } else if (t1 < 0) { ++ t = t2; ++ } else if (t2 < 0) { ++ t = t1; ++ } else if (t1 < t2) { ++ t = t1; ++ } else { ++ t = t2; ++ } ++ if (t > f) { ++ sub = cert.substring(f, t); ++ all = all + " " + sub + "\n"; ++ } ++ } ++ } ++ return all; ++ } ++} ++ ++class ProxyDialog implements ActionListener { ++ String guessedHost = null; ++ String guessedPort = null; ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry; ++ String reply = ""; ++ ++ ProxyDialog (String h, int p) { ++ guessedHost = h; ++ try { ++ guessedPort = Integer.toString(p); ++ } catch (Exception e) { ++ guessedPort = "8080"; ++ } ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Need Proxy host:port"); ++ ++ dialog = new Dialog(frame, true); ++ ++ ++ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); ++ //label.setFont(new Font("Helvetica", Font.BOLD, 16)); ++ entry = new TextField(30); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ String guess = ""; ++ if (guessedHost != null) { ++ guess = guessedHost + ":" + guessedPort; ++ } ++ entry.setText(guess); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry); ++ dialog.add("South", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return; ++ } ++ ++ public String getHost() { ++ int i = reply.indexOf(":"); ++ if (i < 0) { ++ return "unknown"; ++ } ++ String h = reply.substring(0, i); ++ return h; ++ } ++ ++ public int getPort() { ++ int i = reply.indexOf(":"); ++ int p = 8080; ++ if (i < 0) { ++ return p; ++ } ++ i++; ++ String ps = reply.substring(i); ++ try { ++ Integer I = new Integer(ps); ++ p = I.intValue(); ++ } catch (Exception e) { ++ ; ++ } ++ return p; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply = entry.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ ++class ProxyPasswdDialog implements ActionListener { ++ String guessedHost = null; ++ String guessedPort = null; ++ String guessedUser = null; ++ String guessedPasswd = null; ++ String realm = null; ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry1; ++ TextField entry2; ++ String reply1 = ""; ++ String reply2 = ""; ++ ++ ProxyPasswdDialog (String h, int p, String realm) { ++ guessedHost = h; ++ try { ++ guessedPort = Integer.toString(p); ++ } catch (Exception e) { ++ guessedPort = "8080"; ++ } ++ this.realm = realm; ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Proxy Requires Username and Password"); ++ ++ dialog = new Dialog(frame, true); ++ ++ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); ++ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); ++ entry1 = new TextField(30); ++ entry2 = new TextField(30); ++ entry2.setEchoChar('*'); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry1); ++ dialog.add("South", entry2); ++ dialog.add("East", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return; ++ } ++ ++ public String getAuth() { ++ return reply1 + ":" + reply2; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply1 = entry1.getText(); ++ reply2 = entry2.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ ++class ClientCertDialog implements ActionListener { ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry; ++ String reply = ""; ++ ++ ClientCertDialog() { ++ ; ++ } ++ ++ public String queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Enter SSL Client Cert+Key String"); ++ ++ dialog = new Dialog(frame, true); ++ ++ ++ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); ++ entry = new TextField(30); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry); ++ dialog.add("South", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return reply; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply = entry.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ ++class BrowserCertsDialog implements ActionListener { ++ Button yes, no; ++ Dialog dialog; ++ String vncServer; ++ String hostport; ++ public boolean showCertDialog = true; ++ ++ BrowserCertsDialog(String serv, String hp) { ++ vncServer = serv; ++ hostport = hp; ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Use Browser/JVM Certs?"); ++ ++ dialog = new Dialog(frame, true); ++ ++ String m = ""; ++m += "\n"; ++m += "This VNC Viewer applet does not have its own keystore to track\n"; ++m += "SSL certificates, and so cannot authenticate the certificate\n"; ++m += "of the VNC Server:\n"; ++m += "\n"; ++m += " " + hostport + "\n\n " + vncServer + "\n"; ++m += "\n"; ++m += "on its own.\n"; ++m += "\n"; ++m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; ++m += "has previously accepted the same certificate. You may have set\n"; ++m += "this up permanently or just for this session, or the server\n"; ++m += "certificate was signed by a CA cert that your Web Browser or\n"; ++m += "Java VM Plugin has.\n"; ++m += "\n"; ++m += "If the VNC Server connection times out while you are reading this\n"; ++m += "dialog, then restart the connection and try again.\n"; ++m += "\n"; ++m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; ++m += "\n"; ++ ++ TextArea textarea = new TextArea(m, 22, 64, ++ TextArea.SCROLLBARS_VERTICAL_ONLY); ++ textarea.setEditable(false); ++ yes = new Button("Yes"); ++ yes.addActionListener(this); ++ no = new Button("No, Let Me See the Certificate."); ++ no.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", textarea); ++ dialog.add("Center", yes); ++ dialog.add("South", no); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til Yes or No pressed. */ ++ System.out.println("done show()"); ++ return; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == yes) { ++ showCertDialog = false; ++ //dialog.dispose(); ++ dialog.hide(); ++ } else if (evt.getSource() == no) { ++ showCertDialog = true; ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ System.out.println("done actionPerformed()"); ++ } ++} ++ ++class CertInfo { ++ String fields[] = {"CN", "OU", "O", "L", "C"}; ++ java.security.cert.Certificate cert; ++ String certString = ""; ++ ++ CertInfo(java.security.cert.Certificate c) { ++ cert = c; ++ certString = cert.toString(); ++ } ++ ++ String get_certinfo(String which) { ++ int i; ++ String cs = new String(certString); ++ String all = ""; ++ ++ /* ++ * For now we simply scrape the cert string, there must ++ * be an API for this... perhaps optionValue? ++ */ ++ for (i=0; i < fields.length; i++) { ++ int f, t, t1, t2; ++ String sub, mat = fields[i] + "="; ++ ++ f = cs.indexOf(mat, 0); ++ if (f > 0) { ++ t1 = cs.indexOf(", ", f); ++ t2 = cs.indexOf("\n", f); ++ if (t1 < 0 && t2 < 0) { ++ continue; ++ } else if (t1 < 0) { ++ t = t2; ++ } else if (t2 < 0) { ++ t = t1; ++ } else if (t1 < t2) { ++ t = t1; ++ } else { ++ t = t2; ++ } ++ if (t > f) { ++ sub = cs.substring(f, t); ++ all = all + " " + sub + "\n"; ++ if (which.equals(fields[i])) { ++ return sub; ++ } ++ } ++ } ++ } ++ if (which.equals("all")) { ++ return all; ++ } else { ++ return ""; ++ } ++ } ++} ++ ++class Base64Coder { ++ ++ // Mapping table from 6-bit nibbles to Base64 characters. ++ private static char[] map1 = new char[64]; ++ static { ++ int i=0; ++ for (char c='A'; c<='Z'; c++) map1[i++] = c; ++ for (char c='a'; c<='z'; c++) map1[i++] = c; ++ for (char c='0'; c<='9'; c++) map1[i++] = c; ++ map1[i++] = '+'; map1[i++] = '/'; } ++ ++ // Mapping table from Base64 characters to 6-bit nibbles. ++ private static byte[] map2 = new byte[128]; ++ static { ++ for (int i=0; iin. ++ * @return A character array with the Base64 encoded data. ++ */ ++ public static char[] encode (byte[] in, int iLen) { ++ int oDataLen = (iLen*4+2)/3; // output length without padding ++ int oLen = ((iLen+2)/3)*4; // output length including padding ++ char[] out = new char[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++] & 0xff; ++ int i1 = ip < iLen ? in[ip++] & 0xff : 0; ++ int i2 = ip < iLen ? in[ip++] & 0xff : 0; ++ int o0 = i0 >>> 2; ++ int o1 = ((i0 & 3) << 4) | (i1 >>> 4); ++ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); ++ int o3 = i2 & 0x3F; ++ out[op++] = map1[o0]; ++ out[op++] = map1[o1]; ++ out[op] = op < oDataLen ? map1[o2] : '='; op++; ++ out[op] = op < oDataLen ? map1[o3] : '='; op++; } ++ return out; } ++ ++ /** ++ * Decodes a string from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return A String containing the decoded data. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static String decodeString (String s) { ++ return new String(decode(s)); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (String s) { ++ return decode(s.toCharArray()); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * No blanks or line breaks are allowed within the Base64 encoded data. ++ * @param in a character array containing the Base64 encoded data. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (char[] in) { ++ int iLen = in.length; ++ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); ++ while (iLen > 0 && in[iLen-1] == '=') iLen--; ++ int oLen = (iLen*3) / 4; ++ byte[] out = new byte[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++]; ++ int i1 = in[ip++]; ++ int i2 = ip < iLen ? in[ip++] : 'A'; ++ int i3 = ip < iLen ? in[ip++] : 'A'; ++ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int b0 = map2[i0]; ++ int b1 = map2[i1]; ++ int b2 = map2[i2]; ++ int b3 = map2[i3]; ++ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int o0 = ( b0 <<2) | (b1>>>4); ++ int o1 = ((b1 & 0xf)<<4) | (b2>>>2); ++ int o2 = ((b2 & 3)<<6) | b3; ++ out[op++] = (byte)o0; ++ if (op 0) + { + viewer.options.oldEightBitColors = viewer.options.eightBitColors; +@@ -237,6 +259,9 @@ + } + else + { ++// begin runge/x11vnc ++ viewer.options.oldEightBitColors = viewer.options.eightBitColors; ++// end runge/x11vnc + rfb.writeSetPixelFormat( + 32, + 24, +@@ -376,12 +401,14 @@ + // Start/stop session recording if necessary. + viewer.checkRecordingStatus(); + +- rfb.writeFramebufferUpdateRequest( +- 0, +- 0, +- rfb.framebufferWidth, +- rfb.framebufferHeight, +- false); ++ if (!viewer.graftFtp) { ++ rfb.writeFramebufferUpdateRequest( ++ 0, ++ 0, ++ rfb.framebufferWidth, ++ rfb.framebufferHeight, ++ false); ++ } + + // + // main dispatch loop +@@ -390,6 +417,9 @@ + while (true) { + // Read message type from the server. + int msgType = rfb.readServerMessageType(); ++ if (viewer.ftpOnly && msgType != RfbProto.rfbFileTransfer) { ++ System.out.println("msgType:" + msgType); ++ } + + // Process the message depending on its type. + switch (msgType) { +@@ -1532,9 +1562,14 @@ + else + { + result = +- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) +- << 16 | (pixBuf[i * 4 + 2] & 0xFF) +- << 8 | (pixBuf[i * 4 + 3] & 0xFF); ++// begin runge/x11vnc ++// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) ++// << 16 | (pixBuf[i * 4 + 2] & 0xFF) ++// << 8 | (pixBuf[i * 4 + 3] & 0xFF); ++ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) ++ << 16 | (pixBuf[i * 4 + 1] & 0xFF) ++ << 8 | (pixBuf[i * 4 + 0] & 0xFF); ++// end runge/x11vnc + } + } else { + result = 0; // Transparent pixel +@@ -1565,9 +1600,14 @@ + else + { + result = +- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) +- << 16 | (pixBuf[i * 4 + 2] & 0xFF) +- << 8 | (pixBuf[i * 4 + 3] & 0xFF); ++// begin runge/x11vnc ++// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) ++// << 16 | (pixBuf[i * 4 + 2] & 0xFF) ++// << 8 | (pixBuf[i * 4 + 3] & 0xFF); ++ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) ++ << 16 | (pixBuf[i * 4 + 1] & 0xFF) ++ << 8 | (pixBuf[i * 4 + 0] & 0xFF); ++// end runge/x11vnc + } + } else { + result = 0; // Transparent pixel +diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java +--- JavaViewer.orig/VncViewer.java 2006-05-24 15:14:40.000000000 -0400 ++++ JavaViewer/VncViewer.java 2010-03-27 18:00:28.000000000 -0400 +@@ -41,6 +41,7 @@ + import java.io.*; + import java.net.*; + import javax.swing.*; ++import java.util.Date; + + public class VncViewer extends java.applet.Applet + implements java.lang.Runnable, WindowListener { +@@ -80,11 +81,11 @@ + GridBagLayout gridbag; + ButtonPanel buttonPanel; + AuthPanel authenticator; +- VncCanvas vc; ++ VncCanvas vc = null; + OptionsFrame options; + ClipboardFrame clipboard; + RecordingFrame rec; +- FTPFrame ftp; // KMC: FTP Frame declaration ++ FTPFrame ftp = null; // KMC: FTP Frame declaration + + // Control session recording. + Object recordingSync; +@@ -96,7 +97,7 @@ + + // Variables read from parameter values. + String host; +- int port; ++ int port, vncserverport; + String passwordParam; + String encPasswordParam; + boolean showControls; +@@ -115,28 +116,75 @@ + int i; + // mslogon support 2 end + ++// begin runge/x11vnc ++boolean disableSSL; ++boolean GET; ++String CONNECT; ++String urlPrefix; ++String httpsPort; ++String oneTimeKey; ++String serverCert; ++String ftpDropDown; ++String proxyHost; ++String proxyPort; ++boolean forceProxy; ++boolean ignoreProxy; ++boolean trustAllVncCerts; ++boolean trustUrlVncCert; ++boolean debugCerts; ++boolean debugKeyboard; ++boolean mapF5_to_atsign; ++boolean forbid_Ctrl_Alt; ++ ++boolean ignoreMSLogonCheck; ++boolean delayAuthPanel; ++boolean ftpOnly; ++boolean graftFtp; ++boolean dsmActive; ++ ++boolean gotAuth; ++int authGot; ++// end runge/x11vnc ++ ++ + // + // init() + // + ++public void ftp_init() { ++ boolean show = false; ++ if (ftp != null) { ++ show = true; ++ } ++ ftp = null; ++ ++ ftp = new FTPFrame(this); // KMC: FTPFrame creation ++ ++ if (show) { ++ ftp.doOpen(); ++ rfb.readServerDriveList(); ++ } ++} ++ + public void init() { + + readParameters(); + + if (inSeparateFrame) { +- vncFrame = new Frame("Ultr@VNC"); +- if (!inAnApplet) { +- vncFrame.add("Center", this); +- } +- vncContainer = vncFrame; ++ vncFrame = new Frame("Ultr@VNC"); ++ if (!inAnApplet) { ++ vncFrame.add("Center", this); ++ } ++ vncContainer = vncFrame; + } else { +- vncContainer = this; ++ vncContainer = this; + } + + recordingSync = new Object(); + + options = new OptionsFrame(this); + clipboard = new ClipboardFrame(this); ++ + // authenticator = new AuthPanel(false); // mslogon support : go to connectAndAuthenticate() + if (RecordingFrame.checkSecurity()) + rec = new RecordingFrame(this); +@@ -147,10 +195,11 @@ + cursorUpdatesDef = null; + eightBitColorsDef = null; + +- if (inSeparateFrame) ++ if (inSeparateFrame && vncFrame != null) + vncFrame.addWindowListener(this); + +- ftp = new FTPFrame(this); // KMC: FTPFrame creation ++ ftp_init(); ++ + rfbThread = new Thread(this); + rfbThread.start(); + } +@@ -186,6 +235,30 @@ + gbc.weightx = 1.0; + gbc.weighty = 1.0; + ++ if (ftpOnly) { ++ if (showControls) { ++ buttonPanel.enableButtons(); ++ } ++ ActionListener taskPerformer = new ActionListener() { ++ public void actionPerformed(ActionEvent evt) { ++ vncFrame.setVisible(false); ++ ftp.setSavedLocations(); ++ if (ftp.isVisible()) { ++ ftp.doClose(); ++ } else { ++ ftp.doOpen(); ++ } ++ rfb.readServerDriveList(); ++ } ++ }; ++ Timer t = new Timer(300, taskPerformer); ++ t.setRepeats(false); ++ t.start(); ++ ++ vc.processNormalProtocol(); ++ return; ++ } ++ + // Add ScrollPanel to applet mode + + // Create a panel which itself is resizeable and can hold +@@ -286,6 +359,24 @@ + + void connectAndAuthenticate() throws Exception { + ++ if (graftFtp) { ++ rfb = new RfbProto(host, port, this); ++ rfb.desktopName = "ftponly"; ++ rfb.framebufferWidth = 12; ++ rfb.framebufferHeight = 12; ++ rfb.bitsPerPixel = 32; ++ rfb.depth = 24; ++ rfb.trueColour = true; ++ rfb.redMax = 255; ++ rfb.greenMax = 255; ++ rfb.blueMax = 255; ++ rfb.redShift = 16; ++ rfb.greenShift = 8; ++ rfb.blueShift = 0; ++ rfb.inNormalProtocol = true; ++ return; ++ } ++ + // If "ENCPASSWORD" parameter is set, decrypt the password into + // the passwordParam string. + +@@ -336,7 +427,22 @@ + // + + +- prologueDetectAuthProtocol() ; ++// begin runge/x11vnc ++ gotAuth = false; ++ if (delayAuthPanel) { ++ if (tryAuthenticate(null, null)) { ++ if (inSeparateFrame) { ++ vncFrame.pack(); ++ vncFrame.show(); ++ } ++ return; ++ } ++ } ++// prologueDetectAuthProtocol() ; ++ if (ignoreMSLogonCheck == false) { ++ prologueDetectAuthProtocol() ; ++ } ++// end runge/x11vnc + + authenticator = new AuthPanel(mslogon); + +@@ -371,6 +477,7 @@ + //mslogon support end + } + ++ int tries = 0; + while (true) { + // Wait for user entering a password, or a username and a password + synchronized(authenticator) { +@@ -390,6 +497,13 @@ + break; + //mslogon support end + ++// begin runge/x11vnc ++ gotAuth = false; ++ if (++tries > 2) { ++ throw new Exception("Incorrect password entered " + tries + " times."); ++ } ++// end runge/x11vnc ++ + // Retry on authentication failure. + authenticator.retry(); + } +@@ -405,9 +519,11 @@ + + void prologueDetectAuthProtocol() throws Exception { + +- rfb = new RfbProto(host, port, this); ++ if (!gotAuth) { ++ rfb = new RfbProto(host, port, this); + +- rfb.readVersionMsg(); ++ rfb.readVersionMsg(); ++ } + + System.out.println("RFB server supports protocol version " + + rfb.serverMajor + "." + rfb.serverMinor); +@@ -431,16 +547,36 @@ + + boolean tryAuthenticate(String us, String pw) throws Exception { + +- rfb = new RfbProto(host, port, this); ++ int authScheme; + +- rfb.readVersionMsg(); ++ if (!gotAuth) { ++ rfb = new RfbProto(host, port, this); + +- System.out.println("RFB server supports protocol version " + +- rfb.serverMajor + "." + rfb.serverMinor); ++ rfb.readVersionMsg(); + +- rfb.writeVersionMsg(); ++ System.out.println("RFB server supports protocol version: " + ++ rfb.serverMajor + "." + rfb.serverMinor); + +- int authScheme = rfb.readAuthScheme(); ++ rfb.writeVersionMsg(); ++ ++ authScheme = rfb.readAuthScheme(); ++ ++ gotAuth = true; ++ authGot = authScheme; ++ } else { ++ authScheme = authGot; ++ } ++// begin runge/x11vnc ++ if (delayAuthPanel && pw == null) { ++ if (authScheme == RfbProto.NoAuth) { ++ System.out.println("No authentication needed"); ++ return true; ++ } else { ++ return false; ++ } ++ } ++System.out.println("as: " + authScheme); ++// end runge/x11vnc + + switch (authScheme) { + +@@ -629,6 +765,10 @@ + + void doProtocolInitialisation() throws IOException { + ++ if (graftFtp) { ++ return; ++ } ++ + rfb.writeClientInit(); + + rfb.readServerInit(); +@@ -774,9 +914,28 @@ + fatalError("HOST parameter not specified"); + } + } ++ Date d = new Date(); ++ System.out.println("-\nSSL VNC Java Applet starting. " + d); + +- String str = readParameter("PORT", true); +- port = Integer.parseInt(str); ++ port = 0; ++ String str = readParameter("PORT", false); ++ if (str != null) { ++ port = Integer.parseInt(str); ++ } ++ // When there is a proxy VNCSERVERPORT may be inaccessible (inside firewall). ++ vncserverport = 0; ++ str = readParameter("VNCSERVERPORT", false); ++ if (str != null) { ++ vncserverport = Integer.parseInt(str); ++ } ++ if (port == 0 && vncserverport == 0) { ++ fatalError("Neither PORT nor VNCSERVERPORT parameters specified"); ++ } ++ if (port == 0) { ++ // Nevertheless, fall back to vncserverport if we have to. ++ System.out.println("using vncserverport: '" + vncserverport + "' for PORT."); ++ port = vncserverport; ++ } + + if (inAnApplet) { + str = readParameter("Open New Window", false); +@@ -804,6 +963,158 @@ + deferScreenUpdates = readIntParameter("Defer screen updates", 20); + deferCursorUpdates = readIntParameter("Defer cursor updates", 10); + deferUpdateRequests = readIntParameter("Defer update requests", 50); ++ ++// begin runge/x11vnc ++ // SSL ++ disableSSL = false; ++ str = readParameter("DisableSSL", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) ++ disableSSL = true; ++ ++ httpsPort = readParameter("httpsPort", false); ++ ++ // Extra GET, CONNECT string: ++ CONNECT = readParameter("CONNECT", false); ++ if (CONNECT != null) { ++ CONNECT = CONNECT.replaceAll(" ", ":"); ++ } ++ ++ GET = false; ++ str = readParameter("GET", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ GET = true; ++ } ++ if (str != null && str.equalsIgnoreCase("1")) { ++ GET = true; ++ } ++ ++ urlPrefix = readParameter("urlPrefix", false); ++ if (urlPrefix != null) { ++ urlPrefix = urlPrefix.replaceAll("%2F", "/"); ++ urlPrefix = urlPrefix.replaceAll("%2f", "/"); ++ urlPrefix = urlPrefix.replaceAll("_2F_", "/"); ++ if (urlPrefix.indexOf("/") != 0) { ++ urlPrefix = "/" + urlPrefix; ++ } ++ } else { ++ urlPrefix = ""; ++ } ++ System.out.println("urlPrefix: '" + urlPrefix + "'"); ++ ++ ftpDropDown = readParameter("ftpDropDown", false); ++ if (ftpDropDown != null) { ++ ftpDropDown = ftpDropDown.replaceAll("%2F", "/"); ++ ftpDropDown = ftpDropDown.replaceAll("%2f", "/"); ++ ftpDropDown = ftpDropDown.replaceAll("_2F_", "/"); ++ ftpDropDown = ftpDropDown.replaceAll("%20", " "); ++ System.out.println("ftpDropDown: '" + ftpDropDown + "'"); ++ } ++ ++ ++ oneTimeKey = readParameter("oneTimeKey", false); ++ if (oneTimeKey != null) { ++ System.out.println("oneTimeKey is set."); ++ } ++ ++ serverCert = readParameter("serverCert", false); ++ if (serverCert != null) { ++ System.out.println("serverCert is set."); ++ } ++ ++ forceProxy = false; ++ proxyHost = null; ++ proxyPort = null; ++ str = readParameter("forceProxy", false); ++ if (str != null) { ++ if (str.equalsIgnoreCase("Yes")) { ++ forceProxy = true; ++ } else if (str.equalsIgnoreCase("No")) { ++ forceProxy = false; ++ } else { ++ forceProxy = true; ++ String[] pieces = str.split(" "); ++ proxyHost = new String(pieces[0]); ++ if (pieces.length >= 2) { ++ proxyPort = new String(pieces[1]); ++ } else { ++ proxyPort = new String("8080"); ++ } ++ } ++ } ++ str = readParameter("proxyHost", false); ++ if (str != null) { ++ proxyHost = new String(str); ++ } ++ str = readParameter("proxyPort", false); ++ if (str != null) { ++ proxyPort = new String(str); ++ } ++ if (proxyHost != null && proxyPort == null) { ++ proxyPort = new String("8080"); ++ } ++ ++ ignoreProxy = false; ++ str = readParameter("ignoreProxy", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ ignoreProxy = true; ++ } ++ ++ trustAllVncCerts = false; ++ str = readParameter("trustAllVncCerts", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ trustAllVncCerts = true; ++ } ++ trustUrlVncCert = false; ++ str = readParameter("trustUrlVncCert", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ trustUrlVncCert = true; ++ } ++ debugCerts = false; ++ str = readParameter("debugCerts", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ debugCerts = true; ++ } ++ debugKeyboard = false; ++ str = readParameter("debugKeyboard", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ debugKeyboard = true; ++ } ++ mapF5_to_atsign = false; ++ str = readParameter("mapF5_to_atsign", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ mapF5_to_atsign = true; ++ } ++ forbid_Ctrl_Alt = false; ++ str = readParameter("forbid_Ctrl_Alt", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ forbid_Ctrl_Alt = true; ++ } ++ ignoreMSLogonCheck = false; ++ str = readParameter("ignoreMSLogonCheck", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ ignoreMSLogonCheck = true; ++ } ++ ftpOnly = false; ++ str = readParameter("ftpOnly", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ ftpOnly = true; ++ } ++ graftFtp = false; ++ str = readParameter("graftFtp", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ graftFtp = true; ++ } ++ dsmActive = false; ++ str = readParameter("dsmActive", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ dsmActive = true; ++ } ++ delayAuthPanel = false; ++ str = readParameter("delayAuthPanel", false); ++ if (str != null && str.equalsIgnoreCase("Yes")) { ++ delayAuthPanel = true; ++ } ++// end runge/x11vnc + } + + public String readParameter(String name, boolean required) { diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/.cvsignore new file mode 100755 index 0000000..d5dc0d6 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/.cvsignore @@ -0,0 +1,9 @@ +.deps +Makefile +Makefile.in +SDLvncviewer +ppmtest +vnc2mpg +*.avi +*.mpg + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/Makefile.am new file mode 100755 index 0000000..c26c1c9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/Makefile.am @@ -0,0 +1,33 @@ +INCLUDES = -I$(top_srcdir) +LDADD = ../libvncclient/libvncclient.la @WSOCKLIB@ + +if WITH_FFMPEG +FFMPEG_HOME=@with_ffmpeg@ + +if HAVE_MP3LAME +MP3LAME_LIB=-lmp3lame +endif + +vnc2mpg_CFLAGS=-I$(FFMPEG_HOME)/libavformat -I$(FFMPEG_HOME)/libavcodec -I$(FFMPEG_HOME)/libavutil +vnc2mpg_LDADD=$(LDADD) $(FFMPEG_HOME)/libavformat/libavformat.a $(FFMPEG_HOME)/libavcodec/libavcodec.a $(MP3LAME_LIB) -lm + +FFMPEG_CLIENT=vnc2mpg +endif + +if HAVE_LIBSDL +SDLVIEWER=SDLvncviewer + +SDLvncviewer_CFLAGS=$(SDL_CFLAGS) + +if HAVE_X11 +X11_LIB=-lX11 +endif + +# thanks to autoconf, this looks ugly +SDLvncviewer_LDADD=$(LDADD) $(SDL_LIBS) $(X11_LIB) +endif + +noinst_PROGRAMS=ppmtest $(SDLVIEWER) $(FFMPEG_CLIENT) backchannel + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/SDLvncviewer.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/SDLvncviewer.c new file mode 100755 index 0000000..5d23ec7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/SDLvncviewer.c @@ -0,0 +1,553 @@ +#include +#include +#include +#include "scrap.c" + +struct { int sdl; int rfb; } buttonMapping[]={ + {1, rfbButton1Mask}, + {2, rfbButton2Mask}, + {3, rfbButton3Mask}, + {4, rfbButton4Mask}, + {5, rfbButton5Mask}, + {0,0} +}; + +static int enableResizable, viewOnly, listenLoop, buttonMask; +#ifdef SDL_ASYNCBLIT + int sdlFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; +#else + int sdlFlags = SDL_HWSURFACE | SDL_HWACCEL; +#endif +static int realWidth, realHeight, bytesPerPixel, rowStride; +static char *sdlPixels; + +static int rightAltKeyDown, leftAltKeyDown; + +static rfbBool resize(rfbClient* client) { + int width=client->width,height=client->height, + depth=client->format.bitsPerPixel; + + if (enableResizable) + sdlFlags |= SDL_RESIZABLE; + + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = width; client->updateRect.h = height; + rfbBool okay=SDL_VideoModeOK(width,height,depth,sdlFlags); + if(!okay) + for(depth=24;!okay && depth>4;depth/=2) + okay=SDL_VideoModeOK(width,height,depth,sdlFlags); + if(okay) { + SDL_Surface* sdl=SDL_SetVideoMode(width,height,depth,sdlFlags); + rfbClientSetClientData(client, SDL_Init, sdl); + client->width = sdl->pitch / (depth / 8); + if (sdlPixels) { + free(client->frameBuffer); + sdlPixels = NULL; + } + client->frameBuffer=sdl->pixels; + + client->format.bitsPerPixel=depth; + client->format.redShift=sdl->format->Rshift; + client->format.greenShift=sdl->format->Gshift; + client->format.blueShift=sdl->format->Bshift; + client->format.redMax=sdl->format->Rmask>>client->format.redShift; + client->format.greenMax=sdl->format->Gmask>>client->format.greenShift; + client->format.blueMax=sdl->format->Bmask>>client->format.blueShift; + SetFormatAndEncodings(client); + + } else { + SDL_Surface* sdl=rfbClientGetClientData(client, SDL_Init); + rfbClientLog("Could not set resolution %dx%d!\n", + client->width,client->height); + if(sdl) { + client->width=sdl->pitch / (depth / 8); + client->height=sdl->h; + } else { + client->width=0; + client->height=0; + } + return FALSE; + } + SDL_WM_SetCaption(client->desktopName, "SDL"); + return TRUE; +} + +static rfbKeySym SDL_key2rfbKeySym(SDL_KeyboardEvent* e) { + rfbKeySym k = 0; + switch(e->keysym.sym) { + case SDLK_BACKSPACE: k = XK_BackSpace; break; + case SDLK_TAB: k = XK_Tab; break; + case SDLK_CLEAR: k = XK_Clear; break; + case SDLK_RETURN: k = XK_Return; break; + case SDLK_PAUSE: k = XK_Pause; break; + case SDLK_ESCAPE: k = XK_Escape; break; + case SDLK_SPACE: k = XK_space; break; + case SDLK_DELETE: k = XK_Delete; break; + case SDLK_KP0: k = XK_KP_0; break; + case SDLK_KP1: k = XK_KP_1; break; + case SDLK_KP2: k = XK_KP_2; break; + case SDLK_KP3: k = XK_KP_3; break; + case SDLK_KP4: k = XK_KP_4; break; + case SDLK_KP5: k = XK_KP_5; break; + case SDLK_KP6: k = XK_KP_6; break; + case SDLK_KP7: k = XK_KP_7; break; + case SDLK_KP8: k = XK_KP_8; break; + case SDLK_KP9: k = XK_KP_9; break; + case SDLK_KP_PERIOD: k = XK_KP_Decimal; break; + case SDLK_KP_DIVIDE: k = XK_KP_Divide; break; + case SDLK_KP_MULTIPLY: k = XK_KP_Multiply; break; + case SDLK_KP_MINUS: k = XK_KP_Subtract; break; + case SDLK_KP_PLUS: k = XK_KP_Add; break; + case SDLK_KP_ENTER: k = XK_KP_Enter; break; + case SDLK_KP_EQUALS: k = XK_KP_Equal; break; + case SDLK_UP: k = XK_Up; break; + case SDLK_DOWN: k = XK_Down; break; + case SDLK_RIGHT: k = XK_Right; break; + case SDLK_LEFT: k = XK_Left; break; + case SDLK_INSERT: k = XK_Insert; break; + case SDLK_HOME: k = XK_Home; break; + case SDLK_END: k = XK_End; break; + case SDLK_PAGEUP: k = XK_Page_Up; break; + case SDLK_PAGEDOWN: k = XK_Page_Down; break; + case SDLK_F1: k = XK_F1; break; + case SDLK_F2: k = XK_F2; break; + case SDLK_F3: k = XK_F3; break; + case SDLK_F4: k = XK_F4; break; + case SDLK_F5: k = XK_F5; break; + case SDLK_F6: k = XK_F6; break; + case SDLK_F7: k = XK_F7; break; + case SDLK_F8: k = XK_F8; break; + case SDLK_F9: k = XK_F9; break; + case SDLK_F10: k = XK_F10; break; + case SDLK_F11: k = XK_F11; break; + case SDLK_F12: k = XK_F12; break; + case SDLK_F13: k = XK_F13; break; + case SDLK_F14: k = XK_F14; break; + case SDLK_F15: k = XK_F15; break; + case SDLK_NUMLOCK: k = XK_Num_Lock; break; + case SDLK_CAPSLOCK: k = XK_Caps_Lock; break; + case SDLK_SCROLLOCK: k = XK_Scroll_Lock; break; + case SDLK_RSHIFT: k = XK_Shift_R; break; + case SDLK_LSHIFT: k = XK_Shift_L; break; + case SDLK_RCTRL: k = XK_Control_R; break; + case SDLK_LCTRL: k = XK_Control_L; break; + case SDLK_RALT: k = XK_Alt_R; break; + case SDLK_LALT: k = XK_Alt_L; break; + case SDLK_RMETA: k = XK_Meta_R; break; + case SDLK_LMETA: k = XK_Meta_L; break; +#if 0 + /* TODO: find out keysyms */ + case SDLK_LSUPER: k = XK_LSuper; break; /* left "windows" key */ + case SDLK_RSUPER: k = XK_RSuper; break; /* right "windows" key */ + case SDLK_COMPOSE: k = XK_Compose; break; +#endif + case SDLK_MODE: k = XK_Mode_switch; break; + case SDLK_HELP: k = XK_Help; break; + case SDLK_PRINT: k = XK_Print; break; + case SDLK_SYSREQ: k = XK_Sys_Req; break; + case SDLK_BREAK: k = XK_Break; break; + default: break; + } + if (k == 0 && e->keysym.sym >= SDLK_a && e->keysym.sym <= SDLK_z) { + k = XK_a + e->keysym.sym - SDLK_a; + if (e->keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) + k &= ~0x20; + } + if (k == 0) { + if (e->keysym.unicode < 0x100) + k = e->keysym.unicode; + else + rfbClientLog("Unknown keysym: %d\n",e->keysym.sym); + } + + return k; +} + +static uint32_t get(rfbClient *cl, int x, int y) +{ + switch (bytesPerPixel) { + case 1: return ((uint8_t *)cl->frameBuffer)[x + y * cl->width]; + case 2: return ((uint16_t *)cl->frameBuffer)[x + y * cl->width]; + case 4: return ((uint32_t *)cl->frameBuffer)[x + y * cl->width]; + default: + rfbClientErr("Unknown bytes/pixel: %d", bytesPerPixel); + exit(1); + } +} + +static void put(int x, int y, uint32_t v) +{ + switch (bytesPerPixel) { + case 1: ((uint8_t *)sdlPixels)[x + y * rowStride] = v; break; + case 2: ((uint16_t *)sdlPixels)[x + y * rowStride] = v; break; + case 4: ((uint32_t *)sdlPixels)[x + y * rowStride] = v; break; + default: + rfbClientErr("Unknown bytes/pixel: %d", bytesPerPixel); + exit(1); + } +} + +static void resizeRectangleToReal(rfbClient *cl, int x, int y, int w, int h) +{ + int i0 = x * realWidth / cl->width; + int i1 = ((x + w) * realWidth - 1) / cl->width + 1; + int j0 = y * realHeight / cl->height; + int j1 = ((y + h) * realHeight - 1) / cl->height + 1; + int i, j; + + for (j = j0; j < j1; j++) + for (i = i0; i < i1; i++) { + int x0 = i * cl->width / realWidth; + int x1 = ((i + 1) * cl->width - 1) / realWidth + 1; + int y0 = j * cl->height / realHeight; + int y1 = ((j + 1) * cl->height - 1) / realHeight + 1; + uint32_t r = 0, g = 0, b = 0; + + for (y = y0; y < y1; y++) + for (x = x0; x < x1; x++) { + uint32_t v = get(cl, x, y); +#define REDSHIFT cl->format.redShift +#define REDMAX cl->format.redMax +#define GREENSHIFT cl->format.greenShift +#define GREENMAX cl->format.greenMax +#define BLUESHIFT cl->format.blueShift +#define BLUEMAX cl->format.blueMax + r += (v >> REDSHIFT) & REDMAX; + g += (v >> GREENSHIFT) & GREENMAX; + b += (v >> BLUESHIFT) & BLUEMAX; + } + r /= (x1 - x0) * (y1 - y0); + g /= (x1 - x0) * (y1 - y0); + b /= (x1 - x0) * (y1 - y0); + + put(i, j, (r << REDSHIFT) | (g << GREENSHIFT) | + (b << BLUESHIFT)); + } +} + +static void update(rfbClient* cl,int x,int y,int w,int h) { + if (sdlPixels) { + resizeRectangleToReal(cl, x, y, w, h); + w = ((x + w) * realWidth - 1) / cl->width + 1; + h = ((y + h) * realHeight - 1) / cl->height + 1; + x = x * realWidth / cl->width; + y = y * realHeight / cl->height; + w -= x; + h -= y; + } + SDL_UpdateRect(rfbClientGetClientData(cl, SDL_Init), x, y, w, h); +} + +static void setRealDimension(rfbClient *client, int w, int h) +{ + SDL_Surface* sdl; + + if (w < 0) { + const SDL_VideoInfo *info = SDL_GetVideoInfo(); + w = info->current_h; + h = info->current_w; + } + + if (w == realWidth && h == realHeight) + return; + + if (!sdlPixels) { + int size; + + sdlPixels = (char *)client->frameBuffer; + rowStride = client->width; + + bytesPerPixel = client->format.bitsPerPixel / 8; + size = client->width * bytesPerPixel * client->height; + client->frameBuffer = malloc(size); + if (!client->frameBuffer) { + rfbClientErr("Could not allocate %d bytes", size); + exit(1); + } + memcpy(client->frameBuffer, sdlPixels, size); + } + + sdl = rfbClientGetClientData(client, SDL_Init); + if (sdl->w != w || sdl->h != h) { + int depth = sdl->format->BitsPerPixel; + sdl = SDL_SetVideoMode(w, h, depth, sdlFlags); + rfbClientSetClientData(client, SDL_Init, sdl); + sdlPixels = sdl->pixels; + rowStride = sdl->pitch / (depth / 8); + } + + realWidth = w; + realHeight = h; + update(client, 0, 0, client->width, client->height); +} + +static void kbd_leds(rfbClient* cl, int value, int pad) { + /* note: pad is for future expansion 0=unused */ + fprintf(stderr,"Led State= 0x%02X\n", value); + fflush(stderr); +} + +/* trivial support for textchat */ +static void text_chat(rfbClient* cl, int value, char *text) { + switch(value) { + case rfbTextChatOpen: + fprintf(stderr,"TextChat: We should open a textchat window!\n"); + TextChatOpen(cl); + break; + case rfbTextChatClose: + fprintf(stderr,"TextChat: We should close our window!\n"); + break; + case rfbTextChatFinished: + fprintf(stderr,"TextChat: We should close our window!\n"); + break; + default: + fprintf(stderr,"TextChat: Received \"%s\"\n", text); + break; + } + fflush(stderr); +} + +#ifdef __MINGW32__ +#define LOG_TO_FILE +#endif + +#ifdef LOG_TO_FILE +#include +static void +log_to_file(const char *format, ...) +{ + FILE* logfile; + static char* logfile_str=0; + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + if(logfile_str==0) { + logfile_str=getenv("VNCLOG"); + if(logfile_str==0) + logfile_str="vnc.log"; + } + + logfile=fopen(logfile_str,"a"); + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock)); + fprintf(logfile,buf); + + vfprintf(logfile, format, args); + fflush(logfile); + + va_end(args); + fclose(logfile); +} +#endif + + +static void cleanup(rfbClient* cl) +{ + /* + just in case we're running in listenLoop: + close viewer window by restarting SDL video subsystem + */ + SDL_QuitSubSystem(SDL_INIT_VIDEO); + SDL_InitSubSystem(SDL_INIT_VIDEO); + if(cl) + rfbClientCleanup(cl); +} + + +static rfbBool handleSDLEvent(rfbClient *cl, SDL_Event *e) +{ + switch(e->type) { +#if SDL_MAJOR_VERSION > 1 || SDL_MINOR_VERSION >= 2 + case SDL_VIDEOEXPOSE: + SendFramebufferUpdateRequest(cl, 0, 0, + cl->width, cl->height, FALSE); + break; +#endif + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEMOTION: + { + int x, y, state, i; + if (viewOnly) + break; + + if (e->type == SDL_MOUSEMOTION) { + x = e->motion.x; + y = e->motion.y; + state = e->motion.state; + } + else { + x = e->button.x; + y = e->button.y; + state = e->button.button; + for (i = 0; buttonMapping[i].sdl; i++) + if (state == buttonMapping[i].sdl) { + state = buttonMapping[i].rfb; + if (e->type == SDL_MOUSEBUTTONDOWN) + buttonMask |= state; + else + buttonMask &= ~state; + break; + } + } + if (sdlPixels) { + x = x * cl->width / realWidth; + y = y * cl->height / realHeight; + } + SendPointerEvent(cl, x, y, buttonMask); + buttonMask &= ~(rfbButton4Mask | rfbButton5Mask); + break; + } + case SDL_KEYUP: + case SDL_KEYDOWN: + if (viewOnly) + break; + SendKeyEvent(cl, SDL_key2rfbKeySym(&e->key), + e->type == SDL_KEYDOWN ? TRUE : FALSE); + if (e->key.keysym.sym == SDLK_RALT) + rightAltKeyDown = e->type == SDL_KEYDOWN; + if (e->key.keysym.sym == SDLK_LALT) + leftAltKeyDown = e->type == SDL_KEYDOWN; + break; + case SDL_QUIT: + if(listenLoop) + { + cleanup(cl); + return FALSE; + } + else + { + rfbClientCleanup(cl); + exit(0); + } + case SDL_ACTIVEEVENT: + if (!e->active.gain && rightAltKeyDown) { + SendKeyEvent(cl, XK_Alt_R, FALSE); + rightAltKeyDown = FALSE; + rfbClientLog("released right Alt key\n"); + } + if (!e->active.gain && leftAltKeyDown) { + SendKeyEvent(cl, XK_Alt_L, FALSE); + leftAltKeyDown = FALSE; + rfbClientLog("released left Alt key\n"); + } + + if (e->active.gain && lost_scrap()) { + static char *data = NULL; + static int len = 0; + get_scrap(T('T', 'E', 'X', 'T'), &len, &data); + if (len) + SendClientCutText(cl, data, len); + } + break; + case SDL_SYSWMEVENT: + clipboard_filter(e); + break; + case SDL_VIDEORESIZE: + setRealDimension(cl, e->resize.w, e->resize.h); + break; + default: + rfbClientLog("ignore SDL event: 0x%x\n", e->type); + } + return TRUE; +} + +static void got_selection(rfbClient *cl, const char *text, int len) +{ + put_scrap(T('T', 'E', 'X', 'T'), len, text); +} + + +#ifdef mac +#define main SDLmain +#endif + +int main(int argc,char** argv) { + rfbClient* cl; + int i, j; + SDL_Event e; + +#ifdef LOG_TO_FILE + rfbClientLog=rfbClientErr=log_to_file; +#endif + + for (i = 1, j = 1; i < argc; i++) + if (!strcmp(argv[i], "-viewonly")) + viewOnly = 1; + else if (!strcmp(argv[i], "-resizable")) + enableResizable = 1; + else if (!strcmp(argv[i], "-listen")) { + listenLoop = 1; + argv[i] = "-listennofork"; + ++j; + } + else { + if (i != j) + argv[j] = argv[i]; + j++; + } + argc = j; + + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); + SDL_EnableUNICODE(1); + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, + SDL_DEFAULT_REPEAT_INTERVAL); + atexit(SDL_Quit); + signal(SIGINT, exit); + + do { + /* 16-bit: cl=rfbGetClient(5,3,2); */ + cl=rfbGetClient(8,3,4); + cl->MallocFrameBuffer=resize; + cl->canHandleNewFBSize = TRUE; + cl->GotFrameBufferUpdate=update; + cl->HandleKeyboardLedState=kbd_leds; + cl->HandleTextChat=text_chat; + cl->GotXCutText = got_selection; + cl->listenPort = LISTEN_PORT_OFFSET; + if(!rfbInitClient(cl,&argc,argv)) + { + cl = NULL; /* rfbInitClient has already freed the client struct */ + cleanup(cl); + break; + } + + init_scrap(); + + while(1) { + if(SDL_PollEvent(&e)) { + /* + handleSDLEvent() return 0 if user requested window close. + In this case, handleSDLEvent() will have called cleanup(). + */ + if(!handleSDLEvent(cl, &e)) + break; + } + else { + i=WaitForMessage(cl,500); + if(i<0) + { + cleanup(cl); + break; + } + if(i) + if(!HandleRFBServerMessage(cl)) + { + cleanup(cl); + break; + } + } + } + } + while(listenLoop); + + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/backchannel.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/backchannel.c new file mode 100755 index 0000000..643754e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/backchannel.c @@ -0,0 +1,99 @@ +/* A simple example of an RFB client */ + +#include +#include +#include +#include +#include + +static void HandleRect(rfbClient* client, int x, int y, int w, int h) { +} + +/* + * The client part of the back channel extension example. + * + */ + +#define rfbBackChannel 155 + +typedef struct backChannelMsg { + uint8_t type; + uint8_t pad1; + uint16_t pad2; + uint32_t size; +} backChannelMsg; + +static void sendMessage(rfbClient* client, char* text) +{ + backChannelMsg msg; + uint32_t length = strlen(text)+1; + + msg.type = rfbBackChannel; + msg.size = rfbClientSwap32IfLE(length); + if(!WriteToRFBServer(client, (char*)&msg, sizeof(msg)) || + !WriteToRFBServer(client, text, length)) { + rfbClientLog("enableBackChannel: write error (%d: %s)", errno, strerror(errno)); + } +} + +static rfbBool handleBackChannelMessage(rfbClient* client, + rfbServerToClientMsg* message) +{ + backChannelMsg msg; + char* text; + + if(message->type != rfbBackChannel) + return FALSE; + + rfbClientSetClientData(client, sendMessage, sendMessage); + + if(!ReadFromRFBServer(client, ((char*)&msg)+1, sizeof(msg)-1)) + return TRUE; + msg.size = rfbClientSwap32IfLE(msg.size); + text = malloc(msg.size); + if(!ReadFromRFBServer(client, text, msg.size)) { + free(text); + return TRUE; + } + + rfbClientLog("got back channel message: %s\n", text); + free(text); + + return TRUE; +} + +static int backChannelEncodings[] = { rfbBackChannel, 0 }; + +static rfbClientProtocolExtension backChannel = { + backChannelEncodings, /* encodings */ + NULL, /* handleEncoding */ + handleBackChannelMessage, /* handleMessage */ + NULL /* next extension */ +}; + +int +main(int argc, char **argv) +{ + rfbClient* client = rfbGetClient(8,3,4); + + client->GotFrameBufferUpdate = HandleRect; + rfbClientRegisterExtension(&backChannel); + + if (!rfbInitClient(client,&argc,argv)) + return 1; + + while (1) { + /* After each idle second, send a message */ + if(WaitForMessage(client,1000000)>0) + HandleRFBServerMessage(client); + else if(rfbClientGetClientData(client, sendMessage)) + sendMessage(client, "Dear Server,\n" + "thank you for understanding " + "back channel messages!"); + } + + rfbClientCleanup(client); + + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/ppmtest.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/ppmtest.c new file mode 100755 index 0000000..0422937 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/ppmtest.c @@ -0,0 +1,97 @@ +/* A simple example of an RFB client */ + +#include +#include +#include +#include +#include + +static void PrintRect(rfbClient* client, int x, int y, int w, int h) { + rfbClientLog("Received an update for %d,%d,%d,%d.\n",x,y,w,h); +} + +static void SaveFramebufferAsPPM(rfbClient* client, int x, int y, int w, int h) { + static time_t t=0,t1; + FILE* f; + int i,j; + rfbPixelFormat* pf=&client->format; + int bpp=pf->bitsPerPixel/8; + int row_stride=client->width*bpp; + + /* save one picture only if the last is older than 2 seconds */ + t1=time(NULL); + if(t1-t>2) + t=t1; + else + return; + + /* assert bpp=4 */ + if(bpp!=4 && bpp!=2) { + rfbClientLog("bpp = %d (!=4)\n",bpp); + return; + } + + f=fopen("framebuffer.ppm","wb"); + if(!f) { + rfbClientErr("Could not open framebuffer.ppm\n"); + return; + } + + fprintf(f,"P6\n# %s\n%d %d\n255\n",client->desktopName,client->width,client->height); + for(j=0;jheight*row_stride;j+=row_stride) + for(i=0;iwidth*bpp;i+=bpp) { + unsigned char* p=client->frameBuffer+j+i; + unsigned int v; + if(bpp==4) + v=*(unsigned int*)p; + else if(bpp==2) + v=*(unsigned short*)p; + else + v=*(unsigned char*)p; + fputc((v>>pf->redShift)*256/(pf->redMax+1),f); + fputc((v>>pf->greenShift)*256/(pf->greenMax+1),f); + fputc((v>>pf->blueShift)*256/(pf->blueMax+1),f); + } + fclose(f); +} + +int +main(int argc, char **argv) +{ + rfbClient* client = rfbGetClient(8,3,4); + time_t t=time(NULL); + + if(argc>1 && !strcmp("-print",argv[1])) { + client->GotFrameBufferUpdate = PrintRect; + argv[1]=argv[0]; argv++; argc--; + } else + client->GotFrameBufferUpdate = SaveFramebufferAsPPM; + + /* The -listen option is used to make us a daemon process which listens for + incoming connections from servers, rather than actively connecting to a + given server. The -tunnel and -via options are useful to create + connections tunneled via SSH port forwarding. We must test for the + -listen option before invoking any Xt functions - this is because we use + forking, and Xt doesn't seem to cope with forking very well. For -listen + option, when a successful incoming connection has been accepted, + listenForIncomingConnections() returns, setting the listenSpecified + flag. */ + + if (!rfbInitClient(client,&argc,argv)) + return 1; + + /* TODO: better wait for update completion */ + while (time(NULL)-t<5) { + static int i=0; + fprintf(stderr,"\r%d",i++); + if(WaitForMessage(client,50)<0) + break; + if(!HandleRFBServerMessage(client)) + break; + } + + rfbClientCleanup(client); + + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.c new file mode 100755 index 0000000..c28800c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.c @@ -0,0 +1,558 @@ +/* Handle clipboard text and data in arbitrary formats */ + +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#endif +#include "scrap.h" +#include "rfb/rfbconfig.h" + +/* Determine what type of clipboard we are using */ +#if defined(__unix__) && !defined(__QNXNTO__) && defined(LIBVNCSERVER_HAVE_X11) +#define X11_SCRAP +#elif defined(__WIN32__) +#define WIN_SCRAP +#elif defined(__QNXNTO__) +#define QNX_SCRAP +#else +#warning Unknown window manager for clipboard handling +#endif /* scrap type */ + +/* System dependent data types */ +#if defined(X11_SCRAP) +typedef Atom scrap_type; +static Atom XA_TARGETS, XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; +#elif defined(WIN_SCRAP) +typedef UINT scrap_type; +#elif defined(QNX_SCRAP) +typedef uint32_t scrap_type; +#define Ph_CL_TEXT T('T', 'E', 'X', 'T') +#else +typedef int scrap_type; +#endif /* scrap type */ + +/* System dependent variables */ +#if defined(X11_SCRAP) +static Display *SDL_Display; +static Window SDL_Window; +static void (*Lock_Display)(void); +static void (*Unlock_Display)(void); +static Atom XA_UTF8_STRING; +#elif defined(WIN_SCRAP) +static HWND SDL_Window; +#elif defined(QNX_SCRAP) +static unsigned short InputGroup; +#endif /* scrap type */ + +#define FORMAT_PREFIX "SDL_scrap_0x" + +static scrap_type convert_format(int type) +{ + switch (type) { + case T('T', 'E', 'X', 'T'): +#if defined(X11_SCRAP) + return XA_UTF8_STRING ? XA_UTF8_STRING : XA_STRING; +#elif defined(WIN_SCRAP) + return CF_TEXT; +#elif defined(QNX_SCRAP) + return Ph_CL_TEXT; +#endif /* scrap type */ + default: + { + char format[sizeof(FORMAT_PREFIX)+8+1]; + + sprintf(format, "%s%08lx", FORMAT_PREFIX, + (unsigned long)type); +#if defined(X11_SCRAP) + return XInternAtom(SDL_Display, format, False); +#elif defined(WIN_SCRAP) + return RegisterClipboardFormat(format); +#endif /* scrap type */ + } + } +} + +/* Convert internal data to scrap format */ +static int convert_data(int type, char *dst, const char *src, int srclen) +{ + int dstlen; + + dstlen = 0; + switch (type) { + case T('T', 'E', 'X', 'T'): + if (dst) { + while (--srclen >= 0) { +#if defined(__unix__) + if (*src == '\r') { + *dst++ = '\n'; + ++dstlen; + } + else +#elif defined(__WIN32__) + if (*src == '\r') { + *dst++ = '\r'; + ++dstlen; + *dst++ = '\n'; + ++dstlen; + } + else +#endif + { + *dst++ = *src; + ++dstlen; + } + ++src; + } + *dst = '\0'; + ++dstlen; + } + else { + while (--srclen >= 0) { +#if defined(__unix__) + if (*src == '\r') + ++dstlen; + else +#elif defined(__WIN32__) + if (*src == '\r') { + ++dstlen; + ++dstlen; + } + else +#endif + { + ++dstlen; + } + ++src; + } + ++dstlen; + } + break; + default: + if (dst) { + *(int *)dst = srclen; + dst += sizeof(int); + memcpy(dst, src, srclen); + } + dstlen = sizeof(int)+srclen; + break; + } + return(dstlen); +} + +/* Convert scrap data to internal format */ +static int convert_scrap(int type, char *dst, char *src, int srclen) +{ + int dstlen; + + dstlen = 0; + switch (type) { + case T('T', 'E', 'X', 'T'): + { + if (srclen == 0) + srclen = strlen(src); + if (dst) { + while (--srclen >= 0) { +#if defined(__WIN32__) + if (*src == '\r') + /* drop extraneous '\r' */; + else +#endif + if (*src == '\n') { + *dst++ = '\r'; + ++dstlen; + } + else { + *dst++ = *src; + ++dstlen; + } + ++src; + } + *dst = '\0'; + ++dstlen; + } + else { + while (--srclen >= 0) { +#if defined(__WIN32__) + /* drop extraneous '\r' */; + if (*src != '\r') +#endif + ++dstlen; + ++src; + } + ++dstlen; + } + break; + } + default: + dstlen = *(int *)src; + if (dst) + memcpy(dst, src + sizeof(int), + srclen ? srclen - sizeof(int) : dstlen); + break; + } + return dstlen; +} + +int init_scrap(void) +{ + SDL_SysWMinfo info; + int retval; + + /* Grab the window manager specific information */ + retval = -1; + SDL_SetError("SDL is not running on known window manager"); + + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info)) { + /* Save the information for later use */ +#if defined(X11_SCRAP) + if (info.subsystem == SDL_SYSWM_X11) { + SDL_Display = info.info.x11.display; + SDL_Window = info.info.x11.window; + Lock_Display = info.info.x11.lock_func; + Unlock_Display = info.info.x11.unlock_func; + + /* Enable the special window hook events */ + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + SDL_SetEventFilter(clipboard_filter); + + XA_TARGETS = XInternAtom(SDL_Display, "TARGETS", False); + XA_TEXT = XInternAtom(SDL_Display, "TEXT", False); + XA_COMPOUND_TEXT = XInternAtom(SDL_Display, + "COMPOUND_TEXT", False); + XA_UTF8_STRING = XInternAtom(SDL_Display, + "UTF8_STRING", False); + + retval = 0; + } + else + SDL_SetError("SDL is not running on X11"); +#elif defined(WIN_SCRAP) + SDL_Window = info.window; + retval = 0; +#elif defined(QNX_SCRAP) + InputGroup = PhInputGroup(NULL); + retval = 0; +#endif /* scrap type */ + } + return(retval); +} + +int lost_scrap(void) +{ + int retval; + +#if defined(X11_SCRAP) + if (Lock_Display) + Lock_Display(); + retval = (XGetSelectionOwner(SDL_Display, XA_PRIMARY) != SDL_Window); + if (Unlock_Display) + Unlock_Display(); +#elif defined(WIN_SCRAP) + retval = (GetClipboardOwner() != SDL_Window); +#elif defined(QNX_SCRAP) + retval = (PhInputGroup(NULL) != InputGroup); +#endif /* scrap type */ + + return(retval); +} + +void put_scrap(int type, int srclen, const char *src) +{ + scrap_type format; + int dstlen; + char *dst; + + format = convert_format(type); + dstlen = convert_data(type, NULL, src, srclen); + +#if defined(X11_SCRAP) + dst = (char *)malloc(dstlen); + if (dst != NULL) { + if (Lock_Display) + Lock_Display(); + convert_data(type, dst, src, srclen); + XChangeProperty(SDL_Display, DefaultRootWindow(SDL_Display), + XA_CUT_BUFFER0, format, 8, PropModeReplace, + (unsigned char *)dst, dstlen); + free(dst); + if (lost_scrap()) + XSetSelectionOwner(SDL_Display, XA_PRIMARY, + SDL_Window, CurrentTime); + if (Unlock_Display) + Unlock_Display(); + } +#elif defined(WIN_SCRAP) + if (OpenClipboard(SDL_Window)) { + HANDLE hMem; + + hMem = GlobalAlloc((GMEM_MOVEABLE|GMEM_DDESHARE), dstlen); + if (hMem != NULL) { + dst = (char *)GlobalLock(hMem); + convert_data(type, dst, src, srclen); + GlobalUnlock(hMem); + EmptyClipboard(); + SetClipboardData(format, hMem); + } + CloseClipboard(); + } +#elif defined(QNX_SCRAP) +#if (_NTO_VERSION < 620) /* before 6.2.0 releases */ +#define PhClipboardHdr PhClipHeader +#endif + { + PhClipboardHdr clheader = { Ph_CLIPBOARD_TYPE_TEXT, 0, NULL }; + int* cldata; + int status; + + dst = (char *)malloc(dstlen+4); + if (dst != NULL) { + cldata = (int*)dst; + *cldata = type; + convert_data(type, dst+4, src, srclen); + clheader.data = dst; +#if (_NTO_VERSION < 620) /* before 6.2.0 releases */ + if (dstlen > 65535) + /* maximum photon clipboard size :(*/ + clheader.length = 65535; + else +#endif + clheader.length = dstlen+4; + status = PhClipboardCopy(InputGroup, 1, &clheader); + if (status == -1) + fprintf(stderr, + "Photon: copy to clipboard failed!\n"); + free(dst); + } + } +#endif /* scrap type */ +} + +void get_scrap(int type, int *dstlen, char **dst) +{ + scrap_type format; + + *dstlen = 0; + format = convert_format(type); + +#if defined(X11_SCRAP) + { + Window owner; + Atom selection; + Atom seln_type; + int seln_format; + unsigned long nbytes; + unsigned long overflow; + char *src; + + if (Lock_Display) + Lock_Display(); + owner = XGetSelectionOwner(SDL_Display, XA_PRIMARY); + if (Unlock_Display) + Unlock_Display(); + if ((owner == None) || (owner == SDL_Window)) { + owner = DefaultRootWindow(SDL_Display); + selection = XA_CUT_BUFFER0; + } + else { + int selection_response = 0; + SDL_Event event; + + owner = SDL_Window; + if (Lock_Display) + Lock_Display(); + selection = XInternAtom(SDL_Display, "SDL_SELECTION", + False); + XConvertSelection(SDL_Display, XA_PRIMARY, format, + selection, owner, CurrentTime); + if (Unlock_Display) + Unlock_Display(); + while (!selection_response) { + SDL_WaitEvent(&event); + if (event.type == SDL_SYSWMEVENT) { + XEvent xevent = + event.syswm.msg->event.xevent; + + if ((xevent.type == SelectionNotify) && + (xevent.xselection.requestor + == owner)) + selection_response = 1; + } + } + } + if (Lock_Display) + Lock_Display(); + if (XGetWindowProperty(SDL_Display, owner, selection, + 0, INT_MAX/4, False, format, &seln_type, + &seln_format, &nbytes, &overflow, + (unsigned char **)&src) == Success) { + if (seln_type == format) { + *dstlen = convert_scrap(type, NULL, + src, nbytes); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, src, nbytes); + } + XFree(src); + } + } + if (Unlock_Display) + Unlock_Display(); +#elif defined(WIN_SCRAP) + if (IsClipboardFormatAvailable(format) && OpenClipboard(SDL_Window)) { + HANDLE hMem; + char *src; + + hMem = GetClipboardData(format); + if (hMem != NULL) { + src = (char *)GlobalLock(hMem); + *dstlen = convert_scrap(type, NULL, src, 0); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, src, 0); + GlobalUnlock(hMem); + } + CloseClipboard(); + } +#elif defined(QNX_SCRAP) +#if (_NTO_VERSION < 620) /* before 6.2.0 releases */ + { + void* clhandle; + PhClipHeader* clheader; + int* cldata; + + clhandle = PhClipboardPasteStart(InputGroup); + if (clhandle != NULL) { + clheader = PhClipboardPasteType(clhandle, + Ph_CLIPBOARD_TYPE_TEXT); + if (clheader != NULL) { + cldata = clheader->data; + if ((clheader->length>4) && (*cldata == type)) { + *dstlen = convert_scrap(type, NULL, + (char*)clheader->data+4, + clheader->length-4); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, + (char*)clheader->data+4, + clheader->length-4); + } + } + PhClipboardPasteFinish(clhandle); + } + } +#else /* 6.2.0 and 6.2.1 and future releases */ + { + void* clhandle; + PhClipboardHdr* clheader; + int* cldata; + + clheader=PhClipboardRead(InputGroup, Ph_CLIPBOARD_TYPE_TEXT); + if (clheader!=NULL) { + cldata=clheader->data; + if ((clheader->length>4) && (*cldata==type)) { + *dstlen = convert_scrap(type, NULL, + (char*)clheader->data+4, + clheader->length-4); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, + (char*)clheader->data+4, + clheader->length-4); + } + } + } +#endif +#endif /* scrap type */ +} + +int clipboard_filter(const SDL_Event *event) +{ +#if defined(X11_SCRAP) + /* Post all non-window manager specific events */ + if (event->type != SDL_SYSWMEVENT) + return(1); + + /* Handle window-manager specific clipboard events */ + switch (event->syswm.msg->event.xevent.type) { + /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ + case SelectionRequest: { + XSelectionRequestEvent *req; + XEvent sevent; + int seln_format; + unsigned long nbytes; + unsigned long overflow; + unsigned char *seln_data; + + req = &event->syswm.msg->event.xevent.xselectionrequest; + if (req->target == XA_TARGETS) { + Atom supported[] = { + XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING, + XA_TARGETS, XA_STRING + }; + XEvent response; + + XChangeProperty(SDL_Display, req->requestor, + req->property, req->target, 32, PropModeReplace, + (unsigned char*)supported, + sizeof(supported) / sizeof(supported[0])); + response.xselection.property=None; + response.xselection.type= SelectionNotify; + response.xselection.display= req->display; + response.xselection.requestor= req->requestor; + response.xselection.selection=req->selection; + response.xselection.target= req->target; + response.xselection.time = req->time; + XSendEvent (SDL_Display, req->requestor,0,0,&response); + XFlush (SDL_Display); + return 1; + } + + sevent.xselection.type = SelectionNotify; + sevent.xselection.display = req->display; + sevent.xselection.selection = req->selection; + sevent.xselection.target = None; + sevent.xselection.property = req->property; + sevent.xselection.requestor = req->requestor; + sevent.xselection.time = req->time; + if (XGetWindowProperty(SDL_Display, + DefaultRootWindow(SDL_Display), XA_CUT_BUFFER0, + 0, INT_MAX/4, False, req->target, + &sevent.xselection.target, &seln_format, + &nbytes, &overflow, &seln_data) == Success) { + if (sevent.xselection.target == req->target) { + if (sevent.xselection.target == XA_STRING && + nbytes > 0 && + seln_data[nbytes-1] == '\0') + --nbytes; + XChangeProperty(SDL_Display, req->requestor, + req->property, sevent.xselection.target, + seln_format, PropModeReplace, + seln_data, nbytes); + sevent.xselection.property = req->property; + } + XFree(seln_data); + } + XSendEvent(SDL_Display,req->requestor,False,0,&sevent); + XSync(SDL_Display, False); + break; + } + } + /* Post the event for X11 clipboard reading above */ +#endif /* X11_SCRAP */ + return(1); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.h b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.h new file mode 100755 index 0000000..647bd74 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.h @@ -0,0 +1,18 @@ +/* Handle clipboard text and data in arbitrary formats */ + +/* Miscellaneous defines */ +#define T(A, B, C, D) (int)((A<<24)|(B<<16)|(C<<8)|(D<<0)) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern int init_scrap(void); +extern int lost_scrap(void); +extern void put_scrap(int type, int srclen, const char *src); +extern void get_scrap(int type, int *dstlen, char **dst); +extern int clipboard_filter(const SDL_Event *event); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/vnc2mpg.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/vnc2mpg.c new file mode 100755 index 0000000..57fe1a8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/vnc2mpg.c @@ -0,0 +1,435 @@ +/* + * Simple movie writer for vnc; based on Libavformat API example from FFMPEG + * + * Copyright (c) 2003 Fabrice Bellard, 2004 Johannes E. Schindelin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.1415926535897931 +#endif + +#include "avformat.h" +#include + +#define STREAM_FRAME_RATE 25 /* 25 images/s */ + +/**************************************************************/ +/* video output */ + +AVFrame *picture, *tmp_picture; +uint8_t *video_outbuf; +int frame_count, video_outbuf_size; + +/* add a video output stream */ +AVStream *add_video_stream(AVFormatContext *oc, int codec_id, int w, int h) +{ + AVCodecContext *c; + AVStream *st; + + st = av_new_stream(oc, 0); + if (!st) { + fprintf(stderr, "Could not alloc stream\n"); + exit(1); + } + +#if LIBAVFORMAT_BUILD<4629 + c = &st->codec; +#else + c = st->codec; +#endif + c->codec_id = codec_id; + c->codec_type = CODEC_TYPE_VIDEO; + + /* put sample parameters */ + c->bit_rate = 800000; + /* resolution must be a multiple of two */ + c->width = w; + c->height = h; + /* frames per second */ +#if LIBAVCODEC_BUILD<4754 + c->frame_rate = STREAM_FRAME_RATE; + c->frame_rate_base = 1; +#else + c->time_base.den = STREAM_FRAME_RATE; + c->time_base.num = 1; + c->pix_fmt = PIX_FMT_YUV420P; +#endif + c->gop_size = 12; /* emit one intra frame every twelve frames at most */ + if (c->codec_id == CODEC_ID_MPEG2VIDEO) { + /* just for testing, we also add B frames */ + c->max_b_frames = 2; + } + if (c->codec_id == CODEC_ID_MPEG1VIDEO){ + /* needed to avoid using macroblocks in which some coeffs overflow + this doesnt happen with normal video, it just happens here as the + motion of the chroma plane doesnt match the luma plane */ + c->mb_decision=2; + } + /* some formats want stream headers to be seperate */ + if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp")) + c->flags |= CODEC_FLAG_GLOBAL_HEADER; + + return st; +} + +AVFrame *alloc_picture(int pix_fmt, int width, int height) +{ + AVFrame *picture; + uint8_t *picture_buf; + int size; + + picture = avcodec_alloc_frame(); + if (!picture) + return NULL; + size = avpicture_get_size(pix_fmt, width, height); + picture_buf = malloc(size); + if (!picture_buf) { + av_free(picture); + return NULL; + } + avpicture_fill((AVPicture *)picture, picture_buf, + pix_fmt, width, height); + return picture; +} + +void open_video(AVFormatContext *oc, AVStream *st) +{ + AVCodec *codec; + AVCodecContext *c; + +#if LIBAVFORMAT_BUILD<4629 + c = &st->codec; +#else + c = st->codec; +#endif + + /* find the video encoder */ + codec = avcodec_find_encoder(c->codec_id); + if (!codec) { + fprintf(stderr, "codec not found\n"); + exit(1); + } + + /* open the codec */ + if (avcodec_open(c, codec) < 0) { + fprintf(stderr, "could not open codec\n"); + exit(1); + } + + video_outbuf = NULL; + if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { + /* allocate output buffer */ + /* XXX: API change will be done */ + video_outbuf_size = 200000; + video_outbuf = malloc(video_outbuf_size); + } + + /* allocate the encoded raw picture */ + picture = alloc_picture(c->pix_fmt, c->width, c->height); + if (!picture) { + fprintf(stderr, "Could not allocate picture\n"); + exit(1); + } + + /* if the output format is not RGB565, then a temporary RGB565 + picture is needed too. It is then converted to the required + output format */ + tmp_picture = NULL; + if (c->pix_fmt != PIX_FMT_RGB565) { + tmp_picture = alloc_picture(PIX_FMT_RGB565, c->width, c->height); + if (!tmp_picture) { + fprintf(stderr, "Could not allocate temporary picture\n"); + exit(1); + } + } +} + +void write_video_frame(AVFormatContext *oc, AVStream *st) +{ + int out_size, ret; + AVCodecContext *c; + AVFrame *picture_ptr; + +#if LIBAVFORMAT_BUILD<4629 + c = &st->codec; +#else + c = st->codec; +#endif + + if (c->pix_fmt != PIX_FMT_RGB565) { + /* as we only generate a RGB565 picture, we must convert it + to the codec pixel format if needed */ + img_convert((AVPicture *)picture, c->pix_fmt, + (AVPicture *)tmp_picture, PIX_FMT_RGB565, + c->width, c->height); + } + picture_ptr = picture; + + + if (oc->oformat->flags & AVFMT_RAWPICTURE) { + /* raw video case. The API will change slightly in the near + futur for that */ + AVPacket pkt; + av_init_packet(&pkt); + + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index= st->index; + pkt.data= (uint8_t *)picture_ptr; + pkt.size= sizeof(AVPicture); + + ret = av_write_frame(oc, &pkt); + } else { + /* encode the image */ + out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture_ptr); + /* if zero size, it means the image was buffered */ + if (out_size != 0) { + AVPacket pkt; + av_init_packet(&pkt); + + pkt.pts= c->coded_frame->pts; + if(c->coded_frame->key_frame) + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index= st->index; + pkt.data= video_outbuf; + pkt.size= out_size; + + /* write the compressed frame in the media file */ + ret = av_write_frame(oc, &pkt); + } else { + ret = 0; + } + } + if (ret != 0) { + fprintf(stderr, "Error while writing video frame\n"); + exit(1); + } + frame_count++; +} + +void close_video(AVFormatContext *oc, AVStream *st) +{ + avcodec_close(st->codec); + av_free(picture->data[0]); + av_free(picture); + if (tmp_picture) { + av_free(tmp_picture->data[0]); + av_free(tmp_picture); + } + av_free(video_outbuf); +} + +static const char *filename; +static AVOutputFormat *fmt; +static AVFormatContext *oc; +static AVStream *video_st; +static double video_pts; + +static int movie_open(int w, int h) { + if (fmt->video_codec != CODEC_ID_NONE) { + video_st = add_video_stream(oc, fmt->video_codec, w, h); + } else + return 1; + + /* set the output parameters (must be done even if no + parameters). */ + if (av_set_parameters(oc, NULL) < 0) { + fprintf(stderr, "Invalid output format parameters\n"); + return 2; + } + + dump_format(oc, 0, filename, 1); + + /* now that all the parameters are set, we can open the audio and + video codecs and allocate the necessary encode buffers */ + if (video_st) + open_video(oc, video_st); + + /* open the output file, if needed */ + if (!(fmt->flags & AVFMT_NOFILE)) { + if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) { + fprintf(stderr, "Could not open '%s'\n", filename); + return 3; + } + } + + /* write the stream header, if any */ + av_write_header(oc); + + return 0; +} + +static int movie_close() { + int i; + + /* close each codec */ + close_video(oc, video_st); + + /* write the trailer, if any */ + av_write_trailer(oc); + + /* free the streams */ + for(i = 0; i < oc->nb_streams; i++) { + av_freep(&oc->streams[i]); + } + + if (!(fmt->flags & AVFMT_NOFILE)) { + /* close the output file */ + url_fclose(&oc->pb); + } + + /* free the stream */ + av_free(oc); + +} + +static rfbBool quit=FALSE; +static void signal_handler(int signal) { + fprintf(stderr,"Cleaning up.\n"); + quit=TRUE; +} + +/**************************************************************/ +/* VNC callback functions */ +static rfbBool resize(rfbClient* client) { + static rfbBool first=TRUE; + if(!first) { + movie_close(); + perror("I don't know yet how to change resolutions!\n"); + } + movie_open(client->width, client->height); + signal(SIGINT,signal_handler); + if(tmp_picture) + client->frameBuffer=tmp_picture->data[0]; + else + client->frameBuffer=picture->data[0]; + return TRUE; +} + +static void update(rfbClient* client,int x,int y,int w,int h) { +} + +/**************************************************************/ +/* media file output */ + +int main(int argc, char **argv) +{ + time_t stop=0; + rfbClient* client; + int i,j; + + /* get a vnc client structure (don't connect yet). */ + client = rfbGetClient(5,3,2); + client->format.redShift=11; client->format.redMax=31; + client->format.greenShift=5; client->format.greenMax=63; + client->format.blueShift=0; client->format.blueMax=31; + + /* initialize libavcodec, and register all codecs and formats */ + av_register_all(); + + if(!strncmp(argv[argc-1],":",1) || + !strncmp(argv[argc-1],"127.0.0.1",9) || + !strncmp(argv[argc-1],"localhost",9)) + client->appData.encodingsString="raw"; + + filename=0; + for(i=1;ii+1 && !strcmp("-o",argv[i])) { + filename=argv[2]; + j+=2; + } else if(argc>i+1 && !strcmp("-t",argv[i])) { + stop=time(0)+atoi(argv[i+1]); + j+=2; + } + if(j>i) { + argc-=j-i; + memmove(argv+i,argv+j,(argc-i)*sizeof(char*)); + i--; + } + } + + + /* auto detect the output format from the name. default is + mpeg. */ + fmt = filename?guess_format(NULL, filename, NULL):0; + if (!fmt) { + printf("Could not deduce output format from file extension: using MPEG.\n"); + fmt = guess_format("mpeg", NULL, NULL); + } + if (!fmt) { + fprintf(stderr, "Could not find suitable output format\n"); + exit(1); + } + + /* allocate the output media context */ + oc = av_alloc_format_context(); + if (!oc) { + fprintf(stderr, "Memory error\n"); + exit(1); + } + oc->oformat = fmt; + snprintf(oc->filename, sizeof(oc->filename), "%s", filename); + + /* add the audio and video streams using the default format codecs + and initialize the codecs */ + video_st = NULL; + + /* open VNC connection */ + client->MallocFrameBuffer=resize; + client->GotFrameBufferUpdate=update; + if(!rfbInitClient(client,&argc,argv)) { + printf("usage: %s [-o output_file] [-t seconds] server:port\n" + "Shoot a movie from a VNC server.\n", argv[0]); + exit(1); + } + if(client->serverPort==-1) + client->vncRec->doNotSleep = TRUE; /* vncrec playback */ + + /* main loop */ + + while(!quit) { + int i=WaitForMessage(client,1000000/STREAM_FRAME_RATE); + if(i<0) { + movie_close(); + return 0; + } + if(i) + if(!HandleRFBServerMessage(client)) + quit=TRUE; + else { + /* compute current audio and video time */ + video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; + + /* write interleaved audio and video frames */ + write_video_frame(oc, video_st); + } + if(stop!=0 && stop]) + + if test "x$with_fbpm" != "xno"; then + AC_CHECK_LIB(Xext, FBPMForceLevel, + [AC_DEFINE(HAVE_FBPM)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_dpms" != "xno"; then + AC_CHECK_LIB(Xext, DPMSForceLevel, + [AC_DEFINE(HAVE_DPMS)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + AC_CHECK_LIB(Xtst, XTestGrabControl, + X_PRELIBS="-lXtst $X_PRELIBS" + [AC_DEFINE(HAVE_XTESTGRABCONTROL) HAVE_XTESTGRABCONTROL="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + + AC_CHECK_LIB(Xtst, XTestFakeKeyEvent, + X_PRELIBS="-lXtst $X_PRELIBS" + [AC_DEFINE(HAVE_XTEST) HAVE_XTEST="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + + if test "x$with_xrecord" != "xno"; then + AC_CHECK_LIB(Xtst, XRecordEnableContextAsync, + X_PRELIBS="-lXtst $X_PRELIBS" + [AC_DEFINE(HAVE_RECORD)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + # we use XTRAP on X11R5, or user can set X11VNC_USE_XTRAP + if test "x$with_xtrap" != "xno"; then + if test ! -z "$X11VNC_USE_XTRAP" -o -z "$HAVE_XTESTGRABCONTROL"; then + AC_CHECK_LIB(XTrap, XETrapSetGrabServer, + X_PRELIBS="$X_PRELIBS -lXTrap" + [AC_DEFINE(HAVE_LIBXTRAP)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + # tru64 uses libXETrap.so + AC_CHECK_LIB(XETrap, XETrapSetGrabServer, + X_PRELIBS="$X_PRELIBS -lXETrap" + [AC_DEFINE(HAVE_LIBXTRAP)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + fi + + if test "x$with_xkeyboard" != "xno"; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + AC_CHECK_HEADER(X11/XKBlib.h, HAVE_XKBLIB_H="true", + HAVE_XKBLIB_H="false", [#include ]) + CPPFLAGS="$saved_CPPFLAGS" + if test $HAVE_XKBLIB_H = "true"; then + AC_CHECK_LIB(X11, XkbSelectEvents, + [AC_DEFINE(HAVE_XKEYBOARD)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + fi + + if test "x$with_xinerama" != "xno"; then + AC_CHECK_LIB(Xinerama, XineramaQueryScreens, + X_PRELIBS="$X_PRELIBS -lXinerama" + [AC_DEFINE(HAVE_LIBXINERAMA)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_xrandr" != "xno"; then + AC_CHECK_LIB(Xrandr, XRRSelectInput, + X_PRELIBS="$X_PRELIBS -lXrandr" + [AC_DEFINE(HAVE_LIBXRANDR) HAVE_LIBXRANDR="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_xfixes" != "xno"; then + AC_CHECK_LIB(Xfixes, XFixesGetCursorImage, + X_PRELIBS="$X_PRELIBS -lXfixes" + [AC_DEFINE(HAVE_LIBXFIXES) HAVE_LIBXFIXES="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_xdamage" != "xno"; then + AC_CHECK_LIB(Xdamage, XDamageQueryExtension, + X_PRELIBS="$X_PRELIBS -lXdamage" + [AC_DEFINE(HAVE_LIBXDAMAGE) HAVE_LIBXDAMAGE="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test ! -z "$HAVE_LIBXFIXES" -o ! -z "$HAVE_LIBXDAMAGE"; then + # need /usr/sfw/lib in RPATH for Solaris 10 and later + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) X_EXTRA_LIBS="$X_EXTRA_LIBS -R/usr/sfw/lib" ;; + esac + fi + if test ! -z "$HAVE_LIBXRANDR"; then + # also need /usr/X11/include for Solaris 10 10/08 and later + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) CPPFLAGS="$CPPFLAGS -I/usr/X11/include" ;; + esac + fi + + X_LIBS="$X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS" + fi + # end x11vnc only. +fi + +AC_SUBST(X_LIBS) +AM_CONDITIONAL(HAVE_X11, test $HAVE_X11 != "false") + +# x11vnc only: +if test "$build_x11vnc" = "yes"; then + +if test "x$HAVE_X11" = "xfalse" -a "x$with_x" != "xno"; then + AC_MSG_ERROR([ +========================================================================== +*** A working X window system build environment is required to build *** +x11vnc. Make sure any required X development packages are installed. +If they are installed in non-standard locations, one can use the +--x-includes=DIR and --x-libraries=DIR configure options or set the +CPPFLAGS and LDFLAGS environment variables to indicate where the X +window system header files and libraries may be found. On 64+32 bit +machines you may need to point to lib64 or lib32 directories to pick up +the correct word size. + +If you want to build x11vnc without X support (e.g. for -rawfb use only +or for native Mac OS X), specify the --without-x configure option. +========================================================================== +]) +fi + +if test "x$HAVE_X11" = "xtrue" -a "x$HAVE_XTEST" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** A working build environment for the XTEST extension was not found *** +(libXtst). An x11vnc built this way will be *ONLY BARELY USABLE*. +You will be able to move the mouse but not click or type. There can +also be deadlocks if an application grabs the X server. + +It is recommended that you install the necessary development packages +for XTEST (perhaps it is named something like libxtst-dev) and run +configure again. +========================================================================== +]) + sleep 5 +fi + +# set some ld -R nonsense +# +uname_s=`(uname -s) 2>/dev/null` +ld_minus_R="yes" +if test "x$uname_s" = "xHP-UX"; then + ld_minus_R="no" +elif test "x$uname_s" = "xOSF1"; then + ld_minus_R="no" +elif test "x$uname_s" = "xDarwin"; then + ld_minus_R="no" +fi + +if test "x$with_v4l" != "xno"; then + AC_CHECK_HEADER(linux/videodev.h, + [AC_DEFINE(HAVE_LINUX_VIDEODEV_H)],,) +fi +if test "x$with_fbdev" != "xno"; then + AC_CHECK_HEADER(linux/fb.h, + [AC_DEFINE(HAVE_LINUX_FB_H)],,) +fi +if test "x$with_uinput" != "xno"; then + AC_CHECK_HEADER(linux/input.h, + [AC_DEFINE(HAVE_LINUX_INPUT_H) HAVE_LINUX_INPUT_H="true"],,) + if test "x$HAVE_LINUX_INPUT_H" = "xtrue"; then + AC_CHECK_HEADER(linux/uinput.h, + [AC_DEFINE(HAVE_LINUX_UINPUT_H)],, [#include ]) + fi +fi + +if test "x$with_macosx_native" != "xno"; then + AC_DEFINE(HAVE_MACOSX_NATIVE_DISPLAY) +fi + +AH_TEMPLATE(HAVE_AVAHI, [Avahi/mDNS client build environment present]) +AC_ARG_WITH(avahi, +[ --without-avahi disable support for Avahi/mDNS] +[ --with-avahi=DIR use avahi include/library files in DIR],,) +if test "x$with_avahi" != "xno"; then + printf "checking for avahi... " + if test ! -z "$with_avahi" -a "x$with_avahi" != "xyes"; then + AVAHI_CFLAGS="-I$with_avahi/include" + AVAHI_LIBS="-L$with_avahi/lib -lavahi-common -lavahi-client" + echo "using $with_avahi" + with_avahi=yes + elif pkg-config --atleast-version=0.6.4 avahi-client >/dev/null 2>&1; then + AVAHI_CFLAGS=`pkg-config --cflags avahi-client` + AVAHI_LIBS=`pkg-config --libs avahi-client` + with_avahi=yes + echo yes + else + with_avahi=no + echo no + fi +fi +if test "x$with_avahi" = "xyes"; then + AC_DEFINE(HAVE_AVAHI) + AC_SUBST(AVAHI_CFLAGS) + AC_SUBST(AVAHI_LIBS) +fi + +fi +# end x11vnc only. + + +AH_TEMPLATE(HAVE_LIBCRYPT, [libcrypt library present]) +AC_ARG_WITH(crypt, +[ --without-crypt disable support for libcrypt],,) +if test "x$with_crypt" != "xno"; then + AC_CHECK_FUNCS([crypt], HAVE_LIBC_CRYPT="true") + if test -z "$HAVE_LIBC_CRYPT"; then + AC_CHECK_LIB(crypt, crypt, + CRYPT_LIBS="-lcrypt" + [AC_DEFINE(HAVE_LIBCRYPT)], ,) + fi +fi +AC_SUBST(CRYPT_LIBS) + +# some OS's need both -lssl and -lcrypto on link line: +AH_TEMPLATE(HAVE_LIBCRYPTO, [openssl libcrypto library present]) +AC_ARG_WITH(crypto, +[ --without-crypto disable support for openssl libcrypto],,) + +AH_TEMPLATE(HAVE_LIBSSL, [openssl libssl library present]) +AC_ARG_WITH(ssl, +[ --without-ssl disable support for openssl libssl] +[ --with-ssl=DIR use openssl include/library files in DIR],,) + +if test "x$with_crypto" != "xno" -a "x$with_ssl" != "xno"; then + if test ! -z "$with_ssl" -a "x$with_ssl" != "xyes"; then + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_ssl/include" + LDFLAGS="$LDFLAGS -L$with_ssl/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + LDFLAGS="$LDFLAGS -Xlinker -R$with_ssl/lib" + else + LDFLAGS="$LDFLAGS -R$with_ssl/lib" + fi + fi + AC_CHECK_LIB(crypto, RAND_file_name, + [AC_DEFINE(HAVE_LIBCRYPTO) HAVE_LIBCRYPTO="true"], ,) + if test ! -z "$with_ssl" -a "x$with_ssl" != "xyes"; then + if test "x$HAVE_LIBCRYPTO" != "xtrue"; then + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi +fi + +AH_TEMPLATE(HAVE_X509_PRINT_EX_FP, [open ssl X509_print_ex_fp available]) +if test "x$with_ssl" != "xno"; then + if test "x$HAVE_LIBCRYPTO" = "xtrue"; then + AC_CHECK_LIB(ssl, SSL_library_init, + SSL_LIBS="-lssl -lcrypto" + [AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], , + -lcrypto) + else + AC_CHECK_LIB(ssl, SSL_library_init, + SSL_LIBS="-lssl" + [AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,) + fi +fi +AC_SUBST(SSL_LIBS) + + if test "x$HAVE_LIBSSL" != "xtrue" -a "x$with_ssl" != "xno"; then + AC_MSG_WARN([ +========================================================================== +*** The openssl encryption library libssl.so was not found. *** +An x11vnc built this way will not support SSL encryption. To enable +SSL install the necessary development packages (perhaps it is named +something like libssl-dev) and run configure again. +========================================================================== +]) + sleep 5 + elif test "x$with_ssl" != "xno"; then + AC_CHECK_LIB(ssl, X509_print_ex_fp, + [AC_DEFINE(HAVE_X509_PRINT_EX_FP) HAVE_X509_PRINT_EX_FP="true"], , $SSL_LIBS + ) + fi + + +# Checks for libraries. + +if test ! -z "$with_system_libvncserver" -a "x$with_system_libvncserver" != "xno"; then + printf "checking for system libvncserver... " + vneed="0.9.1" + if test "X$VNEED" != "X"; then + vneed=$VNEED + fi + if test "x$with_system_libvncserver" != "xyes"; then + rflag="" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + rflag="-Xlinker -R$with_system_libvncserver/lib" + else + rflag="-R$with_system_libvncserver/lib" + fi + cmd="$with_system_libvncserver/bin/libvncserver-config" + if $cmd --version 1>/dev/null 2>&1; then + cvers=`$cmd --version 2>/dev/null` + cscore=`echo "$cvers" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + nscore=`echo "$vneed" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + + if test $cscore -lt $nscore; then + echo "no" + with_system_libvncserver=no + AC_MSG_ERROR([ +========================================================================== +*** Need libvncserver version $vneed, have version $cvers *** +You are building with a system installed libvncserver and it is not +new enough. +========================================================================== +]) + else + SYSTEM_LIBVNCSERVER_CFLAGS="-I$with_system_libvncserver/include" + SYSTEM_LIBVNCSERVER_LIBS="-L$with_system_libvncserver/lib $rflag -lvncserver -lvncclient" + echo "using $with_system_libvncserver" + with_system_libvncserver=yes + fi + else + echo " *** cannot run $cmd *** " 1>&2 + with_system_libvncserver=no + echo no + fi + elif libvncserver-config --version 1>/dev/null 2>&1; then + rflag="" + rprefix=`libvncserver-config --prefix` + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + rflag=" -Xlinker -R$rprefix/lib " + else + rflag=" -R$rprefix/lib " + fi + cvers=`libvncserver-config --version 2>/dev/null` + cscore=`echo "$cvers" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + nscore=`echo "$vneed" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + + if test $cscore -lt $nscore; then + echo "no" + AC_MSG_ERROR([ +========================================================================== +*** Need libvncserver version $vneed, have version $cvers *** +You are building with a system installed libvncserver and it is not +new enough. +========================================================================== +]) + else + SYSTEM_LIBVNCSERVER_CFLAGS=`libvncserver-config --cflags` + SYSTEM_LIBVNCSERVER_LIBS="$rflag"`libvncserver-config --libs` + with_system_libvncserver=yes + echo yes + fi + else + with_system_libvncserver=no + echo no + fi +fi + +if test "x$with_system_libvncserver" = "xyes"; then + AC_DEFINE(HAVE_SYSTEM_LIBVNCSERVER) + AC_SUBST(SYSTEM_LIBVNCSERVER_CFLAGS) + AC_SUBST(SYSTEM_LIBVNCSERVER_LIBS) +fi +AM_CONDITIONAL(HAVE_SYSTEM_LIBVNCSERVER, test "x$with_system_libvncserver" = "xyes") + + +AC_ARG_WITH(jpeg, +[ --without-jpeg disable support for jpeg] +[ --with-jpeg=DIR use jpeg include/library files in DIR],,) + +# At this point: +# no jpeg on command line with_jpeg="" +# -with-jpeg with_jpeg="yes" +# -without-jpeg with_jpeg="no" +# -with-jpeg=/foo/dir with_jpeg="/foo/dir" + +if test "x$with_jpeg" != "xno"; then + if test ! -z "$with_jpeg" -a "x$with_jpeg" != "xyes"; then + # add user supplied directory to flags: + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_jpeg/include" + LDFLAGS="$LDFLAGS -L$with_jpeg/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + # this is not complete... in general a rat's nest. + LDFLAGS="$LDFLAGS -Xlinker -R$with_jpeg/lib" + else + LDFLAGS="$LDFLAGS -R$with_jpeg/lib" + fi + fi + AC_CHECK_HEADER(jpeglib.h, HAVE_JPEGLIB_H="true") + if test "x$HAVE_JPEGLIB_H" = "xtrue"; then + AC_CHECK_LIB(jpeg, jpeg_CreateCompress, , HAVE_JPEGLIB_H="") + fi + if test ! -z "$with_jpeg" -a "x$with_jpeg" != "xyes"; then + if test "x$HAVE_JPEGLIB_H" != "xtrue"; then + # restore old flags on failure: + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi + if test "$build_x11vnc" = "yes"; then + if test "x$HAVE_JPEGLIB_H" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** The libjpeg compression library was not found. *** +This may lead to reduced performance, especially over slow links. +If libjpeg is in a non-standard location use --with-jpeg=DIR to +indicate the header file is in DIR/include/jpeglib.h and the library +in DIR/lib/libjpeg.a. A copy of libjpeg may be obtained from: +ftp://ftp.uu.net/graphics/jpeg/ +========================================================================== +]) + sleep 5 + fi + fi +fi + +AC_ARG_WITH(png, +[ --without-png disable support for png] +[ --with-png=DIR use png include/library files in DIR],,) + +# At this point: +# no png on command line with_png="" +# -with-png with_png="yes" +# -without-png with_png="no" +# -with-png=/foo/dir with_png="/foo/dir" + +if test "x$with_png" != "xno"; then + if test ! -z "$with_png" -a "x$with_png" != "xyes"; then + # add user supplied directory to flags: + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_png/include" + LDFLAGS="$LDFLAGS -L$with_png/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + # this is not complete... in general a rat's nest. + LDFLAGS="$LDFLAGS -Xlinker -R$with_png/lib" + else + LDFLAGS="$LDFLAGS -R$with_png/lib" + fi + fi + AC_CHECK_HEADER(png.h, HAVE_PNGLIB_H="true") + if test "x$HAVE_PNGLIB_H" = "xtrue"; then + AC_CHECK_LIB(png, png_create_write_struct, , HAVE_PNGLIB_H="") + fi + if test ! -z "$with_png" -a "x$with_png" != "xyes"; then + if test "x$HAVE_PNGLIB_H" != "xtrue"; then + # restore old flags on failure: + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi + if test "$build_x11vnc" = "yes"; then + if test "x$HAVE_PNGLIB_H" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** The libpng compression library was not found. *** +This may lead to reduced performance, especially over slow links. +If libpng is in a non-standard location use --with-png=DIR to +indicate the header file is in DIR/include/png.h and the library +in DIR/lib/libpng.a. A copy of libpng may be obtained from: +http://www.libpng.org/pub/png/libpng.html +========================================================================== +]) + sleep 5 + fi + fi +fi + +AC_ARG_WITH(libz, +[ --without-libz disable support for deflate],,) +AC_ARG_WITH(zlib, +[ --without-zlib disable support for deflate] +[ --with-zlib=DIR use zlib include/library files in DIR],,) + +if test "x$with_zlib" != "xno" -a "x$with_libz" != "xno"; then + if test ! -z "$with_zlib" -a "x$with_zlib" != "xyes"; then + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_zlib/include" + LDFLAGS="$LDFLAGS -L$with_zlib/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + LDFLAGS="$LDFLAGS -Xlinker -R$with_zlib/lib" + else + LDFLAGS="$LDFLAGS -R$with_zlib/lib" + fi + fi + AC_CHECK_HEADER(zlib.h, HAVE_ZLIB_H="true") + if test "x$HAVE_ZLIB_H" = "xtrue"; then + AC_CHECK_LIB(z, deflate, , HAVE_ZLIB_H="") + fi + if test ! -z "$with_zlib" -a "x$with_zlib" != "xyes"; then + if test "x$HAVE_ZLIB_H" != "xtrue"; then + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi + if test "$build_x11vnc" = "yes"; then + if test "x$HAVE_ZLIB_H" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** The libz compression library was not found. *** +This may lead to reduced performance, especially over slow links. +If libz is in a non-standard location use --with-zlib=DIR to indicate the +header file is in DIR/include/zlib.h and the library in DIR/lib/libz.a. +A copy of libz may be obtained from: http://www.gzip.org/zlib/ +========================================================================== +]) + sleep 5 + fi + fi +fi + +AC_ARG_WITH(pthread, +[ --without-pthread disable support for libpthread],,) + +if test "x$with_pthread" != "xno"; then + AC_CHECK_HEADER(pthread.h, HAVE_PTHREAD_H="true") + if test ! -z "$HAVE_PTHREAD_H"; then + AC_CHECK_LIB(pthread, pthread_mutex_lock) + AC_CHECK_LIB(pthread, pthread_mutex_lock, HAVE_LIBPTHREAD="true") + fi +fi +AM_CONDITIONAL(HAVE_LIBPTHREAD, test ! -z "$HAVE_LIBPTHREAD") + +AC_MSG_CHECKING([for __thread]) +AC_LINK_IFELSE([AC_LANG_PROGRAM(, [static __thread int p = 0])], + [AC_DEFINE(HAVE_TLS, 1, + Define to 1 if compiler supports __thread) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + +# tightvnc-filetransfer implemented using threads: +if test -z "$HAVE_LIBPTHREAD"; then + with_tightvnc_filetransfer="" +fi +if test "x$with_tightvnc_filetransfer" = "xyes"; then + AC_DEFINE(WITH_TIGHTVNC_FILETRANSFER) +fi +AM_CONDITIONAL(WITH_TIGHTVNC_FILETRANSFER, test "$with_tightvnc_filetransfer" = "yes") + +# websockets implemented using base64 from resolve +if test "x$HAVE_B64" != "xtrue"; then + with_websockets="" +fi +if test "x$with_websockets" = "xyes"; then + LIBS="$LIBS -lresolv" + AC_DEFINE(WITH_WEBSOCKETS) +fi +AM_CONDITIONAL(WITH_WEBSOCKETS, test "$with_websockets" = "yes") + +AM_CONDITIONAL(HAVE_LIBZ, test ! -z "$HAVE_ZLIB_H") +AM_CONDITIONAL(HAVE_LIBJPEG, test ! -z "$HAVE_JPEGLIB_H") +AM_CONDITIONAL(HAVE_LIBPNG, test ! -z "$HAVE_PNGLIB_H") + + +SDLCONFIG="sdl-config" +AC_ARG_WITH(sdl-config, +[[ --with-sdl-config=FILE + Use the given path to sdl-config when determining + SDL configuration; defaults to "sdl-config"]], +[ + if test "$withval" != "yes" -a "$withval" != ""; then + SDLCONFIG=$withval + fi +]) + +if test -z "$with_sdl"; then + if $SDLCONFIG --version >/dev/null 2>&1; then + with_sdl=yes + SDL_CFLAGS=`$SDLCONFIG --cflags` + SDL_LIBS=`$SDLCONFIG --libs` + else + with_sdl=no + fi +fi +AM_CONDITIONAL(HAVE_LIBSDL, test "x$with_sdl" = "xyes") +AC_SUBST(SDL_CFLAGS) +AC_SUBST(SDL_LIBS) + + +AC_CANONICAL_HOST +MINGW=`echo $host_os | grep mingw32 2>/dev/null` +AM_CONDITIONAL(MINGW, test ! -z "$MINGW" ) +if test ! -z "$MINGW"; then + WSOCKLIB="-lws2_32" +fi +AC_SUBST(WSOCKLIB) + +# Checks for GnuTLS +AH_TEMPLATE(WITH_CLIENT_TLS, [Enable support for gnutls in libvncclient]) +AC_ARG_WITH(gnutls, +[ --without-gnutls disable support for gnutls],,) +AC_ARG_WITH(client-tls, +[ --without-client-tls disable support for gnutls in libvncclient],,) + +if test "x$with_gnutls" != "xno"; then + PKG_CHECK_MODULES(GNUTLS, gnutls >= 2.4.0, , with_client_tls=no) + CFLAGS="$CFLAGS $GNUTLS_CFLAGS" + LIBS="$LIBS $GNUTLS_LIBS" + if test "x$with_client_tls" != "xno"; then + AC_DEFINE(WITH_CLIENT_TLS) + fi +fi + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h]) + +# x11vnc only: +if test "$build_x11vnc" = "yes"; then + AC_CHECK_HEADERS([pwd.h sys/wait.h utmpx.h termios.h sys/ioctl.h sys/stropts.h]) +fi + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_C_BIGENDIAN +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_HEADER_SYS_WAIT +AC_TYPE_SOCKLEN_T +if test ! -d ./rfb; then + echo "creating subdir ./rfb for rfbint.h" + mkdir ./rfb +fi +AC_CREATE_STDINT_H(rfb/rfbint.h) +AC_CACHE_CHECK([for in_addr_t], + vnc_cv_inaddrt, [ + AC_TRY_COMPILE([#include +#include ], + [in_addr_t foo; return 0;], + [inaddrt=yes], + [inaddrt=no]), + ]) +AH_TEMPLATE(NEED_INADDR_T, [Need a typedef for in_addr_t]) +if test $inaddrt = no ; then + AC_DEFINE(NEED_INADDR_T) +fi + +# Checks for library functions. +AC_FUNC_MEMCMP +AC_FUNC_STAT +AC_FUNC_STRFTIME +AC_FUNC_VPRINTF +AC_FUNC_FORK +AC_CHECK_LIB(nsl,gethostbyname) +AC_CHECK_LIB(socket,socket) + +uname_s=`(uname -s) 2>/dev/null` +if test "x$uname_s" = "xHP-UX"; then + # need -lsec for getspnam() + LDFLAGS="$LDFLAGS -lsec" +fi + +AC_CHECK_FUNCS([ftime gethostbyname gethostname gettimeofday inet_ntoa memmove memset mmap mkfifo select socket strchr strcspn strdup strerror strstr]) +# x11vnc only: +if test "$build_x11vnc" = "yes"; then + AC_CHECK_FUNCS([setsid setpgrp getpwuid getpwnam getspnam getuid geteuid setuid setgid seteuid setegid initgroups waitpid setutxent grantpt shmat]) +fi + +# check, if shmget is in cygipc.a +AC_CHECK_LIB(cygipc,shmget) +AM_CONDITIONAL(CYGIPC, test "$HAVE_CYGIPC" = "true") + +# Check if /dev/vcsa1 exists, if so, define LINUX +AM_CONDITIONAL(LINUX, test -c /dev/vcsa1) + +# Check for OS X specific header +AC_CHECK_HEADER(ApplicationServices/ApplicationServices.h, HAVE_OSX="true") +AM_CONDITIONAL(OSX, test "$HAVE_OSX" = "true") + +# On Solaris 2.7, write() returns ENOENT when it really means EAGAIN +AH_TEMPLATE(ENOENT_WORKAROUND, [work around when write() returns ENOENT but does not mean it]) +case `(uname -sr) 2>/dev/null` in + "SunOS 5.7") + AC_DEFINE(ENOENT_WORKAROUND) + ;; +esac + +# Check for rpm SOURCES path +printf "checking for rpm sources path... " +RPMSOURCEDIR="NOT-FOUND" +for directory in packages OpenLinux redhat RedHat rpm RPM "" ; do + if test -d /usr/src/${directory}/SOURCES; then + RPMSOURCEDIR="/usr/src/${directory}/SOURCES/" + fi +done +echo "$RPMSOURCEDIR" +AM_CONDITIONAL(HAVE_RPM, test "$RPMSOURCEDIR" != "NOT-FOUND") +AM_CONDITIONAL(WITH_X11VNC, test "$build_x11vnc" = "yes") +AC_SUBST(RPMSOURCEDIR) + +AC_CONFIG_FILES([Makefile + libvncserver/Makefile + contrib/Makefile + examples/Makefile + vncterm/Makefile + classes/Makefile + classes/ssl/Makefile + libvncclient/Makefile + client_examples/Makefile + test/Makefile + libvncserver-config + LibVNCServer.spec]) +# +# x11vnc only: +# +if test "$build_x11vnc" = "yes"; then + # + # NOTE: if you are using the LibVNCServer-X.Y.Z.tar.gz source + # tarball and nevertheless want to run autoconf (i.e. aclocal, + # autoheader, automake, autoconf) AGAIN (perhaps you have a + # special target system, e.g. embedded) then you will need to + # comment out the following 'AC_CONFIG_FILES' line to avoid + # automake error messages like: + # + # configure.ac:690: required file `x11vnc/Makefile.in' not found + # + AC_CONFIG_FILES([x11vnc/Makefile x11vnc/misc/Makefile x11vnc/misc/turbovnc/Makefile]) +fi + +AC_CONFIG_COMMANDS([chmod-libvncserver-config],[chmod a+x libvncserver-config]) +AC_OUTPUT +chmod a+x ./libvncserver-config + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/consolefont2c.pl b/droidvncgrab/vnc/libvncserver-kanaka/consolefont2c.pl new file mode 100755 index 0000000..9196649 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/consolefont2c.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +# convert a linux console font (8x16 format) to a font definition +# suitable for processing with LibVNCServer + +#if($#ARGV == 0) { exit; } + +foreach $i (@ARGV) { + $fontname = $i; + $fontname =~ s/\.fnt$//; + $fontname =~ s/^.*\///g; + $fontname =~ y/+/_/; + + print STDERR "$i -> $fontname\n"; + + open IN, "<$i"; + print STDERR read(IN,$x,4096); + close(IN); + + open OUT, ">$fontname.h"; + print OUT "unsigned char ".$fontname."FontData[4096+1]={"; + for($i=0;$i<4096;$i++) { + if(($i%16)==0) { + print OUT "\n"; + } + printf OUT "0x%02x,", ord(substr($x,$i)); + } + + print OUT "\n};\nint ".$fontname."FontMetaData[256*5+1]={\n"; + for($i=0;$i<256;$i++) { + print OUT ($i*16).",8,16,0,0,"; + } + + print OUT "};\nrfbFontData ".$fontname."Font = { ".$fontname."FontData, " + .$fontname."FontMetaData };\n"; + + close OUT; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/contrib/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/contrib/.cvsignore new file mode 100755 index 0000000..4bb318a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/contrib/.cvsignore @@ -0,0 +1,6 @@ +Makefile +Makefile.in +x11vnc +zippy +.deps + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/contrib/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/contrib/Makefile.am new file mode 100755 index 0000000..637fea7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/contrib/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I$(top_srcdir) +LDADD = ../libvncserver/libvncserver.la @WSOCKLIB@ + +noinst_PROGRAMS=zippy + +zippy_SOURCES=zippy.c + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/contrib/zippy.c b/droidvncgrab/vnc/libvncserver-kanaka/contrib/zippy.c new file mode 100755 index 0000000..d8a90d7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/contrib/zippy.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include + +static int maxx=400, maxy=400, bpp=4; +/* odd maxx doesn't work (vncviewer bug) */ + +/* Here we create a structure so that every client has it's own pointer */ + +/* turns the framebuffer black */ +void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2); +/* displays a red bar, a green bar, and a blue bar */ +void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2); +void linecount (char* frame_buffer); +/* handles mouse events */ +void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl); +/* handles keyboard events */ +void on_key_press (rfbBool down,rfbKeySym key,rfbClientPtr cl); + +int main (int argc, char **argv) +{ + rfbScreenInfoPtr server; + + if(!rfbProcessSizeArguments(&maxx,&maxy,&bpp,&argc,argv)) + return 1; + + server = rfbGetScreen (&argc, argv, maxx, maxy, 8, 3, bpp); + server->desktopName = "Zippy das wundersquirrel\'s VNC server"; + server->frameBuffer = (char*)malloc(maxx*maxy*bpp); + server->alwaysShared = TRUE; + server->kbdAddEvent = on_key_press; + server->ptrAddEvent = on_mouse_event; + + rfbInitServer (server); + + blank_framebuffer(server->frameBuffer, 0, 0, maxx, maxy); + rfbRunEventLoop (server, -1, FALSE); + free(server->frameBuffer); + rfbScreenCleanup (server); + return 0; +} + +void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2) +{ + int i; + for (i=0; i < maxx * maxy * bpp; i++) frame_buffer[i]=(char) 0; +} + +void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2) +{ + int i, j, current_pixel; + for (i=y1; i < y2; i++){ + for (j=x1; j < x2; j++) { + current_pixel = (i*x2 + j) * bpp; + if (i < y2 ) { + frame_buffer[current_pixel+0] = (char) 128; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 0; + } + if (i < y2/3*2) { + frame_buffer[current_pixel+0] = (char) 0; + frame_buffer[current_pixel+1] = (char) 128; + frame_buffer[current_pixel+2] = (char) 0; + } + if (i < y2/3) { + frame_buffer[current_pixel+0] = (char) 0; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 128; + } + } + } + } + +/* Dscho's versions (slower, but works for bpp != 3 or 4) */ +static void draw_primary_colours_generic(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2) +{ + rfbPixelFormat f=s->serverFormat; + int i,j; + for(j=y1;jserverFormat; + int i,j,y3=(y1*2+y2)/3,y4=(y1+y2*2)/3; + /* draw first pixel */ + rfbDrawPixel(s,x1,y1,f.redMax<frameBuffer+(x)*bpp+(y)*s->paddedWidthInBytes + memcpy(ADDR(i,j+y1),ADDR(x1,y1),bpp); + memcpy(ADDR(i,j+y3),ADDR(x1,y3),bpp); + memcpy(ADDR(i,j+y4),ADDR(x1,y4),bpp); + } +} + +static void draw_primary_colours_generic_ultrafast(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2) +{ + rfbPixelFormat f=s->serverFormat; + int y3=(y1*2+y2)/3,y4=(y1+y2*2)/3; + /* fill rectangles */ + rfbFillRect(s,x1,y1,x2,y3,f.redMax<maxy-20; i-=4) + for (j=0; j<4; j++) for (k=0; k < maxx; k++) { + current_pixel = (i*j*maxx + k) * bpp; + if (i%2 == 0) { + frame_buffer[current_pixel+0] = (char) 0; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 128; + } + + if (i%2 == 1) { + frame_buffer[current_pixel+0] = (char) 128; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 0; + } + } + +} + + +void on_key_press (rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if (down) /* or else the action occurs on both the press and depress */ + switch (key) { + + case XK_b: + case XK_B: + blank_framebuffer(cl->screen->frameBuffer, 0, 0, maxx, maxy); + rfbDrawString(cl->screen,&default8x16Font,20,maxy-20,"Hello, World!",0xffffff); + rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy); + rfbLog("Framebuffer blanked\n"); + break; + case XK_p: + case XK_P: + /* draw_primary_colors (cl->screen->frameBuffer, 0, 0, maxx, maxy); */ + draw_primary_colours_generic_ultrafast (cl->screen, 0, 0, maxx, maxy); + rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy); + rfbLog("Primary colors displayed\n"); + break; + case XK_Q: + case XK_q: + rfbLog("Exiting now\n"); + exit(0); + case XK_C: + case XK_c: + rfbDrawString(cl->screen,&default8x16Font,20,100,"Hello, World!",0xffffff); + rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy); + break; + default: + rfbLog("The %c key was pressed\n", (char) key); + } +} + + +void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl) +{ + printf("buttonMask: %i\n" + "x: %i\n" "y: %i\n", buttonMask, x, y); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/cvs_update_anonymously b/droidvncgrab/vnc/libvncserver-kanaka/cvs_update_anonymously new file mode 100755 index 0000000..bbe3c77 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/cvs_update_anonymously @@ -0,0 +1,13 @@ +#!/bin/bash + +case "$1" in +#cvs --help-commands 2>&1 | sed "s/[ ][ ]*/ /g" | cut -d " " -f 2 +add|admin|annotate|checkout|commit|diff|edit|editors|export|history|import|\ +init|log|login|logout|pserver|rdiff|release|remove|rtag|server|status|\ +tag|unedit|update|watch|watchers) + cmd="$1"; shift;; +*) cmd=update;; +esac + +cvs -z3 -d :pserver:anonymous@cvs.libvncserver.sf.net:/cvsroot/libvncserver $cmd "$@" + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/examples/.cvsignore new file mode 100755 index 0000000..88ce9f4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/.cvsignore @@ -0,0 +1,18 @@ +Makefile +*test +example +fontsel +pnmshow +pnmshow24 +storepasswd +vncev +Makefile.in +.deps +simple +simple15 +colourmaptest +regiontest +mac +filetransfer +backchannel +rotate diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/1instance.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/1instance.c new file mode 100755 index 0000000..f6c4315 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/1instance.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + char* filename; /* this file is the pipe (set by user) */ + char is_server; /* this is set by open_control_file */ + int fd; /* this is set by open_control_file */ +} single_instance_struct; + +/* returns fd, is_server is set to -1 if server, 0 if client */ +int open_control_file(single_instance_struct* str) +{ + struct stat buf; + + if(stat(str->filename,&buf)) { + mkfifo(str->filename,128|256); + str->is_server=-1; + str->fd=open(str->filename,O_NONBLOCK|O_RDONLY); + } else { + str->fd=open(str->filename,O_NONBLOCK|O_WRONLY); + if(errno==ENXIO) { + str->is_server=-1; + str->fd=open(str->filename,O_NONBLOCK|O_RDONLY); + } else + str->is_server=0; + } + + return(str->fd); +} + +void delete_control_file(single_instance_struct* str) +{ + remove(str->filename); +} + +void close_control_file(single_instance_struct* str) +{ + close(str->fd); +} + +typedef void (*event_dispatcher)(char* message); + +int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs) +{ + struct timeval tv; + fd_set fdset; + int num_fds; + + FD_ZERO(&fdset); + FD_SET(str->fd,&fdset); + tv.tv_sec=0; + tv.tv_usec=usecs; + + num_fds=select(str->fd+1,&fdset,NULL,NULL,&tv); + if(num_fds) { + int reallen; + + reallen=read(str->fd,buffer,len); + if(reallen==0) { + close(str->fd); + str->fd=open(str->filename,O_NONBLOCK|O_RDONLY); + num_fds--; + } + buffer[reallen]=0; +#ifdef DEBUG_1INSTANCE + if(reallen!=0) rfbLog("message received: %s.\n",buffer); +#endif + } + + return(num_fds); +} + +int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs) +{ + char buffer[1024]; + int num_fds; + + if((num_fds=get_next_message(buffer,1024,str,usecs)) && buffer[0]) + dispatcher(buffer); + + return(num_fds); +} + +int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher) +{ + open_control_file(str); + if(str->is_server) { + while(1) + dispatch_event(str,dispatcher,50); + } + + return(str->fd); +} + +void send_message(single_instance_struct* str,char* message) +{ +#ifdef DEBUG_1INSTANCE + int i= +#endif + write(str->fd,message,strlen(message)); +#ifdef DEBUG_1INSTANCE + rfbLog("send: %s => %d(%d)\n",message,i,strlen(message)); +#endif +} + +#ifdef DEBUG_MAIN + +#include +#include + +single_instance_struct str1 = { "/tmp/1instance" }; + +void my_dispatcher(char* message) +{ +#ifdef DEBUG_1INSTANCE + rfbLog("Message arrived: %s.\n",message); +#endif + if(!strcmp(message,"quit")) { + delete_control_file(str1); + exit(0); + } +} + +int main(int argc,char** argv) +{ + int i; + + loop_if_server(str1,my_dispatcher); + + for(i=1;i + +/* + * This is a simple example demonstrating a protocol extension. + * + * The "back channel" permits sending commands between client and server. + * It works by sending plain text messages. + * + * As suggested in the RFB protocol, the back channel is enabled by asking + * for a "pseudo encoding", and enabling the back channel on the client side + * as soon as it gets a back channel message from the server. + * + * This implements the server part. + * + * Note: If you design your own extension and want it to be useful for others, + * too, you should make sure that + * + * - your server as well as your client can speak to other clients and + * servers respectively (i.e. they are nice if they are talking to a + * program which does not know about your extension). + * + * - if the machine is little endian, all 16-bit and 32-bit integers are + * swapped before they are sent and after they are received. + * + */ + +#define rfbBackChannel 155 + +typedef struct backChannelMsg { + uint8_t type; + uint8_t pad1; + uint16_t pad2; + uint32_t size; +} backChannelMsg; + +rfbBool enableBackChannel(rfbClientPtr cl, void** data, int encoding) +{ + if(encoding == rfbBackChannel) { + backChannelMsg msg; + const char* text="Server acknowledges back channel encoding\n"; + uint32_t length = strlen(text)+1; + int n; + + rfbLog("Enabling the back channel\n"); + + msg.type = rfbBackChannel; + msg.size = Swap32IfLE(length); + if((n = rfbWriteExact(cl, (char*)&msg, sizeof(msg))) <= 0 || + (n = rfbWriteExact(cl, text, length)) <= 0) { + rfbLogPerror("enableBackChannel: write"); + } + return TRUE; + } + return FALSE; +} + +static rfbBool handleBackChannelMessage(rfbClientPtr cl, void* data, + const rfbClientToServerMsg* message) +{ + if(message->type == rfbBackChannel) { + backChannelMsg msg; + char* text; + int n; + if((n = rfbReadExact(cl, ((char*)&msg)+1, sizeof(backChannelMsg)-1)) <= 0) { + if(n != 0) + rfbLogPerror("handleBackChannelMessage: read"); + rfbCloseClient(cl); + return TRUE; + } + msg.size = Swap32IfLE(msg.size); + if((text = malloc(msg.size)) == NULL) { + rfbErr("Could not allocate %d bytes\n", msg.size); + return TRUE; + } + if((n = rfbReadExact(cl, text, msg.size)) <= 0) { + if(n != 0) + rfbLogPerror("handleBackChannelMessage: read"); + rfbCloseClient(cl); + return TRUE; + } + rfbLog("got message:\n%s\n", text); + free(text); + return TRUE; + } + return FALSE; +} + +static int backChannelEncodings[] = {rfbBackChannel, 0}; + +static rfbProtocolExtension backChannelExtension = { + NULL, /* newClient */ + NULL, /* init */ + backChannelEncodings, /* pseudoEncodings */ + enableBackChannel, /* enablePseudoEncoding */ + handleBackChannelMessage, /* handleMessage */ + NULL, /* close */ + NULL, /* usage */ + NULL, /* processArgument */ + NULL /* next extension */ +}; + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr server; + + rfbRegisterProtocolExtension(&backChannelExtension); + + server=rfbGetScreen(&argc,argv,400,300,8,3,4); + server->frameBuffer=(char*)malloc(400*300*4); + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/blooptest.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/blooptest.c new file mode 100755 index 0000000..f0e411c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/blooptest.c @@ -0,0 +1,2 @@ +#define BACKGROUND_LOOP_TEST +#include "example.c" diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/camera.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/camera.c new file mode 100755 index 0000000..23cb91a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/camera.c @@ -0,0 +1,152 @@ + +/* + * Question: I need to display a live camera image via VNC. Until now I just + * grab an image, set the rect to modified and do a 0.1 s sleep to give the + * system time to transfer the data. + * This is obviously a solution which doesn't scale very well to different + * connection speeds/cpu horsepowers, so I wonder if there is a way for the + * server application to determine if the updates have been sent. This would + * cause the live image update rate to always be the maximum the connection + * supports while avoiding excessive loads. + * + * Thanks in advance, + * + * + * Christian Daschill + * + * + * Answer: Originally, I thought about using seperate threads and using a + * mutex to determine when the frame buffer was being accessed by any client + * so we could determine a safe time to take a picture. The probem is, we + * are lock-stepping everything with framebuffer access. Why not be a + * single-thread application and in-between rfbProcessEvents perform a + * camera snapshot. And this is what I do here. It guarantees that the + * clients have been serviced before taking another picture. + * + * The downside to this approach is that the more clients you have, there is + * less time available for you to service the camera equating to reduced + * frame rate. (or, your clients are on really slow links). Increasing your + * systems ethernet transmit queues may help improve the overall performance + * as the libvncserver should not stall on transmitting to any single + * client. + * + * Another solution would be to provide a seperate framebuffer for each + * client and use mutexes to determine if any particular client is ready for + * a snapshot. This way, your not updating a framebuffer for a slow client + * while it is being transferred. + */ + +#include +#include +#include +#include + + +#define WIDTH 640 +#define HEIGHT 480 +#define BPP 4 + +/* 15 frames per second (if we can) */ +#define PICTURE_TIMEOUT (1.0/15.0) + + +/* + * throttle camera updates +*/ +int TimeToTakePicture() { + static struct timeval now={0,0}, then={0,0}; + double elapsed, dnow, dthen; + + gettimeofday(&now,NULL); + + dnow = now.tv_sec + (now.tv_usec /1000000.0); + dthen = then.tv_sec + (then.tv_usec/1000000.0); + elapsed = dnow - dthen; + + if (elapsed > PICTURE_TIMEOUT) + memcpy((char *)&then, (char *)&now, sizeof(struct timeval)); + return elapsed > PICTURE_TIMEOUT; +} + + + +/* + * simulate grabbing a picture from some device + */ +int TakePicture(unsigned char *buffer) +{ + static int last_line=0, fps=0, fcount=0; + int line=0; + int i,j; + struct timeval now; + + /* + * simulate grabbing data from a device by updating the entire framebuffer + */ + + for(j=0;jHEIGHT) line=HEIGHT-1; + memset(&buffer[(WIDTH * BPP) * line], 0, (WIDTH * BPP)); + + /* frames per second (informational only) */ + fcount++; + if (last_line > line) { + fps = fcount; + fcount = 0; + } + last_line = line; + fprintf(stderr,"%03d/%03d Picture (%03d fps)\r", line, HEIGHT, fps); + + /* success! We have a new picture! */ + return (1==1); +} + + + + +/* + * Single-threaded application that interleaves client servicing with taking + * pictures from the camera. This way, we do not update the framebuffer + * while an encoding is working on it too (banding, and image artifacts). + */ +int main(int argc,char** argv) +{ + long usec; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,WIDTH,HEIGHT,8,3,BPP); + server->desktopName = "Live Video Feed Example"; + server->frameBuffer=(char*)malloc(WIDTH*HEIGHT*BPP); + server->alwaysShared=(1==1); + + /* Initialize the server */ + rfbInitServer(server); + + /* Loop, processing clients and taking pictures */ + while (rfbIsActive(server)) { + if (TimeToTakePicture()) + if (TakePicture((unsigned char *)server->frameBuffer)) + rfbMarkRectAsModified(server,0,0,WIDTH,HEIGHT); + + usec = server->deferUpdateTime*1000; + rfbProcessEvents(server,usec); + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/colourmaptest.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/colourmaptest.c new file mode 100755 index 0000000..e403164 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/colourmaptest.c @@ -0,0 +1,32 @@ +#include + + +int main(int argc,char** argv) +{ + int i; + uint8_t bytes[256*3]; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,256,256,8,1,1); + + server->serverFormat.trueColour=FALSE; + server->colourMap.count=256; + server->colourMap.is16=FALSE; + for(i=0;i<256;i++) { + bytes[i*3+0]=255-i; /* red */ + bytes[i*3+1]=0; /* green */ + bytes[i*3+2]=i; /* blue */ + } + bytes[128*3+0]=0xff; + bytes[128*3+1]=0; + bytes[128*3+2]=0; + server->colourMap.data.bytes=bytes; + + server->frameBuffer=(char*)malloc(256*256); + for(i=0;i<256*256;i++) + server->frameBuffer[i]=(i/256); + + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/example.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.c new file mode 100755 index 0000000..871ab0c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.c @@ -0,0 +1,336 @@ +/* + * + * This is an example of how to use libvncserver. + * + * libvncserver example + * Copyright (C) 2001 Johannes E. Schindelin + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef WIN32 +#define sleep Sleep +#else +#include +#endif + +#ifdef __IRIX__ +#include +#endif + +#include +#include + +static const int bpp=4; +static int maxx=800, maxy=600; +/* TODO: odd maxx doesn't work (vncviewer bug) */ + +/* This initializes a nice (?) background */ + +static void initBuffer(unsigned char* buffer) +{ + int i,j; + for(j=0;jclientData); +} + +static enum rfbNewClientAction newclient(rfbClientPtr cl) +{ + cl->clientData = (void*)calloc(sizeof(ClientData),1); + cl->clientGoneHook = clientgone; + return RFB_CLIENT_ACCEPT; +} + +/* switch to new framebuffer contents */ + +static void newframebuffer(rfbScreenInfoPtr screen, int width, int height) +{ + unsigned char *oldfb, *newfb; + + maxx = width; + maxy = height; + oldfb = (unsigned char*)screen->frameBuffer; + newfb = (unsigned char*)malloc(maxx * maxy * bpp); + initBuffer(newfb); + rfbNewFramebuffer(screen, (char*)newfb, maxx, maxy, 8, 3, bpp); + free(oldfb); + + /*** FIXME: Re-install cursor. ***/ +} + +/* aux function to draw a line */ + +static void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2) +{ + int i,j; + i=x1-x2; j=y1-y2; + if(i==0 && j==0) { + for(i=0;iy2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; } + for(j=y1;j<=y2;j++) + for(i=0;ix2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; } + for(i=x1;i<=x2;i++) + for(j=0;jclientData; + + if(x>=0 && y>=0 && xoldButton==buttonMask) { /* draw a line */ + drawline((unsigned char*)cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp, + x,y,cd->oldx,cd->oldy); + x1=x; y1=y; + if(x1>cd->oldx) x1++; else cd->oldx++; + if(y1>cd->oldy) y1++; else cd->oldy++; + rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy); + } else { /* draw a point (diameter depends on button) */ + int w=cl->screen->paddedWidthInBytes; + x1=x-buttonMask; if(x1<0) x1=0; + x2=x+buttonMask; if(x2>maxx) x2=maxx; + y1=y-buttonMask; if(y1<0) y1=0; + y2=y+buttonMask; if(y2>maxy) y2=maxy; + + for(i=x1*bpp;iscreen->frameBuffer[j*w+i]=(char)0xff; + rfbMarkRectAsModified(cl->screen,x1,y1,x2,y2); + } + + /* we could get a selection like that: + rfbGotXCutText(cl->screen,"Hallo",5); + */ + } else + cd->oldButton=0; + + cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask; + } + rfbDefaultPtrAddEvent(buttonMask,x,y,cl); +} + +/* aux function to draw a character to x, y */ + +#include "radon.h" + +/* Here the key events are handled */ + +static void dokey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down) { + if(key==XK_Escape) + rfbCloseClient(cl); + else if(key==XK_F12) + /* close down server, disconnecting clients */ + rfbShutdownServer(cl->screen,TRUE); + else if(key==XK_F11) + /* close down server, but wait for all clients to disconnect */ + rfbShutdownServer(cl->screen,FALSE); + else if(key==XK_Page_Up) { + initBuffer((unsigned char*)cl->screen->frameBuffer); + rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy); + } else if (key == XK_Up) { + if (maxx < 1024) { + if (maxx < 800) { + newframebuffer(cl->screen, 800, 600); + } else { + newframebuffer(cl->screen, 1024, 768); + } + } + } else if(key==XK_Down) { + if (maxx > 640) { + if (maxx > 800) { + newframebuffer(cl->screen, 800, 600); + } else { + newframebuffer(cl->screen, 640, 480); + } + } + } else if(key>=' ' && key<0x100) { + ClientData* cd=cl->clientData; + int x1=cd->oldx,y1=cd->oldy,x2,y2; + cd->oldx+=rfbDrawCharWithClip(cl->screen,&radonFont,cd->oldx,cd->oldy,(char)key,0,0,cl->screen->width,cl->screen->height,0x00ffffff,0x00ffffff); + rfbFontBBox(&radonFont,(char)key,&x1,&y1,&x2,&y2); + rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1); + } + } +} + +/* Example for an XCursor (foreground/background only) */ + +#ifdef JUST_AN_EXAMPLE + +static int exampleXCursorWidth=9,exampleXCursorHeight=7; +static char exampleXCursor[]= + " " + " xx xx " + " xx xx " + " xxx " + " xx xx " + " xx xx " + " "; + +#endif + +/* Example for a rich cursor (full-colour) */ + +static void MakeRichCursor(rfbScreenInfoPtr rfbScreen) +{ + int i,j,w=32,h=32; + rfbCursorPtr c = rfbScreen->cursor; + char bitmap[]= + " " + " xxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxx xxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxx xxxxxxxxx xxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxx xxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxx xxxxxxxxxxxxxx " + " xxxxxxxxxx xxxxxxxxxxxx " + " xxxxxxxxx xxxxxxxxx " + " xxxxxxxxxx xxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxx " + " xxxx xxxxxxxxxxxxx " + " xx x xxxxxxxxxxx " + " xxx xxxxxxxxxxx " + " xxxx xxxxxxxxxxx " + " xxxxxx xxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxx " + " "; + c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap); + c->xhot = 16; c->yhot = 24; + + c->richSource = (unsigned char*)malloc(w*h*bpp); + c->cleanupRichSource = TRUE; + for(j=0;jrichSource[j*w*bpp+i*bpp+0]=i*0xff/w; + c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h); + c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h; + c->richSource[j*w*bpp+i*bpp+3]=0; + } + } +} + +/* Initialization */ + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr rfbScreen = + rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp); + rfbScreen->desktopName = "LibVNCServer Example"; + rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp); + rfbScreen->alwaysShared = TRUE; + rfbScreen->ptrAddEvent = doptr; + rfbScreen->kbdAddEvent = dokey; + rfbScreen->newClientHook = newclient; + rfbScreen->httpDir = "../classes"; + rfbScreen->httpEnableProxyConnect = TRUE; + + initBuffer((unsigned char*)rfbScreen->frameBuffer); + rfbDrawString(rfbScreen,&radonFont,20,100,"Hello, World!",0xffffff); + + /* This call creates a mask and then a cursor: */ + /* rfbScreen->defaultCursor = + rfbMakeXCursor(exampleCursorWidth,exampleCursorHeight,exampleCursor,0); + */ + + MakeRichCursor(rfbScreen); + + /* initialize the server */ + rfbInitServer(rfbScreen); + +#ifndef BACKGROUND_LOOP_TEST +#ifdef USE_OWN_LOOP + { + int i; + for(i=0;rfbIsActive(rfbScreen);i++) { + fprintf(stderr,"%d\r",i); + rfbProcessEvents(rfbScreen,100000); + } + } +#else + /* this is the blocking event loop, i.e. it never returns */ + /* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */ + rfbRunEventLoop(rfbScreen,40000,FALSE); +#endif /* OWN LOOP */ +#else +#if !defined(LIBVNCSERVER_HAVE_LIBPTHREAD) +#error "I need pthreads for that." +#endif + + /* this is the non-blocking event loop; a background thread is started */ + rfbRunEventLoop(rfbScreen,-1,TRUE); + fprintf(stderr, "Running background loop...\n"); + /* now we could do some cool things like rendering in idle time */ + while(1) sleep(5); /* render(); */ +#endif /* BACKGROUND_LOOP */ + + free(rfbScreen->frameBuffer); + rfbScreenCleanup(rfbScreen); + + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/example.dsp b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.dsp new file mode 100755 index 0000000..16788cb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.dsp @@ -0,0 +1,93 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=example - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "example.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "example - Win32 Release" (basierend auf "Win32 (x86) Console Application") +!MESSAGE "example - Win32 Debug" (basierend auf "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "zlib" /I "libjpeg" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib zlib.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"msvcrt.lib" + +!ELSEIF "$(CFG)" == "example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "zlib" /I "libjpeg" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "example - Win32 Release" +# Name "example - Win32 Debug" +# Begin Group "Sources" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\example.c +# End Source File +# End Group +# End Target +# End Project diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/filetransfer.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/filetransfer.c new file mode 100755 index 0000000..dacf73d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/filetransfer.c @@ -0,0 +1,11 @@ +#include + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4); + server->frameBuffer=(char*)malloc(400*300*4); + rfbRegisterTightVNCFileTransferExtension(); + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/fontsel.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/fontsel.c new file mode 100755 index 0000000..85d2624 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/fontsel.c @@ -0,0 +1,73 @@ +#include + +#define FONTDIR "/usr/lib/kbd/consolefonts/" +#define DEFAULTFONT FONTDIR "default8x16" + +static char *fontlist[50]={ +"8x16alt", "b.fnt", "c.fnt", "default8x16", "m.fnt", "ml.fnt", "mod_d.fnt", +"mod_s.fnt", "mr.fnt", "mu.fnt", "r.fnt", "rl.fnt", "ro.fnt", "s.fnt", +"sc.fnt", "scrawl_s.fnt", "scrawl_w.fnt", "sd.fnt", "t.fnt", + NULL +}; + +static rfbScreenInfoPtr rfbScreen = NULL; +static rfbFontDataPtr curFont = NULL; +static void showFont(int index) +{ + char buffer[1024]; + + if(!rfbScreen) return; + + if(curFont) + rfbFreeFont(curFont); + + strcpy(buffer,FONTDIR); + strcat(buffer,fontlist[index]); + curFont = rfbLoadConsoleFont(buffer); + + rfbFillRect(rfbScreen,210,30-20,210+10*16,30-20+256*20/16,0xb77797); + if(curFont) { + int i,j; + for(j=0;j<256;j+=16) + for(i=0;i<16;i++) + rfbDrawCharWithClip(rfbScreen,curFont,210+10*i,30+j*20/16,j+i, + 0,0,640,480,0xffffff,0x000000); + } +} + +int main(int argc,char** argv) +{ + rfbFontDataPtr font; + rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,640,480,8,3,3); + int i,j; + + s->frameBuffer=(char*)malloc(640*480*3); + rfbInitServer(s); + + for(j=0;j<480;j++) + for(i=0;i<640;i++) { + s->frameBuffer[(j*640+i)*3+0]=j*256/480; + s->frameBuffer[(j*640+i)*3+1]=i*256/640; + s->frameBuffer[(j*640+i)*3+2]=(i+j)*256/(480+640); + } + + rfbScreen = s; + font=rfbLoadConsoleFont(DEFAULTFONT); + if(!font) { + rfbErr("Couldn't find %s\n",DEFAULTFONT); + exit(1); + } + + for(j=0;j<0 && rfbIsActive(s);j++) + rfbProcessEvents(s,900000); + + i = rfbSelectBox(s,font,fontlist,10,20,200,300,0xffdfdf,0x602040,2,showFont); + rfbLog("Selection: %d: %s\n",i,(i>=0)?fontlist[i]:"cancelled"); + + rfbFreeFont(font); + free(s->frameBuffer); + rfbScreenCleanup(s); + + return(0); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/mac.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/mac.c new file mode 100755 index 0000000..2d335a4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/mac.c @@ -0,0 +1,551 @@ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * Cut in two parts by Johannes Schindelin (2001): libvncserver and OSXvnc. + * + * + * This file implements every system specific function for Mac OS X. + * + * It includes the keyboard functions: + * + void KbdAddEvent(down, keySym, cl) + rfbBool down; + rfbKeySym keySym; + rfbClientPtr cl; + void KbdReleaseAllKeys() + * + * the mouse functions: + * + void PtrAddEvent(buttonMask, x, y, cl) + int buttonMask; + int x; + int y; + rfbClientPtr cl; + * + */ + +#include +#include +#include +/* zlib doesn't like Byte already defined */ +#undef Byte +#undef TRUE +#undef rfbBool +#include +#include + +#include +#include +#include +#include +#include + +rfbBool rfbNoDimming = FALSE; +rfbBool rfbNoSleep = TRUE; + +static pthread_mutex_t dimming_mutex; +static unsigned long dim_time; +static unsigned long sleep_time; +static mach_port_t master_dev_port; +static io_connect_t power_mgt; +static rfbBool initialized = FALSE; +static rfbBool dim_time_saved = FALSE; +static rfbBool sleep_time_saved = FALSE; + +static int +saveDimSettings(void) +{ + if (IOPMGetAggressiveness(power_mgt, + kPMMinutesToDim, + &dim_time) != kIOReturnSuccess) + return -1; + + dim_time_saved = TRUE; + return 0; +} + +static int +restoreDimSettings(void) +{ + if (!dim_time_saved) + return -1; + + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToDim, + dim_time) != kIOReturnSuccess) + return -1; + + dim_time_saved = FALSE; + dim_time = 0; + return 0; +} + +static int +saveSleepSettings(void) +{ + if (IOPMGetAggressiveness(power_mgt, + kPMMinutesToSleep, + &sleep_time) != kIOReturnSuccess) + return -1; + + sleep_time_saved = TRUE; + return 0; +} + +static int +restoreSleepSettings(void) +{ + if (!sleep_time_saved) + return -1; + + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToSleep, + sleep_time) != kIOReturnSuccess) + return -1; + + sleep_time_saved = FALSE; + sleep_time = 0; + return 0; +} + + +int +rfbDimmingInit(void) +{ + pthread_mutex_init(&dimming_mutex, NULL); + + if (IOMasterPort(bootstrap_port, &master_dev_port) != kIOReturnSuccess) + return -1; + + if (!(power_mgt = IOPMFindPowerManagement(master_dev_port))) + return -1; + + if (rfbNoDimming) { + if (saveDimSettings() < 0) + return -1; + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToDim, 0) != kIOReturnSuccess) + return -1; + } + + if (rfbNoSleep) { + if (saveSleepSettings() < 0) + return -1; + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToSleep, 0) != kIOReturnSuccess) + return -1; + } + + initialized = TRUE; + return 0; +} + + +int +rfbUndim(void) +{ + int result = -1; + + pthread_mutex_lock(&dimming_mutex); + + if (!initialized) + goto DONE; + + if (!rfbNoDimming) { + if (saveDimSettings() < 0) + goto DONE; + if (IOPMSetAggressiveness(power_mgt, kPMMinutesToDim, 0) != kIOReturnSuccess) + goto DONE; + if (restoreDimSettings() < 0) + goto DONE; + } + + if (!rfbNoSleep) { + if (saveSleepSettings() < 0) + goto DONE; + if (IOPMSetAggressiveness(power_mgt, kPMMinutesToSleep, 0) != kIOReturnSuccess) + goto DONE; + if (restoreSleepSettings() < 0) + goto DONE; + } + + result = 0; + + DONE: + pthread_mutex_unlock(&dimming_mutex); + return result; +} + + +int +rfbDimmingShutdown(void) +{ + int result = -1; + + if (!initialized) + goto DONE; + + pthread_mutex_lock(&dimming_mutex); + if (dim_time_saved) + if (restoreDimSettings() < 0) + goto DONE; + if (sleep_time_saved) + if (restoreSleepSettings() < 0) + goto DONE; + + result = 0; + + DONE: + pthread_mutex_unlock(&dimming_mutex); + return result; +} + +rfbScreenInfoPtr rfbScreen; + +void rfbShutdown(rfbClientPtr cl); + +/* some variables to enable special behaviour */ +int startTime = -1, maxSecsToConnect = 0; +rfbBool disconnectAfterFirstClient = TRUE; + +/* Where do I get the "official" list of Mac key codes? + Ripped these out of a Mac II emulator called Basilisk II + that I found on the net. */ +static int keyTable[] = { + /* The alphabet */ + XK_A, 0, /* A */ + XK_B, 11, /* B */ + XK_C, 8, /* C */ + XK_D, 2, /* D */ + XK_E, 14, /* E */ + XK_F, 3, /* F */ + XK_G, 5, /* G */ + XK_H, 4, /* H */ + XK_I, 34, /* I */ + XK_J, 38, /* J */ + XK_K, 40, /* K */ + XK_L, 37, /* L */ + XK_M, 46, /* M */ + XK_N, 45, /* N */ + XK_O, 31, /* O */ + XK_P, 35, /* P */ + XK_Q, 12, /* Q */ + XK_R, 15, /* R */ + XK_S, 1, /* S */ + XK_T, 17, /* T */ + XK_U, 32, /* U */ + XK_V, 9, /* V */ + XK_W, 13, /* W */ + XK_X, 7, /* X */ + XK_Y, 16, /* Y */ + XK_Z, 6, /* Z */ + XK_a, 0, /* a */ + XK_b, 11, /* b */ + XK_c, 8, /* c */ + XK_d, 2, /* d */ + XK_e, 14, /* e */ + XK_f, 3, /* f */ + XK_g, 5, /* g */ + XK_h, 4, /* h */ + XK_i, 34, /* i */ + XK_j, 38, /* j */ + XK_k, 40, /* k */ + XK_l, 37, /* l */ + XK_m, 46, /* m */ + XK_n, 45, /* n */ + XK_o, 31, /* o */ + XK_p, 35, /* p */ + XK_q, 12, /* q */ + XK_r, 15, /* r */ + XK_s, 1, /* s */ + XK_t, 17, /* t */ + XK_u, 32, /* u */ + XK_v, 9, /* v */ + XK_w, 13, /* w */ + XK_x, 7, /* x */ + XK_y, 16, /* y */ + XK_z, 6, /* z */ + + /* Numbers */ + XK_0, 29, /* 0 */ + XK_1, 18, /* 1 */ + XK_2, 19, /* 2 */ + XK_3, 20, /* 3 */ + XK_4, 21, /* 4 */ + XK_5, 23, /* 5 */ + XK_6, 22, /* 6 */ + XK_7, 26, /* 7 */ + XK_8, 28, /* 8 */ + XK_9, 25, /* 9 */ + + /* Symbols */ + XK_exclam, 18, /* ! */ + XK_at, 19, /* @ */ + XK_numbersign, 20, /* # */ + XK_dollar, 21, /* $ */ + XK_percent, 23, /* % */ + XK_asciicircum, 22, /* ^ */ + XK_ampersand, 26, /* & */ + XK_asterisk, 28, /* * */ + XK_parenleft, 25, /* ( */ + XK_parenright, 29, /* ) */ + XK_minus, 27, /* - */ + XK_underscore, 27, /* _ */ + XK_equal, 24, /* = */ + XK_plus, 24, /* + */ + XK_grave, 10, /* ` */ /* XXX ? */ + XK_asciitilde, 10, /* ~ */ + XK_bracketleft, 33, /* [ */ + XK_braceleft, 33, /* { */ + XK_bracketright, 30, /* ] */ + XK_braceright, 30, /* } */ + XK_semicolon, 41, /* ; */ + XK_colon, 41, /* : */ + XK_apostrophe, 39, /* ' */ + XK_quotedbl, 39, /* " */ + XK_comma, 43, /* , */ + XK_less, 43, /* < */ + XK_period, 47, /* . */ + XK_greater, 47, /* > */ + XK_slash, 44, /* / */ + XK_question, 44, /* ? */ + XK_backslash, 42, /* \ */ + XK_bar, 42, /* | */ + + /* "Special" keys */ + XK_space, 49, /* Space */ + XK_Return, 36, /* Return */ + XK_Delete, 117, /* Delete */ + XK_Tab, 48, /* Tab */ + XK_Escape, 53, /* Esc */ + XK_Caps_Lock, 57, /* Caps Lock */ + XK_Num_Lock, 71, /* Num Lock */ + XK_Scroll_Lock, 107, /* Scroll Lock */ + XK_Pause, 113, /* Pause */ + XK_BackSpace, 51, /* Backspace */ + XK_Insert, 114, /* Insert */ + + /* Cursor movement */ + XK_Up, 126, /* Cursor Up */ + XK_Down, 125, /* Cursor Down */ + XK_Left, 123, /* Cursor Left */ + XK_Right, 124, /* Cursor Right */ + XK_Page_Up, 116, /* Page Up */ + XK_Page_Down, 121, /* Page Down */ + XK_Home, 115, /* Home */ + XK_End, 119, /* End */ + + /* Numeric keypad */ + XK_KP_0, 82, /* KP 0 */ + XK_KP_1, 83, /* KP 1 */ + XK_KP_2, 84, /* KP 2 */ + XK_KP_3, 85, /* KP 3 */ + XK_KP_4, 86, /* KP 4 */ + XK_KP_5, 87, /* KP 5 */ + XK_KP_6, 88, /* KP 6 */ + XK_KP_7, 89, /* KP 7 */ + XK_KP_8, 91, /* KP 8 */ + XK_KP_9, 92, /* KP 9 */ + XK_KP_Enter, 76, /* KP Enter */ + XK_KP_Decimal, 65, /* KP . */ + XK_KP_Add, 69, /* KP + */ + XK_KP_Subtract, 78, /* KP - */ + XK_KP_Multiply, 67, /* KP * */ + XK_KP_Divide, 75, /* KP / */ + + /* Function keys */ + XK_F1, 122, /* F1 */ + XK_F2, 120, /* F2 */ + XK_F3, 99, /* F3 */ + XK_F4, 118, /* F4 */ + XK_F5, 96, /* F5 */ + XK_F6, 97, /* F6 */ + XK_F7, 98, /* F7 */ + XK_F8, 100, /* F8 */ + XK_F9, 101, /* F9 */ + XK_F10, 109, /* F10 */ + XK_F11, 103, /* F11 */ + XK_F12, 111, /* F12 */ + + /* Modifier keys */ + XK_Shift_L, 56, /* Shift Left */ + XK_Shift_R, 56, /* Shift Right */ + XK_Control_L, 59, /* Ctrl Left */ + XK_Control_R, 59, /* Ctrl Right */ + XK_Meta_L, 58, /* Logo Left (-> Option) */ + XK_Meta_R, 58, /* Logo Right (-> Option) */ + XK_Alt_L, 55, /* Alt Left (-> Command) */ + XK_Alt_R, 55, /* Alt Right (-> Command) */ + + /* Weirdness I can't figure out */ +#if 0 + XK_3270_PrintScreen, 105, /* PrintScrn */ + ??? 94, 50, /* International */ + XK_Menu, 50, /* Menu (-> International) */ +#endif +}; + +void +KbdAddEvent(rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl) +{ + int i; + CGKeyCode keyCode = -1; + int found = 0; + + if(((int)cl->clientData)==-1) return; /* viewOnly */ + + rfbUndim(); + + for (i = 0; i < (sizeof(keyTable) / sizeof(int)); i += 2) { + if (keyTable[i] == keySym) { + keyCode = keyTable[i+1]; + found = 1; + break; + } + } + + if (!found) { + rfbErr("warning: couldn't figure out keycode for X keysym %d (0x%x)\n", + (int)keySym, (int)keySym); + } else { + /* Hopefully I can get away with not specifying a CGCharCode. + (Why would you need both?) */ + CGPostKeyboardEvent((CGCharCode)0, keyCode, down); + } +} + +void +PtrAddEvent(buttonMask, x, y, cl) + int buttonMask; + int x; + int y; + rfbClientPtr cl; +{ + CGPoint position; + + if(((int)cl->clientData)==-1) return; /* viewOnly */ + + rfbUndim(); + + position.x = x; + position.y = y; + + CGPostMouseEvent(position, TRUE, 8, + (buttonMask & (1 << 0)) ? TRUE : FALSE, + (buttonMask & (1 << 1)) ? TRUE : FALSE, + (buttonMask & (1 << 2)) ? TRUE : FALSE, + (buttonMask & (1 << 3)) ? TRUE : FALSE, + (buttonMask & (1 << 4)) ? TRUE : FALSE, + (buttonMask & (1 << 5)) ? TRUE : FALSE, + (buttonMask & (1 << 6)) ? TRUE : FALSE, + (buttonMask & (1 << 7)) ? TRUE : FALSE); +} + +rfbBool viewOnly = FALSE, sharedMode = FALSE; + +void +ScreenInit(int argc, char**argv) +{ + int bitsPerSample=CGDisplayBitsPerSample(kCGDirectMainDisplay); + rfbScreen = rfbGetScreen(&argc,argv, + CGDisplayPixelsWide(kCGDirectMainDisplay), + CGDisplayPixelsHigh(kCGDirectMainDisplay), + bitsPerSample, + CGDisplaySamplesPerPixel(kCGDirectMainDisplay),4); + rfbScreen->serverFormat.redShift = bitsPerSample*2; + rfbScreen->serverFormat.greenShift = bitsPerSample*1; + rfbScreen->serverFormat.blueShift = 0; + + gethostname(rfbScreen->thisHost, 255); + rfbScreen->paddedWidthInBytes = CGDisplayBytesPerRow(kCGDirectMainDisplay); + rfbScreen->frameBuffer = + (char *)CGDisplayBaseAddress(kCGDirectMainDisplay); + + /* we cannot write to the frame buffer */ + rfbScreen->cursor = NULL; + + rfbScreen->ptrAddEvent = PtrAddEvent; + rfbScreen->kbdAddEvent = KbdAddEvent; + + if(sharedMode) { + rfbScreen->alwaysShared = TRUE; + } + + rfbInitServer(rfbScreen); +} + +static void +refreshCallback(CGRectCount count, const CGRect *rectArray, void *ignore) +{ + int i; + + if(startTime>0 && time(0)>startTime+maxSecsToConnect) + rfbShutdown(0); + + for (i = 0; i < count; i++) + rfbMarkRectAsModified(rfbScreen, + rectArray[i].origin.x,rectArray[i].origin.y, + rectArray[i].origin.x + rectArray[i].size.width, + rectArray[i].origin.y + rectArray[i].size.height); +} + +void clientGone(rfbClientPtr cl) +{ + rfbShutdown(cl); +} + +enum rfbNewClientAction newClient(rfbClientPtr cl) +{ + if(startTime>0 && time(0)>startTime+maxSecsToConnect) + rfbShutdown(cl); + + if(disconnectAfterFirstClient) + cl->clientGoneHook = clientGone; + + cl->clientData=(void*)((viewOnly)?-1:0); + + return(RFB_CLIENT_ACCEPT); +} + +int main(int argc,char *argv[]) +{ + int i; + + for(i=argc-1;i>0;i--) + if(inewClientHook = newClient; + + /* enter background event loop */ + rfbRunEventLoop(rfbScreen,40,TRUE); + + /* enter OS X loop */ + CGRegisterScreenRefreshCallback(refreshCallback, NULL); + RunApplicationEventLoop(); + + rfbDimmingShutdown(); + + return(0); /* never ... */ +} + +void rfbShutdown(rfbClientPtr cl) +{ + rfbScreenCleanup(rfbScreen); + rfbDimmingShutdown(); + exit(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow.c new file mode 100755 index 0000000..6268577 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow.c @@ -0,0 +1,121 @@ +#include +#include +#include + +#ifndef HAVE_HANDLEKEY +static void HandleKey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down && (key==XK_Escape || key=='q' || key=='Q')) + rfbCloseClient(cl); +} +#endif + +int main(int argc,char** argv) +{ + FILE* in=stdin; + int i,j,k,l,width,height,paddedWidth; + char buffer[1024]; + rfbScreenInfoPtr rfbScreen; + enum { BW, GRAY, TRUECOLOUR } picType=TRUECOLOUR; + int bytesPerPixel,bitsPerPixelInFile; + + if(argc>1) { + in=fopen(argv[1],"rb"); + if(!in) { + printf("Couldn't find file %s.\n",argv[1]); + exit(1); + } + } + + fgets(buffer,1024,in); + if(!strncmp(buffer,"P6",2)) { + picType=TRUECOLOUR; + bytesPerPixel=4; bitsPerPixelInFile=3*8; + } else if(!strncmp(buffer,"P5",2)) { + picType=GRAY; + bytesPerPixel=1; bitsPerPixelInFile=1*8; + } else if(!strncmp(buffer,"P4",2)) { + picType=BW; + bytesPerPixel=1; bitsPerPixelInFile=1; + } else { + printf("Not a ppm.\n"); + exit(2); + } + + /* skip comments */ + do { + fgets(buffer,1024,in); + } while(buffer[0]=='#'); + + /* get width & height */ + sscanf(buffer,"%d %d",&width,&height); + rfbLog("Got width %d and height %d.\n",width,height); + if(picType!=BW) + fgets(buffer,1024,in); + else + width=1+((width-1)|7); + + /* vncviewers have problems with widths which are no multiple of 4. */ + paddedWidth = width; + if(width&3) + paddedWidth+=4-(width&3); + + /* initialize data for vnc server */ + rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,(bitsPerPixelInFile+7)/8,bytesPerPixel); + if(argc>1) + rfbScreen->desktopName = argv[1]; + else + rfbScreen->desktopName = "Picture"; + rfbScreen->alwaysShared = TRUE; + rfbScreen->kbdAddEvent = HandleKey; + + /* enable http */ + rfbScreen->httpDir = "../classes"; + + /* allocate picture and read it */ + rfbScreen->frameBuffer = (char*)malloc(paddedWidth*bytesPerPixel*height); + fread(rfbScreen->frameBuffer,width*bitsPerPixelInFile/8,height,in); + fclose(in); + + if(picType!=TRUECOLOUR) { + rfbScreen->serverFormat.trueColour=FALSE; + rfbScreen->colourMap.count=256; + rfbScreen->colourMap.is16=FALSE; + rfbScreen->colourMap.data.bytes=malloc(256*3); + for(i=0;i<256;i++) + memset(rfbScreen->colourMap.data.bytes+3*i,i,3); + } + + switch(picType) { + case TRUECOLOUR: + /* correct the format to 4 bytes instead of 3 (and pad to paddedWidth) */ + for(j=height-1;j>=0;j--) { + for(i=width-1;i>=0;i--) + for(k=2;k>=0;k--) + rfbScreen->frameBuffer[(j*paddedWidth+i)*4+k]= + rfbScreen->frameBuffer[(j*width+i)*3+k]; + for(i=width*4;iframeBuffer[j*paddedWidth*4+i]=0; + } + break; + case GRAY: + break; + case BW: + /* correct the format from 1 bit to 8 bits */ + for(j=height-1;j>=0;j--) + for(i=width-1;i>=0;i-=8) { + l=(unsigned char)rfbScreen->frameBuffer[(j*width+i)/8]; + for(k=7;k>=0;k--) + rfbScreen->frameBuffer[j*paddedWidth+i+7-k]=(l&(1< +#include +#include + +#ifndef LIBVNCSERVER_ALLOW24BPP +int main() { + printf("I need the ALLOW24BPP LibVNCServer flag to work\n"); + exit(1); +} +#else + +static void HandleKey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down && (key==XK_Escape || key=='q' || key=='Q')) + rfbCloseClient(cl); +} + +int main(int argc,char** argv) +{ + FILE* in=stdin; + int j,width,height,paddedWidth; + char buffer[1024]; + rfbScreenInfoPtr rfbScreen; + + if(argc>1) { + in=fopen(argv[1],"rb"); + if(!in) { + printf("Couldn't find file %s.\n",argv[1]); + exit(1); + } + } + + fgets(buffer,1024,in); + if(strncmp(buffer,"P6",2)) { + printf("Not a ppm.\n"); + exit(2); + } + + /* skip comments */ + do { + fgets(buffer,1024,in); + } while(buffer[0]=='#'); + + /* get width & height */ + sscanf(buffer,"%d %d",&width,&height); + rfbLog("Got width %d and height %d.\n",width,height); + fgets(buffer,1024,in); + + /* vncviewers have problems with widths which are no multiple of 4. */ + paddedWidth = width; + + /* if your vncviewer doesn't have problems with a width + which is not a multiple of 4, you can comment this. */ + if(width&3) + paddedWidth+=4-(width&3); + + /* initialize data for vnc server */ + rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,3,3); + if(argc>1) + rfbScreen->desktopName = argv[1]; + else + rfbScreen->desktopName = "Picture"; + rfbScreen->alwaysShared = TRUE; + rfbScreen->kbdAddEvent = HandleKey; + + /* enable http */ + rfbScreen->httpDir = "../classes"; + + /* allocate picture and read it */ + rfbScreen->frameBuffer = (char*)malloc(paddedWidth*3*height); + fread(rfbScreen->frameBuffer,width*3,height,in); + fclose(in); + + /* pad to paddedWidth */ + if(width != paddedWidth) { + int padCount = 3*(paddedWidth - width); + for(j=height-1;j>=0;j--) { + memmove(rfbScreen->frameBuffer+3*paddedWidth*j, + rfbScreen->frameBuffer+3*width*j, + 3*width); + memset(rfbScreen->frameBuffer+3*paddedWidth*(j+1)-padCount, + 0,padCount); + } + } + + /* initialize server */ + rfbInitServer(rfbScreen); + + /* run event loop */ + rfbRunEventLoop(rfbScreen,40000,FALSE); + + return(0); +} +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/radon.h b/droidvncgrab/vnc/libvncserver-kanaka/examples/radon.h new file mode 100755 index 0000000..b6209a9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/radon.h @@ -0,0 +1,195 @@ +static unsigned char radonFontData[2280]={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32 */ +0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x00,0x00, /* 33 */ +0x00,0x28,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 34 */ +0x00,0x44,0x44,0xba,0x44,0x44,0x44,0xba,0x44,0x44,0x00,0x00, /* 35 */ +0x10,0x7e,0x80,0x90,0x80,0x7c,0x02,0x12,0x02,0xfc,0x10,0x00, /* 36 */ +0x00,0x62,0x92,0x94,0x68,0x10,0x2c,0x52,0x92,0x8c,0x00,0x00, /* 37 */ +0x00,0x60,0x90,0x90,0x40,0x20,0x90,0x8a,0x84,0x7a,0x00,0x00, /* 38 */ +0x00,0x10,0x10,0x10,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 39 */ +0x00,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x00,0x00, /* 40 */ +0x00,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x00,0x00, /* 41 */ +0x00,0x10,0x92,0x54,0x10,0x10,0x54,0x92,0x10,0x00,0x00,0x00, /* 42 */ +0x00,0x00,0x10,0x10,0x10,0xd6,0x10,0x10,0x10,0x00,0x00,0x00, /* 43 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x30,0x00, /* 44 */ +0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, /* 45 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00, /* 46 */ +0x00,0x02,0x02,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,0x00, /* 47 */ +0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x7c,0x00,0x00, /* 48 */ +0x00,0x08,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 49 */ +0x00,0xfc,0x02,0x02,0x02,0x7c,0x80,0x80,0x00,0xfe,0x00,0x00, /* 50 */ +0x00,0xfc,0x02,0x02,0x02,0x3c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 51 */ +0x00,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0x02,0x02,0x00,0x00, /* 52 */ +0x00,0xfe,0x00,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 53 */ +0x00,0x7c,0x80,0x80,0xbc,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 54 */ +0x00,0xfc,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, /* 55 */ +0x00,0x7c,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x7c,0x00,0x00, /* 56 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0xfc,0x00,0x00, /* 57 */ +0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00, /* 58 */ +0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x60,0x00,0x00, /* 59 */ +0x00,0x08,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x08,0x00,0x00, /* 60 */ +0x00,0x00,0x00,0x00,0xfe,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, /* 61 */ +0x00,0x10,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x10,0x00,0x00, /* 62 */ +0x00,0xfc,0x02,0x02,0x02,0x1c,0x20,0x20,0x00,0x20,0x00,0x00, /* 63 */ +0x00,0x7c,0x82,0x8a,0x92,0x92,0x92,0x8c,0x80,0x7c,0x00,0x00, /* 64 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x00,0x00, /* 65 */ +0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0xbc,0x00,0x00, /* 66 */ +0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7c,0x00,0x00, /* 67 */ +0x00,0xbc,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xbc,0x00,0x00, /* 68 */ +0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x7c,0x00,0x00, /* 69 */ +0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x80,0x00,0x00, /* 70 */ +0x00,0x7c,0x80,0x80,0x80,0x80,0x9a,0x82,0x82,0x7c,0x00,0x00, /* 71 */ +0x00,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x82,0x00,0x00, /* 72 */ +0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 73 */ +0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x84,0x78,0x00,0x00, /* 74 */ +0x00,0x82,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 75 */ +0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7e,0x00,0x00, /* 76 */ +0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x82,0x82,0x82,0x00,0x00, /* 77 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 78 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 79 */ +0x00,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x80,0x80,0x00,0x00, /* 80 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x8a,0x8a,0x82,0x7c,0x00,0x00, /* 81 */ +0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 82 */ +0x00,0x7e,0x80,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 83 */ +0x00,0xfe,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 84 */ +0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 85 */ +0x00,0x82,0x82,0x82,0x82,0x82,0x84,0x88,0x90,0xa0,0x00,0x00, /* 86 */ +0x00,0x82,0x82,0x82,0x82,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 87 */ +0x00,0x82,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x82,0x00,0x00, /* 88 */ +0x00,0x82,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 89 */ +0x00,0xfc,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x7e,0x00,0x00, /* 90 */ +0x00,0x1c,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x1c,0x00,0x00, /* 91 */ +0x00,0x80,0x80,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00, /* 92 */ +0x00,0x38,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x38,0x00,0x00, /* 93 */ +0x00,0x38,0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 94 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00, /* 95 */ +0x00,0x08,0x08,0x08,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 96 */ +0x00,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 97 */ +0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 98 */ +0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x3c,0x00,0x00, /* 99 */ +0x00,0x00,0x02,0x02,0x3a,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 100 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 101 */ +0x00,0x00,0x0c,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x00,0x00, /* 102 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 103 */ +0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 104 */ +0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 105 */ +0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x30, /* 106 */ +0x00,0x00,0x40,0x40,0x42,0x42,0x5c,0x42,0x42,0x42,0x00,0x00, /* 107 */ +0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 108 */ +0x00,0x00,0x00,0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x00,0x00, /* 109 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 110 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 111 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x5c,0x40,0x40, /* 112 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x02, /* 113 */ +0x00,0x00,0x00,0x00,0x0c,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 114 */ +0x00,0x00,0x00,0x00,0x3e,0x40,0x3c,0x02,0x02,0x7c,0x00,0x00, /* 115 */ +0x00,0x00,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x0c,0x00,0x00, /* 116 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 117 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x44,0x48,0x50,0x00,0x00, /* 118 */ +0x00,0x00,0x00,0x00,0x92,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 119 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x3c,0x42,0x42,0x42,0x00,0x00, /* 120 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 121 */ +0x00,0x00,0x00,0x00,0x7c,0x02,0x0c,0x30,0x40,0x3e,0x00,0x00, /* 122 */ +0x00,0x1c,0x20,0x20,0x20,0x40,0x20,0x20,0x20,0x1c,0x00,0x00, /* 123 */ +0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00,0x00, /* 124 */ +0x00,0x38,0x04,0x04,0x04,0x02,0x04,0x04,0x04,0x38,0x00,0x00, /* 125 */ +0x00,0x04,0x38,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 126 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160 */ +0x00,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 161 */ +0x00,0x00,0x08,0x3e,0x40,0x48,0x48,0x40,0x3e,0x08,0x00,0x00, /* 162 */ +0x00,0x1c,0x20,0x20,0x20,0xa8,0x20,0x20,0x42,0xbc,0x00,0x00, /* 163 */ +0x00,0x00,0x82,0x38,0x44,0x44,0x44,0x38,0x82,0x00,0x00,0x00, /* 164 */ +0x00,0x82,0x82,0x82,0x7c,0x00,0x54,0x10,0x54,0x10,0x00,0x00, /* 165 */ +0x00,0x10,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x10,0x00,0x00, /* 166 */ +0x00,0x38,0x40,0x38,0x44,0x44,0x44,0x44,0x38,0x04,0x38,0x00, /* 167 */ +0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168 */ +0x00,0x7c,0x82,0x9a,0xa2,0xa2,0xa2,0x9a,0x82,0x7c,0x00,0x00, /* 169 */ +0x38,0x04,0x34,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00, /* 170 */ +0x00,0x00,0x00,0x24,0x48,0x00,0x48,0x24,0x00,0x00,0x00,0x00, /* 171 */ +0x00,0x00,0x00,0x00,0x00,0xfc,0x02,0x02,0x02,0x00,0x00,0x00, /* 172 */ +0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 173 */ +0x00,0x7c,0x82,0x92,0xaa,0xb2,0xaa,0xaa,0x82,0x7c,0x00,0x00, /* 174 */ +0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 175 */ +0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176 */ +0x00,0x10,0x10,0xd6,0x10,0x10,0x00,0xfe,0x00,0x00,0x00,0x00, /* 177 */ +0x38,0x04,0x18,0x20,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 178 */ +0x38,0x04,0x38,0x04,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 179 */ +0x18,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 180 */ +0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x58,0x40,0x40, /* 181 */ +0x00,0x79,0xfa,0xfa,0xfa,0x7a,0x02,0x0a,0x0a,0x0a,0x0a,0x00, /* 182 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00, /* 183 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00, /* 184 */ +0x08,0x18,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 185 */ +0x38,0x44,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 186 */ +0x00,0x00,0x00,0x48,0x24,0x00,0x24,0x48,0x00,0x00,0x00,0x00, /* 187 */ +0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 188 */ +0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x2e,0x41,0x86,0x08,0x0f, /* 189 */ +0xe0,0x12,0xe2,0x12,0xe4,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 190 */ +0x00,0x08,0x00,0x08,0x08,0x70,0x80,0x80,0x80,0x7e,0x00,0x00, /* 191 */ +0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 192 */ +0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 193 */ +0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 194 */ +0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 195 */ +0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 196 */ +0x38,0x44,0x38,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 197 */ +0x00,0x77,0x88,0x88,0x88,0x8b,0xa8,0x88,0x88,0x8b,0x00,0x00, /* 198 */ +0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x6c,0x10,0x20, /* 199 */ +0x20,0x18,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 200 */ +0x08,0x30,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 201 */ +0x38,0x44,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 202 */ +0x6c,0x00,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 203 */ +0x20,0x18,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 204 */ +0x08,0x30,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 205 */ +0x38,0x44,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 206 */ +0x6c,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 207 */ +0x00,0xbc,0x82,0x82,0x82,0xb2,0x82,0x82,0x82,0xbc,0x00,0x00, /* 208 */ +0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 209 */ +0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 210 */ +0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 211 */ +0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 212 */ +0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 213 */ +0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 214 */ +0x00,0x00,0x00,0x00,0x44,0x28,0x00,0x28,0x44,0x00,0x00,0x00, /* 215 */ +0x00,0x7a,0x84,0x82,0x8a,0x92,0xa2,0x82,0x42,0xbc,0x00,0x00, /* 216 */ +0x20,0x18,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 217 */ +0x08,0x30,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 218 */ +0x38,0x44,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 219 */ +0x6c,0x00,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 220 */ +0x08,0xb2,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 221 */ +0x00,0x80,0x80,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x00,0x00, /* 222 */ +0x00,0x3c,0x42,0x42,0x42,0x5c,0x42,0x42,0x42,0x9c,0x00,0x00, /* 223 */ +0x20,0x18,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 224 */ +0x08,0x30,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 225 */ +0x38,0x44,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 226 */ +0x32,0x4c,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 227 */ +0x6c,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 228 */ +0x18,0x24,0x18,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 229 */ +0x00,0x00,0x00,0x00,0x6c,0x12,0x52,0x94,0x90,0x6e,0x00,0x00, /* 230 */ +0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x34,0x08,0x10, /* 231 */ +0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 232 */ +0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 233 */ +0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 234 */ +0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 235 */ +0x20,0x18,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 236 */ +0x08,0x30,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 237 */ +0x38,0x44,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 238 */ +0x6c,0x00,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 239 */ +0x00,0x14,0x08,0x14,0x02,0x3a,0x42,0x42,0x42,0x3c,0x00,0x00, /* 240 */ +0x00,0x32,0x4c,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 241 */ +0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 242 */ +0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 243 */ +0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 244 */ +0x32,0x4c,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 245 */ +0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 246 */ +0x00,0x00,0x00,0x00,0x38,0x00,0xfe,0x00,0x38,0x00,0x00,0x00, /* 247 */ +0x00,0x00,0x00,0x00,0x3a,0x44,0x4a,0x52,0x22,0x5c,0x00,0x00, /* 248 */ +0x20,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 249 */ +0x08,0x30,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 250 */ +0x38,0x44,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 251 */ +0x6c,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 252 */ +0x04,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 253 */ +0x00,0x80,0x80,0x9c,0xa2,0x82,0xa2,0x9c,0x80,0x80,0x00,0x00, /* 254 */ +}; +static int radonFontMetaData[256*5]={ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,12,0,-2,12,8,12,0,-2,24,8,12,0,-2,36,8,12,0,-2,48,8,12,0,-2,60,8,12,0,-2,72,8,12,0,-2,84,8,12,0,-2,96,8,12,0,-2,108,8,12,0,-2,120,8,12,0,-2,132,8,12,0,-2,144,8,12,0,-2,156,8,12,0,-2,168,8,12,0,-2,180,8,12,0,-2,192,8,12,0,-2,204,8,12,0,-2,216,8,12,0,-2,228,8,12,0,-2,240,8,12,0,-2,252,8,12,0,-2,264,8,12,0,-2,276,8,12,0,-2,288,8,12,0,-2,300,8,12,0,-2,312,8,12,0,-2,324,8,12,0,-2,336,8,12,0,-2,348,8,12,0,-2,360,8,12,0,-2,372,8,12,0,-2,384,8,12,0,-2,396,8,12,0,-2,408,8,12,0,-2,420,8,12,0,-2,432,8,12,0,-2,444,8,12,0,-2,456,8,12,0,-2,468,8,12,0,-2,480,8,12,0,-2,492,8,12,0,-2,504,8,12,0,-2,516,8,12,0,-2,528,8,12,0,-2,540,8,12,0,-2,552,8,12,0,-2,564,8,12,0,-2,576,8,12,0,-2,588,8,12,0,-2,600,8,12,0,-2,612,8,12,0,-2,624,8,12,0,-2,636,8,12,0,-2,648,8,12,0,-2,660,8,12,0,-2,672,8,12,0,-2,684,8,12,0,-2,696,8,12,0,-2,708,8,12,0,-2,720,8,12,0,-2,732,8,12,0,-2,744,8,12,0,-2,756,8,12,0,-2,768,8,12,0,-2,780,8,12,0,-2,792,8,12,0,-2,804,8,12,0,-2,816,8,12,0,-2,828,8,12,0,-2,840,8,12,0,-2,852,8,12,0,-2,864,8,12,0,-2,876,8,12,0,-2,888,8,12,0,-2,900,8,12,0,-2,912,8,12,0,-2,924,8,12,0,-2,936,8,12,0,-2,948,8,12,0,-2,960,8,12,0,-2,972,8,12,0,-2,984,8,12,0,-2,996,8,12,0,-2,1008,8,12,0,-2,1020,8,12,0,-2,1032,8,12,0,-2,1044,8,12,0,-2,1056,8,12,0,-2,1068,8,12,0,-2,1080,8,12,0,-2,1092,8,12,0,-2,1104,8,12,0,-2,1116,8,12,0,-2,1128,8,12,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1140,8,12,0,-2,1152,8,12,0,-2,1164,8,12,0,-2,1176,8,12,0,-2,1188,8,12,0,-2,1200,8,12,0,-2,1212,8,12,0,-2,1224,8,12,0,-2,1236,8,12,0,-2,1248,8,12,0,-2,1260,8,12,0,-2,1272,8,12,0,-2,1284,8,12,0,-2,1296,8,12,0,-2,1308,8,12,0,-2,1320,8,12,0,-2,1332,8,12,0,-2,1344,8,12,0,-2,1356,8,12,0,-2,1368,8,12,0,-2,1380,8,12,0,-2,1392,8,12,0,-2,1404,8,12,0,-2,1416,8,12,0,-2,1428,8,12,0,-2,1440,8,12,0,-2,1452,8,12,0,-2,1464,8,12,0,-2,1476,8,12,0,-2,1488,8,12,0,-2,1500,8,12,0,-2,1512,8,12,0,-2,1524,8,12,0,-2,1536,8,12,0,-2,1548,8,12,0,-2,1560,8,12,0,-2,1572,8,12,0,-2,1584,8,12,0,-2,1596,8,12,0,-2,1608,8,12,0,-2,1620,8,12,0,-2,1632,8,12,0,-2,1644,8,12,0,-2,1656,8,12,0,-2,1668,8,12,0,-2,1680,8,12,0,-2,1692,8,12,0,-2,1704,8,12,0,-2,1716,8,12,0,-2,1728,8,12,0,-2,1740,8,12,0,-2,1752,8,12,0,-2,1764,8,12,0,-2,1776,8,12,0,-2,1788,8,12,0,-2,1800,8,12,0,-2,1812,8,12,0,-2,1824,8,12,0,-2,1836,8,12,0,-2,1848,8,12,0,-2,1860,8,12,0,-2,1872,8,12,0,-2,1884,8,12,0,-2,1896,8,12,0,-2,1908,8,12,0,-2,1920,8,12,0,-2,1932,8,12,0,-2,1944,8,12,0,-2,1956,8,12,0,-2,1968,8,12,0,-2,1980,8,12,0,-2,1992,8,12,0,-2,2004,8,12,0,-2,2016,8,12,0,-2,2028,8,12,0,-2,2040,8,12,0,-2,2052,8,12,0,-2,2064,8,12,0,-2,2076,8,12,0,-2,2088,8,12,0,-2,2100,8,12,0,-2,2112,8,12,0,-2,2124,8,12,0,-2,2136,8,12,0,-2,2148,8,12,0,-2,2160,8,12,0,-2,2172,8,12,0,-2,2184,8,12,0,-2,2196,8,12,0,-2,2208,8,12,0,-2,2220,8,12,0,-2,2232,8,12,0,-2,2244,8,12,0,-2,2256,8,12,0,-2,2268,8,12,0,-2,0,0,0,0,0,}; +static rfbFontData radonFont={radonFontData, radonFontMetaData}; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/regiontest.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/regiontest.c new file mode 100755 index 0000000..91f1a17 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/regiontest.c @@ -0,0 +1,3 @@ +#define SRA_TEST +#include "../libvncserver/rfbregion.c" + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/rotate.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotate.c new file mode 100755 index 0000000..66fca80 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotate.c @@ -0,0 +1,92 @@ +#include +#include +#include + +static int gcd(int x, int y) +{ + if (x == 0) + return y; + return gcd((y % x), x); +} + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + +#define FUNCNAME rfbRotate +#define FUNC(i, j) (h - 1 - j + i * h) +#define SWAPDIMENSIONS +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +#define FUNCNAME rfbRotateCounterClockwise +#define FUNC(i, j) (j + (w - 1 - i) * h) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC +#undef SWAPDIMENSIONS + +#define FUNCNAME rfbFlipHorizontally +#define FUNC(i, j) ((w - 1 - i) + j * w) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +#define FUNCNAME rfbFlipVertically +#define FUNC(i, j) (i + (h - 1 - j) * w) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +#define FUNCNAME rfbRotateHundredAndEighty +#define FUNC(i, j) ((w - 1 - i) + (h - 1 - j) * w) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +static void HandleKey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down) { + if (key==XK_Escape || key=='q' || key=='Q') + rfbCloseClient(cl); + else if (key == 'r') + rfbRotate(cl->screen); + else if (key == 'R') + rfbRotateCounterClockwise(cl->screen); + else if (key == 'f') + rfbFlipHorizontally(cl->screen); + else if (key == 'F') + rfbFlipVertically(cl->screen); + } +} + +#define HAVE_HANDLEKEY +#include "pnmshow.c" + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/rotatetemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotatetemplate.c new file mode 100755 index 0000000..57dc052 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotatetemplate.c @@ -0,0 +1,52 @@ +#define OUT_T CONCAT3E(uint,OUT,_t) +#define FUNCTION CONCAT2E(FUNCNAME,OUT) + +static void FUNCTION(rfbScreenInfoPtr screen) +{ + OUT_T* buffer = (OUT_T*)screen->frameBuffer; + int i, j, w = screen->width, h = screen->height; + OUT_T* newBuffer = (OUT_T*)malloc(w * h * sizeof(OUT_T)); + + for (j = 0; j < h; j++) + for (i = 0; i < w; i++) + newBuffer[FUNC(i, j)] = buffer[i + j * w]; + + memcpy(buffer, newBuffer, w * h * sizeof(OUT_T)); + free(newBuffer); + +#ifdef SWAPDIMENSIONS + screen->width = h; + screen->paddedWidthInBytes = h * OUT / 8; + screen->height = w; + + { + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + iterator = rfbGetClientIterator(screen); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) + cl->newFBSizePending = 1; + } +#endif + + rfbMarkRectAsModified(screen, 0, 0, screen->width, screen->height); +} + +#if OUT == 32 +void FUNCNAME(rfbScreenInfoPtr screen) { + if (screen->serverFormat.bitsPerPixel == 32) + CONCAT2E(FUNCNAME,32)(screen); + else if (screen->serverFormat.bitsPerPixel == 16) + CONCAT2E(FUNCNAME,16)(screen); + else if (screen->serverFormat.bitsPerPixel == 8) + CONCAT2E(FUNCNAME,8)(screen); + else { + rfbErr("Unsupported pixel depth: %d\n", + screen->serverFormat.bitsPerPixel); + return; + } +} +#endif + +#undef FUNCTION +#undef OUT + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/simple.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple.c new file mode 100755 index 0000000..f6e94dc --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple.c @@ -0,0 +1,10 @@ +#include + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4); + server->frameBuffer=(char*)malloc(400*300*4); + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/simple15.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple15.c new file mode 100755 index 0000000..faff4f7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple15.c @@ -0,0 +1,24 @@ +/* This example shows how to use 15-bit (which is handled as 16-bit + internally). */ + +#include + +int main(int argc,char** argv) +{ + int i,j; + uint16_t* f; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,5,3,2); + + server->frameBuffer=(char*)malloc(400*300*2); + f=(uint16_t*)server->frameBuffer; + for(j=0;j<300;j++) + for(i=0;i<400;i++) + f[j*400+i]=/* red */ ((j*32/300) << 10) | + /* green */ (((j+400-i)*32/700) << 5) | + /* blue */ ((i*32/400)); + + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/storepasswd.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/storepasswd.c new file mode 100755 index 0000000..7c358d9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/storepasswd.c @@ -0,0 +1,46 @@ +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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 +#include + +static void usage(void) +{ + printf("\nusage: storepasswd \n\n"); + + printf("Stores a password in encrypted format.\n"); + printf("The resulting file can be used with the -rfbauth argument to OSXvnc.\n\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + if (argc != 3) + usage(); + + if (rfbEncryptAndStorePasswd(argv[1], argv[2]) != 0) { + printf("storing password failed.\n"); + return 1; + } else { + printf("storing password succeeded.\n"); + return 0; + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/vncev.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/vncev.c new file mode 100755 index 0000000..affac00 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/vncev.c @@ -0,0 +1,128 @@ +/* This program is a simple server to show events coming from the client */ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#ifndef __MINGW32__ +#include +#endif +#include +#include + +#define width 100 +#define height 100 +static char f[width*height]; +static char* keys[0x400]; + +static int hex2number(unsigned char c) +{ + if(c>'f') return(-1); + else if(c>'F') + return(10+c-'a'); + else if(c>'9') + return(10+c-'A'); + else + return(c-'0'); +} + +static void read_keys(void) +{ + int i,j,k; + char buffer[1024]; + FILE* keysyms=fopen("keysym.h","r"); + + memset(keys,0,0x400*sizeof(char*)); + + if(!keysyms) + return; + + while(!feof(keysyms)) { + fgets(buffer,1024,keysyms); + if(!strncmp(buffer,"#define XK_",strlen("#define XK_"))) { + for(i=strlen("#define XK_");buffer[i] && buffer[i]!=' ' + && buffer[i]!='\t';i++); + if(buffer[i]==0) /* don't support wrapped lines */ + continue; + buffer[i]=0; + for(i++;buffer[i] && buffer[i]!='0';i++); + if(buffer[i]==0 || buffer[i+1]!='x') continue; + for(j=0,i+=2;(k=hex2number(buffer[i]))>=0;i++) + j=j*16+k; + if(keys[j&0x3ff]) { + char* x=(char*)malloc(1+strlen(keys[j&0x3ff])+1+strlen(buffer+strlen("#define "))); + strcpy(x,keys[j&0x3ff]); + strcat(x,","); + strcat(x,buffer+strlen("#define ")); + free(keys[j&0x3ff]); + keys[j&0x3ff]=x; + } else + keys[j&0x3ff] = strdup(buffer+strlen("#define ")); + } + + } + fclose(keysyms); +} + +static int lineHeight=16,lineY=height-16; +static void output(rfbScreenInfoPtr s,char* line) +{ + rfbDoCopyRect(s,0,0,width,height-lineHeight,0,-lineHeight); + rfbDrawString(s,&default8x16Font,10,lineY,line,0x01); + rfbLog("%s\n",line); +} + +static void dokey(rfbBool down,rfbKeySym k,rfbClientPtr cl) +{ + char buffer[1024+32]; + + sprintf(buffer,"%s: %s (0x%x)", + down?"down":"up",keys[k&0x3ff]?keys[k&0x3ff]:"",(unsigned int)k); + output(cl->screen,buffer); +} + +static void doptr(int buttonMask,int x,int y,rfbClientPtr cl) +{ + char buffer[1024]; + if(buttonMask) { + sprintf(buffer,"Ptr: mouse button mask 0x%x at %d,%d",buttonMask,x,y); + output(cl->screen,buffer); + } + +} + +static enum rfbNewClientAction newclient(rfbClientPtr cl) +{ + char buffer[1024]; + struct sockaddr_in addr; + unsigned int len=sizeof(addr),ip; + + getpeername(cl->sock,(struct sockaddr*)&addr,&len); + ip=ntohl(addr.sin_addr.s_addr); + sprintf(buffer,"Client connected from ip %d.%d.%d.%d", + (ip>>24)&0xff,(ip>>16)&0xff,(ip>>8)&0xff,ip&0xff); + output(cl->screen,buffer); + return RFB_CLIENT_ACCEPT; +} + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,width,height,8,1,1); + s->colourMap.is16=FALSE; + s->colourMap.count=2; + s->colourMap.data.bytes=(unsigned char*)"\xd0\xd0\xd0\x30\x01\xe0"; + s->serverFormat.trueColour=FALSE; + s->frameBuffer=f; + s->kbdAddEvent=dokey; + s->ptrAddEvent=doptr; + s->newClientHook=newclient; + + memset(f,0,width*height); + read_keys(); + rfbInitServer(s); + + while(1) { + rfbProcessEvents(s,999999); + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/index.html b/droidvncgrab/vnc/libvncserver-kanaka/index.html new file mode 100755 index 0000000..1ee3fc4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/index.html @@ -0,0 +1,191 @@ + + + + LibVNCServer/LibVNCClient + + + +

LibVNCServer/LibVNCClient

+ +
+ + If you have problems updating with CVS, here is a preliminary version. If you are looking for more information + on Karl's wonderful x11vnc, either download it + here, or + look at x11vnc's homepage. +

+ +

News

+ 2005/09/29 LibVNCServer now sports a brand new method to extend the protocol, thanks to Rohit Kumar! He also extended the library to support RFB 3.7. Furthermore, he contributed TightVNC file transfer protocol support to LibVNCServer! +

+ 2005/05/25 LibVNCClient now features ZRLE decoding! +

+ 2005/05/15 Another round of valgrinding completed. This time it is augmented by changes instigated by using Linus' sparse. In the course, the complete sources were converted to ANSI C. +

+ 2005/05/07 The member socketInitDone was renamed to socketState, and no longer contains a bool value. This allows us to quit a server cleanly from the event loop via rfbShutdownServer(), so that the structures can be cleaned up properly. This is demonstrated in examples/example.c. +

+ 2005/01/21 The function rfbMakeMaskFromAlphaSource() applies a Floyd-Steinberg dither to approximate a binary mask from a cursor with alpha channel. A demonstration can be found in test/cursortest.c. +

+ 2005/01/16 Renamed this page to reflect that LibVNCClient is actually very usable. +

+ 2005/01/16 Karl Runge has done awesome work to support cursors with alpha blending! You can try it with x11vnc as in CVS, or wait a few more days for x11vnc to be released officially! +

+ 2005/01/15 Happy new year! It begins with a new macro recorder based on LibVNCServer/LibVNCClient using perl as script language. The macro recorder is itself written in perl, and writes out perl scripts, acting as a VNC proxy, so that you can connect a vncviewer to it, and it records all your input, possibly looking for a certain button, image, word, etc. before continuing. I called it VisualNaCro, and it's in CVS. +

+ 2004/12/20 Just before christmas, a new release! Version 0.7 brings you the first non-beta of LibVNCServer... +

+ 2004/12/02 Finally MinGW32 support. I only had problems with a vncviewer which wouldn't connect to localhost: I use SDLvncviewer... +

+ 2004/12/01 LibVNCClient is getting better and better... Expect a very powerful client soon! +

+ 2004/10/16 LibVNCServer has automated test, thanks to LibVNCClient (included). It doesn't do ZRLE yet, and exposed some bugs, the only remaining of these is CoRRE (not sure yet if it's a bug in the client or the server). +

+ 2004/09/14 Added + + Success stories. +

+ 2004/09/07 The API was cleaned up. The structures and functions now have a prefix (mostly "rfb", sometimes "zrle" or "sra") in order not to clutter the namespace, while the structure's members don't need such a prefix. +

+ 2004/08/17 I finally came around to fix mouse behaviour in QEMU's VNC frontend for Windows 98. Please find the patch here. If mouse behaves strangely, try to wiggle the pointer to a free spot on the desktop, hit Ctrl+Shift and release them. After that, the mouse should behave nicely. +

+ 2004/06/07 After silently being added almost a year ago, libvncclient's API was modified for real use, and three examples were added: ppmtest (a very simple demo), SDLvncviewer, and vnc2mpg (which lets you record your VNC session to a movie). Automated regression tests of the libraries are planned. +

+ 2004/06/02 x11vnc-0.6.1 was released! This reflects the long way the original, small example has gone, improved in many possible ways and having a broad user base. +

+ 2004/05/29 Some patches were created for QEMU, a FAST! emulator by Fabrice Bellard, to control those sessions with a vncviewer. +

+ 2004/02/29 LibVNCServer is listed as a project using Valgrind! +

+ 2003/11/07 Version 0.6 is out! x11vnc performance boosts! You no longer need a c++ compiler in order to have ZRLE coding! LinuxVNC was added (This is to the text console what x11vnc is to X11)! +

+ 2003/02/21 rdp2vnc is in rdesktop's CVS. +

+ 2003/02/19 A preliminary patch for rdesktop (CVS) to make +rdp2vnc, a translator from Windows Terminal Server's protocol to VNC's protocol, +is available. It needs a new version of +libvncserver; try CVS until I release 0.6. +

+ 2003/02/09 Version 0.5 is out! Features include autoconf based configure, rpm package (YMMV), cleanup of directory structure, NEW x11vnc! ZRLE encoding! HTTP tunnelling through LibVNCServer's HTTP support! Many bug fixes! +

+ 2002/07/28 Version 0.4 is out! Biggest feature: NewFB encoding. Quite a few bugfixes also (Thanks to all!). +

+ 2001/12/14 A new version of + rdesktop+vnc is available! + (Includes support for other platforms keyboard mapping with plain rdesktop!) +

+ 2001/10/23 Added a link to my homepage at the end. +

+ 2001/10/18 I released the rdp2vnc extensions as well as + patches for general keyboard handling, working inside Xvnc and + process_text2 (the famous "font:" error) to rdesktop. Please find it on + the + download page. +

+ 2001/10/13 A snapshot of + + LibVNCServer and + + RDP2VNC + is now available. You can also download the + + diff against rdesktop-1.1.0. + rdp2vnc also contains the patches for keyboards other than PC keyboards, + and you can specify "-k fr" again. + +


+ +

Introduction

+ If you don't know VNC, have a look at + the original VNC or at + Tridia VNC, who also have commercial + support for it. + +

+ + Now that you know what it is, maybe you want to make your own server. + If this is not the case, you can ignore the rest of this page an go on + surfing the internet. + +

+ + Now that you want to make a VNC server, that is, a server which speaks + the RFB protocol, you can download this library from + sourceforge. + +

+ + The simplest server looks like this:

+ +

+#include <rfb/rfb.h>
+
+int main(int argc,char** argv)
+{
+  rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4);
+  server->frameBuffer=malloc(400*300*4);
+  rfbInitServer(server);
+  rfbRunEventLoop(server,-1,FALSE);
+  return(0);
+}
+
+
+ + This sample creates a 400x300 frame buffer in true colour. There are + 4 bytes per pixel, because 3 (which are only used instead of all 4) is + such an odd number. Then the server is initialized and a blocking event + loop is started. + +

+ Of course, this program only shows rubbish (whatever is in the frame + buffer you malloc'd), but it proves that writing a server can be + very easy. + +

+ For details (especially if you want to write a real server) look into the + provided examples, pnmshow.c and example.c, and into the README. You find + there documentation for much more complicated servers. + +

+ Serious comments, suggestions, pizzas, etc. go to + me + (delete the RuBBISH). + +

+ Here are some links: + +

+ LibVNCServer is an adapted + OSXvnc-server by + Dan McGuirk, + which is in turn an adapted original + Xvnc. +

+ I use it to to drive a +Windows Terminal Server (RDP) to RFB converter with it. + Much work has been done to make + rdesktop + a good X client to Windows Terminal Services (both NT and 2000, see + rdesktop patches). + Previous work was done by Tim Edmonds + who has set up such a converter named + vdesktop + including a single client server and a multi client server, rdp2vnc. + Unfortunately he used the example code from rfbcounter, which can encode only + RRE, which is not a good compression. +

+ Other people + have used this library as well. +

+ If you want to know about other of my projects, look at + my homepage. +


+ Project hosted on the fantastic + + SourceForge Logo
+ + +Last modified: Mon Jan 17 18:23:00 MESZ 2005 + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/.cvsignore new file mode 100755 index 0000000..d498e83 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/.cvsignore @@ -0,0 +1,5 @@ +.deps +Makefile +Makefile.in +libvncclient.a + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/Makefile.am new file mode 100755 index 0000000..9f42fd3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(top_srcdir) + +libvncclient_la_SOURCES=cursor.c listen.c rfbproto.c sockets.c vncviewer.c minilzo.c tls.c + +noinst_HEADERS=lzoconf.h minilzo.h tls.h + +rfbproto.o: rfbproto.c corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c + +EXTRA_DIST=corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c tls.c + +$(libvncclient_la_OBJECTS): ../rfb/rfbclient.h + +lib_LTLIBRARIES=libvncclient.la + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/corre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/corre.c new file mode 100755 index 0000000..baf91cc --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/corre.c @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/* + * corre.c - handle CoRRE encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles a CoRRE + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleCoRREBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbRREHeader hdr; + int i; + CARDBPP pix; + uint8_t *ptr; + int x, y, w, h; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader)) + return FALSE; + + hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects); + + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + FillRectangle(client, rx, ry, rw, rh, pix); + + if (!ReadFromRFBServer(client, client->buffer, hdr.nSubrects * (4 + (BPP / 8)))) + return FALSE; + + ptr = (uint8_t *)client->buffer; + + for (i = 0; i < hdr.nSubrects; i++) { + pix = *(CARDBPP *)ptr; + ptr += BPP/8; + x = *ptr++; + y = *ptr++; + w = *ptr++; + h = *ptr++; + + FillRectangle(client, rx+x, ry+y, w, h, pix); + } + + return TRUE; +} + +#undef CARDBPP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/cursor.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/cursor.c new file mode 100755 index 0000000..a48d7c5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/cursor.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2001,2002 Constantin Kaplinsky. 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. + */ + +/* + * cursor.c - code to support cursor shape updates (XCursor and + * RichCursor preudo-encodings). + */ + +#include + + +#define OPER_SAVE 0 +#define OPER_RESTORE 1 + +#define RGB24_TO_PIXEL(bpp,r,g,b) \ + ((((uint##bpp##_t)(r) & 0xFF) * client->format.redMax + 127) / 255 \ + << client->format.redShift | \ + (((uint##bpp##_t)(g) & 0xFF) * client->format.greenMax + 127) / 255 \ + << client->format.greenShift | \ + (((uint##bpp##_t)(b) & 0xFF) * client->format.blueMax + 127) / 255 \ + << client->format.blueShift) + + +/********************************************************************* + * HandleCursorShape(). Support for XCursor and RichCursor shape + * updates. We emulate cursor operating on the frame buffer (that is + * why we call it "software cursor"). + ********************************************************************/ + +rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc) +{ + int bytesPerPixel; + size_t bytesPerRow, bytesMaskData; + rfbXCursorColors rgb; + uint32_t colors[2]; + char *buf; + uint8_t *ptr; + int x, y, b; + + bytesPerPixel = client->format.bitsPerPixel / 8; + bytesPerRow = (width + 7) / 8; + bytesMaskData = bytesPerRow * height; + + if (width * height == 0) + return TRUE; + + /* Allocate memory for pixel data and temporary mask data. */ + if(client->rcSource) + free(client->rcSource); + + client->rcSource = malloc(width * height * bytesPerPixel); + if (client->rcSource == NULL) + return FALSE; + + buf = malloc(bytesMaskData); + if (buf == NULL) { + free(client->rcSource); + client->rcSource = NULL; + return FALSE; + } + + /* Read and decode cursor pixel data, depending on the encoding type. */ + + if (enc == rfbEncodingXCursor) { + /* Read and convert background and foreground colors. */ + if (!ReadFromRFBServer(client, (char *)&rgb, sz_rfbXCursorColors)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); + colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); + + /* Read 1bpp pixel data into a temporary buffer. */ + if (!ReadFromRFBServer(client, buf, bytesMaskData)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + /* Convert 1bpp data to byte-wide color indices. */ + ptr = client->rcSource; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + for (b = 7; b >= 0; b--) { + *ptr = buf[y * bytesPerRow + x] >> b & 1; + ptr += bytesPerPixel; + } + } + for (b = 7; b > 7 - width % 8; b--) { + *ptr = buf[y * bytesPerRow + x] >> b & 1; + ptr += bytesPerPixel; + } + } + + /* Convert indices into the actual pixel values. */ + switch (bytesPerPixel) { + case 1: + for (x = 0; x < width * height; x++) + client->rcSource[x] = (uint8_t)colors[client->rcSource[x]]; + break; + case 2: + for (x = 0; x < width * height; x++) + ((uint16_t *)client->rcSource)[x] = (uint16_t)colors[client->rcSource[x * 2]]; + break; + case 4: + for (x = 0; x < width * height; x++) + ((uint32_t *)client->rcSource)[x] = colors[client->rcSource[x * 4]]; + break; + } + + } else { /* enc == rfbEncodingRichCursor */ + + if (!ReadFromRFBServer(client, (char *)client->rcSource, width * height * bytesPerPixel)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + } + + /* Read and decode mask data. */ + + if (!ReadFromRFBServer(client, buf, bytesMaskData)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + client->rcMask = malloc(width * height); + if (client->rcMask == NULL) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + ptr = client->rcMask; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + for (b = 7; b >= 0; b--) { + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; + } + } + for (b = 7; b > 7 - width % 8; b--) { + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; + } + } + + if (client->GotCursorShape != NULL) { + client->GotCursorShape(client, xhot, yhot, width, height, bytesPerPixel); + } + + free(buf); + + return TRUE; +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/hextile.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/hextile.c new file mode 100755 index 0000000..8698445 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/hextile.c @@ -0,0 +1,127 @@ +/* + * 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. + */ + +/* + * hextile.c - handle hextile encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles a hextile + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleHextileBPP CONCAT2E(HandleHextile,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleHextileBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + CARDBPP bg, fg; + int i; + uint8_t *ptr; + int x, y, w, h; + int sx, sy, sw, sh; + uint8_t subencoding; + uint8_t nSubrects; + + for (y = ry; y < ry+rh; y += 16) { + for (x = rx; x < rx+rw; x += 16) { + w = h = 16; + if (rx+rw - x < 16) + w = rx+rw - x; + if (ry+rh - y < 16) + h = ry+rh - y; + + if (!ReadFromRFBServer(client, (char *)&subencoding, 1)) + return FALSE; + + if (subencoding & rfbHextileRaw) { + if (!ReadFromRFBServer(client, client->buffer, w * h * (BPP / 8))) + return FALSE; + + CopyRectangle(client, (uint8_t *)client->buffer, x, y, w, h); + + continue; + } + + if (subencoding & rfbHextileBackgroundSpecified) + if (!ReadFromRFBServer(client, (char *)&bg, sizeof(bg))) + return FALSE; + + FillRectangle(client, x, y, w, h, bg); + + if (subencoding & rfbHextileForegroundSpecified) + if (!ReadFromRFBServer(client, (char *)&fg, sizeof(fg))) + return FALSE; + + if (!(subencoding & rfbHextileAnySubrects)) { + continue; + } + + if (!ReadFromRFBServer(client, (char *)&nSubrects, 1)) + return FALSE; + + ptr = (uint8_t*)client->buffer; + + if (subencoding & rfbHextileSubrectsColoured) { + if (!ReadFromRFBServer(client, client->buffer, nSubrects * (2 + (BPP / 8)))) + return FALSE; + + for (i = 0; i < nSubrects; i++) { +#if BPP==8 + GET_PIXEL8(fg, ptr); +#elif BPP==16 + GET_PIXEL16(fg, ptr); +#elif BPP==32 + GET_PIXEL32(fg, ptr); +#else +#error "Invalid BPP" +#endif + sx = rfbHextileExtractX(*ptr); + sy = rfbHextileExtractY(*ptr); + ptr++; + sw = rfbHextileExtractW(*ptr); + sh = rfbHextileExtractH(*ptr); + ptr++; + + FillRectangle(client, x+sx, y+sy, sw, sh, fg); + } + + } else { + if (!ReadFromRFBServer(client, client->buffer, nSubrects * 2)) + return FALSE; + + for (i = 0; i < nSubrects; i++) { + sx = rfbHextileExtractX(*ptr); + sy = rfbHextileExtractY(*ptr); + ptr++; + sw = rfbHextileExtractW(*ptr); + sh = rfbHextileExtractH(*ptr); + ptr++; + + FillRectangle(client, x+sx, y+sy, sw, sh, fg); + } + } + } + } + + return TRUE; +} + +#undef CARDBPP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/listen.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/listen.c new file mode 100755 index 0000000..637abb1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/listen.c @@ -0,0 +1,171 @@ +/* + * 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. + */ + +/* + * listen.c - listen for incoming connections + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#ifdef __MINGW32__ +#define close closesocket +#include +#else +#include +#include +#endif +#include +#include + +/* + * listenForIncomingConnections() - listen for incoming connections from + * servers, and fork a new process to deal with each connection. + */ + +void +listenForIncomingConnections(rfbClient* client) +{ +#ifdef __MINGW32__ + /* FIXME */ + rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n"); + return; +#else + int listenSocket; + fd_set fds; + + client->listenSpecified = TRUE; + + listenSocket = ListenAtTcpPort(client->listenPort); + + if ((listenSocket < 0)) + return; + + rfbClientLog("%s -listen: Listening on port %d\n", + client->programName,client->listenPort); + rfbClientLog("%s -listen: Command line errors are not reported until " + "a connection comes in.\n", client->programName); + + while (TRUE) { + + /* reap any zombies */ + int status, pid; + while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); + + /* TODO: callback for discard any events (like X11 events) */ + + FD_ZERO(&fds); + + FD_SET(listenSocket, &fds); + + select(listenSocket+1, &fds, NULL, NULL, NULL); + + if (FD_ISSET(listenSocket, &fds)) { + client->sock = AcceptTcpConnection(listenSocket); + if (client->sock < 0) + return; + if (!SetNonBlocking(client->sock)) + return; + + /* Now fork off a new process to deal with it... */ + + switch (fork()) { + + case -1: + rfbClientErr("fork\n"); + return; + + case 0: + /* child - return to caller */ + close(listenSocket); + return; + + default: + /* parent - go round and listen again */ + close(client->sock); + break; + } + } + } +#endif +} + + + +/* + * listenForIncomingConnectionsNoFork() - listen for incoming connections + * from servers, but DON'T fork, instead just wait timeout microseconds. + * If timeout is negative, block indefinitly. + * Returns 1 on success (there was an incoming connection on the listen socket + * and we accepted it successfully), -1 on error, 0 on timeout. + */ + +int +listenForIncomingConnectionsNoFork(rfbClient* client, int timeout) +{ + fd_set fds; + struct timeval to; + int r; + + to.tv_sec= timeout / 1000000; + to.tv_usec= timeout % 1000000; + + client->listenSpecified = TRUE; + + if (client->listenSock < 0) + { + client->listenSock = ListenAtTcpPort(client->listenPort); + + if (client->listenSock < 0) + return -1; + + rfbClientLog("%s -listennofork: Listening on port %d\n", + client->programName,client->listenPort); + rfbClientLog("%s -listennofork: Command line errors are not reported until " + "a connection comes in.\n", client->programName); + } + + FD_ZERO(&fds); + + FD_SET(client->listenSock, &fds); + + if (timeout < 0) + r = select(client->listenSock+1, &fds, NULL, NULL, NULL); + else + r = select(client->listenSock+1, &fds, NULL, NULL, &to); + + if (r > 0) + { + client->sock = AcceptTcpConnection(client->listenSock); + if (client->sock < 0) + return -1; + if (!SetNonBlocking(client->sock)) + return -1; + + close(client->listenSock); + return r; + } + + /* r is now either 0 (timeout) or -1 (error) */ + return r; +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/lzoconf.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/lzoconf.h new file mode 100755 index 0000000..96db180 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/lzoconf.h @@ -0,0 +1,451 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H +#define __LZOCONF_H + +#define LZO_VERSION 0x1080 +#define LZO_VERSION_STRING "1.08" +#define LZO_VERSION_DATE "Jul 12 2002" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* workaround a cpp bug under hpux 10.20 */ +#define LZO_0xffffffffL 4294967295ul + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) c ## U +# endif +#endif + + +/*********************************************************************** +// architecture defines +************************************************************************/ + +#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) +# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# define __LZO_WIN +# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) +# define __LZO_WIN +# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) +# define __LZO_WIN +# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) +# define __LZO_DOS +# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) +# define __LZO_OS2 +# elif defined(__palmos__) +# define __LZO_PALMOS +# elif defined(__TOS__) || defined(__atarist__) +# define __LZO_TOS +# endif +#endif + +#if (UINT_MAX < LZO_0xffffffffL) +# if defined(__LZO_WIN) +# define __LZO_WIN16 +# elif defined(__LZO_DOS) +# define __LZO_DOS16 +# elif defined(__LZO_PALMOS) +# define __LZO_PALMOS16 +# elif defined(__LZO_TOS) +# define __LZO_TOS16 +# elif defined(__C166__) +# else + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ +# error "16-bit target not supported - contact me for porting hints" +# endif +#endif + +#if !defined(__LZO_i386) +# if defined(__LZO_DOS) || defined(__LZO_WIN16) +# define __LZO_i386 +# elif defined(__i386__) || defined(__386__) || defined(_M_IX86) +# define __LZO_i386 +# endif +#endif + +#if defined(__LZO_STRICT_16BIT) +# if (UINT_MAX < LZO_0xffffffffL) +# include +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER +# elif defined(__CHECKER__) +# define __LZO_CHECKER +# elif defined(__INSURE__) +# define __LZO_CHECKER +# elif defined(__PURIFY__) +# define __LZO_CHECKER +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* Integral types with 32 bits or more */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* lzo_uint is used like size_t */ +#if !defined(LZO_UINT_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +typedef int lzo_bool; + + +/*********************************************************************** +// memory models +************************************************************************/ + +/* Memory model for the public code segment. */ +#if !defined(__LZO_CMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CMODEL __near +# else +# define __LZO_CMODEL +# endif +#endif + +/* Memory model for the public data segment. */ +#if !defined(__LZO_DMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_DMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_DMODEL __near +# else +# define __LZO_DMODEL +# endif +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_MMODEL __huge +# define LZO_999_UNSUPPORTED +# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) +# define __LZO_MMODEL +# else +# error "__LZO_MMODEL" +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_byte unsigned char __LZO_MMODEL +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t sizeof(lzo_bytep) +#endif + + +/*********************************************************************** +// calling conventions and function types +************************************************************************/ + +/* linkage */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(_MSC_VER) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# else +# define __LZO_CDECL __LZO_CMODEL +# endif +#endif +#if !defined(__LZO_ENTRY) +# define __LZO_ENTRY __LZO_CDECL +#endif + +/* C++ exception specification for extern "C" function types */ +#if !defined(__cplusplus) +# undef LZO_NOTHROW +# define LZO_NOTHROW +#elif !defined(LZO_NOTHROW) +# define LZO_NOTHROW +#endif + + +typedef int +(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + +typedef int +(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + + +/* assembler versions always use __cdecl */ +typedef int +(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + + +/* a progress indicator callback function */ +typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); + + +/*********************************************************************** +// export information +************************************************************************/ + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* exported calling convention for C functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY +#endif + +/* exported __cdecl calling convention for assembler functions */ +#if !defined(LZO_PUBLIC_CDECL) +# define LZO_PUBLIC_CDECL(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN_CDECL) +# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) +#endif + +/* exported global variables (LZO currently uses no static variables and + * is fully thread safe) */ +#if !defined(LZO_PUBLIC_VAR) +# define LZO_PUBLIC_VAR(_type) \ + __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL +#endif +#if !defined(LZO_EXTERN_VAR) +# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) +#endif + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) + + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_compress_t)) +LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + +/* misc. */ +LZO_EXTERN(lzo_bool) lzo_assert(int _expr); +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + +/* deprecated - only for backward compatibility */ +#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.c new file mode 100755 index 0000000..85771eb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.c @@ -0,0 +1,2935 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#if !defined(LZO_NO_SYS_TYPES_H) +# include +#endif +#include + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +# ifndef __LZOCONF_H +# include +# endif +#endif + +#if defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(LZO_HAVE_CONFIG_H) +# include +# include +# if !defined(NO_STDLIB_H) +# include +# endif +# define HAVE_MEMCMP +# define HAVE_MEMCPY +# define HAVE_MEMMOVE +# define HAVE_MEMSET +#else +# include +# if defined(HAVE_STDDEF_H) +# include +# endif +# if defined(STDC_HEADERS) +# include +# include +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define HAVE_MALLOC_H +# define HAVE_HALLOC +#endif + +#undef NDEBUG +#if !defined(LZO_DEBUG) +# define NDEBUG +#endif +#if defined(LZO_DEBUG) || !defined(NDEBUG) +# if !defined(NO_STDIO_H) +# include +# endif +#endif +#include + +#if !defined(LZO_COMPILE_TIME_ASSERT) +# define LZO_COMPILE_TIME_ASSERT(expr) \ + { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; } +#endif + +#if !defined(LZO_UNUSED) +# if 1 +# define LZO_UNUSED(var) ((void)&var) +# elif 0 +# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; } +# else +# define LZO_UNUSED(parm) (parm = parm) +# endif +#endif + +#if !defined(__inline__) && !defined(__GNUC__) +# if defined(__cplusplus) +# define __inline__ inline +# else +# define __inline__ +# endif +#endif + +#if defined(NO_MEMCMP) +# undef HAVE_MEMCMP +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp lzo_memcmp +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy lzo_memcpy +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove lzo_memmove +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset lzo_memset +#endif + +#if 0 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) +#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) + +#if !defined(SIZEOF_UNSIGNED) +# if (UINT_MAX == 0xffff) +# define SIZEOF_UNSIGNED 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 4 +# elif (UINT_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 8 +# else +# error "SIZEOF_UNSIGNED" +# endif +#endif + +#if !defined(SIZEOF_UNSIGNED_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 4 +# elif (ULONG_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 8 +# else +# error "SIZEOF_UNSIGNED_LONG" +# endif +#endif + +#if !defined(SIZEOF_SIZE_T) +# define SIZEOF_SIZE_T SIZEOF_UNSIGNED +#endif +#if !defined(SIZE_T_MAX) +# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) +#endif + +#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) +# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) +# define LZO_UNALIGNED_OK_2 +# endif +# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) +# define LZO_UNALIGNED_OK_4 +# endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) +# if !defined(LZO_UNALIGNED_OK) +# define LZO_UNALIGNED_OK +# endif +#endif + +#if defined(__LZO_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +#endif + +#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) +# error "LZO_UNALIGNED_OK_2 must not be defined on this system" +#endif +#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_UNALIGNED_OK_4 must not be defined on this system" +#endif + +#if defined(__LZO_NO_ALIGNED) +# undef LZO_ALIGNED_OK_4 +#endif + +#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_ALIGNED_OK_4 must not be defined on this system" +#endif + +#define LZO_LITTLE_ENDIAN 1234 +#define LZO_BIG_ENDIAN 4321 +#define LZO_PDP_ENDIAN 3412 + +#if !defined(LZO_BYTE_ORDER) +# if defined(MFX_BYTE_ORDER) +# define LZO_BYTE_ORDER MFX_BYTE_ORDER +# elif defined(__LZO_i386) +# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN +# elif defined(BYTE_ORDER) +# define LZO_BYTE_ORDER BYTE_ORDER +# elif defined(__BYTE_ORDER) +# define LZO_BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(LZO_BYTE_ORDER) +# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ + (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) +# error "invalid LZO_BYTE_ORDER" +# endif +#endif + +#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) +# error "LZO_BYTE_ORDER is not defined" +#endif + +#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY + +#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER) +# if defined(__GNUC__) && defined(__i386__) +# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) +# define LZO_OPTIMIZE_GNUC_i386 +# endif +# endif +#endif + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const lzo_byte __lzo_copyright[]; +LZO_EXTERN(const lzo_byte *) lzo_copyright(void); +__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; + +#define _LZO_STRINGIZE(x) #x +#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) + +#define _LZO_CONCAT2(a,b) a ## b +#define _LZO_CONCAT3(a,b,c) a ## b ## c +#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d +#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e + +#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) +#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) +#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) +#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) + +#if 0 + +#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#endif + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# include +# if 1 && defined(__WATCOMC__) +# include + __LZO_EXTERN_C unsigned char _HShift; +# define __LZO_HShift _HShift +# elif 1 && defined(_MSC_VER) + __LZO_EXTERN_C unsigned short __near _AHSHIFT; +# define __LZO_HShift ((unsigned) &_AHSHIFT) +# elif defined(__LZO_WIN16) +# define __LZO_HShift 3 +# else +# define __LZO_HShift 12 +# endif +# if !defined(_FP_SEG) && defined(FP_SEG) +# define _FP_SEG FP_SEG +# endif +# if !defined(_FP_OFF) && defined(FP_OFF) +# define _FP_OFF FP_OFF +# endif +#endif + +#if !defined(lzo_ptrdiff_t) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef ptrdiff_t lzo_ptrdiff_t; +# else + typedef long lzo_ptrdiff_t; +# endif +#endif + +#if !defined(__LZO_HAVE_PTR_T) +# if defined(lzo_ptr_t) +# define __LZO_HAVE_PTR_T +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) +# error "no suitable type for lzo_ptr_t" +# else + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_ptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#if !defined(lzo_moff_t) +#define lzo_moff_t lzo_uint +#endif + +#endif + +LZO_PUBLIC(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_ptr_t p; + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) + p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); +#else + p = PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ + lzo_ptr_t p, s, n; + + assert(size > 0); + + p = __lzo_ptr_linear(ptr); + s = (lzo_ptr_t) (size - 1); +#if 0 + assert((size & (size - 1)) == 0); + n = ((p + s) & ~s) - p; +#else + n = (((p + s) / size) * size) - p; +#endif + + assert((long)n >= 0); + assert(n <= s); + + return (unsigned)n; +} + +#ifndef __LZO_UTIL_H +#define __LZO_UTIL_H + +#ifndef __LZO_CONF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 && defined(HAVE_MEMCPY) +#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) + +#define MEMCPY8_DS(dest,src,len) \ + memcpy(dest,src,len); \ + dest += len; \ + src += len + +#endif +#endif + +#if 0 && !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + len -= 8; \ + } while (len > 0); } + +#endif + +#if !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { register lzo_uint __l = (len) / 8; \ + do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + } while (--__l > 0); } + +#endif + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#define MEMMOVE_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) + +#define BZERO8_PTR(s,l,n) \ +__asm__ __volatile__( \ + "movl %0,%%eax \n" \ + "movl %1,%%edi \n" \ + "movl %2,%%ecx \n" \ + "cld \n" \ + "rep \n" \ + "stosl %%eax,(%%edi) \n" \ + : \ + :"g" (0),"g" (s),"g" (n) \ + :"eax","edi","ecx", "memory", "cc" \ +) + +#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + +#if 1 +#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) +#else +#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) +#endif + +#else + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#endif + +#if 0 +#if defined(__GNUC__) && defined(__i386__) + +unsigned char lzo_rotr8(unsigned char value, int shift); +extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) +{ + unsigned char result; + + __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +unsigned short lzo_rotr16(unsigned short value, int shift); +extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) +{ + unsigned short result; + + __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +LZO_PUBLIC(lzo_bool) +lzo_assert(int expr) +{ + return (expr) ? 1 : 0; +} + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +const lzo_byte __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\n\n\n" + "LZO real-time data compression library.\n" + "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com/opensource/lzo/\n" + "\n" + "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" + "LZO build date: " __DATE__ " " __TIME__ "\n\n" + "LZO special compilation options:\n" +#ifdef __cplusplus + " __cplusplus\n" +#endif +#if defined(__PIC__) + " __PIC__\n" +#elif defined(__pic__) + " __pic__\n" +#endif +#if (UINT_MAX < LZO_0xffffffffL) + " 16BIT\n" +#endif +#if defined(__LZO_STRICT_16BIT) + " __LZO_STRICT_16BIT\n" +#endif +#if (UINT_MAX > LZO_0xffffffffL) + " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" +#endif +#if (ULONG_MAX > LZO_0xffffffffL) + " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" +#endif +#if defined(LZO_BYTE_ORDER) + " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" +#endif +#if defined(LZO_UNALIGNED_OK_2) + " LZO_UNALIGNED_OK_2\n" +#endif +#if defined(LZO_UNALIGNED_OK_4) + " LZO_UNALIGNED_OK_4\n" +#endif +#if defined(LZO_ALIGNED_OK_4) + " LZO_ALIGNED_OK_4\n" +#endif +#if defined(LZO_DICT_USE_PTR) + " LZO_DICT_USE_PTR\n" +#endif +#if defined(__LZO_QUERY_COMPRESS) + " __LZO_QUERY_COMPRESS\n" +#endif +#if defined(__LZO_QUERY_DECOMPRESS) + " __LZO_QUERY_DECOMPRESS\n" +#endif +#if defined(__LZO_IN_MINILZO) + " __LZO_IN_MINILZO\n" +#endif + "\n\n" + "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ +#if defined(__GNUC__) && defined(__VERSION__) + " by gcc " __VERSION__ +#elif defined(__BORLANDC__) + " by Borland C " _LZO_MEXPAND(__BORLANDC__) +#elif defined(_MSC_VER) + " by Microsoft C " _LZO_MEXPAND(_MSC_VER) +#elif defined(__PUREC__) + " by Pure C " _LZO_MEXPAND(__PUREC__) +#elif defined(__SC__) + " by Symantec C " _LZO_MEXPAND(__SC__) +#elif defined(__TURBOC__) + " by Turbo C " _LZO_MEXPAND(__TURBOC__) +#elif defined(__WATCOMC__) + " by Watcom C " _LZO_MEXPAND(__WATCOMC__) +#endif + " $\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; +#endif + +LZO_PUBLIC(const lzo_byte *) +lzo_copyright(void) +{ + return __lzo_copyright; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (int) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +LZO_PUBLIC(int) +lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP) + return memcmp(s1,s2,len); +#else + const lzo_byte *p1 = (const lzo_byte *) s1; + const lzo_byte *p2 = (const lzo_byte *) s2; + int d; + + if (len > 0) do + { + d = *p1 - *p2; + if (d != 0) + return d; + p1++; + p2++; + } + while (--len > 0); + return 0; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY) + return memcpy(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + do + *p1++ = *p2++; + while (--len > 0); + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE) + return memmove(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + + if (p1 < p2) + { + do + *p1++ = *p2++; + while (--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while (--len > 0); + } + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memset(lzo_voidp s, int c, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + return memset(s,c,len); +#else + lzo_byte *p = (lzo_byte *) s; + + if (len > 0) do + *p++ = LZO_BYTE(c); + while (--len > 0); + return s; +#endif +} + +#if 0 +# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) +# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) +#else +# define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) +# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) +#endif + +#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +static lzo_bool schedule_insns_bug(void); +static lzo_bool strength_reduce_bug(int *); + +#if 0 || defined(LZO_DEBUG) +#include +static lzo_bool __lzo_assert_fail(const char *s, unsigned line) +{ +#if defined(__palmos__) + printf("LZO assertion failed in line %u: '%s'\n",line,s); +#else + fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); +#endif + return 0; +} +# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) +#else +# define __lzo_assert(x) ((x) ? 1 : 0) +#endif + +#undef COMPILE_TIME_ASSERT +#if 0 +# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) +#else +# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif + +static lzo_bool basic_integral_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(CHAR_BIT == 8); + COMPILE_TIME_ASSERT(sizeof(char) == 1); + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + COMPILE_TIME_ASSERT(sizeof(long) >= 4); + COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); + COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); +#if defined(__LZO_STRICT_16BIT) + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); +#else + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); +#endif + +#if (USHRT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(short) == 2); +#elif (USHRT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) == 4); +#elif (USHRT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) > 4); +#endif +#if (UINT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(int) == 2); +#elif (UINT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) == 4); +#elif (UINT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) > 4); +#endif +#if (ULONG_MAX == 65535ul) + COMPILE_TIME_ASSERT(sizeof(long) == 2); +#elif (ULONG_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) == 4); +#elif (ULONG_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) > 4); +#endif + +#if defined(SIZEOF_UNSIGNED) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); +#endif +#if defined(SIZEOF_UNSIGNED_LONG) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); +#endif +#if defined(SIZEOF_UNSIGNED_SHORT) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); +#endif +#if !defined(__LZO_IN_MINILZO) +#if defined(SIZEOF_SIZE_T) + COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); +#endif +#endif + + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); + COMPILE_TIME_ASSERT(IS_SIGNED(short)); + COMPILE_TIME_ASSERT(IS_SIGNED(int)); + COMPILE_TIME_ASSERT(IS_SIGNED(long)); + + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); + + COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); + COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); + COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); + COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); + COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); + COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); + COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); + COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); +#if !defined(__LZO_IN_MINILZO) + COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); +#endif + + r &= __lzo_assert(LZO_BYTE(257) == 1); + + return r; +} + +static lzo_bool basic_ptr_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); + COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); + + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); + + COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); + +#if defined(SIZEOF_CHAR_P) + COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); +#endif +#if defined(SIZEOF_PTRDIFF_T) + COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); +#endif + + COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); + + return r; +} + +static lzo_bool ptr_check(void) +{ + lzo_bool r = 1; + int i; + char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; + lzo_bytep wrkmem; + lzo_bytepp dict; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + long d; + lzo_full_align_t a; + lzo_full_align_t u; + + for (i = 0; i < (int) sizeof(x); i++) + x[i] = LZO_BYTE(i); + + wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t)); + +#if 0 + dict = (lzo_bytepp) wrkmem; +#else + + u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp; +#endif + + d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); + r &= __lzo_assert(d >= 0); + r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t)); + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_lzo_voidp == NULL); + + memset(&a,0xff,sizeof(a)); + r &= __lzo_assert(a.a_ushort == USHRT_MAX); + r &= __lzo_assert(a.a_uint == UINT_MAX); + r &= __lzo_assert(a.a_ulong == ULONG_MAX); + r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); + r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); + + if (r == 1) + { + for (i = 0; i < 8; i++) + r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); + } + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_char_p == NULL); + r &= __lzo_assert(a.a_lzo_bytep == NULL); + r &= __lzo_assert(NULL == (void *)0); + if (r == 1) + { + for (i = 0; i < 10; i++) + dict[i] = wrkmem; + BZERO8_PTR(dict+1,sizeof(dict[0]),8); + r &= __lzo_assert(dict[0] == wrkmem); + for (i = 1; i < 9; i++) + r &= __lzo_assert(dict[i] == NULL); + r &= __lzo_assert(dict[9] == wrkmem); + } + + if (r == 1) + { + unsigned k = 1; + const unsigned n = (unsigned) sizeof(lzo_uint32); + lzo_byte *p0; + lzo_byte *p1; + + k += __lzo_align_gap(&x[k],n); + p0 = (lzo_bytep) &x[k]; +#if defined(PTR_LINEAR) + r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); +#else + r &= __lzo_assert(n == 4); + r &= __lzo_assert(PTR_ALIGNED_4(p0)); +#endif + + r &= __lzo_assert(k >= 1); + p1 = (lzo_bytep) &x[1]; + r &= __lzo_assert(PTR_GE(p0,p1)); + + r &= __lzo_assert(k < 1+n); + p1 = (lzo_bytep) &x[1+n]; + r &= __lzo_assert(PTR_LT(p0,p1)); + + if (r == 1) + { + lzo_uint32 v0, v1; +#if 0 + v0 = * (lzo_uint32 *) &x[k]; + v1 = * (lzo_uint32 *) &x[k+n]; +#else + + u.a_uchar_p = &x[k]; + v0 = *u.a_lzo_uint32_p; + u.a_uchar_p = &x[k+n]; + v1 = *u.a_lzo_uint32_p; +#endif + r &= __lzo_assert(v0 > 0); + r &= __lzo_assert(v1 > 0); + } + } + + return r; +} + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + int i; + union { + lzo_uint32 a; + unsigned short b; + lzo_uint32 aa[4]; + unsigned char x[4*sizeof(lzo_full_align_t)]; + } u; + + COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255); + COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0); + +#if 0 + r &= __lzo_assert((const void *)&u == (const void *)&u.a); + r &= __lzo_assert((const void *)&u == (const void *)&u.b); + r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); + r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); +#endif + + r &= basic_integral_check(); + r &= basic_ptr_check(); + if (r != 1) + return LZO_E_ERROR; + + u.a = 0; u.b = 0; + for (i = 0; i < (int) sizeof(u.x); i++) + u.x[i] = LZO_BYTE(i); + +#if defined(LZO_BYTE_ORDER) + if (r == 1) + { +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); + unsigned short b = (unsigned short) (u.b & 0xffff); + r &= __lzo_assert(a == 0x03020100L); + r &= __lzo_assert(b == 0x0100); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); + unsigned short b = u.b >> (8 * sizeof(u.b) - 16); + r &= __lzo_assert(a == 0x00010203L); + r &= __lzo_assert(b == 0x0001); +# else +# error "invalid LZO_BYTE_ORDER" +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_2) + COMPILE_TIME_ASSERT(sizeof(short) == 2); + if (r == 1) + { + unsigned short b[4]; + + for (i = 0; i < 4; i++) + b[i] = * (const unsigned short *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(b[0] == 0x0100); + r &= __lzo_assert(b[1] == 0x0201); + r &= __lzo_assert(b[2] == 0x0302); + r &= __lzo_assert(b[3] == 0x0403); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(b[0] == 0x0001); + r &= __lzo_assert(b[1] == 0x0102); + r &= __lzo_assert(b[2] == 0x0203); + r &= __lzo_assert(b[3] == 0x0304); +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + if (r == 1) + { + lzo_uint32 a[4]; + + for (i = 0; i < 4; i++) + a[i] = * (const lzo_uint32 *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(a[0] == 0x03020100L); + r &= __lzo_assert(a[1] == 0x04030201L); + r &= __lzo_assert(a[2] == 0x05040302L); + r &= __lzo_assert(a[3] == 0x06050403L); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(a[0] == 0x00010203L); + r &= __lzo_assert(a[1] == 0x01020304L); + r &= __lzo_assert(a[2] == 0x02030405L); + r &= __lzo_assert(a[3] == 0x03040506L); +# endif + } +#endif + +#if defined(LZO_ALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); +#endif + + COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); + +#if defined(__LZO_IN_MINLZO) + if (r == 1) + { + lzo_uint32 adler; + adler = lzo_adler32(0, NULL, 0); + adler = lzo_adler32(adler, lzo_copyright(), 200); + r &= __lzo_assert(adler == 0xc76f1751L); + } +#endif + + if (r == 1) + { + r &= __lzo_assert(!schedule_insns_bug()); + } + + if (r == 1) + { + static int x[3]; + static unsigned xn = 3; + register unsigned j; + + for (j = 0; j < xn; j++) + x[j] = (int)j - 3; + r &= __lzo_assert(!strength_reduce_bug(x)); + } + + if (r == 1) + { + r &= ptr_check(); + } + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +static lzo_bool schedule_insns_bug(void) +{ +#if defined(__LZO_CHECKER) + return 0; +#else + const int clone[] = {1, 2, 0}; + const int *q; + q = clone; + return (*q) ? 0 : 1; +#endif +} + +static lzo_bool strength_reduce_bug(int *x) +{ + return x[0] != -3 || x[1] != -2 || x[2] != -1; +} + +#undef COMPILE_TIME_ASSERT + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +LZO_EXTERN(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); + +LZO_PUBLIC(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) +{ + if (v == 0 || v > 0x1010) + return LZO_E_ERROR; + return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); +} + +#endif + +#define do_compress _lzo1x_1_do_compress + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) +{ + lzo_uint32 df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR( \ + (PTR_LT(m_pos,in) || \ + (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset) )) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + ((lzo_moff_t) ((ip)-(in)) <= m_off || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static +lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *ip __asm__("%esi"); +#else + register const lzo_byte *ip; +#endif + lzo_byte *op; + const lzo_byte * const in_end = in + in_len; + const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *m_pos __asm__("%edi"); +#else + register const lzo_byte *m_pos; +#endif + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if (m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if (ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = ip - ii; + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if (ip >= ip_end) + break; + } + + *out_len = op - out; + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_byte *op = out; + lzo_uint t; + +#if defined(__LZO_QUERY_COMPRESS) + if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); +#endif + + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_byte *ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_DECOMPRESS_OVERRUN +#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#define LZO_TEST_DECOMPRESS_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +/***** End of minilzo.c *****/ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.h new file mode 100755 index 0000000..e3270f9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.h @@ -0,0 +1,100 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x1080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rfbproto.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rfbproto.c new file mode 100755 index 0000000..33307d2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rfbproto.c @@ -0,0 +1,2123 @@ +/* + * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. 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. + */ + +/* + * rfbproto.c - functions to deal with client side of RFB protocol. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#ifndef WIN32 +#include +#include +#include +#else +#define strncasecmp _strnicmp +#endif +#include +#ifndef WIN32 +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_LIBZ +#include +#ifdef __CHECKER__ +#undef Z_NULL +#define Z_NULL NULL +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +#include +#endif +#include +#include + +#include "minilzo.h" +#include "tls.h" + +/* + * rfbClientLog prints a time-stamped message to the log file (stderr). + */ + +rfbBool rfbEnableClientLogging=TRUE; + +static void +rfbDefaultClientLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock)); + fprintf(stderr, "%s", buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); +} + +rfbClientLogProc rfbClientLog=rfbDefaultClientLog; +rfbClientLogProc rfbClientErr=rfbDefaultClientLog; + +/* extensions */ + +rfbClientProtocolExtension* rfbClientExtensions = NULL; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e) +{ + e->next = rfbClientExtensions; + rfbClientExtensions = e; +} + +/* client data */ + +void rfbClientSetClientData(rfbClient* client, void* tag, void* data) +{ + rfbClientData* clientData = client->clientData; + + while(clientData && clientData->tag != tag) + clientData = clientData->next; + if(clientData == NULL) { + clientData = calloc(sizeof(rfbClientData), 1); + clientData->next = client->clientData; + client->clientData = clientData; + clientData->tag = tag; + } + + clientData->data = data; +} + +void* rfbClientGetClientData(rfbClient* client, void* tag) +{ + rfbClientData* clientData = client->clientData; + + while(clientData) { + if(clientData->tag == tag) + return clientData->data; + clientData = clientData->next; + } + + return NULL; +} + +/* messages */ + +static void FillRectangle(rfbClient* client, int x, int y, int w, int h, uint32_t colour) { + int i,j; + +#define FILL_RECT(BPP) \ + for(j=y*client->width;j<(y+h)*client->width;j+=client->width) \ + for(i=x;iframeBuffer)[j+i]=colour; + + switch(client->format.bitsPerPixel) { + case 8: FILL_RECT(8); break; + case 16: FILL_RECT(16); break; + case 32: FILL_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +static void CopyRectangle(rfbClient* client, uint8_t* buffer, int x, int y, int w, int h) { + int j; + +#define COPY_RECT(BPP) \ + { \ + int rs = w * BPP / 8, rs2 = client->width * BPP / 8; \ + for (j = ((x * (BPP / 8)) + (y * rs2)); j < (y + h) * rs2; j += rs2) { \ + memcpy(client->frameBuffer + j, buffer, rs); \ + buffer += rs; \ + } \ + } + + switch(client->format.bitsPerPixel) { + case 8: COPY_RECT(8); break; + case 16: COPY_RECT(16); break; + case 32: COPY_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +/* TODO: test */ +static void CopyRectangleFromRectangle(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { + int i,j; + +#define COPY_RECT_FROM_RECT(BPP) \ + { \ + uint##BPP##_t* _buffer=((uint##BPP##_t*)client->frameBuffer)+(src_y-dest_y)*client->width+src_x-dest_x; \ + if (dest_y < src_y) { \ + for(j = dest_y*client->width; j < (dest_y+h)*client->width; j += client->width) { \ + if (dest_x < src_x) { \ + for(i = dest_x; i < dest_x+w; i++) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } else { \ + for(i = dest_x+w-1; i >= dest_x; i--) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } \ + } \ + } else { \ + for(j = (dest_y+h-1)*client->width; j >= dest_y*client->width; j-=client->width) { \ + if (dest_x < src_x) { \ + for(i = dest_x; i < dest_x+w; i++) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } else { \ + for(i = dest_x+w-1; i >= dest_x; i--) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } \ + } \ + } \ + } + + switch(client->format.bitsPerPixel) { + case 8: COPY_RECT_FROM_RECT(8); break; + case 16: COPY_RECT_FROM_RECT(16); break; + case 32: COPY_RECT_FROM_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +static rfbBool HandleRRE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleRRE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleRRE32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh); +#ifdef LIBVNCSERVER_HAVE_LIBZ +static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZlib32(rfbClient* client, int rx, int ry, int rw, int rh); +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +static rfbBool HandleTight8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTight16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTight32(rfbClient* client, int rx, int ry, int rw, int rh); + +static long ReadCompactLen (rfbClient* client); + +static void JpegInitSource(j_decompress_ptr cinfo); +static boolean JpegFillInputBuffer(j_decompress_ptr cinfo); +static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes); +static void JpegTermSource(j_decompress_ptr cinfo); +static void JpegSetSrcManager(j_decompress_ptr cinfo, uint8_t *compressedData, + int compressedLen); +#endif +static rfbBool HandleZRLE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE15(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24Up(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE32(rfbClient* client, int rx, int ry, int rw, int rh); +#endif + +/* + * Server Capability Functions + */ +rfbBool +SupportsClient2Server(rfbClient* client, int messageType) +{ + return (client->supportedMessages.client2server[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE); +} + +rfbBool +SupportsServer2Client(rfbClient* client, int messageType) +{ + return (client->supportedMessages.server2client[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE); +} + +void +SetClient2Server(rfbClient* client, int messageType) +{ + client->supportedMessages.client2server[((messageType & 0xFF)/8)] |= (1<<(messageType % 8)); +} + +void +SetServer2Client(rfbClient* client, int messageType) +{ + client->supportedMessages.server2client[((messageType & 0xFF)/8)] |= (1<<(messageType % 8)); +} + +void +ClearClient2Server(rfbClient* client, int messageType) +{ + client->supportedMessages.client2server[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8))); +} + +void +ClearServer2Client(rfbClient* client, int messageType) +{ + client->supportedMessages.server2client[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8))); +} + + +void +DefaultSupportedMessages(rfbClient* client) +{ + memset((char *)&client->supportedMessages,0,sizeof(client->supportedMessages)); + + /* Default client supported messages (universal RFB 3.3 protocol) */ + SetClient2Server(client, rfbSetPixelFormat); + /* SetClient2Server(client, rfbFixColourMapEntries); Not currently supported */ + SetClient2Server(client, rfbSetEncodings); + SetClient2Server(client, rfbFramebufferUpdateRequest); + SetClient2Server(client, rfbKeyEvent); + SetClient2Server(client, rfbPointerEvent); + SetClient2Server(client, rfbClientCutText); + /* technically, we only care what we can *send* to the server + * but, we set Server2Client Just in case it ever becomes useful + */ + SetServer2Client(client, rfbFramebufferUpdate); + SetServer2Client(client, rfbSetColourMapEntries); + SetServer2Client(client, rfbBell); + SetServer2Client(client, rfbServerCutText); +} + +void +DefaultSupportedMessagesUltraVNC(rfbClient* client) +{ + DefaultSupportedMessages(client); + SetClient2Server(client, rfbFileTransfer); + SetClient2Server(client, rfbSetScale); + SetClient2Server(client, rfbSetServerInput); + SetClient2Server(client, rfbSetSW); + SetClient2Server(client, rfbTextChat); + SetClient2Server(client, rfbPalmVNCSetScaleFactor); + /* technically, we only care what we can *send* to the server */ + SetServer2Client(client, rfbResizeFrameBuffer); + SetServer2Client(client, rfbPalmVNCReSizeFrameBuffer); + SetServer2Client(client, rfbFileTransfer); + SetServer2Client(client, rfbTextChat); +} + + +void +DefaultSupportedMessagesTightVNC(rfbClient* client) +{ + DefaultSupportedMessages(client); + SetClient2Server(client, rfbFileTransfer); + SetClient2Server(client, rfbSetServerInput); + SetClient2Server(client, rfbSetSW); + /* SetClient2Server(client, rfbTextChat); */ + /* technically, we only care what we can *send* to the server */ + SetServer2Client(client, rfbFileTransfer); + SetServer2Client(client, rfbTextChat); +} + +#ifndef WIN32 +static rfbBool +IsUnixSocket(const char *name) +{ + struct stat sb; + if(stat(name, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFSOCK) + return TRUE; + return FALSE; +} +#endif + +/* + * ConnectToRFBServer. + */ + +rfbBool +ConnectToRFBServer(rfbClient* client,const char *hostname, int port) +{ + unsigned int host; + + if (client->serverPort==-1) { + /* serverHost is a file recorded by vncrec. */ + const char* magic="vncLog0.0"; + char buffer[10]; + rfbVNCRec* rec = (rfbVNCRec*)malloc(sizeof(rfbVNCRec)); + client->vncRec = rec; + + rec->file = fopen(client->serverHost,"rb"); + rec->tv.tv_sec = 0; + rec->readTimestamp = FALSE; + rec->doNotSleep = FALSE; + + if (!rec->file) { + rfbClientLog("Could not open %s.\n",client->serverHost); + return FALSE; + } + setbuf(rec->file,NULL); + fread(buffer,1,strlen(magic),rec->file); + if (strncmp(buffer,magic,strlen(magic))) { + rfbClientLog("File %s was not recorded by vncrec.\n",client->serverHost); + fclose(rec->file); + return FALSE; + } + client->sock = -1; + return TRUE; + } + +#ifndef WIN32 + if(IsUnixSocket(hostname)) + /* serverHost is a UNIX socket. */ + client->sock = ConnectClientToUnixSock(hostname); + else +#endif + { + /* serverHost is a hostname */ + if (!StringToIPAddr(hostname, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", hostname); + return FALSE; + } + client->sock = ConnectClientToTcpAddr(host, port); + } + + if (client->sock < 0) { + rfbClientLog("Unable to connect to VNC server\n"); + return FALSE; + } + + return SetNonBlocking(client->sock); +} + +/* + * ConnectToRFBRepeater. + */ + +rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort) +{ + unsigned int host; + rfbProtocolVersionMsg pv; + int major,minor; + char tmphost[250]; + + if (!StringToIPAddr(repeaterHost, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost); + return FALSE; + } + + client->sock = ConnectClientToTcpAddr(host, repeaterPort); + + if (client->sock < 0) { + rfbClientLog("Unable to connect to VNC repeater\n"); + return FALSE; + } + + if (!SetNonBlocking(client->sock)) + return FALSE; + + if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) + return FALSE; + pv[sz_rfbProtocolVersionMsg] = 0; + + /* UltraVNC repeater always report version 000.000 to identify itself */ + if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2 || major != 0 || minor != 0) { + rfbClientLog("Not a valid VNC repeater (%s)\n",pv); + return FALSE; + } + + rfbClientLog("Connected to VNC repeater, using protocol version %d.%d\n", major, minor); + + snprintf(tmphost, sizeof(tmphost), "%s:%d", destHost, destPort); + if (!WriteToRFBServer(client, tmphost, sizeof(tmphost))) + return FALSE; + + return TRUE; +} + +extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd); +extern void rfbClientEncryptBytes2(unsigned char *where, const int length, unsigned char *key); + +rfbBool +rfbHandleAuthResult(rfbClient* client) +{ + uint32_t authResult=0, reasonLen=0; + char *reason=NULL; + + if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE; + + authResult = rfbClientSwap32IfLE(authResult); + + switch (authResult) { + case rfbVncAuthOK: + rfbClientLog("VNC authentication succeeded\n"); + return TRUE; + break; + case rfbVncAuthFailed: + if (client->major==3 && client->minor>7) + { + /* we have an error following */ + if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE; + reasonLen = rfbClientSwap32IfLE(reasonLen); + reason = malloc(reasonLen+1); + if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; } + reason[reasonLen]=0; + rfbClientLog("VNC connection failed: %s\n",reason); + free(reason); + return FALSE; + } + rfbClientLog("VNC authentication failed\n"); + return FALSE; + case rfbVncAuthTooMany: + rfbClientLog("VNC authentication failed - too many tries\n"); + return FALSE; + } + + rfbClientLog("Unknown VNC authentication result: %d\n", + (int)authResult); + return FALSE; +} + +static void +ReadReason(rfbClient* client) +{ + uint32_t reasonLen; + char *reason; + + /* we have an error following */ + if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return; + reasonLen = rfbClientSwap32IfLE(reasonLen); + reason = malloc(reasonLen+1); + if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return; } + reason[reasonLen]=0; + rfbClientLog("VNC connection failed: %s\n",reason); + free(reason); +} + +static rfbBool +ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) +{ + uint8_t count=0; + uint8_t loop=0; + uint8_t flag=0; + uint8_t tAuth[256]; + char buf1[500],buf2[10]; + uint32_t authScheme; + + if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; + + if (count==0) + { + rfbClientLog("List of security types is ZERO, expecting an error to follow\n"); + ReadReason(client); + return FALSE; + } + if (count>sizeof(tAuth)) + { + rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth)); + return FALSE; + } + + rfbClientLog("We have %d security types to read\n", count); + authScheme=0; + /* now, we have a list of available security types to read ( uint8_t[] ) */ + for (loop=0;loopclientAuthSchemes) + { + int i; + for (i=0;client->clientAuthSchemes[i];i++) + { + if (client->clientAuthSchemes[i]==(uint32_t)tAuth[loop]) + { + flag++; + authScheme=tAuth[loop]; + break; + } + } + } + else + { + flag++; + authScheme=tAuth[loop]; + } + if (flag) + { + rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count); + /* send back a single byte indicating which security type to use */ + if (!WriteToRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE; + } + } + } + if (authScheme==0) + { + memset(buf1, 0, sizeof(buf1)); + for (loop=0;loop=sizeof(buf1)-1) break; + snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]); + strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1); + } + rfbClientLog("Unknown authentication scheme from VNC server: %s\n", + buf1); + return FALSE; + } + *result = authScheme; + return TRUE; +} + +static rfbBool +HandleVncAuth(rfbClient *client) +{ + uint8_t challenge[CHALLENGESIZE]; + char *passwd=NULL; + int i; + + if (!ReadFromRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE; + + if (client->serverPort!=-1) { /* if not playing a vncrec file */ + if (client->GetPassword) + passwd = client->GetPassword(client); + + if ((!passwd) || (strlen(passwd) == 0)) { + rfbClientLog("Reading password failed\n"); + return FALSE; + } + if (strlen(passwd) > 8) { + passwd[8] = '\0'; + } + + rfbClientEncryptBytes(challenge, passwd); + + /* Lose the password from memory */ + for (i = strlen(passwd); i >= 0; i--) { + passwd[i] = '\0'; + } + free(passwd); + + if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE; + } + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +static void +FreeUserCredential(rfbCredential *cred) +{ + if (cred->userCredential.username) free(cred->userCredential.username); + if (cred->userCredential.password) free(cred->userCredential.password); + free(cred); +} + +static rfbBool +HandlePlainAuth(rfbClient *client) +{ + uint32_t ulen, ulensw; + uint32_t plen, plensw; + rfbCredential *cred; + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + cred = client->GetCredential(client, rfbCredentialTypeUser); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + ulen = (cred->userCredential.username ? strlen(cred->userCredential.username) : 0); + ulensw = rfbClientSwap32IfLE(ulen); + plen = (cred->userCredential.password ? strlen(cred->userCredential.password) : 0); + plensw = rfbClientSwap32IfLE(plen); + if (!WriteToRFBServer(client, (char *)&ulensw, 4) || + !WriteToRFBServer(client, (char *)&plensw, 4)) + { + FreeUserCredential(cred); + return FALSE; + } + if (ulen > 0) + { + if (!WriteToRFBServer(client, cred->userCredential.username, ulen)) + { + FreeUserCredential(cred); + return FALSE; + } + } + if (plen > 0) + { + if (!WriteToRFBServer(client, cred->userCredential.password, plen)) + { + FreeUserCredential(cred); + return FALSE; + } + } + + FreeUserCredential(cred); + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +/* Simple 64bit big integer arithmetic implementation */ +/* (x + y) % m, works even if (x + y) > 64bit */ +#define rfbAddM64(x,y,m) ((x+y)%m+(x+y0;x>>=1) + { + if (x&1) r=rfbAddM64(r,y,m); + y=rfbAddM64(y,y,m); + } + return r; +} +/* (x ^ y) % m */ +static uint64_t +rfbPowM64(uint64_t b, uint64_t e, uint64_t m) +{ + uint64_t r; + for(r=1;e>0;e>>=1) + { + if(e&1) r=rfbMulM64(r,b,m); + b=rfbMulM64(b,b,m); + } + return r; +} + +static rfbBool +HandleMSLogonAuth(rfbClient *client) +{ + uint64_t gen, mod, resp, priv, pub, key; + uint8_t username[256], password[64]; + rfbCredential *cred; + + if (!ReadFromRFBServer(client, (char *)&gen, 8)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&mod, 8)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&resp, 8)) return FALSE; + gen = rfbClientSwap64IfLE(gen); + mod = rfbClientSwap64IfLE(mod); + resp = rfbClientSwap64IfLE(resp); + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + rfbClientLog("WARNING! MSLogon security type has very low password encryption! "\ + "Use it only with SSH tunnel or trusted network.\n"); + cred = client->GetCredential(client, rfbCredentialTypeUser); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + memset(username, 0, sizeof(username)); + strncpy((char *)username, cred->userCredential.username, sizeof(username)); + memset(password, 0, sizeof(password)); + strncpy((char *)password, cred->userCredential.password, sizeof(password)); + FreeUserCredential(cred); + + srand(time(NULL)); + priv = ((uint64_t)rand())<<32; + priv |= (uint64_t)rand(); + + pub = rfbPowM64(gen, priv, mod); + key = rfbPowM64(resp, priv, mod); + pub = rfbClientSwap64IfLE(pub); + key = rfbClientSwap64IfLE(key); + + rfbClientEncryptBytes2(username, sizeof(username), (unsigned char *)&key); + rfbClientEncryptBytes2(password, sizeof(password), (unsigned char *)&key); + + if (!WriteToRFBServer(client, (char *)&pub, 8)) return FALSE; + if (!WriteToRFBServer(client, (char *)username, sizeof(username))) return FALSE; + if (!WriteToRFBServer(client, (char *)password, sizeof(password))) return FALSE; + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +/* + * SetClientAuthSchemes. + */ + +void +SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size) +{ + int i; + + if (client->clientAuthSchemes) + { + free(client->clientAuthSchemes); + client->clientAuthSchemes = NULL; + } + if (authSchemes) + { + if (size<0) + { + /* If size<0 we assume the passed-in list is also 0-terminate, so we + * calculate the size here */ + for (size=0;authSchemes[size];size++) ; + } + client->clientAuthSchemes = (uint32_t*)malloc(sizeof(uint32_t)*(size+1)); + for (i=0;iclientAuthSchemes[i] = authSchemes[i]; + client->clientAuthSchemes[size] = 0; + } +} + +/* + * InitialiseRFBConnection. + */ + +rfbBool +InitialiseRFBConnection(rfbClient* client) +{ + rfbProtocolVersionMsg pv; + int major,minor; + uint32_t authScheme; + uint32_t subAuthScheme; + rfbClientInitMsg ci; + + /* if the connection is immediately closed, don't report anything, so + that pmw's monitor can make test connections */ + + if (client->listenSpecified) + errorMessageOnReadFailure = FALSE; + + if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE; + pv[sz_rfbProtocolVersionMsg]=0; + + errorMessageOnReadFailure = TRUE; + + pv[sz_rfbProtocolVersionMsg] = 0; + + if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { + rfbClientLog("Not a valid VNC server (%s)\n",pv); + return FALSE; + } + + + DefaultSupportedMessages(client); + client->major = major; + client->minor = minor; + + /* fall back to viewer supported version */ + if ((major==rfbProtocolMajorVersion) && (minor>rfbProtocolMinorVersion)) + client->minor = rfbProtocolMinorVersion; + + /* UltraVNC uses minor codes 4 and 6 for the server */ + if (major==3 && (minor==4 || minor==6)) { + rfbClientLog("UltraVNC server detected, enabling UltraVNC specific messages\n",pv); + DefaultSupportedMessagesUltraVNC(client); + } + + /* TightVNC uses minor codes 5 for the server */ + if (major==3 && minor==5) { + rfbClientLog("TightVNC server detected, enabling TightVNC specific messages\n",pv); + DefaultSupportedMessagesTightVNC(client); + } + + /* we do not support > RFB3.8 */ + if ((major==3 && minor>8) || major>3) + { + client->major=3; + client->minor=8; + } + + rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n", + major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion); + + sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor); + + if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE; + + + /* 3.7 and onwards sends a # of security types first */ + if (client->major==3 && client->minor > 6) + { + if (!ReadSupportedSecurityType(client, &authScheme, FALSE)) return FALSE; + } + else + { + if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE; + authScheme = rfbClientSwap32IfLE(authScheme); + } + + rfbClientLog("Selected Security Scheme %d\n", authScheme); + client->authScheme = authScheme; + + switch (authScheme) { + + case rfbConnFailed: + ReadReason(client); + return FALSE; + + case rfbNoAuth: + rfbClientLog("No authentication needed\n"); + + /* 3.8 and upwards sends a Security Result for rfbNoAuth */ + if ((client->major==3 && client->minor > 7) || client->major>3) + if (!rfbHandleAuthResult(client)) return FALSE; + + break; + + case rfbVncAuth: + if (!HandleVncAuth(client)) return FALSE; + break; + + case rfbMSLogon: + if (!HandleMSLogonAuth(client)) return FALSE; + break; + + case rfbTLS: +#ifndef LIBVNCSERVER_WITH_CLIENT_TLS + rfbClientLog("TLS support was not compiled in\n"); + return FALSE; +#else + if (!HandleAnonTLSAuth(client)) return FALSE; + /* After the TLS session is established, sub auth types are expected. + * Note that all following reading/writing are through the TLS session from here. + */ + if (!ReadSupportedSecurityType(client, &subAuthScheme, TRUE)) return FALSE; + client->subAuthScheme = subAuthScheme; + + switch (subAuthScheme) { + + case rfbConnFailed: + ReadReason(client); + return FALSE; + + case rfbNoAuth: + rfbClientLog("No sub authentication needed\n"); + /* 3.8 and upwards sends a Security Result for rfbNoAuth */ + if ((client->major==3 && client->minor > 7) || client->major>3) + if (!rfbHandleAuthResult(client)) return FALSE; + break; + + case rfbVncAuth: + if (!HandleVncAuth(client)) return FALSE; + break; + + default: + rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", + (int)subAuthScheme); + return FALSE; + } +#endif + + break; + + case rfbVeNCrypt: +#ifndef LIBVNCSERVER_WITH_CLIENT_TLS + rfbClientLog("TLS support was not compiled in\n"); + return FALSE; +#else + if (!HandleVeNCryptAuth(client)) return FALSE; + + switch (client->subAuthScheme) { + + case rfbVeNCryptTLSNone: + case rfbVeNCryptX509None: + rfbClientLog("No sub authentication needed\n"); + if (!rfbHandleAuthResult(client)) return FALSE; + break; + + case rfbVeNCryptTLSVNC: + case rfbVeNCryptX509VNC: + if (!HandleVncAuth(client)) return FALSE; + break; + + case rfbVeNCryptTLSPlain: + case rfbVeNCryptX509Plain: + if (!HandlePlainAuth(client)) return FALSE; + break; + + default: + rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", + client->subAuthScheme); + return FALSE; + } +#endif + break; + + default: + rfbClientLog("Unknown authentication scheme from VNC server: %d\n", + (int)authScheme); + return FALSE; + } + + ci.shared = (client->appData.shareDesktop ? 1 : 0); + + if (!WriteToRFBServer(client, (char *)&ci, sz_rfbClientInitMsg)) return FALSE; + + if (!ReadFromRFBServer(client, (char *)&client->si, sz_rfbServerInitMsg)) return FALSE; + + client->si.framebufferWidth = rfbClientSwap16IfLE(client->si.framebufferWidth); + client->si.framebufferHeight = rfbClientSwap16IfLE(client->si.framebufferHeight); + client->si.format.redMax = rfbClientSwap16IfLE(client->si.format.redMax); + client->si.format.greenMax = rfbClientSwap16IfLE(client->si.format.greenMax); + client->si.format.blueMax = rfbClientSwap16IfLE(client->si.format.blueMax); + client->si.nameLength = rfbClientSwap32IfLE(client->si.nameLength); + + client->desktopName = malloc(client->si.nameLength + 1); + if (!client->desktopName) { + rfbClientLog("Error allocating memory for desktop name, %lu bytes\n", + (unsigned long)client->si.nameLength); + return FALSE; + } + + if (!ReadFromRFBServer(client, client->desktopName, client->si.nameLength)) return FALSE; + + client->desktopName[client->si.nameLength] = 0; + + rfbClientLog("Desktop name \"%s\"\n",client->desktopName); + + rfbClientLog("Connected to VNC server, using protocol version %d.%d\n", + client->major, client->minor); + + rfbClientLog("VNC server default format:\n"); + PrintPixelFormat(&client->si.format); + + return TRUE; +} + + +/* + * SetFormatAndEncodings. + */ + +rfbBool +SetFormatAndEncodings(rfbClient* client) +{ + rfbSetPixelFormatMsg spf; + char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4]; + + rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf; + uint32_t *encs = (uint32_t *)(&buf[sz_rfbSetEncodingsMsg]); + int len = 0; + rfbBool requestCompressLevel = FALSE; + rfbBool requestQualityLevel = FALSE; + rfbBool requestLastRectEncoding = FALSE; + rfbClientProtocolExtension* e; + + if (!SupportsClient2Server(client, rfbSetPixelFormat)) return TRUE; + + spf.type = rfbSetPixelFormat; + spf.format = client->format; + spf.format.redMax = rfbClientSwap16IfLE(spf.format.redMax); + spf.format.greenMax = rfbClientSwap16IfLE(spf.format.greenMax); + spf.format.blueMax = rfbClientSwap16IfLE(spf.format.blueMax); + + if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg)) + return FALSE; + + + if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE; + + se->type = rfbSetEncodings; + se->nEncodings = 0; + + if (client->appData.encodingsString) { + const char *encStr = client->appData.encodingsString; + int encStrLen; + do { + const char *nextEncStr = strchr(encStr, ' '); + if (nextEncStr) { + encStrLen = nextEncStr - encStr; + nextEncStr++; + } else { + encStrLen = strlen(encStr); + } + + if (strncasecmp(encStr,"raw",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw); + } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect); +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + } else if (strncasecmp(encStr,"tight",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight); + requestLastRectEncoding = TRUE; + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + if (client->appData.enableJPEG) + requestQualityLevel = TRUE; +#endif +#endif + } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile); +#ifdef LIBVNCSERVER_HAVE_LIBZ + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib); + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + } else if (strncasecmp(encStr,"zlibhex",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlibHex); + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); + } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE); + requestQualityLevel = TRUE; +#endif + } else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) { + /* There are 2 encodings used in 'ultra' */ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip); + } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); + } else if (strncasecmp(encStr,"rre",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE); + } else { + rfbClientLog("Unknown encoding '%.*s'\n",encStrLen,encStr); + } + + encStr = nextEncStr; + } while (encStr && se->nEncodings < MAX_ENCODINGS); + + if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel + + rfbEncodingCompressLevel0); + } + + if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { + if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9) + client->appData.qualityLevel = 5; + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel + + rfbEncodingQualityLevel0); + } + } + else { + if (SameMachine(client->sock)) { + /* TODO: + if (!tunnelSpecified) { + */ + rfbClientLog("Same machine: preferring raw encoding\n"); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw); + /* + } else { + rfbClientLog("Tunneling active: preferring tight encoding\n"); + } + */ + } + + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect); +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight); + requestLastRectEncoding = TRUE; +#endif +#endif + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile); +#ifdef LIBVNCSERVER_HAVE_LIBZ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE); +#endif + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE); + + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel + + rfbEncodingCompressLevel0); + } else /* if (!tunnelSpecified) */ { + /* If -tunnel option was provided, we assume that server machine is + not in the local network so we use default compression level for + tight encoding instead of fast compression. Thus we are + requesting level 1 compression only if tunneling is not used. */ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCompressLevel1); + } + + if (client->appData.enableJPEG) { + if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9) + client->appData.qualityLevel = 5; + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel + + rfbEncodingQualityLevel0); + } + } + + + + /* Remote Cursor Support (local to viewer) */ + if (client->appData.useRemoteCursor) { + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXCursor); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRichCursor); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos); + } + + /* Keyboard State Encodings */ + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState); + + /* New Frame Buffer Size */ + if (se->nEncodings < MAX_ENCODINGS && client->canHandleNewFBSize) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingNewFBSize); + + /* Last Rect */ + if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect); + + /* Server Capabilities */ + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedMessages); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedEncodings); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingServerIdentity); + + + /* client extensions */ + for(e = rfbClientExtensions; e; e = e->next) + if(e->encodings) { + int* enc; + for(enc = e->encodings; *enc; enc++) + encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc); + } + + len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; + + se->nEncodings = rfbClientSwap16IfLE(se->nEncodings); + + if (!WriteToRFBServer(client, buf, len)) return FALSE; + + return TRUE; +} + + +/* + * SendIncrementalFramebufferUpdateRequest. + */ + +rfbBool +SendIncrementalFramebufferUpdateRequest(rfbClient* client) +{ + return SendFramebufferUpdateRequest(client, + client->updateRect.x, client->updateRect.y, + client->updateRect.w, client->updateRect.h, TRUE); +} + + +/* + * SendFramebufferUpdateRequest. + */ + +rfbBool +SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbBool incremental) +{ + rfbFramebufferUpdateRequestMsg fur; + + if (!SupportsClient2Server(client, rfbFramebufferUpdateRequest)) return TRUE; + + fur.type = rfbFramebufferUpdateRequest; + fur.incremental = incremental ? 1 : 0; + fur.x = rfbClientSwap16IfLE(x); + fur.y = rfbClientSwap16IfLE(y); + fur.w = rfbClientSwap16IfLE(w); + fur.h = rfbClientSwap16IfLE(h); + + if (!WriteToRFBServer(client, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) + return FALSE; + + return TRUE; +} + + +/* + * SendScaleSetting. + */ +rfbBool +SendScaleSetting(rfbClient* client,int scaleSetting) +{ + rfbSetScaleMsg ssm; + + ssm.scale = scaleSetting; + ssm.pad = 0; + + /* favor UltraVNC SetScale if both are supported */ + if (SupportsClient2Server(client, rfbSetScale)) { + ssm.type = rfbSetScale; + if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg)) + return FALSE; + } + + if (SupportsClient2Server(client, rfbPalmVNCSetScaleFactor)) { + ssm.type = rfbPalmVNCSetScaleFactor; + if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg)) + return FALSE; + } + + return TRUE; +} + +/* + * TextChatFunctions (UltraVNC) + * Extremely bandwidth friendly method of communicating with a user + * (Think HelpDesk type applications) + */ + +rfbBool TextChatSend(rfbClient* client, char *text) +{ + rfbTextChatMsg chat; + int count = strlen(text); + + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = (uint32_t)count; + chat.length = rfbClientSwap32IfLE(chat.length); + + if (!WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg)) + return FALSE; + + if (count>0) { + if (!WriteToRFBServer(client, text, count)) + return FALSE; + } + return TRUE; +} + +rfbBool TextChatOpen(rfbClient* client) +{ + rfbTextChatMsg chat; + + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatOpen); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +rfbBool TextChatClose(rfbClient* client) +{ + rfbTextChatMsg chat; + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatClose); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +rfbBool TextChatFinish(rfbClient* client) +{ + rfbTextChatMsg chat; + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatFinished); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +/* + * UltraVNC Server Input Disable + * Apparently, the remote client can *prevent* the local user from interacting with the display + * I would think this is extremely helpful when used in a HelpDesk situation + */ +rfbBool PermitServerInput(rfbClient* client, int enabled) +{ + rfbSetServerInputMsg msg; + + if (!SupportsClient2Server(client, rfbSetServerInput)) return TRUE; + /* enabled==1, then server input from local keyboard is disabled */ + msg.type = rfbSetServerInput; + msg.status = (enabled ? 1 : 0); + msg.pad = 0; + return (WriteToRFBServer(client, (char *)&msg, sz_rfbSetServerInputMsg) ? TRUE : FALSE); +} + + +/* + * SendPointerEvent. + */ + +rfbBool +SendPointerEvent(rfbClient* client,int x, int y, int buttonMask) +{ + rfbPointerEventMsg pe; + + if (!SupportsClient2Server(client, rfbPointerEvent)) return TRUE; + + pe.type = rfbPointerEvent; + pe.buttonMask = buttonMask; + if (x < 0) x = 0; + if (y < 0) y = 0; + + pe.x = rfbClientSwap16IfLE(x); + pe.y = rfbClientSwap16IfLE(y); + return WriteToRFBServer(client, (char *)&pe, sz_rfbPointerEventMsg); +} + + +/* + * SendKeyEvent. + */ + +rfbBool +SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down) +{ + rfbKeyEventMsg ke; + + if (!SupportsClient2Server(client, rfbKeyEvent)) return TRUE; + + ke.type = rfbKeyEvent; + ke.down = down ? 1 : 0; + ke.key = rfbClientSwap32IfLE(key); + return WriteToRFBServer(client, (char *)&ke, sz_rfbKeyEventMsg); +} + + +/* + * SendClientCutText. + */ + +rfbBool +SendClientCutText(rfbClient* client, char *str, int len) +{ + rfbClientCutTextMsg cct; + + if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE; + + cct.type = rfbClientCutText; + cct.length = rfbClientSwap32IfLE(len); + return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) && + WriteToRFBServer(client, str, len)); +} + + + +/* + * HandleRFBServerMessage. + */ + +rfbBool +HandleRFBServerMessage(rfbClient* client) +{ + rfbServerToClientMsg msg; + + if (client->serverPort==-1) + client->vncRec->readTimestamp = TRUE; + if (!ReadFromRFBServer(client, (char *)&msg, 1)) + return FALSE; + + switch (msg.type) { + + case rfbSetColourMapEntries: + { + /* TODO: + int i; + uint16_t rgb[3]; + XColor xc; + + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbSetColourMapEntriesMsg - 1)) + return FALSE; + + msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour); + msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours); + + for (i = 0; i < msg.scme.nColours; i++) { + if (!ReadFromRFBServer(client, (char *)rgb, 6)) + return FALSE; + xc.pixel = msg.scme.firstColour + i; + xc.red = rfbClientSwap16IfLE(rgb[0]); + xc.green = rfbClientSwap16IfLE(rgb[1]); + xc.blue = rfbClientSwap16IfLE(rgb[2]); + xc.flags = DoRed|DoGreen|DoBlue; + XStoreColor(dpy, cmap, &xc); + } + */ + + break; + } + + case rfbFramebufferUpdate: + { + rfbFramebufferUpdateRectHeader rect; + int linesToRead; + int bytesPerLine; + int i; + + if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1, + sz_rfbFramebufferUpdateMsg - 1)) + return FALSE; + + msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects); + + for (i = 0; i < msg.fu.nRects; i++) { + if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader)) + return FALSE; + + rect.encoding = rfbClientSwap32IfLE(rect.encoding); + if (rect.encoding == rfbEncodingLastRect) + break; + + rect.r.x = rfbClientSwap16IfLE(rect.r.x); + rect.r.y = rfbClientSwap16IfLE(rect.r.y); + rect.r.w = rfbClientSwap16IfLE(rect.r.w); + rect.r.h = rfbClientSwap16IfLE(rect.r.h); + + + if (rect.encoding == rfbEncodingXCursor || + rect.encoding == rfbEncodingRichCursor) { + + if (!HandleCursorShape(client, + rect.r.x, rect.r.y, rect.r.w, rect.r.h, + rect.encoding)) { + return FALSE; + } + continue; + } + + if (rect.encoding == rfbEncodingPointerPos) { + if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) { + return FALSE; + } + continue; + } + + if (rect.encoding == rfbEncodingKeyboardLedState) { + /* OK! We have received a keyboard state message!!! */ + client->KeyboardLedStateEnabled = 1; + if (client->HandleKeyboardLedState!=NULL) + client->HandleKeyboardLedState(client, rect.r.x, 0); + /* stash it for the future */ + client->CurrentKeyboardLedState = rect.r.x; + continue; + } + + if (rect.encoding == rfbEncodingNewFBSize) { + client->width = rect.r.w; + client->height = rect.r.h; + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h); + continue; + } + + /* rect.r.w=byte count */ + if (rect.encoding == rfbEncodingSupportedMessages) { + int loop; + if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages)) + return FALSE; + + /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */ + /* currently ignored by this library */ + + rfbClientLog("client2server supported messages (bit flags)\n"); + for (loop=0;loop<32;loop+=8) + rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop, + client->supportedMessages.client2server[loop], client->supportedMessages.client2server[loop+1], + client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3], + client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5], + client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]); + + rfbClientLog("server2client supported messages (bit flags)\n"); + for (loop=0;loop<32;loop+=8) + rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop, + client->supportedMessages.server2client[loop], client->supportedMessages.server2client[loop+1], + client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3], + client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5], + client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]); + continue; + } + + /* rect.r.w=byte count, rect.r.h=# of encodings */ + if (rect.encoding == rfbEncodingSupportedEncodings) { + char *buffer; + buffer = malloc(rect.r.w); + if (!ReadFromRFBServer(client, buffer, rect.r.w)) + { + free(buffer); + return FALSE; + } + + /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */ + /* currently ignored by this library */ + free(buffer); + continue; + } + + /* rect.r.w=byte count */ + if (rect.encoding == rfbEncodingServerIdentity) { + char *buffer; + buffer = malloc(rect.r.w+1); + if (!ReadFromRFBServer(client, buffer, rect.r.w)) + { + free(buffer); + return FALSE; + } + buffer[rect.r.w]=0; /* null terminate, just in case */ + rfbClientLog("Connected to Server \"%s\"\n", buffer); + free(buffer); + continue; + } + + /* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */ + if (rect.encoding != rfbEncodingUltraZip) + { + if ((rect.r.x + rect.r.w > client->width) || + (rect.r.y + rect.r.h > client->height)) + { + rfbClientLog("Rect too large: %dx%d at (%d, %d)\n", + rect.r.w, rect.r.h, rect.r.x, rect.r.y); + return FALSE; + } + + /* UltraVNC with scaling, will send rectangles with a zero W or H + * + if ((rect.encoding != rfbEncodingTight) && + (rect.r.h * rect.r.w == 0)) + { + rfbClientLog("Zero size rect - ignoring (encoding=%d (0x%08x) %dx, %dy, %dw, %dh)\n", rect.encoding, rect.encoding, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + continue; + } + */ + + /* If RichCursor encoding is used, we should prevent collisions + between framebuffer updates and cursor drawing operations. */ + client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + } + + switch (rect.encoding) { + + case rfbEncodingRaw: { + int y=rect.r.y, h=rect.r.h; + + bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8; + linesToRead = RFB_BUFFER_SIZE / bytesPerLine; + + while (h > 0) { + if (linesToRead > h) + linesToRead = h; + + if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead)) + return FALSE; + + CopyRectangle(client, (uint8_t *)client->buffer, + rect.r.x, y, rect.r.w,linesToRead); + + h -= linesToRead; + y += linesToRead; + + } + } break; + + case rfbEncodingCopyRect: + { + rfbCopyRect cr; + + if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect)) + return FALSE; + + cr.srcX = rfbClientSwap16IfLE(cr.srcX); + cr.srcY = rfbClientSwap16IfLE(cr.srcY); + + /* If RichCursor encoding is used, we should extend our + "cursor lock area" (previously set to destination + rectangle) to the source rectangle as well. */ + client->SoftCursorLockArea(client, + cr.srcX, cr.srcY, rect.r.w, rect.r.h); + + if (client->GotCopyRect != NULL) { + client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h, + rect.r.x, rect.r.y); + } else + CopyRectangleFromRectangle(client, + cr.srcX, cr.srcY, rect.r.w, rect.r.h, + rect.r.x, rect.r.y); + + break; + } + + case rfbEncodingRRE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingCoRRE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingHextile: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingUltra: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + case rfbEncodingUltraZip: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZlib: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + case rfbEncodingTight: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } +#endif + case rfbEncodingZRLE: + /* Fail safe for ZYWRLE unsupport VNC server. */ + client->appData.qualityLevel = 9; + /* fall through */ + case rfbEncodingZYWRLE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (client->si.format.greenMax > 0x1F) { + if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else { + if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } + break; + case 32: + { + uint32_t maxColor=(client->format.redMax<format.redShift)| + (client->format.greenMax<format.greenShift)| + (client->format.blueMax<format.blueShift); + if ((client->format.bigEndian && (maxColor&0xff)==0) || + (!client->format.bigEndian && (maxColor&0xff000000)==0)) { + if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (!client->format.bigEndian && (maxColor&0xff)==0) { + if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (client->format.bigEndian && (maxColor&0xff000000)==0) { + if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + } + break; + } + +#endif + + default: + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleEncoding && e->handleEncoding(client, &rect)) + handled = TRUE; + + if(!handled) { + rfbClientLog("Unknown rect encoding %d\n", + (int)rect.encoding); + return FALSE; + } + } + } + + /* Now we may discard "soft cursor locks". */ + client->SoftCursorUnlockScreen(client); + + client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + } + + if (!SendIncrementalFramebufferUpdateRequest(client)) + return FALSE; + + if (client->FinishedFrameBufferUpdate) + client->FinishedFrameBufferUpdate(client); + + break; + } + + case rfbBell: + { + client->Bell(client); + + break; + } + + case rfbServerCutText: + { + char *buffer; + + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbServerCutTextMsg - 1)) + return FALSE; + + msg.sct.length = rfbClientSwap32IfLE(msg.sct.length); + + buffer = malloc(msg.sct.length+1); + + if (!ReadFromRFBServer(client, buffer, msg.sct.length)) + return FALSE; + + buffer[msg.sct.length] = 0; + + if (client->GotXCutText) + client->GotXCutText(client, buffer, msg.sct.length); + + free(buffer); + + break; + } + + case rfbTextChat: + { + char *buffer=NULL; + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbTextChatMsg- 1)) + return FALSE; + msg.tc.length = rfbClientSwap32IfLE(msg.sct.length); + switch(msg.tc.length) { + case rfbTextChatOpen: + rfbClientLog("Received TextChat Open\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatOpen, NULL); + break; + case rfbTextChatClose: + rfbClientLog("Received TextChat Close\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatClose, NULL); + break; + case rfbTextChatFinished: + rfbClientLog("Received TextChat Finished\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatFinished, NULL); + break; + default: + buffer=malloc(msg.tc.length+1); + if (!ReadFromRFBServer(client, buffer, msg.tc.length)) + { + free(buffer); + return FALSE; + } + /* Null Terminate */ + buffer[msg.tc.length]=0; + rfbClientLog("Received TextChat \"%s\"\n", buffer); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)msg.tc.length, buffer); + free(buffer); + break; + } + break; + } + + case rfbResizeFrameBuffer: + { + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbResizeFrameBufferMsg -1)) + return FALSE; + client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth); + client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth); + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; + } + + case rfbPalmVNCReSizeFrameBuffer: + { + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbPalmVNCReSizeFrameBufferMsg -1)) + return FALSE; + client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w); + client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h); + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; + } + + default: + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleMessage && e->handleMessage(client, &msg)) + handled = TRUE; + + if(!handled) { + char buffer[256]; + rfbClientLog("Unknown message type %d from VNC server\n",msg.type); + ReadFromRFBServer(client, buffer, 256); + return FALSE; + } + } + } + + return TRUE; +} + + +#define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++) + +#define GET_PIXEL16(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \ + ((uint8_t*)&(pix))[1] = *(ptr)++) + +#define GET_PIXEL32(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \ + ((uint8_t*)&(pix))[1] = *(ptr)++, \ + ((uint8_t*)&(pix))[2] = *(ptr)++, \ + ((uint8_t*)&(pix))[3] = *(ptr)++) + +/* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also + expands its arguments if they are macros */ + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + +#define BPP 8 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#undef BPP +#define BPP 16 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#define REALBPP 15 +#include "zrle.c" +#undef BPP +#define BPP 32 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#define REALBPP 24 +#include "zrle.c" +#define REALBPP 24 +#define UNCOMP 8 +#include "zrle.c" +#define REALBPP 24 +#define UNCOMP -8 +#include "zrle.c" +#undef BPP + + +/* + * PrintPixelFormat. + */ + +void +PrintPixelFormat(rfbPixelFormat *format) +{ + if (format->bitsPerPixel == 1) { + rfbClientLog(" Single bit per pixel.\n"); + rfbClientLog( + " %s significant bit in each byte is leftmost on the screen.\n", + (format->bigEndian ? "Most" : "Least")); + } else { + rfbClientLog(" %d bits per pixel.\n",format->bitsPerPixel); + if (format->bitsPerPixel != 8) { + rfbClientLog(" %s significant byte first in each pixel.\n", + (format->bigEndian ? "Most" : "Least")); + } + if (format->trueColour) { + rfbClientLog(" TRUE colour: max red %d green %d blue %d" + ", shift red %d green %d blue %d\n", + format->redMax, format->greenMax, format->blueMax, + format->redShift, format->greenShift, format->blueShift); + } else { + rfbClientLog(" Colour map (not true colour).\n"); + } + } +} + +/* avoid name clashes with LibVNCServer */ + +#define rfbEncryptBytes rfbClientEncryptBytes +#define rfbEncryptBytes2 rfbClientEncryptBytes2 +#define rfbDes rfbClientDes +#define rfbDesKey rfbClientDesKey +#define rfbUseKey rfbClientUseKey +#define rfbCPKey rfbClientCPKey + +#include "../libvncserver/vncauth.c" +#include "../libvncserver/d3des.c" diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rre.c new file mode 100755 index 0000000..94158c9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rre.c @@ -0,0 +1,68 @@ +/* + * 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. + */ + +/* + * rre.c - handle RRE encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an RRE + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleRREBPP CONCAT2E(HandleRRE,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleRREBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbRREHeader hdr; + int i; + CARDBPP pix; + rfbRectangle subrect; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader)) + return FALSE; + + hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects); + + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + FillRectangle(client, rx, ry, rw, rh, pix); + + for (i = 0; i < hdr.nSubrects; i++) { + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + if (!ReadFromRFBServer(client, (char *)&subrect, sz_rfbRectangle)) + return FALSE; + + subrect.x = rfbClientSwap16IfLE(subrect.x); + subrect.y = rfbClientSwap16IfLE(subrect.y); + subrect.w = rfbClientSwap16IfLE(subrect.w); + subrect.h = rfbClientSwap16IfLE(subrect.h); + + FillRectangle(client, rx+subrect.x, ry+subrect.y, subrect.w, subrect.h, pix); + } + + return TRUE; +} + +#undef CARDBPP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/sockets.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/sockets.c new file mode 100755 index 0000000..598dd39 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/sockets.c @@ -0,0 +1,616 @@ +/* + * 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. + */ + +/* + * sockets.c - functions to deal with sockets. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include +#include +#ifdef WIN32 +#undef SOCKET +#include +#define EWOULDBLOCK WSAEWOULDBLOCK +#define close closesocket +#define read(sock,buf,len) recv(sock,buf,len,0) +#define write(sock,buf,len) send(sock,buf,len,0) +#define socklen_t int +#else +#include +#include +#include +#include +#include +#include +#endif +#include "tls.h" + +void PrintInHex(char *buf, int len); + +rfbBool errorMessageOnReadFailure = TRUE; + +/* + * ReadFromRFBServer is called whenever we want to read some data from the RFB + * server. It is non-trivial for two reasons: + * + * 1. For efficiency it performs some intelligent buffering, avoiding invoking + * the read() system call too often. For small chunks of data, it simply + * copies the data out of an internal buffer. For large amounts of data it + * reads directly into the buffer provided by the caller. + * + * 2. Whenever read() would block, it invokes the Xt event dispatching + * mechanism to process X events. In fact, this is the only place these + * events are processed, as there is no XtAppMainLoop in the program. + */ + +rfbBool +ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) +{ +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + char* oout=out; + int nn=n; + rfbClientLog("ReadFromRFBServer %d bytes\n",n); +#endif + if (client->serverPort==-1) { + /* vncrec playing */ + rfbVNCRec* rec = client->vncRec; + struct timeval tv; + + if (rec->readTimestamp) { + rec->readTimestamp = FALSE; + if (!fread(&tv,sizeof(struct timeval),1,rec->file)) + return FALSE; + + tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec); + tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec); + + if (rec->tv.tv_sec!=0 && !rec->doNotSleep) { + struct timeval diff; + diff.tv_sec = tv.tv_sec - rec->tv.tv_sec; + diff.tv_usec = tv.tv_usec - rec->tv.tv_usec; + if(diff.tv_usec<0) { + diff.tv_sec--; + diff.tv_usec+=1000000; + } +#ifndef __MINGW32__ + sleep (diff.tv_sec); + usleep (diff.tv_usec); +#else + Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000); +#endif + } + + rec->tv=tv; + } + + return (fread(out,1,n,rec->file)<0?FALSE:TRUE); + } + + if (n <= client->buffered) { + memcpy(out, client->bufoutptr, n); + client->bufoutptr += n; + client->buffered -= n; +#ifdef DEBUG_READ_EXACT + goto hexdump; +#endif + return TRUE; + } + + memcpy(out, client->bufoutptr, client->buffered); + + out += client->buffered; + n -= client->buffered; + + client->bufoutptr = client->buf; + client->buffered = 0; + + if (n <= RFB_BUF_SIZE) { + + while (client->buffered < n) { + int i; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); + } else { +#endif + i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + } +#endif + if (i <= 0) { + if (i < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + if (errno == EWOULDBLOCK || errno == EAGAIN) { + /* TODO: + ProcessXtEvents(); + */ + i = 0; + } else { + rfbClientErr("read (%d: %s)\n",errno,strerror(errno)); + return FALSE; + } + } else { + if (errorMessageOnReadFailure) { + rfbClientLog("VNC server closed connection\n"); + } + return FALSE; + } + } + client->buffered += i; + } + + memcpy(out, client->bufoutptr, n); + client->bufoutptr += n; + client->buffered -= n; + + } else { + + while (n > 0) { + int i; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + i = ReadFromTLS(client, out, n); + } else { +#endif + i = read(client->sock, out, n); +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + } +#endif + if (i <= 0) { + if (i < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + if (errno == EWOULDBLOCK || errno == EAGAIN) { + /* TODO: + ProcessXtEvents(); + */ + i = 0; + } else { + rfbClientErr("read (%s)\n",strerror(errno)); + return FALSE; + } + } else { + if (errorMessageOnReadFailure) { + rfbClientLog("VNC server closed connection\n"); + } + return FALSE; + } + } + out += i; + n -= i; + } + } + +#ifdef DEBUG_READ_EXACT +hexdump: + { int ii; + for(ii=0;iiserverPort==-1) + return TRUE; /* vncrec playing */ + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + /* WriteToTLS() will guarantee either everything is written, or error/eof returns */ + i = WriteToTLS(client, buf, n); + if (i <= 0) return FALSE; + + return TRUE; + } +#endif + + while (i < n) { + j = write(client->sock, buf + i, (n - i)); + if (j <= 0) { + if (j < 0) { + if (errno == EWOULDBLOCK || +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + errno == ENOENT || +#endif + errno == EAGAIN) { + FD_ZERO(&fds); + FD_SET(client->sock,&fds); + + if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { + rfbClientErr("select\n"); + return FALSE; + } + j = 0; + } else { + rfbClientErr("write\n"); + return FALSE; + } + } else { + rfbClientLog("write failed\n"); + return FALSE; + } + } + i += j; + } + return TRUE; +} + + + +static int initSockets() { +#ifdef WIN32 + WSADATA trash; + static rfbBool WSAinitted=FALSE; + if(!WSAinitted) { + int i=WSAStartup(MAKEWORD(2,0),&trash); + if(i!=0) { + rfbClientErr("Couldn't init Windows Sockets\n"); + return 0; + } + WSAinitted=TRUE; + } +#endif + return 1; +} + +/* + * ConnectToTcpAddr connects to the given TCP port. + */ + +int +ConnectClientToTcpAddr(unsigned int host, int port) +{ + int sock; + struct sockaddr_in addr; + int one = 1; + + if (!initSockets()) + return -1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = host; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + rfbClientErr("ConnectToTcpAddr: socket (%s)\n",strerror(errno)); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + rfbClientErr("ConnectToTcpAddr: connect\n"); + close(sock); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbClientErr("ConnectToTcpAddr: setsockopt\n"); + close(sock); + return -1; + } + + return sock; +} + +int +ConnectClientToUnixSock(const char *sockFile) +{ +#ifdef WIN32 + rfbClientErr("Windows doesn't support UNIX sockets\n"); + return -1; +#else + int sock; + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, sockFile); + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr("ConnectToUnixSock: socket (%s)\n",strerror(errno)); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr.sun_family) + strlen(addr.sun_path)) < 0) { + rfbClientErr("ConnectToUnixSock: connect\n"); + close(sock); + return -1; + } + + return sock; +#endif +} + + + +/* + * FindFreeTcpPort tries to find unused TCP port in the range + * (TUNNEL_PORT_OFFSET, TUNNEL_PORT_OFFSET + 99]. Returns 0 on failure. + */ + +int +FindFreeTcpPort(void) +{ + int sock, port; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (!initSockets()) + return -1; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr(": FindFreeTcpPort: socket\n"); + return 0; + } + + for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { + addr.sin_port = htons((unsigned short)port); + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + close(sock); + return port; + } + } + + close(sock); + return 0; +} + + +/* + * ListenAtTcpPort starts listening at the given TCP port. + */ + +int +ListenAtTcpPort(int port) +{ + int sock; + struct sockaddr_in addr; + int one = 1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (!initSockets()) + return -1; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr("ListenAtTcpPort: socket\n"); + return -1; + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (const char *)&one, sizeof(one)) < 0) { + rfbClientErr("ListenAtTcpPort: setsockopt\n"); + close(sock); + return -1; + } + + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + rfbClientErr("ListenAtTcpPort: bind\n"); + close(sock); + return -1; + } + + if (listen(sock, 5) < 0) { + rfbClientErr("ListenAtTcpPort: listen\n"); + close(sock); + return -1; + } + + return sock; +} + + +/* + * AcceptTcpConnection accepts a TCP connection. + */ + +int +AcceptTcpConnection(int listenSock) +{ + int sock; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + int one = 1; + + sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); + if (sock < 0) { + rfbClientErr("AcceptTcpConnection: accept\n"); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbClientErr("AcceptTcpConnection: setsockopt\n"); + close(sock); + return -1; + } + + return sock; +} + + +/* + * SetNonBlocking sets a socket into non-blocking mode. + */ + +rfbBool +SetNonBlocking(int sock) +{ +#ifndef __MINGW32__ + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbClientErr("AcceptTcpConnection: fcntl\n"); + return FALSE; + } +#else + rfbClientErr("O_NONBLOCK on MinGW32 NOT IMPLEMENTED\n"); +#endif + return TRUE; +} + + +/* + * StringToIPAddr - convert a host string to an IP address. + */ + +rfbBool +StringToIPAddr(const char *str, unsigned int *addr) +{ + struct hostent *hp; + + if (strcmp(str,"") == 0) { + *addr = htonl(INADDR_LOOPBACK); /* local */ + return TRUE; + } + + *addr = inet_addr(str); + + if (*addr != -1) + return TRUE; + + if (!initSockets()) + return -1; + + hp = gethostbyname(str); + + if (hp) { + *addr = *(unsigned int *)hp->h_addr; + return TRUE; + } + + return FALSE; +} + + +/* + * Test if the other end of a socket is on the same machine. + */ + +rfbBool +SameMachine(int sock) +{ + struct sockaddr_in peeraddr, myaddr; + socklen_t addrlen = sizeof(struct sockaddr_in); + + getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen); + getsockname(sock, (struct sockaddr *)&myaddr, &addrlen); + + return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr); +} + + +/* + * Print out the contents of a packet for debugging. + */ + +void +PrintInHex(char *buf, int len) +{ + int i, j; + char c, str[17]; + + str[16] = 0; + + rfbClientLog("ReadExact: "); + + for (i = 0; i < len; i++) + { + if ((i % 16 == 0) && (i != 0)) { + rfbClientLog(" "); + } + c = buf[i]; + str[i % 16] = (((c > 31) && (c < 127)) ? c : '.'); + rfbClientLog("%02x ",(unsigned char)c); + if ((i % 4) == 3) + rfbClientLog(" "); + if ((i % 16) == 15) + { + rfbClientLog("%s\n",str); + } + } + if ((i % 16) != 0) + { + for (j = i % 16; j < 16; j++) + { + rfbClientLog(" "); + if ((j % 4) == 3) rfbClientLog(" "); + } + str[i % 16] = 0; + rfbClientLog("%s\n",str); + } + + fflush(stderr); +} + +int WaitForMessage(rfbClient* client,unsigned int usecs) +{ + fd_set fds; + struct timeval timeout; + int num; + + if (client->serverPort==-1) + /* playing back vncrec file */ + return 1; + + timeout.tv_sec=(usecs/1000000); + timeout.tv_usec=(usecs%1000000); + + FD_ZERO(&fds); + FD_SET(client->sock,&fds); + + num=select(client->sock+1, &fds, NULL, NULL, &timeout); + if(num<0) + rfbClientLog("Waiting for message failed: %d (%s)\n",errno,strerror(errno)); + + return num; +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tight.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tight.c new file mode 100755 index 0000000..2f9fbab --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tight.c @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. 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. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + +/* + * tight.c - handle ``tight'' encoding. + * + * This file shouldn't be compiled directly. It is included multiple + * times by rfbproto.c, each time with a different definition of the + * macro BPP. For each value of BPP, this file defines a function + * which handles a tight-encoded rectangle with BPP bits per pixel. + * + */ + +#define TIGHT_MIN_TO_COMPRESS 12 + +#define CARDBPP CONCAT3E(uint,BPP,_t) +#define filterPtrBPP CONCAT2E(filterPtr,BPP) + +#define HandleTightBPP CONCAT2E(HandleTight,BPP) +#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP) +#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP) +#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP) +#define FilterCopyBPP CONCAT2E(FilterCopy,BPP) +#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP) +#define FilterGradientBPP CONCAT2E(FilterGradient,BPP) + +#if BPP != 8 +#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP) +#endif + +#ifndef RGB_TO_PIXEL + +#define RGB_TO_PIXEL(bpp,r,g,b) \ + (((CARD##bpp)(r) & client->format.redMax) << client->format.redShift | \ + ((CARD##bpp)(g) & client->format.greenMax) << client->format.greenShift | \ + ((CARD##bpp)(b) & client->format.blueMax) << client->format.blueShift) + +#define RGB24_TO_PIXEL(bpp,r,g,b) \ + ((((CARD##bpp)(r) & 0xFF) * client->format.redMax + 127) / 255 \ + << client->format.redShift | \ + (((CARD##bpp)(g) & 0xFF) * client->format.greenMax + 127) / 255 \ + << client->format.greenShift | \ + (((CARD##bpp)(b) & 0xFF) * client->format.blueMax + 127) / 255 \ + << client->format.blueShift) + +#define RGB24_TO_PIXEL32(r,g,b) \ + (((uint32_t)(r) & 0xFF) << client->format.redShift | \ + ((uint32_t)(g) & 0xFF) << client->format.greenShift | \ + ((uint32_t)(b) & 0xFF) << client->format.blueShift) + +#endif + +/* Type declarations */ + +typedef void (*filterPtrBPP)(rfbClient* client, int, CARDBPP *); + +/* Prototypes */ + +static int InitFilterCopyBPP (rfbClient* client, int rw, int rh); +static int InitFilterPaletteBPP (rfbClient* client, int rw, int rh); +static int InitFilterGradientBPP (rfbClient* client, int rw, int rh); +static void FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); +static void FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); +static void FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); + +#if BPP != 8 +static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h); +#endif + +/* Definitions */ + +static rfbBool +HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + CARDBPP fill_colour; + uint8_t comp_ctl; + uint8_t filter_id; + filterPtrBPP filterFn; + z_streamp zs; + char *buffer2; + int err, stream_id, compressedLen, bitsPixel; + int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes; + + if (!ReadFromRFBServer(client, (char *)&comp_ctl, 1)) + return FALSE; + + /* Flush zlib streams if we are told by the server to do so. */ + for (stream_id = 0; stream_id < 4; stream_id++) { + if ((comp_ctl & 1) && client->zlibStreamActive[stream_id]) { + if (inflateEnd (&client->zlibStream[stream_id]) != Z_OK && + client->zlibStream[stream_id].msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->zlibStream[stream_id].msg); + client->zlibStreamActive[stream_id] = FALSE; + } + comp_ctl >>= 1; + } + + /* Handle solid rectangles. */ + if (comp_ctl == rfbTightFill) { +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + if (!ReadFromRFBServer(client, client->buffer, 3)) + return FALSE; + fill_colour = RGB24_TO_PIXEL32(client->buffer[0], client->buffer[1], client->buffer[2]); + } else { + if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour))) + return FALSE; + } +#else + if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour))) + return FALSE; +#endif + + FillRectangle(client, rx, ry, rw, rh, fill_colour); + + return TRUE; + } + +#if BPP == 8 + if (comp_ctl == rfbTightJpeg) { + rfbClientLog("Tight encoding: JPEG is not supported in 8 bpp mode.\n"); + return FALSE; + } +#else + if (comp_ctl == rfbTightJpeg) { + return DecompressJpegRectBPP(client, rx, ry, rw, rh); + } +#endif + + /* Quit on unsupported subencoding value. */ + if (comp_ctl > rfbTightMaxSubencoding) { + rfbClientLog("Tight encoding: bad subencoding value received.\n"); + return FALSE; + } + + /* + * Here primary compression mode handling begins. + * Data was processed with optional filter + zlib compression. + */ + + /* First, we should identify a filter to use. */ + if ((comp_ctl & rfbTightExplicitFilter) != 0) { + if (!ReadFromRFBServer(client, (char*)&filter_id, 1)) + return FALSE; + + switch (filter_id) { + case rfbTightFilterCopy: + filterFn = FilterCopyBPP; + bitsPixel = InitFilterCopyBPP(client, rw, rh); + break; + case rfbTightFilterPalette: + filterFn = FilterPaletteBPP; + bitsPixel = InitFilterPaletteBPP(client, rw, rh); + break; + case rfbTightFilterGradient: + filterFn = FilterGradientBPP; + bitsPixel = InitFilterGradientBPP(client, rw, rh); + break; + default: + rfbClientLog("Tight encoding: unknown filter code received.\n"); + return FALSE; + } + } else { + filterFn = FilterCopyBPP; + bitsPixel = InitFilterCopyBPP(client, rw, rh); + } + if (bitsPixel == 0) { + rfbClientLog("Tight encoding: error receiving palette.\n"); + return FALSE; + } + + /* Determine if the data should be decompressed or just copied. */ + rowSize = (rw * bitsPixel + 7) / 8; + if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) { + if (!ReadFromRFBServer(client, (char*)client->buffer, rh * rowSize)) + return FALSE; + + buffer2 = &client->buffer[TIGHT_MIN_TO_COMPRESS * 4]; + filterFn(client, rh, (CARDBPP *)buffer2); + + CopyRectangle(client, (uint8_t *)buffer2, rx, ry, rw, rh); + + return TRUE; + } + + /* Read the length (1..3 bytes) of compressed data following. */ + compressedLen = (int)ReadCompactLen(client); + if (compressedLen <= 0) { + rfbClientLog("Incorrect data received from the server.\n"); + return FALSE; + } + + /* Now let's initialize compression stream if needed. */ + stream_id = comp_ctl & 0x03; + zs = &client->zlibStream[stream_id]; + if (!client->zlibStreamActive[stream_id]) { + zs->zalloc = Z_NULL; + zs->zfree = Z_NULL; + zs->opaque = Z_NULL; + err = inflateInit(zs); + if (err != Z_OK) { + if (zs->msg != NULL) + rfbClientLog("InflateInit error: %s.\n", zs->msg); + return FALSE; + } + client->zlibStreamActive[stream_id] = TRUE; + } + + /* Read, decode and draw actual pixel data in a loop. */ + + bufferSize = RFB_BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC; + buffer2 = &client->buffer[bufferSize]; + if (rowSize > bufferSize) { + /* Should be impossible when RFB_BUFFER_SIZE >= 16384 */ + rfbClientLog("Internal error: incorrect buffer size.\n"); + return FALSE; + } + + rowsProcessed = 0; + extraBytes = 0; + + while (compressedLen > 0) { + if (compressedLen > ZLIB_BUFFER_SIZE) + portionLen = ZLIB_BUFFER_SIZE; + else + portionLen = compressedLen; + + if (!ReadFromRFBServer(client, (char*)client->zlib_buffer, portionLen)) + return FALSE; + + compressedLen -= portionLen; + + zs->next_in = (Bytef *)client->zlib_buffer; + zs->avail_in = portionLen; + + do { + zs->next_out = (Bytef *)&client->buffer[extraBytes]; + zs->avail_out = bufferSize - extraBytes; + + err = inflate(zs, Z_SYNC_FLUSH); + if (err == Z_BUF_ERROR) /* Input exhausted -- no problem. */ + break; + if (err != Z_OK && err != Z_STREAM_END) { + if (zs->msg != NULL) { + rfbClientLog("Inflate error: %s.\n", zs->msg); + } else { + rfbClientLog("Inflate error: %d.\n", err); + } + return FALSE; + } + + numRows = (bufferSize - zs->avail_out) / rowSize; + + filterFn(client, numRows, (CARDBPP *)buffer2); + + extraBytes = bufferSize - zs->avail_out - numRows * rowSize; + if (extraBytes > 0) + memcpy(client->buffer, &client->buffer[numRows * rowSize], extraBytes); + + CopyRectangle(client, (uint8_t *)buffer2, rx, ry+rowsProcessed, rw, numRows); + + rowsProcessed += numRows; + } + while (zs->avail_out == 0); + } + + if (rowsProcessed != rh) { + rfbClientLog("Incorrect number of scan lines after decompression.\n"); + return FALSE; + } + + return TRUE; +} + +/*---------------------------------------------------------------------------- + * + * Filter stuff. + * + */ + +static int +InitFilterCopyBPP (rfbClient* client, int rw, int rh) +{ + client->rectWidth = rw; + +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + client->cutZeros = TRUE; + return 24; + } else { + client->cutZeros = FALSE; + } +#endif + + return BPP; +} + +static void +FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + +#if BPP == 32 + int x, y; + + if (client->cutZeros) { + for (y = 0; y < numRows; y++) { + for (x = 0; x < client->rectWidth; x++) { + dst[y*client->rectWidth+x] = + RGB24_TO_PIXEL32(client->buffer[(y*client->rectWidth+x)*3], + client->buffer[(y*client->rectWidth+x)*3+1], + client->buffer[(y*client->rectWidth+x)*3+2]); + } + } + return; + } +#endif + + memcpy (dst, client->buffer, numRows * client->rectWidth * (BPP / 8)); +} + +static int +InitFilterGradientBPP (rfbClient* client, int rw, int rh) +{ + int bits; + + bits = InitFilterCopyBPP(client, rw, rh); + if (client->cutZeros) + memset(client->tightPrevRow, 0, rw * 3); + else + memset(client->tightPrevRow, 0, rw * 3 * sizeof(uint16_t)); + + return bits; +} + +#if BPP == 32 + +static void +FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst) +{ + int x, y, c; + uint8_t thisRow[2048*3]; + uint8_t pix[3]; + int est[3]; + + for (y = 0; y < numRows; y++) { + + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = client->tightPrevRow[c] + client->buffer[y*client->rectWidth*3+c]; + thisRow[c] = pix[c]; + } + dst[y*client->rectWidth] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + + /* Remaining pixels of a row */ + for (x = 1; x < client->rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = (int)client->tightPrevRow[x*3+c] + (int)pix[c] - + (int)client->tightPrevRow[(x-1)*3+c]; + if (est[c] > 0xFF) { + est[c] = 0xFF; + } else if (est[c] < 0x00) { + est[c] = 0x00; + } + pix[c] = (uint8_t)est[c] + client->buffer[(y*client->rectWidth+x)*3+c]; + thisRow[x*3+c] = pix[c]; + } + dst[y*client->rectWidth+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + } + + memcpy(client->tightPrevRow, thisRow, client->rectWidth * 3); + } +} + +#endif + +static void +FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + int x, y, c; + CARDBPP *src = (CARDBPP *)client->buffer; + uint16_t *thatRow = (uint16_t *)client->tightPrevRow; + uint16_t thisRow[2048*3]; + uint16_t pix[3]; + uint16_t max[3]; + int shift[3]; + int est[3]; + +#if BPP == 32 + if (client->cutZeros) { + FilterGradient24(client, numRows, dst); + return; + } +#endif + + max[0] = client->format.redMax; + max[1] = client->format.greenMax; + max[2] = client->format.blueMax; + + shift[0] = client->format.redShift; + shift[1] = client->format.greenShift; + shift[2] = client->format.blueShift; + + for (y = 0; y < numRows; y++) { + + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = (uint16_t)(((src[y*client->rectWidth] >> shift[c]) + thatRow[c]) & max[c]); + thisRow[c] = pix[c]; + } + dst[y*client->rectWidth] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + + /* Remaining pixels of a row */ + for (x = 1; x < client->rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; + if (est[c] > (int)max[c]) { + est[c] = (int)max[c]; + } else if (est[c] < 0) { + est[c] = 0; + } + pix[c] = (uint16_t)(((src[y*client->rectWidth+x] >> shift[c]) + est[c]) & max[c]); + thisRow[x*3+c] = pix[c]; + } + dst[y*client->rectWidth+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + } + memcpy(thatRow, thisRow, client->rectWidth * 3 * sizeof(uint16_t)); + } +} + +static int +InitFilterPaletteBPP (rfbClient* client, int rw, int rh) +{ + uint8_t numColors; +#if BPP == 32 + int i; + CARDBPP *palette = (CARDBPP *)client->tightPalette; +#endif + + client->rectWidth = rw; + + if (!ReadFromRFBServer(client, (char*)&numColors, 1)) + return 0; + + client->rectColors = (int)numColors; + if (++client->rectColors < 2) + return 0; + +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * 3)) + return 0; + for (i = client->rectColors - 1; i >= 0; i--) { + palette[i] = RGB24_TO_PIXEL32(client->tightPalette[i*3], + client->tightPalette[i*3+1], + client->tightPalette[i*3+2]); + } + return (client->rectColors == 2) ? 1 : 8; + } +#endif + + if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * (BPP / 8))) + return 0; + + return (client->rectColors == 2) ? 1 : 8; +} + +static void +FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + int x, y, b, w; + uint8_t *src = (uint8_t *)client->buffer; + CARDBPP *palette = (CARDBPP *)client->tightPalette; + + if (client->rectColors == 2) { + w = (client->rectWidth + 7) / 8; + for (y = 0; y < numRows; y++) { + for (x = 0; x < client->rectWidth / 8; x++) { + for (b = 7; b >= 0; b--) + dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + } + for (b = 7; b >= 8 - client->rectWidth % 8; b--) { + dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + } + } + } else { + for (y = 0; y < numRows; y++) + for (x = 0; x < client->rectWidth; x++) + dst[y*client->rectWidth+x] = palette[(int)src[y*client->rectWidth+x]]; + } +} + +#if BPP != 8 + +/*---------------------------------------------------------------------------- + * + * JPEG decompression. + * + */ + +static rfbBool +DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + int compressedLen; + uint8_t *compressedData; + CARDBPP *pixelPtr; + JSAMPROW rowPointer[1]; + int dx, dy; + + compressedLen = (int)ReadCompactLen(client); + if (compressedLen <= 0) { + rfbClientLog("Incorrect data received from the server.\n"); + return FALSE; + } + + compressedData = malloc(compressedLen); + if (compressedData == NULL) { + rfbClientLog("Memory allocation error.\n"); + return FALSE; + } + + if (!ReadFromRFBServer(client, (char*)compressedData, compressedLen)) { + free(compressedData); + return FALSE; + } + + cinfo.err = jpeg_std_error(&jerr); + cinfo.client_data = client; + jpeg_create_decompress(&cinfo); + + JpegSetSrcManager(&cinfo, compressedData, compressedLen); + + jpeg_read_header(&cinfo, TRUE); + cinfo.out_color_space = JCS_RGB; + + jpeg_start_decompress(&cinfo); + if (cinfo.output_width != w || cinfo.output_height != h || + cinfo.output_components != 3) { + rfbClientLog("Tight Encoding: Wrong JPEG data received.\n"); + jpeg_destroy_decompress(&cinfo); + free(compressedData); + return FALSE; + } + + rowPointer[0] = (JSAMPROW)client->buffer; + dy = 0; + while (cinfo.output_scanline < cinfo.output_height) { + jpeg_read_scanlines(&cinfo, rowPointer, 1); + if (client->jpegError) { + break; + } + pixelPtr = (CARDBPP *)&client->buffer[RFB_BUFFER_SIZE / 2]; + for (dx = 0; dx < w; dx++) { + *pixelPtr++ = + RGB24_TO_PIXEL(BPP, client->buffer[dx*3], client->buffer[dx*3+1], client->buffer[dx*3+2]); + } + CopyRectangle(client, (uint8_t *)&client->buffer[RFB_BUFFER_SIZE / 2], x, y + dy, w, 1); + dy++; + } + + if (!client->jpegError) + jpeg_finish_decompress(&cinfo); + + jpeg_destroy_decompress(&cinfo); + free(compressedData); + + return !client->jpegError; +} + +#else + +static long +ReadCompactLen (rfbClient* client) +{ + long len; + uint8_t b; + + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len = (int)b & 0x7F; + if (b & 0x80) { + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len |= ((int)b & 0x7F) << 7; + if (b & 0x80) { + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len |= ((int)b & 0xFF) << 14; + } + } + return len; +} + +/* + * JPEG source manager functions for JPEG decompression in Tight decoder. + */ + +static void +JpegInitSource(j_decompress_ptr cinfo) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegError = FALSE; +} + +static boolean +JpegFillInputBuffer(j_decompress_ptr cinfo) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegError = TRUE; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; + + return TRUE; +} + +static void +JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + if (num_bytes < 0 || num_bytes > client->jpegSrcManager->bytes_in_buffer) { + client->jpegError = TRUE; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; + } else { + client->jpegSrcManager->next_input_byte += (size_t) num_bytes; + client->jpegSrcManager->bytes_in_buffer -= (size_t) num_bytes; + } +} + +static void +JpegTermSource(j_decompress_ptr cinfo) +{ + /* nothing to do here. */ +} + +static void +JpegSetSrcManager(j_decompress_ptr cinfo, + uint8_t *compressedData, + int compressedLen) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegBufferPtr = compressedData; + client->jpegBufferLen = (size_t)compressedLen; + + if(client->jpegSrcManager == NULL) + client->jpegSrcManager = malloc(sizeof(struct jpeg_source_mgr)); + client->jpegSrcManager->init_source = JpegInitSource; + client->jpegSrcManager->fill_input_buffer = JpegFillInputBuffer; + client->jpegSrcManager->skip_input_data = JpegSkipInputData; + client->jpegSrcManager->resync_to_restart = jpeg_resync_to_restart; + client->jpegSrcManager->term_source = JpegTermSource; + client->jpegSrcManager->next_input_byte = (JOCTET*)client->jpegBufferPtr; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + + cinfo->src = client->jpegSrcManager; +} + +#endif + +#undef CARDBPP + +/* LIBVNCSERVER_HAVE_LIBZ and LIBVNCSERVER_HAVE_LIBJPEG */ +#endif +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.c new file mode 100755 index 0000000..206dbda --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.c @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2009 Vic Lee. + * + * 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 +#include +#include "tls.h" + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + +static const int rfbCertTypePriority[] = { GNUTLS_CRT_X509, 0 }; +static const int rfbProtoPriority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; +static const int rfbKXPriority[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0}; +static const int rfbKXAnon[] = {GNUTLS_KX_ANON_DH, 0}; + +#define DH_BITS 1024 +static gnutls_dh_params_t rfbDHParams; + +static rfbBool rfbTLSInitialized = FALSE; + +static rfbBool +InitializeTLS(void) +{ + int ret; + + if (rfbTLSInitialized) return TRUE; + if ((ret = gnutls_global_init()) < 0 || + (ret = gnutls_dh_params_init(&rfbDHParams)) < 0 || + (ret = gnutls_dh_params_generate2(rfbDHParams, DH_BITS)) < 0) + { + rfbClientLog("Failed to initialized GnuTLS: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + rfbClientLog("GnuTLS initialized.\n"); + rfbTLSInitialized = TRUE; + return TRUE; +} + +static ssize_t +PushTLS(gnutls_transport_ptr_t transport, const void *data, size_t len) +{ + rfbClient *client = (rfbClient*)transport; + int ret; + + while (1) + { + ret = write(client->sock, data, len); + if (ret < 0) + { + if (errno == EINTR) continue; + return -1; + } + return ret; + } +} + + +static ssize_t +PullTLS(gnutls_transport_ptr_t transport, void *data, size_t len) +{ + rfbClient *client = (rfbClient*)transport; + int ret; + + while (1) + { + ret = read(client->sock, data, len); + if (ret < 0) + { + if (errno == EINTR) continue; + return -1; + } + return ret; + } +} + +static rfbBool +InitializeTLSSession(rfbClient* client, rfbBool anonTLS) +{ + int ret; + + if (client->tlsSession) return TRUE; + + if ((ret = gnutls_init(&client->tlsSession, GNUTLS_CLIENT)) < 0) + { + rfbClientLog("Failed to initialized TLS session: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + + if ((ret = gnutls_set_default_priority(client->tlsSession)) < 0 || + (ret = gnutls_kx_set_priority(client->tlsSession, anonTLS ? rfbKXAnon : rfbKXPriority)) < 0 || + (ret = gnutls_certificate_type_set_priority(client->tlsSession, rfbCertTypePriority)) < 0 || + (ret = gnutls_protocol_set_priority(client->tlsSession, rfbProtoPriority)) < 0) + { + FreeTLS(client); + rfbClientLog("Failed to set TLS priority: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + + gnutls_transport_set_ptr(client->tlsSession, (gnutls_transport_ptr_t)client); + gnutls_transport_set_push_function(client->tlsSession, PushTLS); + gnutls_transport_set_pull_function(client->tlsSession, PullTLS); + + rfbClientLog("TLS session initialized.\n"); + + return TRUE; +} + +static rfbBool +SetTLSAnonCredential(rfbClient* client) +{ + gnutls_anon_client_credentials anonCred; + int ret; + + if ((ret = gnutls_anon_allocate_client_credentials(&anonCred)) < 0 || + (ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_ANON, anonCred)) < 0) + { + FreeTLS(client); + rfbClientLog("Failed to create anonymous credentials: %s", gnutls_strerror(ret)); + return FALSE; + } + rfbClientLog("TLS anonymous credential created.\n"); + return TRUE; +} + +static rfbBool +HandshakeTLS(rfbClient* client) +{ + int timeout = 15; + int ret; + + while (timeout > 0 && (ret = gnutls_handshake(client->tlsSession)) < 0) + { + if (!gnutls_error_is_fatal(ret)) + { + rfbClientLog("TLS handshake blocking.\n"); + sleep(1); + timeout--; + continue; + } + rfbClientLog("TLS handshake failed: %s.\n", gnutls_strerror(ret)); + FreeTLS(client); + return FALSE; + } + + if (timeout <= 0) + { + rfbClientLog("TLS handshake timeout.\n"); + FreeTLS(client); + return FALSE; + } + + rfbClientLog("TLS handshake done.\n"); + return TRUE; +} + +/* VeNCrypt sub auth. 1 byte auth count, followed by count * 4 byte integers */ +static rfbBool +ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result) +{ + uint8_t count=0; + uint8_t loop=0; + uint8_t flag=0; + uint32_t tAuth[256], t; + char buf1[500],buf2[10]; + uint32_t authScheme; + + if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; + + if (count==0) + { + rfbClientLog("List of security types is ZERO. Giving up.\n"); + return FALSE; + } + if (count>sizeof(tAuth)) + { + rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth)); + return FALSE; + } + + rfbClientLog("We have %d security types to read\n", count); + authScheme=0; + /* now, we have a list of available security types to read ( uint8_t[] ) */ + for (loop=0;loop=sizeof(buf1)-1) break; + snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]); + strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1); + } + rfbClientLog("Unknown VeNCrypt authentication scheme from VNC server: %s\n", + buf1); + return FALSE; + } + *result = authScheme; + return TRUE; +} + +static void +FreeX509Credential(rfbCredential *cred) +{ + if (cred->x509Credential.x509CACertFile) free(cred->x509Credential.x509CACertFile); + if (cred->x509Credential.x509CACrlFile) free(cred->x509Credential.x509CACrlFile); + if (cred->x509Credential.x509ClientCertFile) free(cred->x509Credential.x509ClientCertFile); + if (cred->x509Credential.x509ClientKeyFile) free(cred->x509Credential.x509ClientKeyFile); + free(cred); +} + +static gnutls_certificate_credentials_t +CreateX509CertCredential(rfbCredential *cred) +{ + gnutls_certificate_credentials_t x509_cred; + int ret; + + if (!cred->x509Credential.x509CACertFile) + { + rfbClientLog("No CA certificate provided.\n"); + return NULL; + } + + if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) + { + rfbClientLog("Cannot allocate credentials: %s.\n", gnutls_strerror(ret)); + return NULL; + } + if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, + cred->x509Credential.x509CACertFile, GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load CA credentials: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + if (cred->x509Credential.x509ClientCertFile && cred->x509Credential.x509ClientKeyFile) + { + if ((ret = gnutls_certificate_set_x509_key_file(x509_cred, + cred->x509Credential.x509ClientCertFile, cred->x509Credential.x509ClientKeyFile, + GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load client certificate or key: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + } else + { + rfbClientLog("No client certificate or key provided.\n"); + } + if (cred->x509Credential.x509CACrlFile) + { + if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, + cred->x509Credential.x509CACrlFile, GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load CRL: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + } else + { + rfbClientLog("No CRL provided.\n"); + } + gnutls_certificate_set_dh_params (x509_cred, rfbDHParams); + return x509_cred; +} + +#endif + +rfbBool +HandleAnonTLSAuth(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + + if (!InitializeTLS() || !InitializeTLSSession(client, TRUE)) return FALSE; + + if (!SetTLSAnonCredential(client)) return FALSE; + + if (!HandshakeTLS(client)) return FALSE; + + return TRUE; + +#else + rfbClientLog("TLS is not supported.\n"); + return FALSE; +#endif +} + +rfbBool +HandleVeNCryptAuth(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + uint8_t major, minor, status; + uint32_t authScheme; + rfbBool anonTLS; + gnutls_certificate_credentials_t x509_cred = NULL; + int ret; + + if (!InitializeTLS()) return FALSE; + + /* Read VeNCrypt version */ + if (!ReadFromRFBServer(client, (char *)&major, 1) || + !ReadFromRFBServer(client, (char *)&minor, 1)) + { + return FALSE; + } + rfbClientLog("Got VeNCrypt version %d.%d from server.\n", (int)major, (int)minor); + + if (major != 0 && minor != 2) + { + rfbClientLog("Unsupported VeNCrypt version.\n"); + return FALSE; + } + + if (!WriteToRFBServer(client, (char *)&major, 1) || + !WriteToRFBServer(client, (char *)&minor, 1) || + !ReadFromRFBServer(client, (char *)&status, 1)) + { + return FALSE; + } + + if (status != 0) + { + rfbClientLog("Server refused VeNCrypt version %d.%d.\n", (int)major, (int)minor); + return FALSE; + } + + if (!ReadVeNCryptSecurityType(client, &authScheme)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&status, 1) || status != 1) + { + rfbClientLog("Server refused VeNCrypt authentication %d (%d).\n", authScheme, (int)status); + return FALSE; + } + client->subAuthScheme = authScheme; + + /* Some VeNCrypt security types are anonymous TLS, others are X509 */ + switch (authScheme) + { + case rfbVeNCryptTLSNone: + case rfbVeNCryptTLSVNC: + case rfbVeNCryptTLSPlain: + anonTLS = TRUE; + break; + default: + anonTLS = FALSE; + break; + } + + /* Get X509 Credentials if it's not anonymous */ + if (!anonTLS) + { + rfbCredential *cred; + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + cred = client->GetCredential(client, rfbCredentialTypeX509); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + x509_cred = CreateX509CertCredential(cred); + FreeX509Credential(cred); + if (!x509_cred) return FALSE; + } + + /* Start up the TLS session */ + if (!InitializeTLSSession(client, anonTLS)) return FALSE; + + if (anonTLS) + { + if (!SetTLSAnonCredential(client)) return FALSE; + } + else + { + if ((ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_CERTIFICATE, x509_cred)) < 0) + { + rfbClientLog("Cannot set x509 credential: %s.\n", gnutls_strerror(ret)); + FreeTLS(client); + return FALSE; + } + } + + if (!HandshakeTLS(client)) return FALSE; + + /* TODO: validate certificate */ + + /* We are done here. The caller should continue with client->subAuthScheme + * to do actual sub authentication. + */ + return TRUE; + +#else + rfbClientLog("TLS is not supported.\n"); + return FALSE; +#endif +} + +int +ReadFromTLS(rfbClient* client, char *out, unsigned int n) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + ssize_t ret; + + ret = gnutls_record_recv(client->tlsSession, out, n); + if (ret >= 0) return ret; + if (ret == GNUTLS_E_REHANDSHAKE || ret == GNUTLS_E_AGAIN) + { + errno = EAGAIN; + } else + { + rfbClientLog("Error reading from TLS: %s.\n", gnutls_strerror(ret)); + errno = EINTR; + } + return -1; +#else + rfbClientLog("TLS is not supported.\n"); + errno = EINTR; + return -1; +#endif +} + +int +WriteToTLS(rfbClient* client, char *buf, unsigned int n) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + unsigned int offset = 0; + ssize_t ret; + + while (offset < n) + { + ret = gnutls_record_send(client->tlsSession, buf+offset, (size_t)(n-offset)); + if (ret == 0) continue; + if (ret < 0) + { + if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) continue; + rfbClientLog("Error writing to TLS: %s.\n", gnutls_strerror(ret)); + return -1; + } + offset += (unsigned int)ret; + } + return offset; +#else + rfbClientLog("TLS is not supported.\n"); + errno = EINTR; + return -1; +#endif +} + +void FreeTLS(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) + { + gnutls_deinit(client->tlsSession); + client->tlsSession = NULL; + } +#endif +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.h new file mode 100755 index 0000000..48d159b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.h @@ -0,0 +1,51 @@ +#ifndef TLS_H +#define TLS_H + +/* + * Copyright (C) 2009 Vic Lee. + * + * 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. + */ + +/* Handle Anonymous TLS Authentication (18) with the server. + * After authentication, client->tlsSession will be set. + */ +rfbBool HandleAnonTLSAuth(rfbClient* client); + +/* Handle VeNCrypt Authentication (19) with the server. + * The callback function GetX509Credential will be called. + * After authentication, client->tlsSession will be set. + */ +rfbBool HandleVeNCryptAuth(rfbClient* client); + +/* Read desired bytes from TLS session. + * It's a wrapper function over gnutls_record_recv() and return values + * are same as read(), that is, >0 for actual bytes read, 0 for EOF, + * or EAGAIN, EINTR. + * This should be a non-blocking call. Blocking is handled in sockets.c. + */ +int ReadFromTLS(rfbClient* client, char *out, unsigned int n); + +/* Write desired bytes to TLS session. + * It's a wrapper function over gnutls_record_send() and it will be + * blocking call, until all bytes are written or error returned. + */ +int WriteToTLS(rfbClient* client, char *buf, unsigned int n); + +/* Free TLS resources */ +void FreeTLS(rfbClient* client); + +#endif /* TLS_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/ultra.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/ultra.c new file mode 100755 index 0000000..3be150d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/ultra.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2000 Tridia Corporation. 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. + */ + +/* + * ultrazip.c - handle ultrazip encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zlib + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP) +#define HandleUltraBPP CONCAT2E(HandleUltra,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleUltraBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int toRead=0; + int inflateResult=0; + int uncompressedBytes = (( rw * rh ) * ( BPP / 8 )); + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + toRead = rfbClientSwap32IfLE(hdr.nBytes); + if (toRead==0) return TRUE; + + if (uncompressedBytes==0) + { + rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw, rh, BPP); + return FALSE; + } + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < uncompressedBytes) { + if ( client->raw_buffer != NULL ) { + free( client->raw_buffer ); + } + client->raw_buffer_size = uncompressedBytes; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->raw_buffer_size % 4)!=0) + client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + } + + /* allocate enough space to store the incoming compressed packet */ + if ( client->ultra_buffer_size < toRead ) { + if ( client->ultra_buffer != NULL ) { + free( client->ultra_buffer ); + } + client->ultra_buffer_size = toRead; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->ultra_buffer_size % 4)!=0) + client->ultra_buffer_size += (4-(client->ultra_buffer_size % 4)); + client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) + return FALSE; + + /* uncompress the data */ + uncompressedBytes = client->raw_buffer_size; + inflateResult = lzo1x_decompress( + (lzo_byte *)client->ultra_buffer, toRead, + (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, + NULL); + + + if ((rw * rh * (BPP / 8)) != uncompressedBytes) + rfbClientLog("Ultra decompressed too little (%d < %d)", (rw * rh * (BPP / 8)), uncompressedBytes); + + /* Put the uncompressed contents of the update on the screen. */ + if ( inflateResult == LZO_E_OK ) + { + CopyRectangle(client, (unsigned char *)client->raw_buffer, rx, ry, rw, rh); + } + else + { + rfbClientLog("ultra decompress returned error: %d\n", + inflateResult); + return FALSE; + } + return TRUE; +} + + +/* UltraZip is like rre in that it is composed of subrects */ +static rfbBool +HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int i=0; + int toRead=0; + int inflateResult=0; + unsigned char *ptr=NULL; + int uncompressedBytes = ry + (rw * 65535); + unsigned int numCacheRects = rx; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + toRead = rfbClientSwap32IfLE(hdr.nBytes); + + if (toRead==0) return TRUE; + + if (uncompressedBytes==0) + { + rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry, rw, rx); + return FALSE; + } + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < (uncompressedBytes + 500)) { + if ( client->raw_buffer != NULL ) { + free( client->raw_buffer ); + } + client->raw_buffer_size = uncompressedBytes + 500; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->raw_buffer_size % 4)!=0) + client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + } + + + /* allocate enough space to store the incoming compressed packet */ + if ( client->ultra_buffer_size < toRead ) { + if ( client->ultra_buffer != NULL ) { + free( client->ultra_buffer ); + } + client->ultra_buffer_size = toRead; + client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) + return FALSE; + + /* uncompress the data */ + uncompressedBytes = client->raw_buffer_size; + inflateResult = lzo1x_decompress( + (lzo_byte *)client->ultra_buffer, toRead, + (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, NULL); + if ( inflateResult != LZO_E_OK ) + { + rfbClientLog("ultra decompress returned error: %d\n", + inflateResult); + return FALSE; + } + + /* Put the uncompressed contents of the update on the screen. */ + ptr = (unsigned char *)client->raw_buffer; + for (i=0; i +#include +#include +#include +#include +#include "tls.h" + +static void Dummy(rfbClient* client) { +} +static rfbBool DummyPoint(rfbClient* client, int x, int y) { + return TRUE; +} +static void DummyRect(rfbClient* client, int x, int y, int w, int h) { +} + +#ifdef __MINGW32__ +static char* NoPassword(rfbClient* client) { + return strdup(""); +} +#undef SOCKET +#include +#define close closesocket +#else +#include +#include +#endif + +static char* ReadPassword(rfbClient* client) { +#ifdef __MINGW32__ + /* FIXME */ + rfbClientErr("ReadPassword on MinGW32 NOT IMPLEMENTED\n"); + return NoPassword(client); +#else + int i; + char* p=malloc(9); + struct termios save,noecho; + p[0]=0; + if(tcgetattr(fileno(stdin),&save)!=0) return p; + noecho=save; noecho.c_lflag &= ~ECHO; + if(tcsetattr(fileno(stdin),TCSAFLUSH,&noecho)!=0) return p; + fprintf(stderr,"Password: "); + i=0; + while(1) { + int c=fgetc(stdin); + if(c=='\n') + break; + if(i<8) { + p[i]=c; + i++; + p[i]=0; + } + } + tcsetattr(fileno(stdin),TCSAFLUSH,&save); + return p; +#endif +} +static rfbBool MallocFrameBuffer(rfbClient* client) { + if(client->frameBuffer) + free(client->frameBuffer); + client->frameBuffer=malloc(client->width*client->height*client->format.bitsPerPixel/8); + return client->frameBuffer?TRUE:FALSE; +} + +static void initAppData(AppData* data) { + data->shareDesktop=TRUE; + data->viewOnly=FALSE; + data->encodingsString="tight zrle ultra copyrect hextile zlib corre rre raw"; + data->useBGR233=FALSE; + data->nColours=0; + data->forceOwnCmap=FALSE; + data->forceTrueColour=FALSE; + data->requestedDepth=0; + data->compressLevel=3; + data->qualityLevel=5; +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + data->enableJPEG=TRUE; +#else + data->enableJPEG=FALSE; +#endif + data->useRemoteCursor=FALSE; +} + +rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel, + int bytesPerPixel) { + rfbClient* client=(rfbClient*)calloc(sizeof(rfbClient),1); + if(!client) { + rfbClientErr("Couldn't allocate client structure!\n"); + return NULL; + } + initAppData(&client->appData); + client->endianTest = 1; + client->programName=""; + client->serverHost=strdup(""); + client->serverPort=5900; + + client->destHost = NULL; + client->destPort = 5900; + + client->CurrentKeyboardLedState = 0; + client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; + + /* default: use complete frame buffer */ + client->updateRect.x = -1; + + client->format.bitsPerPixel = bytesPerPixel*8; + client->format.depth = bitsPerSample*samplesPerPixel; + client->appData.requestedDepth=client->format.depth; + client->format.bigEndian = *(char *)&client->endianTest?FALSE:TRUE; + client->format.trueColour = TRUE; + + if (client->format.bitsPerPixel == 8) { + client->format.redMax = 7; + client->format.greenMax = 7; + client->format.blueMax = 3; + client->format.redShift = 0; + client->format.greenShift = 3; + client->format.blueShift = 6; + } else { + client->format.redMax = (1 << bitsPerSample) - 1; + client->format.greenMax = (1 << bitsPerSample) - 1; + client->format.blueMax = (1 << bitsPerSample) - 1; + if(!client->format.bigEndian) { + client->format.redShift = 0; + client->format.greenShift = bitsPerSample; + client->format.blueShift = bitsPerSample * 2; + } else { + if(client->format.bitsPerPixel==8*3) { + client->format.redShift = bitsPerSample*2; + client->format.greenShift = bitsPerSample*1; + client->format.blueShift = 0; + } else { + client->format.redShift = bitsPerSample*3; + client->format.greenShift = bitsPerSample*2; + client->format.blueShift = bitsPerSample; + } + } + } + + client->bufoutptr=client->buf; + client->buffered=0; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + client->raw_buffer_size = -1; + client->decompStreamInited = FALSE; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + memset(client->zlibStreamActive,0,sizeof(rfbBool)*4); + client->jpegSrcManager = NULL; +#endif +#endif + + client->HandleCursorPos = DummyPoint; + client->SoftCursorLockArea = DummyRect; + client->SoftCursorUnlockScreen = Dummy; + client->GotFrameBufferUpdate = DummyRect; + client->FinishedFrameBufferUpdate = NULL; + client->GetPassword = ReadPassword; + client->MallocFrameBuffer = MallocFrameBuffer; + client->Bell = Dummy; + client->CurrentKeyboardLedState = 0; + client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; + + client->authScheme = 0; + client->subAuthScheme = 0; + client->GetCredential = NULL; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + client->tlsSession = NULL; +#endif + client->sock = -1; + client->listenSock = -1; + client->clientAuthSchemes = NULL; + return client; +} + +static rfbBool rfbInitConnection(rfbClient* client) +{ + /* Unless we accepted an incoming connection, make a TCP connection to the + given VNC server */ + + if (!client->listenSpecified) { + if (!client->serverHost) + return FALSE; + if (client->destHost) { + if (!ConnectToRFBRepeater(client,client->serverHost,client->serverPort,client->destHost,client->destPort)) + return FALSE; + } else { + if (!ConnectToRFBServer(client,client->serverHost,client->serverPort)) + return FALSE; + } + } + + /* Initialise the VNC connection, including reading the password */ + + if (!InitialiseRFBConnection(client)) + return FALSE; + + client->width=client->si.framebufferWidth; + client->height=client->si.framebufferHeight; + client->MallocFrameBuffer(client); + + if (!SetFormatAndEncodings(client)) + return FALSE; + + if (client->updateRect.x < 0) { + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + } + + if (client->appData.scaleSetting>1) + { + if (!SendScaleSetting(client, client->appData.scaleSetting)) + return FALSE; + if (!SendFramebufferUpdateRequest(client, + client->updateRect.x / client->appData.scaleSetting, + client->updateRect.y / client->appData.scaleSetting, + client->updateRect.w / client->appData.scaleSetting, + client->updateRect.h / client->appData.scaleSetting, + FALSE)) + return FALSE; + } + else + { + if (!SendFramebufferUpdateRequest(client, + client->updateRect.x, client->updateRect.y, + client->updateRect.w, client->updateRect.h, + FALSE)) + return FALSE; + } + + return TRUE; +} + +rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv) { + int i,j; + + if(argv && argc && *argc) { + if(client->programName==0) + client->programName=argv[0]; + + for (i = 1; i < *argc; i++) { + j = i; + if (strcmp(argv[i], "-listen") == 0) { + listenForIncomingConnections(client); + break; + } else if (strcmp(argv[i], "-listennofork") == 0) { + listenForIncomingConnectionsNoFork(client, -1); + break; + } else if (strcmp(argv[i], "-play") == 0) { + client->serverPort = -1; + j++; + } else if (i+1<*argc && strcmp(argv[i], "-encodings") == 0) { + client->appData.encodingsString = argv[i+1]; + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-compress") == 0) { + client->appData.compressLevel = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-quality") == 0) { + client->appData.qualityLevel = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-scale") == 0) { + client->appData.scaleSetting = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-repeaterdest") == 0) { + char* colon=strchr(argv[i+1],':'); + + if(client->destHost) + free(client->destHost); + client->destPort = 5900; + + client->destHost = strdup(argv[i+1]); + if(colon) { + client->destHost[(int)(colon-argv[i+1])] = '\0'; + client->destPort = atoi(colon+1); + } + j+=2; + } else { + char* colon=strchr(argv[i],':'); + + if(client->serverHost) + free(client->serverHost); + + if(colon) { + client->serverHost = strdup(argv[i]); + client->serverHost[(int)(colon-argv[i])] = '\0'; + client->serverPort = atoi(colon+1); + } else { + client->serverHost = strdup(argv[i]); + } + if(client->serverPort >= 0 && client->serverPort < 5900) + client->serverPort += 5900; + } + /* purge arguments */ + if (j>i) { + *argc-=j-i; + memmove(argv+i,argv+j,(*argc-i)*sizeof(char*)); + i--; + } + } + } + + if(!rfbInitConnection(client)) { + rfbClientCleanup(client); + return FALSE; + } + + return TRUE; +} + +void rfbClientCleanup(rfbClient* client) { +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + int i; + + for ( i = 0; i < 4; i++ ) { + if (client->zlibStreamActive[i] == TRUE ) { + if (inflateEnd (&client->zlibStream[i]) != Z_OK && + client->zlibStream[i].msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->zlibStream[i].msg); + } + } + + if ( client->decompStreamInited == TRUE ) { + if (inflateEnd (&client->decompStream) != Z_OK && + client->decompStream.msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->decompStream.msg ); + } + + if (client->jpegSrcManager) + free(client->jpegSrcManager); +#endif +#endif + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + FreeTLS(client); +#endif + if (client->sock >= 0) + close(client->sock); + if (client->listenSock >= 0) + close(client->listenSock); + free(client->desktopName); + free(client->serverHost); + if (client->destHost) + free(client->destHost); + if (client->clientAuthSchemes) + free(client->clientAuthSchemes); + free(client); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zlib.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zlib.c new file mode 100755 index 0000000..e872d40 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zlib.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2000 Tridia Corporation. 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. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/* + * zlib.c - handle zlib encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zlib + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleZlibBPP CONCAT2E(HandleZlib,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleZlibBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int remaining; + int inflateResult; + int toRead; + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) { + + if ( client->raw_buffer != NULL ) { + + free( client->raw_buffer ); + + } + + client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 )); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + + } + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + remaining = rfbClientSwap32IfLE(hdr.nBytes); + + /* Need to initialize the decompressor state. */ + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = 0; + client->decompStream.next_out = ( Bytef * )client->raw_buffer; + client->decompStream.avail_out = client->raw_buffer_size; + client->decompStream.data_type = Z_BINARY; + + /* Initialize the decompression stream structures on the first invocation. */ + if ( client->decompStreamInited == FALSE ) { + + inflateResult = inflateInit( &client->decompStream ); + + if ( inflateResult != Z_OK ) { + rfbClientLog( + "inflateInit returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + client->decompStreamInited = TRUE; + + } + + inflateResult = Z_OK; + + /* Process buffer full of data until no more to process, or + * some type of inflater error, or Z_STREAM_END. + */ + while (( remaining > 0 ) && + ( inflateResult == Z_OK )) { + + if ( remaining > RFB_BUFFER_SIZE ) { + toRead = RFB_BUFFER_SIZE; + } + else { + toRead = remaining; + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->buffer,toRead)) + return FALSE; + + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = toRead; + + /* Need to uncompress buffer full. */ + inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); + + /* We never supply a dictionary for compression. */ + if ( inflateResult == Z_NEED_DICT ) { + rfbClientLog("zlib inflate needs a dictionary!\n"); + return FALSE; + } + if ( inflateResult < 0 ) { + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + /* Result buffer allocated to be at least large enough. We should + * never run out of space! + */ + if (( client->decompStream.avail_in > 0 ) && + ( client->decompStream.avail_out <= 0 )) { + rfbClientLog("zlib inflate ran out of space!\n"); + return FALSE; + } + + remaining -= toRead; + + } /* while ( remaining > 0 ) */ + + if ( inflateResult == Z_OK ) { + + /* Put the uncompressed contents of the update on the screen. */ + CopyRectangle(client, (uint8_t *)client->raw_buffer, rx, ry, rw, rh); + } + else { + + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + + } + + return TRUE; +} + +#undef CARDBPP + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zrle.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zrle.c new file mode 100755 index 0000000..da2db4b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zrle.c @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2005 Johannes E. Schindelin. 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. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/* + * zrle.c - handle zrle encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zrle + * encoded rectangle with BPP bits per pixel. + */ + +#ifndef REALBPP +#define REALBPP BPP +#endif + +#if !defined(UNCOMP) || UNCOMP==0 +#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP) +#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP) +#elif UNCOMP>0 +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down) +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down) +#else +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up) +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up) +#endif +#define CARDBPP CONCAT3E(uint,BPP,_t) +#define CARDREALBPP CONCAT3E(uint,REALBPP,_t) + +#define ENDIAN_LITTLE 0 +#define ENDIAN_BIG 1 +#define ENDIAN_NO 2 +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#undef END_FIX +#if ZYWRLE_ENDIAN == ENDIAN_LITTLE +# define END_FIX LE +#elif ZYWRLE_ENDIAN == ENDIAN_BIG +# define END_FIX BE +#else +# define END_FIX NE +#endif +#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c) +#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b) +#undef CPIXEL +#if REALBPP != BPP +#if UNCOMP == 0 +#define CPIXEL REALBPP +#elif UNCOMP>0 +#define CPIXEL CONCAT2E(REALBPP,Down) +#else +#define CPIXEL CONCAT2E(REALBPP,Up) +#endif +#endif +#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t) +#if BPP!=8 +#define ZYWRLE_DECODE 1 +#include "../libvncserver/zywrletemplate.c" +#endif +#undef CPIXEL + +static int HandleZRLETile(rfbClient* client, + uint8_t* buffer,size_t buffer_length, + int x,int y,int w,int h); + +static rfbBool +HandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZRLEHeader header; + int remaining; + int inflateResult; + int toRead; + int min_buffer_size = rw * rh * (REALBPP / 8) * 2; + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed REALBPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < min_buffer_size) { + + if ( client->raw_buffer != NULL ) { + + free( client->raw_buffer ); + + } + + client->raw_buffer_size = min_buffer_size; + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + + } + + if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader)) + return FALSE; + + remaining = rfbClientSwap32IfLE(header.length); + + /* Need to initialize the decompressor state. */ + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = 0; + client->decompStream.next_out = ( Bytef * )client->raw_buffer; + client->decompStream.avail_out = client->raw_buffer_size; + client->decompStream.data_type = Z_BINARY; + + /* Initialize the decompression stream structures on the first invocation. */ + if ( client->decompStreamInited == FALSE ) { + + inflateResult = inflateInit( &client->decompStream ); + + if ( inflateResult != Z_OK ) { + rfbClientLog( + "inflateInit returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + client->decompStreamInited = TRUE; + + } + + inflateResult = Z_OK; + + /* Process buffer full of data until no more to process, or + * some type of inflater error, or Z_STREAM_END. + */ + while (( remaining > 0 ) && + ( inflateResult == Z_OK )) { + + if ( remaining > RFB_BUFFER_SIZE ) { + toRead = RFB_BUFFER_SIZE; + } + else { + toRead = remaining; + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->buffer,toRead)) + return FALSE; + + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = toRead; + + /* Need to uncompress buffer full. */ + inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); + + /* We never supply a dictionary for compression. */ + if ( inflateResult == Z_NEED_DICT ) { + rfbClientLog("zlib inflate needs a dictionary!\n"); + return FALSE; + } + if ( inflateResult < 0 ) { + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + /* Result buffer allocated to be at least large enough. We should + * never run out of space! + */ + if (( client->decompStream.avail_in > 0 ) && + ( client->decompStream.avail_out <= 0 )) { + rfbClientLog("zlib inflate ran out of space!\n"); + return FALSE; + } + + remaining -= toRead; + + } /* while ( remaining > 0 ) */ + + if ( inflateResult == Z_OK ) { + void* buf=client->raw_buffer; + int i,j; + + remaining = client->raw_buffer_size-client->decompStream.avail_out; + + for(j=0; jrw)?rw-i:rfbZRLETileWidth; + int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; + int result=HandleZRLETile(client,buf,remaining,rx+i,ry+j,subWidth,subHeight); + + if(result<0) { + rfbClientLog("ZRLE decoding failed (%d)\n",result); +return TRUE; + return FALSE; + } + + buf+=result; + remaining-=result; + } + } + else { + + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + + } + + return TRUE; +} + +#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0 +#if UNCOMP>0 +#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP) +#else +#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP))) +#endif +#else +#define UncompressCPixel(pointer) (*(CARDBPP*)pointer) +#endif + +static int HandleZRLETile(rfbClient* client, + uint8_t* buffer,size_t buffer_length, + int x,int y,int w,int h) { + uint8_t* buffer_copy = buffer; + uint8_t* buffer_end = buffer+buffer_length; + uint8_t type; +#if BPP!=8 + uint8_t zywrle_level = (client->appData.qualityLevel & 0x80) ? + 0 : (3 - client->appData.qualityLevel / 3); +#endif + + if(buffer_length<1) + return -2; + + type = *buffer; + buffer++; + { + if( type == 0 ) /* raw */ +#if BPP!=8 + if( zywrle_level > 0 ){ + CARDBPP* pFrame = (CARDBPP*)client->frameBuffer + y*client->width+x; + int ret; + client->appData.qualityLevel |= 0x80; + ret = HandleZRLETile(client, buffer, buffer_end-buffer, x, y, w, h); + client->appData.qualityLevel &= 0x7F; + if( ret < 0 ){ + return ret; + } + ZYWRLE_SYNTHESIZE( pFrame, pFrame, w, h, client->width, zywrle_level, (int*)client->zlib_buffer ); + buffer += ret; + }else +#endif + { +#if REALBPP!=BPP + int i,j; + + if(1+w*h*REALBPP/8>buffer_length) { + rfbClientLog("expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h); + return -3; + } + + for(j=y*client->width; j<(y+h)*client->width; j+=client->width) + for(i=x; iframeBuffer)[j+i] = UncompressCPixel(buffer); +#else + CopyRectangle(client, buffer, x, y, w, h); + buffer+=w*h*REALBPP/8; +#endif + } + else if( type == 1 ) /* solid */ + { + CARDBPP color = UncompressCPixel(buffer); + + if(1+REALBPP/8>buffer_length) + return -4; + + FillRectangle(client, x, y, w, h, color); + + buffer+=REALBPP/8; + + } + else if( (type >= 2)&&(type <= 127) ) /* packed Palette */ + { + CARDBPP palette[16]; + int i,j,shift, + bpp=(type>4?(type>16?8:4):(type>2?2:1)), + mask=(1<buffer_length) + return -5; + + /* read palette */ + for(i=0; iwidth; j<(y+h)*client->width; j+=client->width) { + for(i=x,shift=8-bpp; iframeBuffer)[j+i] = palette[((*buffer)>>shift)&mask]; + shift-=bpp; + if(shift<0) { + shift=8-bpp; + buffer++; + } + } + if(shift<8-bpp) + buffer++; + } + + } + /* case 17 ... 127: not used, but valid */ + else if( type == 128 ) /* plain RLE */ + { + int i=0,j=0; + while(jbuffer_end) + return -7; + color = UncompressCPixel(buffer); + buffer+=REALBPP/8; + /* read run length */ + length=1; + while(*buffer==0xff) { + if(buffer+1>=buffer_end) + return -8; + length+=*buffer; + buffer++; + } + length+=*buffer; + buffer++; + while(j0) { + ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color; + length--; + i++; + if(i>=w) { + i=0; + j++; + } + } + if(length>0) + rfbClientLog("Warning: possible ZRLE corruption\n"); + } + + } + else if( type == 129 ) /* unused */ + { + return -8; + } + else if( (type >= 130)&&(type <= 255) ) /* palette RLE */ + { + CARDBPP palette[128]; + int i,j; + + if(2+(type-128)*REALBPP/8>buffer_length) + return -9; + + /* read palette */ + for(i=0; i=buffer_end) + return -10; + color = palette[(*buffer)&0x7f]; + length=1; + if(*buffer&0x80) { + if(buffer+1>=buffer_end) + return -11; + buffer++; + /* read run length */ + while(*buffer==0xff) { + if(buffer+1>=buffer_end) + return -8; + length+=*buffer; + buffer++; + } + length+=*buffer; + } + buffer++; + while(j0) { + ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color; + length--; + i++; + if(i>=w) { + i=0; + j++; + } + } + if(length>0) + rfbClientLog("Warning: possible ZRLE corruption\n"); + } + } + } + + return buffer-buffer_copy; +} + +#undef CARDBPP +#undef CARDREALBPP +#undef HandleZRLE +#undef HandleZRLETile +#undef UncompressCPixel +#undef REALBPP + +#endif + +#undef UNCOMP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver-config.in b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver-config.in new file mode 100755 index 0000000..ea0bef8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver-config.in @@ -0,0 +1,78 @@ +#!/bin/sh + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no +includedir=@includedir@ +libdir=@libdir@ + +# if this script is in the same directory as libvncserver-config.in, assume not installed +if [ -f "`dirname "$0"`/libvncserver-config.in" ]; then + dir="`dirname "$0"`" + prefix="`cd "$dir"; pwd`" + includedir="$prefix" + libdir="$prefix/libvncserver/.libs $prefix/libvncclient/.libs" +fi + +usage="\ +Usage: @PACKAGE@-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--link] [--libs] [--cflags]" + +if test $# -eq 0; then + echo "${usage}" 1>&2 + exit 1 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix=*) + prefix=$optarg + if test $exec_prefix_set = no ; then + exec_prefix=$optarg + fi + ;; + --prefix) + echo $prefix + ;; + --exec-prefix=*) + exec_prefix=$optarg + exec_prefix_set=yes + ;; + --exec-prefix) + echo $exec_prefix + ;; + --version) + echo @VERSION@ + ;; + --cflags) + if [ "$includedir" != /usr/include ]; then + includes=-I"$includedir" + fi + echo "$includes" + ;; + --libs) + libs="" + for dir in $libdir; do + libs="$libs -L$dir" + if [ "`uname`" = "SunOS" ]; then + # why only Solaris?? + libs="$libs -R$dir" + fi + done + echo "$libs" -lvncserver -lvncclient @LIBS@ @WSOCKLIB@ + ;; + --link) + echo @CC@ + ;; + *) + echo "${usage}" 1>&2 + exit 1 + ;; + esac + shift +done + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsp b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsp new file mode 100755 index 0000000..0dd25b5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsp @@ -0,0 +1,220 @@ +# Microsoft Developer Studio Project File - Name="libvncserver" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libvncserver - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "libvncserver.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "libvncserver.mak" CFG="libvncserver - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "libvncserver - Win32 Release" (basierend auf "Win32 (x86) Static Library") +!MESSAGE "libvncserver - Win32 Debug" (basierend auf "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libvncserver - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "zlib" /I "libjpeg" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libvncserver - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libvncserver___Win32_Debug" +# PROP BASE Intermediate_Dir "libvncserver___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "libvncserver___Win32_Debug" +# PROP Intermediate_Dir "libvncserver___Win32_Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "zlib" /I "libjpeg" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libvncserver - Win32 Release" +# Name "libvncserver - Win32 Debug" +# Begin Group "Sources" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "auth" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\auth.c +# End Source File +# Begin Source File + +SOURCE=.\d3des.c +# End Source File +# Begin Source File + +SOURCE=.\storepasswd.c +# End Source File +# Begin Source File + +SOURCE=.\vncauth.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\cargs.c +# End Source File +# Begin Source File + +SOURCE=.\corre.c +# End Source File +# Begin Source File + +SOURCE=.\cursor.c +# End Source File +# Begin Source File + +SOURCE=.\cutpaste.c +# End Source File +# Begin Source File + +SOURCE=.\draw.c +# End Source File +# Begin Source File + +SOURCE=.\font.c +# End Source File +# Begin Source File + +SOURCE=.\hextile.c +# End Source File +# Begin Source File + +SOURCE=.\httpd.c +# End Source File +# Begin Source File + +SOURCE=.\main.c +# End Source File +# Begin Source File + +SOURCE=.\rfbserver.c +# End Source File +# Begin Source File + +SOURCE=.\rre.c +# End Source File +# Begin Source File + +SOURCE=.\selbox.c +# End Source File +# Begin Source File + +SOURCE=.\sockets.c +# End Source File +# Begin Source File + +SOURCE=.\sraRegion.c +# End Source File +# Begin Source File + +SOURCE=.\stats.c +# End Source File +# Begin Source File + +SOURCE=.\tight.c +# End Source File +# Begin Source File + +SOURCE=.\translate.c +# End Source File +# Begin Source File + +SOURCE=.\zlib.c +# End Source File +# End Group +# Begin Group "Headers" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "auth Nr. 1" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\d3des.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\default8x16.h +# End Source File +# Begin Source File + +SOURCE=.\keysym.h +# End Source File +# Begin Source File + +SOURCE=.\radon.h +# End Source File +# Begin Source File + +SOURCE=.\region.h +# End Source File +# Begin Source File + +SOURCE=.\rfb.h +# End Source File +# Begin Source File + +SOURCE=.\rfbproto.h +# End Source File +# Begin Source File + +SOURCE=.\sraRegion.h +# End Source File +# End Group +# End Target +# End Project diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsw b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsw new file mode 100755 index 0000000..799cfb4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsw @@ -0,0 +1,101 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "example"=.\example.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libvncserver + End Project Dependency + Begin Project Dependency + Project_Dep_Name libjpeg + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "libjpeg"=.\libjpeg\libjpeg.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libvncserver"=.\libvncserver.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libjpeg + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "rdp2vnc"=\my\rdp2vnc\rdp2vnc\rdp2vnc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libvncserver + End Project Dependency + Begin Project Dependency + Project_Dep_Name libjpeg + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "zlib"=.\zlib\zlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/.cvsignore new file mode 100755 index 0000000..c892af4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/.cvsignore @@ -0,0 +1,5 @@ +.deps +Makefile +Makefile.in +libvncserver.a + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/Makefile.am new file mode 100755 index 0000000..629f990 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/Makefile.am @@ -0,0 +1,64 @@ +INCLUDES = -I$(top_srcdir) + +if WITH_TIGHTVNC_FILETRANSFER +TIGHTVNCFILETRANSFERHDRS=tightvnc-filetransfer/filelistinfo.h \ + tightvnc-filetransfer/filetransfermsg.h \ + tightvnc-filetransfer/handlefiletransferrequest.h \ + tightvnc-filetransfer/rfbtightproto.h + +TIGHTVNCFILETRANSFERSRCS = tightvnc-filetransfer/rfbtightserver.c \ + tightvnc-filetransfer/handlefiletransferrequest.c \ + tightvnc-filetransfer/filetransfermsg.c \ + tightvnc-filetransfer/filelistinfo.c +endif + +if WITH_WEBSOCKETS +WEBSOCKETSSRCS = websockets.c md5.c +endif + +includedir=$(prefix)/include/rfb +#include_HEADERS=rfb.h rfbconfig.h rfbint.h rfbproto.h keysym.h rfbregion.h + +include_HEADERS=../rfb/rfb.h ../rfb/rfbconfig.h ../rfb/rfbint.h \ + ../rfb/rfbproto.h ../rfb/keysym.h ../rfb/rfbregion.h ../rfb/rfbclient.h + +noinst_HEADERS=d3des.h ../rfb/default8x16.h zrleoutstream.h \ + zrlepalettehelper.h zrletypes.h private.h minilzo.h lzoconf.h scale.h \ + $(TIGHTVNCFILETRANSFERHDRS) + +EXTRA_DIST=tableinit24.c tableinittctemplate.c tabletranstemplate.c \ + tableinitcmtemplate.c tabletrans24template.c \ + zrleencodetemplate.c + +if HAVE_LIBZ +ZLIBSRCS = zlib.c zrle.c zrleoutstream.c zrlepalettehelper.c zywrletemplate.c +if HAVE_LIBJPEG +TIGHTSRCS = tight.c +else +if HAVE_LIBPNG +TIGHTSRCS = tight.c +endif +endif +endif + +LIB_SRCS = main.c rfbserver.c rfbregion.c auth.c sockets.c $(WEBSOCKETSSRCS) \ + 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 \ + $(ZLIBSRCS) $(TIGHTSRCS) $(TIGHTVNCFILETRANSFERSRCS) + +libvncserver_la_SOURCES=$(LIB_SRCS) +libvncserver_la_LIBADD=@SSL_LIBS@ @CRYPT_LIBS@ + +lib_LTLIBRARIES=libvncserver.la + +if HAVE_RPM +$(PACKAGE)-$(VERSION).tar.gz: dist + +# Rule to build RPM distribution package +rpm: $(PACKAGE)-$(VERSION).tar.gz libvncserver.spec + cp $(PACKAGE)-$(VERSION).tar.gz @RPMSOURCEDIR@ + rpmbuild -ba libvncserver.spec +endif + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/auth.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/auth.c new file mode 100755 index 0000000..c4c5ff1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/auth.c @@ -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 . + * 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 3.8 clients are well informed */ +void rfbClientSendString(rfbClientPtr cl, 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 && sizenext) { + 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; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cargs.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cargs.c new file mode 100755 index 0000000..2e973e8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cargs.c @@ -0,0 +1,227 @@ +/* + * This parses the command line arguments. It was seperated from main.c by + * Justin Dearing . + */ + +/* + * LibVNCServer (C) 2001 Johannes E. Schindelin + * Original OSXvnc (C) 2001 Dan McGuirk . + * Original Xvnc (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * see GPL (latest version) for full details + */ + +#include + +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; + } +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + } else if (strcmp(argv[i], "-sslkeyfile") == 0) { /* -sslkeyfile sslkeyfile */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->sslkeyfile = argv[++i]; + } else if (strcmp(argv[i], "-sslcertfile") == 0) { /* -sslcertfile sslcertfile */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->sslcertfile = argv[++i]; +#endif + } 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; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/corre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/corre.c new file mode 100755 index 0000000..bb07c77 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/corre.c @@ -0,0 +1,360 @@ +/* + * 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 . + * 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 + +/* + * rreBeforeBuf contains pixel data in the client's format. + * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is + * larger than the raw data or if it exceeds rreAfterBufSize then + * raw encoding is used instead. + */ + +static int rreBeforeBufSize = 0; +static char *rreBeforeBuf = NULL; + +static int rreAfterBufSize = 0; +static char *rreAfterBuf = NULL; +static int rreAfterBufLen = 0; + +static int subrectEncode8(uint8_t *data, int w, int h); +static int subrectEncode16(uint16_t *data, int w, int h); +static int subrectEncode32(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); + +void rfbCoRRECleanup(rfbScreenInfoPtr screen) +{ + if (rreBeforeBufSize) { + free(rreBeforeBuf); + rreBeforeBufSize=0; + } + if (rreAfterBufSize) { + free(rreAfterBuf); + rreAfterBufSize=0; + } +} + +/* + * 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 (rreBeforeBufSize < maxRawSize) { + rreBeforeBufSize = maxRawSize; + if (rreBeforeBuf == NULL) + rreBeforeBuf = (char *)malloc(rreBeforeBufSize); + else + rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize); + } + + if (rreAfterBufSize < maxRawSize) { + rreAfterBufSize = maxRawSize; + if (rreAfterBuf == NULL) + rreAfterBuf = (char *)malloc(rreAfterBufSize); + else + rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize); + } + + (*cl->translateFn)(cl->translateLookupTable,&(cl->screen->serverFormat), + &cl->format, fbptr, rreBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + switch (cl->format.bitsPerPixel) { + case 8: + nSubrects = subrectEncode8((uint8_t *)rreBeforeBuf, w, h); + break; + case 16: + nSubrects = subrectEncode16((uint16_t *)rreBeforeBuf, w, h); + break; + case 32: + nSubrects = subrectEncode32((uint32_t *)rreBeforeBuf, 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 + rreAfterBufLen, + 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 < rreAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > rreAfterBufLen) { + bytesToCopy = rreAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[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 rreAfterBuf. 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 [...] where each + * is []. + */ + +#define DEFINE_SUBRECT_ENCODE(bpp) \ +static int \ +subrectEncode##bpp(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*)rreAfterBuf) = bg; \ + \ + rreAfterBufLen = (bpp/8); \ + \ + for (y=0; y 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 = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \ + if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ + return -1; \ + \ + numsubs += 1; \ + *((uint##bpp##_t*)(rreAfterBuf + rreAfterBufLen)) = cl; \ + rreAfterBufLen += (bpp/8); \ + memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \ + rreAfterBufLen += 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) { + 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; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cursor.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cursor.c new file mode 100755 index 0000000..c071dd9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cursor.c @@ -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 +#include +#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;icleanup=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>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>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=0;i--) { + c=source[j*w+i]; + if(j>0) c|=source[(j-1)*w+i]; + if(j0 && (c&0x80)) + mask[j*w+i-1]|=0x01; + if(i>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>(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;jheight;j++) { + for(i=0,bit=0x80;iwidth;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<redShift| + cursor->backGreen<greenShift|cursor->backBlue<blueShift; + foreground=cursor->foreRed<redShift| + cursor->foreGreen<greenShift|cursor->foreBlue<blueShift; + + for(j=0;jheight;j++) + for(i=0,bit=0x80;iwidth;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;jframeBuffer+(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->underCursorBufferLenunderCursorBuffer!=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;junderCursorBuffer+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;jmask[], + * 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;jmask[(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;jheight;j++) { + for(i=0,i1=0,bit=0x80;i1width;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;i1width;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); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cutpaste.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cutpaste.c new file mode 100755 index 0000000..6a9dcb9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cutpaste.c @@ -0,0 +1,38 @@ +/* + * cutpaste.c - routines to deal with cut & paste buffers / selection. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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 + + +/* + * 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); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.c new file mode 100755 index 0000000..2df1aab --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.c @@ -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 + **********************************************************************/ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.h new file mode 100755 index 0000000..e3761ca --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.h @@ -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 diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/draw.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/draw.c new file mode 100755 index 0000000..7e1ed49 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/draw.c @@ -0,0 +1,61 @@ +#include + +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;jframeBuffer+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)y2) + SWAPPOINTS + for(i=y1;i<=y2;i++) + SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i); + /* TODO: Maybe make this more intelligently? */ + if(x2x2) + 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 + +int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,unsigned char c,rfbPixel col) +{ + int i,j,width,height; + unsigned char* data=font->data+font->metaData[c*5]; + unsigned char d=*data; + int rowstride=rfbScreen->paddedWidthInBytes; + int bpp=rfbScreen->serverFormat.bitsPerPixel/8; + char *colour=(char*)&col; + + if(!rfbEndianTest) + colour += 4-bpp; + + width=font->metaData[c*5+1]; + height=font->metaData[c*5+2]; + x+=font->metaData[c*5+3]; + y+=-font->metaData[c*5+4]-height+1; + + for(j=0;j= 0 && y+j < rfbScreen->height && + x+i >= 0 && x+i < rfbScreen->width) + memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp); + d<<=1; + } + /* if((i&7)!=0) data++; */ + } + return(width); +} + +void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,const char* string,rfbPixel colour) +{ + while(*string) { + x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour); + string++; + } +} + +/* TODO: these two functions need to be more efficient */ +/* if col==bcol, assume transparent background */ +int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,unsigned char c, + int x1,int y1,int x2,int y2, + rfbPixel col,rfbPixel bcol) +{ + int i,j,width,height; + unsigned char* data=font->data+font->metaData[c*5]; + unsigned char d; + int rowstride=rfbScreen->paddedWidthInBytes; + int bpp=rfbScreen->serverFormat.bitsPerPixel/8,extra_bytes=0; + char* colour=(char*)&col; + char* bcolour=(char*)&bcol; + + if(!rfbEndianTest) { + colour+=4-bpp; + bcolour+=4-bpp; + } + + width=font->metaData[c*5+1]; + height=font->metaData[c*5+2]; + x+=font->metaData[c*5+3]; + y+=-font->metaData[c*5+4]-height+1; + + /* after clipping, x2 will be count of bytes between rows, + * x1 start of i, y1 start of j, width and height will be adjusted. */ + if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0; + if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0; + if(y2=x1 && x+i=y1 && y+jframeBuffer+(y+j)*rowstride+(x+i)*bpp, + colour,bpp); + } else if(bcol!=col) { + memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp, + bcolour,bpp); + } + } + d<<=1; + } + /* if((i&7)==0) data++; */ + data += extra_bytes; + } + return(width); +} + +void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,const char* string, + int x1,int y1,int x2,int y2, + rfbPixel colour,rfbPixel backColour) +{ + while(*string) { + x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2, + colour,backColour); + string++; + } +} + +int rfbWidthOfString(rfbFontDataPtr font,const char* string) +{ + int i=0; + while(*string) { + i+=font->metaData[*string*5+1]; + string++; + } + return(i); +} + +int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c) +{ + return(font->metaData[c*5+1]+font->metaData[c*5+3]); +} + +void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2) +{ + *x1+=font->metaData[c*5+3]; + *y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1; + *x2=*x1+font->metaData[c*5+1]+1; + *y2=*y1+font->metaData[c*5+2]+1; +} + +#ifndef INT_MAX +#define INT_MAX 0x7fffffff +#endif + +void rfbWholeFontBBox(rfbFontDataPtr font, + int *x1, int *y1, int *x2, int *y2) +{ + int i; + int* m=font->metaData; + + (*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=1-(INT_MAX); + for(i=0;i<256;i++) { + if(m[i*5+1]-m[i*5+3]>(*x2)) + (*x2)=m[i*5+1]-m[i*5+3]; + if(-m[i*5+2]+m[i*5+4]<(*y1)) + (*y1)=-m[i*5+2]+m[i*5+4]; + if(m[i*5+3]<(*x1)) + (*x1)=m[i*5+3]; + if(-m[i*5+4]>(*y2)) + (*y2)=-m[i*5+4]; + } + (*x2)++; + (*y2)++; +} + +rfbFontDataPtr rfbLoadConsoleFont(char *filename) +{ + FILE *f=fopen(filename,"rb"); + rfbFontDataPtr p; + int i; + + if(!f) return NULL; + + p=(rfbFontDataPtr)malloc(sizeof(rfbFontData)); + p->data=(unsigned char*)malloc(4096); + if(1!=fread(p->data,4096,1,f)) { + free(p->data); + free(p); + return NULL; + } + fclose(f); + p->metaData=(int*)malloc(256*5*sizeof(int)); + for(i=0;i<256;i++) { + p->metaData[i*5+0]=i*16; /* offset */ + p->metaData[i*5+1]=8; /* width */ + p->metaData[i*5+2]=16; /* height */ + p->metaData[i*5+3]=0; /* xhot */ + p->metaData[i*5+4]=0; /* yhot */ + } + return(p); +} + +void rfbFreeFont(rfbFontDataPtr f) +{ + free(f->data); + free(f->metaData); + free(f); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/hextile.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/hextile.c new file mode 100755 index 0000000..52920d8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/hextile.c @@ -0,0 +1,342 @@ +/* + * hextile.c + * + * Routines to implement Hextile Encoding + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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 + +static rfbBool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h); + + +/* + * rfbSendRectEncodingHextile - send a rectangle using hextile encoding. + */ + +rfbBool +rfbSendRectEncodingHextile(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > 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(rfbEncodingHextile); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, rfbEncodingHextile, + sz_rfbFramebufferUpdateRectHeader, + sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h); + + switch (cl->format.bitsPerPixel) { + case 8: + return sendHextiles8(cl, x, y, w, h); + case 16: + return sendHextiles16(cl, x, y, w, h); + case 32: + return sendHextiles32(cl, x, y, w, h); + } + + rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel); + return FALSE; +} + + +#define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix)) + +#define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1]) + +#define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3]) + + +#define DEFINE_SEND_HEXTILES(bpp) \ + \ + \ +static rfbBool subrectEncode##bpp(rfbClientPtr cli, uint##bpp##_t *data, \ + int w, int h, uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono);\ +static void testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, \ + rfbBool *solid, uint##bpp##_t *bg, uint##bpp##_t *fg); \ + \ + \ +/* \ + * rfbSendHextiles \ + */ \ + \ +static rfbBool \ +sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) { \ + int x, y, w, h; \ + int startUblen; \ + char *fbptr; \ + uint##bpp##_t bg = 0, fg = 0, newBg, newFg; \ + rfbBool mono, solid; \ + rfbBool validBg = FALSE; \ + rfbBool validFg = FALSE; \ + uint##bpp##_t clientPixelData[16*16*(bpp/8)]; \ + \ + for (y = ry; y < ry+rh; y += 16) { \ + for (x = rx; x < rx+rw; x += 16) { \ + w = h = 16; \ + if (rx+rw - x < 16) \ + w = rx+rw - x; \ + if (ry+rh - y < 16) \ + h = ry+rh - y; \ + \ + if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \ + UPDATE_BUF_SIZE) { \ + if (!rfbSendUpdateBuf(cl)) \ + return FALSE; \ + } \ + \ + fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) \ + + (x * (cl->scaledScreen->bitsPerPixel / 8))); \ + \ + (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->serverFormat), \ + &cl->format, fbptr, (char *)clientPixelData, \ + cl->scaledScreen->paddedWidthInBytes, w, h); \ + \ + startUblen = cl->ublen; \ + cl->updateBuf[startUblen] = 0; \ + cl->ublen++; \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \ + \ + testColours##bpp(clientPixelData, w * h, \ + &mono, &solid, &newBg, &newFg); \ + \ + if (!validBg || (newBg != bg)) { \ + validBg = TRUE; \ + bg = newBg; \ + cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \ + PUT_PIXEL##bpp(bg); \ + } \ + \ + if (solid) { \ + continue; \ + } \ + \ + cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \ + \ + if (mono) { \ + if (!validFg || (newFg != fg)) { \ + validFg = TRUE; \ + fg = newFg; \ + cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \ + PUT_PIXEL##bpp(fg); \ + } \ + } else { \ + validFg = FALSE; \ + cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \ + } \ + \ + if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \ + /* encoding was too large, use raw */ \ + validBg = FALSE; \ + validFg = FALSE; \ + cl->ublen = startUblen; \ + cl->updateBuf[cl->ublen++] = rfbHextileRaw; \ + (*cl->translateFn)(cl->translateLookupTable, \ + &(cl->screen->serverFormat), &cl->format, fbptr, \ + (char *)clientPixelData, \ + cl->scaledScreen->paddedWidthInBytes, w, h); \ + \ + memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \ + w * h * (bpp/8)); \ + \ + cl->ublen += w * h * (bpp/8); \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \ + w * h * (bpp/8)); \ + } \ + } \ + } \ + \ + return TRUE; \ +} \ + \ + \ +static rfbBool \ +subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h, \ + uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono) \ +{ \ + uint##bpp##_t cl2; \ + 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; \ + int nSubrectsUblen; \ + \ + nSubrectsUblen = cl->ublen; \ + cl->ublen++; \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \ + \ + for (y=0; y 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; \ + } \ + \ + if (mono) { \ + newLen = cl->ublen - nSubrectsUblen + 2; \ + } else { \ + newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \ + } \ + \ + if (newLen > (w * h * (bpp/8))) \ + return FALSE; \ + \ + numsubs += 1; \ + \ + if (!mono) PUT_PIXEL##bpp(cl2); \ + \ + cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \ + cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \ + \ + /* \ + * 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; \ + } \ + } \ + } \ + } \ + } \ + \ + cl->updateBuf[nSubrectsUblen] = numsubs; \ + \ + return TRUE; \ +} \ + \ + \ +/* \ + * testColours() tests if there are one (solid), two (mono) or more \ + * colours in a tile and gets a reasonable guess at the best background \ + * pixel, and the foreground pixel for mono. \ + */ \ + \ +static void \ +testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, rfbBool *solid, \ + uint##bpp##_t *bg, uint##bpp##_t *fg) { \ + uint##bpp##_t colour1 = 0, colour2 = 0; \ + int n1 = 0, n2 = 0; \ + *mono = TRUE; \ + *solid = TRUE; \ + \ + for (; size > 0; size--, data++) { \ + \ + if (n1 == 0) \ + colour1 = *data; \ + \ + if (*data == colour1) { \ + n1++; \ + continue; \ + } \ + \ + if (n2 == 0) { \ + *solid = FALSE; \ + colour2 = *data; \ + } \ + \ + if (*data == colour2) { \ + n2++; \ + continue; \ + } \ + \ + *mono = FALSE; \ + break; \ + } \ + \ + if (n1 > n2) { \ + *bg = colour1; \ + *fg = colour2; \ + } else { \ + *bg = colour2; \ + *fg = colour1; \ + } \ +} + +DEFINE_SEND_HEXTILES(8) +DEFINE_SEND_HEXTILES(16) +DEFINE_SEND_HEXTILES(32) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/httpd.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/httpd.c new file mode 100755 index 0000000..7e8e923 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/httpd.c @@ -0,0 +1,631 @@ +/* + * httpd.c - a simple HTTP server + */ + +/* + * Copyright (C) 2002 RealVNC Ltd. + * 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 + +#include +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif +#include + +#ifdef WIN32 +#include +#define close closesocket +#else +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#include +#endif +#include +#endif + +#ifdef USE_LIBWRAP +#include +#endif + +#define connection_close +#ifndef connection_close + +#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \ + "File Not Found\n" \ + "

File Not Found

\n" + +#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\n\r\n" \ + "Invalid Request\n" \ + "

Invalid request

\n" + +#define OK_STR "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" + +#else + +#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\nConnection: close\r\n\r\n" \ + "File Not Found\n" \ + "

File Not Found

\n" + +#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\nConnection: close\r\n\r\n" \ + "Invalid Request\n" \ + "

Invalid request

\n" + +#define OK_STR "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n" + +#endif + +static void httpProcessInput(rfbScreenInfoPtr screen); +static rfbBool compareAndSkip(char **ptr, const char *str); +static rfbBool parseParams(const char *request, char *result, int max_bytes); +static rfbBool validateString(char *str); + +#define BUF_SIZE 32768 + +static char buf[BUF_SIZE]; +static size_t buf_filled=0; + +/* + * httpInitSockets sets up the TCP socket to listen for HTTP connections. + */ + +void +rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) +{ + if (rfbScreen->httpInitDone) + return; + + rfbScreen->httpInitDone = TRUE; + + if (!rfbScreen->httpDir) + return; + + if (rfbScreen->httpPort == 0) { + rfbScreen->httpPort = rfbScreen->port-100; + } + + rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort); + + rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort); + + if ((rfbScreen->httpListenSock = + rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) { + rfbLogPerror("ListenOnTCPPort"); + return; + } + + /*AddEnabledDevice(httpListenSock);*/ +} + +void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { + if(rfbScreen->httpSock>-1) { + close(rfbScreen->httpSock); + FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds); + rfbScreen->httpSock=-1; + } +} + +/* + * httpCheckFds is called from ProcessInputEvents to check for input on the + * HTTP socket(s). If there is input to process, httpProcessInput is called. + */ + +void +rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) +{ + int nfds; + fd_set fds; + struct timeval tv; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + + if (!rfbScreen->httpDir) + return; + + if (rfbScreen->httpListenSock < 0) + return; + + FD_ZERO(&fds); + FD_SET(rfbScreen->httpListenSock, &fds); + if (rfbScreen->httpSock >= 0) { + FD_SET(rfbScreen->httpSock, &fds); + } + tv.tv_sec = 0; + tv.tv_usec = 0; + nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv); + if (nfds == 0) { + return; + } + if (nfds < 0) { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno != EINTR) + rfbLogPerror("httpCheckFds: select"); + return; + } + + if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) { + httpProcessInput(rfbScreen); + } + + if (FD_ISSET(rfbScreen->httpListenSock, &fds)) { + int flags; + if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); + + if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, + (struct sockaddr *)&addr, &addrlen)) < 0) { + rfbLogPerror("httpCheckFds: accept"); + return; + } +#ifdef __MINGW32__ + rfbErr("O_NONBLOCK on MinGW32 NOT IMPLEMENTED"); +#else +#ifdef USE_LIBWRAP + if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), + STRING_UNKNOWN)) { + rfbLog("Rejected HTTP connection from client %s\n", + inet_ntoa(addr.sin_addr)); +#else + flags = fcntl(rfbScreen->httpSock, F_GETFL); + + if (flags < 0 || fcntl(rfbScreen->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { + rfbLogPerror("httpCheckFds: fcntl"); +#endif + close(rfbScreen->httpSock); + rfbScreen->httpSock = -1; + return; + } + + flags=fcntl(rfbScreen->httpSock,F_GETFL); + if(flags==-1 || + fcntl(rfbScreen->httpSock,F_SETFL,flags|O_NONBLOCK)==-1) { + rfbLogPerror("httpCheckFds: fcntl"); + close(rfbScreen->httpSock); + rfbScreen->httpSock=-1; + return; + } +#endif + + /*AddEnabledDevice(httpSock);*/ + } +} + + +static void +httpCloseSock(rfbScreenInfoPtr rfbScreen) +{ + close(rfbScreen->httpSock); + rfbScreen->httpSock = -1; + buf_filled = 0; +} + +static rfbClientRec cl; + +/* + * httpProcessInput is called when input is received on the HTTP socket. + */ + +static void +httpProcessInput(rfbScreenInfoPtr rfbScreen) +{ + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + char fullFname[512]; + char params[1024]; + char *ptr; + char *fname; + unsigned int maxFnameLen; + FILE* fd; + rfbBool performSubstitutions = FALSE; + char str[256+32]; +#ifndef WIN32 + char* user=getenv("USER"); +#endif + + cl.sock=rfbScreen->httpSock; + + if (strlen(rfbScreen->httpDir) > 255) { + rfbErr("-httpd directory too long\n"); + httpCloseSock(rfbScreen); + return; + } + strcpy(fullFname, rfbScreen->httpDir); + fname = &fullFname[strlen(fullFname)]; + maxFnameLen = 511 - strlen(fullFname); + + buf_filled=0; + + /* Read data from the HTTP client until we get a complete request. */ + while (1) { + ssize_t got; + + if (buf_filled > sizeof (buf)) { + rfbErr("httpProcessInput: HTTP request is too long\n"); + httpCloseSock(rfbScreen); + return; + } + + got = read (rfbScreen->httpSock, buf + buf_filled, + sizeof (buf) - buf_filled - 1); + + if (got <= 0) { + if (got == 0) { + rfbErr("httpd: premature connection close\n"); + } else { + if (errno == EAGAIN) { + return; + } + rfbLogPerror("httpProcessInput: read"); + } + httpCloseSock(rfbScreen); + return; + } + + buf_filled += got; + buf[buf_filled] = '\0'; + + /* Is it complete yet (is there a blank line)? */ + if (strstr (buf, "\r\r") || strstr (buf, "\n\n") || + strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r")) + break; + } + + + /* Process the request. */ + if(rfbScreen->httpEnableProxyConnect) { + const static char* PROXY_OK_STR = "HTTP/1.0 200 OK\r\nContent-Type: octet-stream\r\nPragma: no-cache\r\n\r\n"; + if(!strncmp(buf, "CONNECT ", 8)) { + if(atoi(strchr(buf, ':')+1)!=rfbScreen->port) { + rfbErr("httpd: CONNECT format invalid.\n"); + rfbWriteExact(&cl,INVALID_REQUEST_STR, strlen(INVALID_REQUEST_STR)); + httpCloseSock(rfbScreen); + return; + } + /* proxy connection */ + rfbLog("httpd: client asked for CONNECT\n"); + rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR)); + rfbNewClientConnection(rfbScreen,rfbScreen->httpSock); + rfbScreen->httpSock = -1; + return; + } + if (!strncmp(buf, "GET ",4) && !strncmp(strchr(buf,'/'),"/proxied.connection HTTP/1.", 27)) { + /* proxy connection */ + rfbLog("httpd: client asked for /proxied.connection\n"); + rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR)); + rfbNewClientConnection(rfbScreen,rfbScreen->httpSock); + rfbScreen->httpSock = -1; + return; + } + } + + if (strncmp(buf, "GET ", 4)) { + rfbErr("httpd: no GET line\n"); + httpCloseSock(rfbScreen); + return; + } else { + /* Only use the first line. */ + buf[strcspn(buf, "\n\r")] = '\0'; + } + + if (strlen(buf) > maxFnameLen) { + rfbErr("httpd: GET line too long\n"); + httpCloseSock(rfbScreen); + return; + } + + if (sscanf(buf, "GET %s HTTP/1.", fname) != 1) { + rfbErr("httpd: couldn't parse GET line\n"); + httpCloseSock(rfbScreen); + return; + } + + if (fname[0] != '/') { + rfbErr("httpd: filename didn't begin with '/'\n"); + rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); + httpCloseSock(rfbScreen); + return; + } + + if (strchr(fname+1, '/') != NULL) { + rfbErr("httpd: asking for file in other directory\n"); + rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); + httpCloseSock(rfbScreen); + return; + } + + getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen); + rfbLog("httpd: get '%s' for %s\n", fname+1, + inet_ntoa(addr.sin_addr)); + + /* Extract parameters from the URL string if necessary */ + + params[0] = '\0'; + ptr = strchr(fname, '?'); + if (ptr != NULL) { + *ptr = '\0'; + if (!parseParams(&ptr[1], params, 1024)) { + params[0] = '\0'; + rfbErr("httpd: bad parameters in the URL\n"); + } + } + + + /* If we were asked for '/', actually read the file index.vnc */ + + if (strcmp(fname, "/") == 0) { +// strcpy(fname, "/index.vnc"); + strcpy(fname, "/novnc.html"); + rfbLog("httpd: defaulting to '%s'\n", fname+1); + } + + /* Substitutions are performed on files ending .vnc */ + + if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) { + performSubstitutions = TRUE; + } + + /* Open the file */ + + if ((fd = fopen(fullFname, "r")) == 0) { + rfbLogPerror("httpProcessInput: open"); + rfbLogPerror(fname); + + rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); + + httpCloseSock(rfbScreen); + return; + } + + + + + + +if (strstr(fullFname,".js")!=NULL) +{ + char *ok="HTTP/1.0 200 OK\r\nContent-Type: application/x-javascript\r\n\r\n"; + rfbWriteExact(&cl, ok, strlen(ok)); +}else if (strstr(fullFname,".css")!=NULL) +{ + char *ok="HTTP/1.0 200 OK\r\nContent-Type: text/css\r\n\r\n"; + rfbWriteExact(&cl, ok, strlen(ok)); +}else + rfbWriteExact(&cl, OK_STR, strlen(OK_STR)); + + + while (1) { + int n = fread(buf, 1, BUF_SIZE-1, fd); + if (n < 0) { + rfbLogPerror("httpProcessInput: read"); + fclose(fd); + httpCloseSock(rfbScreen); + return; + } + + if (n == 0) + break; + + if (performSubstitutions) { + + /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values. + This won't quite work properly if the .vnc file is longer than + BUF_SIZE, but it's reasonable to assume that .vnc files will + always be short. */ + + char *ptr = buf; + char *dollar; + buf[n] = 0; /* make sure it's null-terminated */ + + while ((dollar = strchr(ptr, '$'))!=NULL) { + rfbWriteExact(&cl, ptr, (dollar - ptr)); + + ptr = dollar; + + if (compareAndSkip(&ptr, "$WIDTH")) { + + sprintf(str, "%d", rfbScreen->width); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$HEIGHT")) { + + sprintf(str, "%d", rfbScreen->height); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) { + + sprintf(str, "%d", rfbScreen->width); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) { + + sprintf(str, "%d", rfbScreen->height + 32); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$PORT")) { + + sprintf(str, "%d", rfbScreen->port); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$DESKTOP")) { + + rfbWriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName)); + + } else if (compareAndSkip(&ptr, "$DISPLAY")) { + + sprintf(str, "%s:%d", rfbScreen->thisHost, rfbScreen->port-5900); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$USER")) { +#ifndef WIN32 + if (user) { + rfbWriteExact(&cl, user, + strlen(user)); + } else +#endif + rfbWriteExact(&cl, "?", 1); + } else if (compareAndSkip(&ptr, "$PARAMS")) { + if (params[0] != '\0') + rfbWriteExact(&cl, params, strlen(params)); + } else { + if (!compareAndSkip(&ptr, "$$")) + ptr++; + + if (rfbWriteExact(&cl, "$", 1) < 0) { + fclose(fd); + httpCloseSock(rfbScreen); + return; + } + } + } + if (rfbWriteExact(&cl, ptr, (&buf[n] - ptr)) < 0) + break; + + } else { + + /* For files not ending .vnc, just write out the buffer */ + + if (rfbWriteExact(&cl, buf, n) < 0) + break; + } + } + + fclose(fd); + httpCloseSock(rfbScreen); +} + + +static rfbBool +compareAndSkip(char **ptr, const char *str) +{ + if (strncmp(*ptr, str, strlen(str)) == 0) { + *ptr += strlen(str); + return TRUE; + } + + return FALSE; +} + +/* + * Parse the request tail after the '?' character, and format a sequence + * of tags for inclusion into an HTML page with embedded applet. + */ + +static rfbBool +parseParams(const char *request, char *result, int max_bytes) +{ + char param_request[128]; + char param_formatted[196]; + const char *tail; + char *delim_ptr; + char *value_str; + int cur_bytes, len; + + result[0] = '\0'; + cur_bytes = 0; + + tail = request; + for (;;) { + /* Copy individual "name=value" string into a buffer */ + delim_ptr = strchr((char *)tail, '&'); + if (delim_ptr == NULL) { + if (strlen(tail) >= sizeof(param_request)) { + return FALSE; + } + strcpy(param_request, tail); + } else { + len = delim_ptr - tail; + if (len >= sizeof(param_request)) { + return FALSE; + } + memcpy(param_request, tail, len); + param_request[len] = '\0'; + } + + /* Split the request into parameter name and value */ + value_str = strchr(¶m_request[1], '='); + if (value_str == NULL) { + return FALSE; + } + *value_str++ = '\0'; + if (strlen(value_str) == 0) { + return FALSE; + } + + /* Validate both parameter name and value */ + if (!validateString(param_request) || !validateString(value_str)) { + return FALSE; + } + + /* Prepare HTML-formatted representation of the name=value pair */ + len = sprintf(param_formatted, + "\n", + param_request, value_str); + if (cur_bytes + len + 1 > max_bytes) { + return FALSE; + } + strcat(result, param_formatted); + cur_bytes += len; + + /* Go to the next parameter */ + if (delim_ptr == NULL) { + break; + } + tail = delim_ptr + 1; + } + return TRUE; +} + +/* + * Check if the string consists only of alphanumeric characters, '+' + * signs, underscores, and dots. Replace all '+' signs with spaces. + */ + +static rfbBool +validateString(char *str) +{ + char *ptr; + + for (ptr = str; *ptr != '\0'; ptr++) { + if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { + if (*ptr == '+') { + *ptr = ' '; + } else { + return FALSE; + } + } + } + return TRUE; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/lzoconf.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/lzoconf.h new file mode 100755 index 0000000..96db180 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/lzoconf.h @@ -0,0 +1,451 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H +#define __LZOCONF_H + +#define LZO_VERSION 0x1080 +#define LZO_VERSION_STRING "1.08" +#define LZO_VERSION_DATE "Jul 12 2002" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* workaround a cpp bug under hpux 10.20 */ +#define LZO_0xffffffffL 4294967295ul + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) c ## U +# endif +#endif + + +/*********************************************************************** +// architecture defines +************************************************************************/ + +#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) +# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# define __LZO_WIN +# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) +# define __LZO_WIN +# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) +# define __LZO_WIN +# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) +# define __LZO_DOS +# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) +# define __LZO_OS2 +# elif defined(__palmos__) +# define __LZO_PALMOS +# elif defined(__TOS__) || defined(__atarist__) +# define __LZO_TOS +# endif +#endif + +#if (UINT_MAX < LZO_0xffffffffL) +# if defined(__LZO_WIN) +# define __LZO_WIN16 +# elif defined(__LZO_DOS) +# define __LZO_DOS16 +# elif defined(__LZO_PALMOS) +# define __LZO_PALMOS16 +# elif defined(__LZO_TOS) +# define __LZO_TOS16 +# elif defined(__C166__) +# else + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ +# error "16-bit target not supported - contact me for porting hints" +# endif +#endif + +#if !defined(__LZO_i386) +# if defined(__LZO_DOS) || defined(__LZO_WIN16) +# define __LZO_i386 +# elif defined(__i386__) || defined(__386__) || defined(_M_IX86) +# define __LZO_i386 +# endif +#endif + +#if defined(__LZO_STRICT_16BIT) +# if (UINT_MAX < LZO_0xffffffffL) +# include +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER +# elif defined(__CHECKER__) +# define __LZO_CHECKER +# elif defined(__INSURE__) +# define __LZO_CHECKER +# elif defined(__PURIFY__) +# define __LZO_CHECKER +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* Integral types with 32 bits or more */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* lzo_uint is used like size_t */ +#if !defined(LZO_UINT_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +typedef int lzo_bool; + + +/*********************************************************************** +// memory models +************************************************************************/ + +/* Memory model for the public code segment. */ +#if !defined(__LZO_CMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CMODEL __near +# else +# define __LZO_CMODEL +# endif +#endif + +/* Memory model for the public data segment. */ +#if !defined(__LZO_DMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_DMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_DMODEL __near +# else +# define __LZO_DMODEL +# endif +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_MMODEL __huge +# define LZO_999_UNSUPPORTED +# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) +# define __LZO_MMODEL +# else +# error "__LZO_MMODEL" +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_byte unsigned char __LZO_MMODEL +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t sizeof(lzo_bytep) +#endif + + +/*********************************************************************** +// calling conventions and function types +************************************************************************/ + +/* linkage */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(_MSC_VER) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# else +# define __LZO_CDECL __LZO_CMODEL +# endif +#endif +#if !defined(__LZO_ENTRY) +# define __LZO_ENTRY __LZO_CDECL +#endif + +/* C++ exception specification for extern "C" function types */ +#if !defined(__cplusplus) +# undef LZO_NOTHROW +# define LZO_NOTHROW +#elif !defined(LZO_NOTHROW) +# define LZO_NOTHROW +#endif + + +typedef int +(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + +typedef int +(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + + +/* assembler versions always use __cdecl */ +typedef int +(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + + +/* a progress indicator callback function */ +typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); + + +/*********************************************************************** +// export information +************************************************************************/ + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* exported calling convention for C functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY +#endif + +/* exported __cdecl calling convention for assembler functions */ +#if !defined(LZO_PUBLIC_CDECL) +# define LZO_PUBLIC_CDECL(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN_CDECL) +# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) +#endif + +/* exported global variables (LZO currently uses no static variables and + * is fully thread safe) */ +#if !defined(LZO_PUBLIC_VAR) +# define LZO_PUBLIC_VAR(_type) \ + __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL +#endif +#if !defined(LZO_EXTERN_VAR) +# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) +#endif + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) + + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_compress_t)) +LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + +/* misc. */ +LZO_EXTERN(lzo_bool) lzo_assert(int _expr); +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + +/* deprecated - only for backward compatibility */ +#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/main.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/main.c new file mode 100755 index 0000000..288fda0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/main.c @@ -0,0 +1,1182 @@ +/* + * This file is called main.c, because it contains most of the new functions + * for use with LibVNCServer. + * + * LibVNCServer (C) 2001 Johannes E. Schindelin + * Original OSXvnc (C) 2001 Dan McGuirk . + * Original Xvnc (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * see GPL (latest version) for full details + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include "private.h" + +#include +#include + +#ifndef false +#define false 0 +#define true -1 +#endif + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifndef WIN32 +#include +#include +#include +#endif + +#include +#include + +static int extMutex_initialized = 0; +static int logMutex_initialized = 0; +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +static MUTEX(logMutex); +static MUTEX(extMutex); +#endif + +static int rfbEnableLogging=1; + +#ifdef LIBVNCSERVER_WORDS_BIGENDIAN +char rfbEndianTest = (1==0); +#else +char rfbEndianTest = (1==1); +#endif + +/* + * Protocol extensions + */ + +static rfbProtocolExtension* rfbExtensionHead = NULL; + +/* + * This method registers a list of new extensions. + * It avoids same extension getting registered multiple times. + * The order is not preserved if multiple extensions are + * registered at one-go. + */ +void +rfbRegisterProtocolExtension(rfbProtocolExtension* extension) +{ + rfbProtocolExtension *head = rfbExtensionHead, *next = NULL; + + if(extension == NULL) + return; + + next = extension->next; + + if (! extMutex_initialized) { + INIT_MUTEX(extMutex); + extMutex_initialized = 1; + } + + LOCK(extMutex); + + while(head != NULL) { + if(head == extension) { + UNLOCK(extMutex); + rfbRegisterProtocolExtension(next); + return; + } + + head = head->next; + } + + extension->next = rfbExtensionHead; + rfbExtensionHead = extension; + + UNLOCK(extMutex); + rfbRegisterProtocolExtension(next); +} + +/* + * This method unregisters a list of extensions. + * These extensions won't be available for any new + * client connection. + */ +void +rfbUnregisterProtocolExtension(rfbProtocolExtension* extension) +{ + + rfbProtocolExtension *cur = NULL, *pre = NULL; + + if(extension == NULL) + return; + + if (! extMutex_initialized) { + INIT_MUTEX(extMutex); + extMutex_initialized = 1; + } + + LOCK(extMutex); + + if(rfbExtensionHead == extension) { + rfbExtensionHead = rfbExtensionHead->next; + UNLOCK(extMutex); + rfbUnregisterProtocolExtension(extension->next); + return; + } + + cur = pre = rfbExtensionHead; + + while(cur) { + if(cur == extension) { + pre->next = cur->next; + break; + } + pre = cur; + cur = cur->next; + } + + UNLOCK(extMutex); + + rfbUnregisterProtocolExtension(extension->next); +} + +rfbProtocolExtension* rfbGetExtensionIterator() +{ + LOCK(extMutex); + return rfbExtensionHead; +} + +void rfbReleaseExtensionIterator() +{ + UNLOCK(extMutex); +} + +rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension, + void* data) +{ + rfbExtensionData* extData; + + /* make sure extension is not yet enabled. */ + for(extData = cl->extensions; extData; extData = extData->next) + if(extData->extension == extension) + return FALSE; + + extData = calloc(sizeof(rfbExtensionData),1); + extData->extension = extension; + extData->data = data; + extData->next = cl->extensions; + cl->extensions = extData; + + return TRUE; +} + +rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension) +{ + rfbExtensionData* extData; + rfbExtensionData* prevData = NULL; + + for(extData = cl->extensions; extData; extData = extData->next) { + if(extData->extension == extension) { + if(extData->data) + free(extData->data); + if(prevData == NULL) + cl->extensions = extData->next; + else + prevData->next = extData->next; + return TRUE; + } + prevData = extData; + } + + return FALSE; +} + +void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension) +{ + rfbExtensionData* data = cl->extensions; + + while(data && data->extension != extension) + data = data->next; + + if(data == NULL) { + rfbLog("Extension is not enabled !\n"); + /* rfbCloseClient(cl); */ + return NULL; + } + + return data->data; +} + +/* + * Logging + */ + +void rfbLogEnable(int enabled) { + rfbEnableLogging=enabled; +} + +/* + * rfbLog prints a time-stamped message to the log file (stderr). + */ + +static void +rfbDefaultLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableLogging) + return; + + if (! logMutex_initialized) { + INIT_MUTEX(logMutex); + logMutex_initialized = 1; + } + + LOCK(logMutex); + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock)); + fprintf(stderr, "%s", buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); + UNLOCK(logMutex); +} + +rfbLogProc rfbLog=rfbDefaultLog; +rfbLogProc rfbErr=rfbDefaultLog; + +void rfbLogPerror(const char *str) +{ + rfbErr("%s: %s\n", str, strerror(errno)); +} + +void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + iterator=rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(iterator))) { + LOCK(cl->updateMutex); + if(cl->useCopyRect) { + sraRegionPtr modifiedRegionBackup; + if(!sraRgnEmpty(cl->copyRegion)) { + if(cl->copyDX!=dx || cl->copyDY!=dy) { + /* if a copyRegion was not yet executed, treat it as a + * modifiedRegion. The idea: in this case it could be + * source of the new copyRect or modified anyway. */ + sraRgnOr(cl->modifiedRegion,cl->copyRegion); + sraRgnMakeEmpty(cl->copyRegion); + } else { + /* we have to set the intersection of the source of the copy + * and the old copy to modified. */ + modifiedRegionBackup=sraRgnCreateRgn(copyRegion); + sraRgnOffset(modifiedRegionBackup,-dx,-dy); + sraRgnAnd(modifiedRegionBackup,cl->copyRegion); + sraRgnOr(cl->modifiedRegion,modifiedRegionBackup); + sraRgnDestroy(modifiedRegionBackup); + } + } + + sraRgnOr(cl->copyRegion,copyRegion); + cl->copyDX = dx; + cl->copyDY = dy; + + /* if there were modified regions, which are now copied, + * mark them as modified, because the source of these can be overlapped + * either by new modified or now copied regions. */ + modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion); + sraRgnOffset(modifiedRegionBackup,dx,dy); + sraRgnAnd(modifiedRegionBackup,cl->copyRegion); + sraRgnOr(cl->modifiedRegion,modifiedRegionBackup); + sraRgnDestroy(modifiedRegionBackup); + + if(!cl->enableCursorShapeUpdates) { + /* + * n.b. (dx, dy) is the vector pointing in the direction the + * copyrect displacement will take place. copyRegion is the + * destination rectangle (say), not the source rectangle. + */ + sraRegionPtr cursorRegion; + int x = cl->cursorX - cl->screen->cursor->xhot; + int y = cl->cursorY - cl->screen->cursor->yhot; + int w = cl->screen->cursor->width; + int h = cl->screen->cursor->height; + + cursorRegion = sraRgnCreateRect(x, y, x + w, y + h); + sraRgnAnd(cursorRegion, cl->copyRegion); + if(!sraRgnEmpty(cursorRegion)) { + /* + * current cursor rect overlaps with the copy region *dest*, + * mark it as modified since we won't copy-rect stuff to it. + */ + sraRgnOr(cl->modifiedRegion, cursorRegion); + } + sraRgnDestroy(cursorRegion); + + cursorRegion = sraRgnCreateRect(x, y, x + w, y + h); + /* displace it to check for overlap with copy region source: */ + sraRgnOffset(cursorRegion, dx, dy); + sraRgnAnd(cursorRegion, cl->copyRegion); + if(!sraRgnEmpty(cursorRegion)) { + /* + * current cursor rect overlaps with the copy region *source*, + * mark the *displaced* cursorRegion as modified since we + * won't copyrect stuff to it. + */ + sraRgnOr(cl->modifiedRegion, cursorRegion); + } + sraRgnDestroy(cursorRegion); + } + + } else { + sraRgnOr(cl->modifiedRegion,copyRegion); + } + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + } + + rfbReleaseClientIterator(iterator); +} + +void rfbDoCopyRegion(rfbScreenInfoPtr screen,sraRegionPtr copyRegion,int dx,int dy) +{ + sraRectangleIterator* i; + sraRect rect; + int j,widthInBytes,bpp=screen->serverFormat.bitsPerPixel/8, + rowstride=screen->paddedWidthInBytes; + char *in,*out; + + /* copy it, really */ + i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0); + while(sraRgnIteratorNext(i,&rect)) { + widthInBytes = (rect.x2-rect.x1)*bpp; + out = screen->frameBuffer+rect.x1*bpp+rect.y1*rowstride; + in = screen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride; + if(dy<0) + for(j=rect.y1;j=rect.y1;j--,out-=rowstride,in-=rowstride) + memmove(out,in,widthInBytes); + } + } + sraRgnReleaseIterator(i); + + rfbScheduleCopyRegion(screen,copyRegion,dx,dy); +} + +void rfbDoCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy) +{ + sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2); + rfbDoCopyRegion(screen,region,dx,dy); + sraRgnDestroy(region); +} + +void rfbScheduleCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy) +{ + sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2); + rfbScheduleCopyRegion(screen,region,dx,dy); + sraRgnDestroy(region); +} + +void rfbMarkRegionAsModified(rfbScreenInfoPtr screen,sraRegionPtr modRegion) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + iterator=rfbGetClientIterator(screen); + while((cl=rfbClientIteratorNext(iterator))) { + LOCK(cl->updateMutex); + sraRgnOr(cl->modifiedRegion,modRegion); + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + } + + rfbReleaseClientIterator(iterator); +} + +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2); +void rfbMarkRectAsModified(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2) +{ + sraRegionPtr region; + int i; + + if(x1>x2) { i=x1; x1=x2; x2=i; } + if(x1<0) x1=0; + if(x2>screen->width) x2=screen->width; + if(x1==x2) return; + + if(y1>y2) { i=y1; y1=y2; y2=i; } + if(y1<0) y1=0; + if(y2>screen->height) y2=screen->height; + if(y1==y2) return; + + /* update scaled copies for this rectangle */ + rfbScaledScreenUpdate(screen,x1,y1,x2,y2); + + region = sraRgnCreateRect(x1,y1,x2,y2); + rfbMarkRegionAsModified(screen,region); + sraRgnDestroy(region); +} + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#include + +static void * +clientOutput(void *data) +{ + rfbClientPtr cl = (rfbClientPtr)data; + rfbBool haveUpdate; + sraRegion* updateRegion; + + while (1) { + haveUpdate = false; + while (!haveUpdate) { + if (cl->sock == -1) { + /* Client has disconnected. */ + return NULL; + } + if (cl->state != RFB_NORMAL || cl->onHold) { + /* just sleep until things get normal */ + usleep(cl->screen->deferUpdateTime * 1000); + continue; + } + + LOCK(cl->updateMutex); + + if (sraRgnEmpty(cl->requestedRegion)) { + ; /* always require a FB Update Request (otherwise can crash.) */ + } else { + haveUpdate = FB_UPDATE_PENDING(cl); + if(!haveUpdate) { + updateRegion = sraRgnCreateRgn(cl->modifiedRegion); + haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion); + sraRgnDestroy(updateRegion); + } + } + + if (!haveUpdate) { + WAIT(cl->updateCond, cl->updateMutex); + } + + UNLOCK(cl->updateMutex); + } + + /* OK, now, to save bandwidth, wait a little while for more + updates to come along. */ + usleep(cl->screen->deferUpdateTime * 1000); + + /* Now, get the region we're going to update, and remove + it from cl->modifiedRegion _before_ we send the update. + That way, if anything that overlaps the region we're sending + is updated, we'll be sure to do another update later. */ + LOCK(cl->updateMutex); + updateRegion = sraRgnCreateRgn(cl->modifiedRegion); + UNLOCK(cl->updateMutex); + + /* Now actually send the update. */ + rfbIncrClientRef(cl); + LOCK(cl->sendMutex); + rfbSendFramebufferUpdate(cl, updateRegion); + UNLOCK(cl->sendMutex); + rfbDecrClientRef(cl); + + sraRgnDestroy(updateRegion); + } + + /* Not reached. */ + return NULL; +} + +static void * +clientInput(void *data) +{ + rfbClientPtr cl = (rfbClientPtr)data; + pthread_t output_thread; + pthread_create(&output_thread, NULL, clientOutput, (void *)cl); + + while (1) { + fd_set rfds, wfds, efds; + struct timeval tv; + int n; + + FD_ZERO(&rfds); + FD_SET(cl->sock, &rfds); + FD_ZERO(&efds); + FD_SET(cl->sock, &efds); + + /* Are we transferring a file in the background? */ + FD_ZERO(&wfds); + if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1)) + FD_SET(cl->sock, &wfds); + + tv.tv_sec = 60; /* 1 minute */ + tv.tv_usec = 0; + n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv); + if (n < 0) { + rfbLogPerror("ReadExact: select"); + break; + } + if (n == 0) /* timeout */ + { + rfbSendFileTransferChunk(cl); + continue; + } + + /* We have some space on the transmit queue, send some data */ + if (FD_ISSET(cl->sock, &wfds)) + rfbSendFileTransferChunk(cl); + + if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds)) + rfbProcessClientMessage(cl); + + if (cl->sock == -1) { + /* Client has disconnected. */ + break; + } + } + + /* Get rid of the output thread. */ + LOCK(cl->updateMutex); + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + IF_PTHREADS(pthread_join(output_thread, NULL)); + + rfbClientConnectionGone(cl); + + return NULL; +} + +static void* +listenerRun(void *data) +{ + rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data; + int client_fd; + struct sockaddr_in peer; + rfbClientPtr cl; + socklen_t len; + + len = sizeof(peer); + + /* TODO: this thread wont die by restarting the server */ + /* TODO: HTTP is not handled */ + while ((client_fd = accept(screen->listenSock, + (struct sockaddr*)&peer, &len)) >= 0) { + cl = rfbNewClient(screen,client_fd); + len = sizeof(peer); + + if (cl && !cl->onHold ) + rfbStartOnHoldClient(cl); + } + return(NULL); +} + + +void +rfbStartOnHoldClient(rfbClientPtr cl) +{ + pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl); +} + +#else + +void +rfbStartOnHoldClient(rfbClientPtr cl) +{ + cl->onHold = FALSE; +} + +#endif + +void +rfbRefuseOnHoldClient(rfbClientPtr cl) +{ + rfbCloseClient(cl); + rfbClientConnectionGone(cl); +} + +static void +rfbDefaultKbdAddEvent(rfbBool down, rfbKeySym keySym, rfbClientPtr cl) +{ +} + +void +rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr other_client; + rfbScreenInfoPtr s = cl->screen; + + if (x != s->cursorX || y != s->cursorY) { + LOCK(s->cursorMutex); + s->cursorX = x; + s->cursorY = y; + UNLOCK(s->cursorMutex); + + /* The cursor was moved by this client, so don't send CursorPos. */ + if (cl->enableCursorPosUpdates) + cl->cursorWasMoved = FALSE; + + /* But inform all remaining clients about this cursor movement. */ + iterator = rfbGetClientIterator(s); + while ((other_client = rfbClientIteratorNext(iterator)) != NULL) { + if (other_client != cl && other_client->enableCursorPosUpdates) { + other_client->cursorWasMoved = TRUE; + } + } + rfbReleaseClientIterator(iterator); + } +} + +static void rfbDefaultSetXCutText(char* text, int len, rfbClientPtr cl) +{ +} + +/* TODO: add a nice VNC or RFB cursor */ + +#if defined(WIN32) || defined(sparc) || !defined(NO_STRICT_ANSI) +static rfbCursor myCursor = +{ + FALSE, FALSE, FALSE, FALSE, + (unsigned char*)"\000\102\044\030\044\102\000", + (unsigned char*)"\347\347\176\074\176\347\347", + 8, 7, 3, 3, + 0, 0, 0, + 0xffff, 0xffff, 0xffff, + NULL +}; +#else +static rfbCursor myCursor = +{ + cleanup: FALSE, + cleanupSource: FALSE, + cleanupMask: FALSE, + cleanupRichSource: FALSE, + source: "\000\102\044\030\044\102\000", + mask: "\347\347\176\074\176\347\347", + width: 8, height: 7, xhot: 3, yhot: 3, + foreRed: 0, foreGreen: 0, foreBlue: 0, + backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff, + richSource: NULL +}; +#endif + +static rfbCursorPtr rfbDefaultGetCursorPtr(rfbClientPtr cl) +{ + return(cl->screen->cursor); +} + +/* response is cl->authChallenge vncEncrypted with passwd */ +static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl,const char* response,int len) +{ + int i; + char *passwd=rfbDecryptPasswdFromFile(cl->screen->authPasswdData); + + if(!passwd) { + rfbErr("Couldn't read password file: %s\n",cl->screen->authPasswdData); + return(FALSE); + } + + rfbEncryptBytes(cl->authChallenge, passwd); + + /* Lose the password from memory */ + for (i = strlen(passwd); i >= 0; i--) { + passwd[i] = '\0'; + } + + free(passwd); + + if (memcmp(cl->authChallenge, response, len) != 0) { + rfbErr("authProcessClientMessage: authentication failed from %s\n", + cl->host); + return(FALSE); + } + + return(TRUE); +} + +/* for this method, authPasswdData is really a pointer to an array + of char*'s, where the last pointer is 0. */ +rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len) +{ + char **passwds; + int i=0; + + for(passwds=(char**)cl->screen->authPasswdData;*passwds;passwds++,i++) { + uint8_t auth_tmp[CHALLENGESIZE]; + memcpy((char *)auth_tmp, (char *)cl->authChallenge, CHALLENGESIZE); + rfbEncryptBytes(auth_tmp, *passwds); + + if (memcmp(auth_tmp, response, len) == 0) { + if(i>=cl->screen->authPasswdFirstViewOnly) + cl->viewOnly=TRUE; + return(TRUE); + } + } + + rfbErr("authProcessClientMessage: authentication failed from %s\n", + cl->host); + return(FALSE); +} + +void rfbDoNothingWithClient(rfbClientPtr cl) +{ +} + +static enum rfbNewClientAction rfbDefaultNewClientHook(rfbClientPtr cl) +{ + return RFB_CLIENT_ACCEPT; +} + +/* + * Update server's pixel format in screenInfo structure. This + * function is called from rfbGetScreen() and rfbNewFramebuffer(). + */ + +static void rfbInitServerFormat(rfbScreenInfoPtr screen, int bitsPerSample) +{ + rfbPixelFormat* format=&screen->serverFormat; + + format->bitsPerPixel = screen->bitsPerPixel; + format->depth = screen->depth; + format->bigEndian = rfbEndianTest?FALSE:TRUE; + format->trueColour = TRUE; + screen->colourMap.count = 0; + screen->colourMap.is16 = 0; + screen->colourMap.data.bytes = NULL; + + if (format->bitsPerPixel == 8) { + format->redMax = 7; + format->greenMax = 7; + format->blueMax = 3; + format->redShift = 0; + format->greenShift = 3; + format->blueShift = 6; + } else { + format->redMax = (1 << bitsPerSample) - 1; + format->greenMax = (1 << bitsPerSample) - 1; + format->blueMax = (1 << bitsPerSample) - 1; + if(rfbEndianTest) { + format->redShift = 0; + format->greenShift = bitsPerSample; + format->blueShift = bitsPerSample * 2; + } else { + if(format->bitsPerPixel==8*3) { + format->redShift = bitsPerSample*2; + format->greenShift = bitsPerSample*1; + format->blueShift = 0; + } else { + format->redShift = bitsPerSample*3; + format->greenShift = bitsPerSample*2; + format->blueShift = bitsPerSample; + } + } + } +} + +rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, + int width,int height,int bitsPerSample,int samplesPerPixel, + int bytesPerPixel) +{ + rfbScreenInfoPtr screen=calloc(sizeof(rfbScreenInfo),1); + + if (! logMutex_initialized) { + INIT_MUTEX(logMutex); + logMutex_initialized = 1; + } + + + if(width&3) + rfbErr("WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width); + + screen->autoPort=FALSE; + screen->clientHead=NULL; + screen->pointerClient=NULL; + screen->port=5900; + screen->socketState=RFB_SOCKET_INIT; + + screen->inetdInitDone = FALSE; + screen->inetdSock=-1; + + screen->udpSock=-1; + screen->udpSockConnected=FALSE; + screen->udpPort=0; + screen->udpClient=NULL; + + screen->maxFd=0; + screen->listenSock=-1; + + screen->httpInitDone=FALSE; + screen->httpEnableProxyConnect=FALSE; + screen->httpPort=0; + screen->httpDir=NULL; + screen->httpListenSock=-1; + screen->httpSock=-1; + + screen->desktopName = "LibVNCServer"; + screen->alwaysShared = FALSE; + screen->neverShared = FALSE; + screen->dontDisconnect = FALSE; + screen->authPasswdData = NULL; + screen->authPasswdFirstViewOnly = 1; + + screen->width = width; + screen->height = height; + screen->bitsPerPixel = screen->depth = 8*bytesPerPixel; + + screen->passwordCheck = rfbDefaultPasswordCheck; + + screen->ignoreSIGPIPE = TRUE; + + /* disable progressive updating per default */ + screen->progressiveSliceHeight = 0; + + screen->listenInterface = htonl(INADDR_ANY); + + screen->deferUpdateTime=5; + screen->maxRectsPerUpdate=50; + + screen->handleEventsEagerly = FALSE; + + screen->protocolMajorVersion = rfbProtocolMajorVersion; + screen->protocolMinorVersion = rfbProtocolMinorVersion; + + screen->permitFileTransfer = FALSE; + + if(!rfbProcessArguments(screen,argc,argv)) { + free(screen); + return NULL; + } + +#ifdef WIN32 + { + DWORD dummy=255; + GetComputerName(screen->thisHost,&dummy); + } +#else + gethostname(screen->thisHost, 255); +#endif + + screen->paddedWidthInBytes = width*bytesPerPixel; + + /* format */ + + rfbInitServerFormat(screen, bitsPerSample); + + /* cursor */ + + screen->cursorX=screen->cursorY=screen->underCursorBufferLen=0; + screen->underCursorBuffer=NULL; + screen->dontConvertRichCursorToXCursor = FALSE; + screen->cursor = &myCursor; + INIT_MUTEX(screen->cursorMutex); + + IF_PTHREADS(screen->backgroundLoop = FALSE); + + /* proc's and hook's */ + + screen->kbdAddEvent = rfbDefaultKbdAddEvent; + screen->kbdReleaseAllKeys = rfbDoNothingWithClient; + screen->ptrAddEvent = rfbDefaultPtrAddEvent; + screen->setXCutText = rfbDefaultSetXCutText; + screen->getCursorPtr = rfbDefaultGetCursorPtr; + screen->setTranslateFunction = rfbSetTranslateFunction; + screen->newClientHook = rfbDefaultNewClientHook; + screen->displayHook = NULL; + screen->displayFinishedHook = NULL; + screen->getKeyboardLedStateHook = NULL; + + /* initialize client list and iterator mutex */ + rfbClientListInit(screen); + + return(screen); +} + +/* + * Switch to another framebuffer (maybe of different size and color + * format). Clients supporting NewFBSize pseudo-encoding will change + * their local framebuffer dimensions if necessary. + * NOTE: Rich cursor data should be converted to new pixel format by + * the caller. + */ + +void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer, + int width, int height, + int bitsPerSample, int samplesPerPixel, + int bytesPerPixel) +{ + rfbPixelFormat old_format; + rfbBool format_changed = FALSE; + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + /* Update information in the screenInfo structure */ + + old_format = screen->serverFormat; + + if (width & 3) + rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width); + + screen->width = width; + screen->height = height; + screen->bitsPerPixel = screen->depth = 8*bytesPerPixel; + screen->paddedWidthInBytes = width*bytesPerPixel; + + rfbInitServerFormat(screen, bitsPerSample); + + if (memcmp(&screen->serverFormat, &old_format, + sizeof(rfbPixelFormat)) != 0) { + format_changed = TRUE; + } + + screen->frameBuffer = framebuffer; + + /* Adjust pointer position if necessary */ + + if (screen->cursorX >= width) + screen->cursorX = width - 1; + if (screen->cursorY >= height) + screen->cursorY = height - 1; + + /* For each client: */ + iterator = rfbGetClientIterator(screen); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) { + + /* Re-install color translation tables if necessary */ + + if (format_changed) + screen->setTranslateFunction(cl); + + /* Mark the screen contents as changed, and schedule sending + NewFBSize message if supported by this client. */ + + LOCK(cl->updateMutex); + sraRgnDestroy(cl->modifiedRegion); + cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height); + sraRgnMakeEmpty(cl->copyRegion); + cl->copyDX = 0; + cl->copyDY = 0; + + if (cl->useNewFBSize) + cl->newFBSizePending = TRUE; + + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + } + rfbReleaseClientIterator(iterator); +} + +/* hang up on all clients and free all reserved memory */ + +void rfbScreenCleanup(rfbScreenInfoPtr screen) +{ + rfbClientIteratorPtr i=rfbGetClientIterator(screen); + rfbClientPtr cl,cl1=rfbClientIteratorNext(i); + while(cl1) { + cl=rfbClientIteratorNext(i); + rfbClientConnectionGone(cl1); + cl1=cl; + } + rfbReleaseClientIterator(i); + +#define FREE_IF(x) if(screen->x) free(screen->x) + FREE_IF(colourMap.data.bytes); + FREE_IF(underCursorBuffer); + TINI_MUTEX(screen->cursorMutex); + if(screen->cursor && screen->cursor->cleanup) + rfbFreeCursor(screen->cursor); + + rfbRRECleanup(screen); + rfbCoRRECleanup(screen); + rfbUltraCleanup(screen); +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbZlibCleanup(screen); +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + rfbTightCleanup(screen); +#endif + + /* free all 'scaled' versions of this screen */ + while (screen->scaledScreenNext!=NULL) + { + rfbScreenInfoPtr ptr; + ptr = screen->scaledScreenNext; + screen->scaledScreenNext = ptr->scaledScreenNext; + free(ptr->frameBuffer); + free(ptr); + } + +#endif + free(screen); +} + +void rfbInitServer(rfbScreenInfoPtr screen) +{ +#ifdef WIN32 + WSADATA trash; + WSAStartup(MAKEWORD(2,2),&trash); +#endif + rfbInitSockets(screen); + rfbHttpInitSockets(screen); +#ifndef __MINGW32__ + if(screen->ignoreSIGPIPE) + signal(SIGPIPE,SIG_IGN); +#endif +} + +void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) { + if(disconnectClients) { + rfbClientPtr cl; + rfbClientIteratorPtr iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) + if (cl->sock > -1) + /* we don't care about maxfd here, because the server goes away */ + rfbCloseClient(cl); + rfbReleaseClientIterator(iter); + } + + rfbShutdownSockets(screen); + rfbHttpShutdownSockets(screen); +} + +#include + +// #ifndef LIBVNCSERVER_HAVE_GETTIMEOFDAY +// #include +// #include +// #include +// +// void gettimeofday(struct timeval* tv,char* dummy) +// { +// SYSTEMTIME t; +// GetSystemTime(&t); +// tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond; +// tv->tv_usec=t.wMilliseconds*1000; +// } +// #endif + +rfbBool +rfbProcessEvents(rfbScreenInfoPtr screen,long usec) +{ + rfbClientIteratorPtr i; + rfbClientPtr cl,clPrev; + struct timeval tv; + rfbBool result=FALSE; + extern rfbClientIteratorPtr + rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen); + + if(usec<0) + usec=screen->deferUpdateTime*1000; + + rfbCheckFds(screen,usec); + rfbHttpCheckFds(screen); +#ifdef CORBA + corbaCheckFds(screen); +#endif + + i = rfbGetClientIteratorWithClosed(screen); + cl=rfbClientIteratorHead(i); + while(cl) { + if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) && + !sraRgnEmpty(cl->requestedRegion)) { + result=TRUE; + if(screen->deferUpdateTime == 0) { + rfbSendFramebufferUpdate(cl,cl->modifiedRegion); + } else if(cl->startDeferring.tv_usec == 0) { + gettimeofday(&cl->startDeferring,NULL); + if(cl->startDeferring.tv_usec == 0) + cl->startDeferring.tv_usec++; + } else { + gettimeofday(&tv,NULL); + if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */ + || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000 + +(tv.tv_usec-cl->startDeferring.tv_usec)/1000) + > screen->deferUpdateTime) { + cl->startDeferring.tv_usec = 0; + rfbSendFramebufferUpdate(cl,cl->modifiedRegion); + } + } + } + + if (!cl->viewOnly && cl->lastPtrX >= 0) { + if(cl->startPtrDeferring.tv_usec == 0) { + gettimeofday(&cl->startPtrDeferring,NULL); + if(cl->startPtrDeferring.tv_usec == 0) + cl->startPtrDeferring.tv_usec++; + } else { + struct timeval tv; + gettimeofday(&tv,NULL); + if(tv.tv_sec < cl->startPtrDeferring.tv_sec /* at midnight */ + || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000 + +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000) + > cl->screen->deferPtrUpdateTime) { + cl->startPtrDeferring.tv_usec = 0; + cl->screen->ptrAddEvent(cl->lastPtrButtons, + cl->lastPtrX, + cl->lastPtrY, cl); + cl->lastPtrX = -1; + } + } + } + clPrev=cl; + cl=rfbClientIteratorNext(i); + if(clPrev->sock==-1) { + rfbClientConnectionGone(clPrev); + result=TRUE; + } + } + rfbReleaseClientIterator(i); + + return result; +} + +rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo) { + return screenInfo->socketState!=RFB_SOCKET_SHUTDOWN || screenInfo->clientHead!=NULL; +} + +static void *httpListen(void *data) +{ + rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data; + while (1) + { + rfbHttpCheckFds(screen);//backgrounded event loop doesnt listen for connections from browser + usleep(100000); + } + return NULL; +} + +void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground) +{ + if(runInBackground) { +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + pthread_t listener_thread; + + screen->backgroundLoop = TRUE; + + pthread_create(&listener_thread, NULL, listenerRun, screen); + pthread_create(&listener_thread, NULL, httpListen, screen); + return; +#else + rfbErr("Can't run in background, because I don't have PThreads!\n"); + return; +#endif + } + + if(usec<0) + usec=screen->deferUpdateTime*1000; + + while(rfbIsActive(screen)) + rfbProcessEvents(screen,usec); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.c new file mode 100755 index 0000000..a12c146 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.c @@ -0,0 +1,448 @@ +/* Functions to compute MD5 message digest of files or memory blocks. + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995,1996,1997,1999,2000,2001,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Written by Ulrich Drepper , 1995. */ + +#include + +# include +# include + +#include "md5.h" + +#ifdef _LIBC +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +/* We need to keep the namespace clean so define the MD5 function + protected using leading __ . */ +# define md5_init_ctx __md5_init_ctx +# define md5_process_block __md5_process_block +# define md5_process_bytes __md5_process_bytes +# define md5_finish_ctx __md5_finish_ctx +# define md5_read_ctx __md5_read_ctx +# define md5_stream __md5_stream +# define md5_buffer __md5_buffer +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (ctx) + struct md5_ctx *ctx; +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (ctx, resbuf) + const struct md5_ctx *ctx; + void *resbuf; +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (ctx, resbuf) + struct md5_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (stream, resblock) + FILE *stream; + void *resblock; +{ + /* Important: BLOCKSIZE must be a multiple of 64. */ +#define BLOCKSIZE 4096 + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + do + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + } + while (sum < BLOCKSIZE && n != 0); + if (n == 0 && ferror (stream)) + return 1; + + /* If end of file is reached, end the loop. */ + if (n == 0) + break; + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); + } + + /* Add the last bytes if necessary. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (buffer, len, resblock) + const char *buffer; + size_t len; + void *resblock; +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) +# else +# define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0) +# endif + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.h new file mode 100755 index 0000000..2709660 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.h @@ -0,0 +1,148 @@ +/* Declaration of functions and data types used for MD5 sum computing + library functions. + Copyright (C) 1995-1997,1999,2000,2001,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include + +#if defined HAVE_LIMITS_H || _LIBC +# include +#endif + +#define MD5_DIGEST_SIZE 16 +#define MD5_BLOCK_SIZE 64 + +/* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but + doing that would require that the configure script compile and *run* + the resulting executable. Locally running cross-compiled executables + is usually not possible. */ + +#ifdef _LIBC +# include +typedef uint32_t md5_uint32; +typedef uintptr_t md5_uintptr; +#else +# if defined __STDC__ && __STDC__ +# define UINT_MAX_32_BITS 4294967295U +# else +# define UINT_MAX_32_BITS 0xFFFFFFFF +# endif + +/* If UINT_MAX isn't defined, assume it's a 32-bit type. + This should be valid for all systems GNU cares about because + that doesn't include 16-bit systems, and only modern systems + (that certainly have ) have 64+-bit integral types. */ + +# ifndef UINT_MAX +# define UINT_MAX UINT_MAX_32_BITS +# endif + +# if UINT_MAX == UINT_MAX_32_BITS + typedef unsigned int md5_uint32; +# else +# if USHRT_MAX == UINT_MAX_32_BITS + typedef unsigned short md5_uint32; +# else +# if ULONG_MAX == UINT_MAX_32_BITS + typedef unsigned long md5_uint32; +# else + /* The following line is intended to evoke an error. + Using #error is not portable enough. */ + "Cannot determine unsigned 32-bit data type." +# endif +# endif +# endif +/* We have to make a guess about the integer type equivalent in size + to pointers which should always be correct. */ +typedef unsigned long int md5_uintptr; +#endif + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); +}; + +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void __md5_init_ctx (struct md5_ctx *ctx) ;//__THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void __md5_process_block (const void *buffer, size_t len, + struct md5_ctx *ctx) ;//__THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void __md5_process_bytes (const void *buffer, size_t len, + struct md5_ctx *ctx) ;//__THROW; + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) ;//__THROW; + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) ;//__THROW; + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int __md5_stream (FILE *stream, void *resblock) ;//__THROW; + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *__md5_buffer (const char *buffer, size_t len, + void *resblock) ;//__THROW; + +#endif /* md5.h */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.c new file mode 100755 index 0000000..85771eb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.c @@ -0,0 +1,2935 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#if !defined(LZO_NO_SYS_TYPES_H) +# include +#endif +#include + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +# ifndef __LZOCONF_H +# include +# endif +#endif + +#if defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(LZO_HAVE_CONFIG_H) +# include +# include +# if !defined(NO_STDLIB_H) +# include +# endif +# define HAVE_MEMCMP +# define HAVE_MEMCPY +# define HAVE_MEMMOVE +# define HAVE_MEMSET +#else +# include +# if defined(HAVE_STDDEF_H) +# include +# endif +# if defined(STDC_HEADERS) +# include +# include +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define HAVE_MALLOC_H +# define HAVE_HALLOC +#endif + +#undef NDEBUG +#if !defined(LZO_DEBUG) +# define NDEBUG +#endif +#if defined(LZO_DEBUG) || !defined(NDEBUG) +# if !defined(NO_STDIO_H) +# include +# endif +#endif +#include + +#if !defined(LZO_COMPILE_TIME_ASSERT) +# define LZO_COMPILE_TIME_ASSERT(expr) \ + { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; } +#endif + +#if !defined(LZO_UNUSED) +# if 1 +# define LZO_UNUSED(var) ((void)&var) +# elif 0 +# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; } +# else +# define LZO_UNUSED(parm) (parm = parm) +# endif +#endif + +#if !defined(__inline__) && !defined(__GNUC__) +# if defined(__cplusplus) +# define __inline__ inline +# else +# define __inline__ +# endif +#endif + +#if defined(NO_MEMCMP) +# undef HAVE_MEMCMP +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp lzo_memcmp +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy lzo_memcpy +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove lzo_memmove +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset lzo_memset +#endif + +#if 0 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) +#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) + +#if !defined(SIZEOF_UNSIGNED) +# if (UINT_MAX == 0xffff) +# define SIZEOF_UNSIGNED 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 4 +# elif (UINT_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 8 +# else +# error "SIZEOF_UNSIGNED" +# endif +#endif + +#if !defined(SIZEOF_UNSIGNED_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 4 +# elif (ULONG_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 8 +# else +# error "SIZEOF_UNSIGNED_LONG" +# endif +#endif + +#if !defined(SIZEOF_SIZE_T) +# define SIZEOF_SIZE_T SIZEOF_UNSIGNED +#endif +#if !defined(SIZE_T_MAX) +# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) +#endif + +#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) +# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) +# define LZO_UNALIGNED_OK_2 +# endif +# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) +# define LZO_UNALIGNED_OK_4 +# endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) +# if !defined(LZO_UNALIGNED_OK) +# define LZO_UNALIGNED_OK +# endif +#endif + +#if defined(__LZO_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +#endif + +#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) +# error "LZO_UNALIGNED_OK_2 must not be defined on this system" +#endif +#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_UNALIGNED_OK_4 must not be defined on this system" +#endif + +#if defined(__LZO_NO_ALIGNED) +# undef LZO_ALIGNED_OK_4 +#endif + +#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_ALIGNED_OK_4 must not be defined on this system" +#endif + +#define LZO_LITTLE_ENDIAN 1234 +#define LZO_BIG_ENDIAN 4321 +#define LZO_PDP_ENDIAN 3412 + +#if !defined(LZO_BYTE_ORDER) +# if defined(MFX_BYTE_ORDER) +# define LZO_BYTE_ORDER MFX_BYTE_ORDER +# elif defined(__LZO_i386) +# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN +# elif defined(BYTE_ORDER) +# define LZO_BYTE_ORDER BYTE_ORDER +# elif defined(__BYTE_ORDER) +# define LZO_BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(LZO_BYTE_ORDER) +# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ + (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) +# error "invalid LZO_BYTE_ORDER" +# endif +#endif + +#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) +# error "LZO_BYTE_ORDER is not defined" +#endif + +#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY + +#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER) +# if defined(__GNUC__) && defined(__i386__) +# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) +# define LZO_OPTIMIZE_GNUC_i386 +# endif +# endif +#endif + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const lzo_byte __lzo_copyright[]; +LZO_EXTERN(const lzo_byte *) lzo_copyright(void); +__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; + +#define _LZO_STRINGIZE(x) #x +#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) + +#define _LZO_CONCAT2(a,b) a ## b +#define _LZO_CONCAT3(a,b,c) a ## b ## c +#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d +#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e + +#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) +#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) +#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) +#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) + +#if 0 + +#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#endif + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# include +# if 1 && defined(__WATCOMC__) +# include + __LZO_EXTERN_C unsigned char _HShift; +# define __LZO_HShift _HShift +# elif 1 && defined(_MSC_VER) + __LZO_EXTERN_C unsigned short __near _AHSHIFT; +# define __LZO_HShift ((unsigned) &_AHSHIFT) +# elif defined(__LZO_WIN16) +# define __LZO_HShift 3 +# else +# define __LZO_HShift 12 +# endif +# if !defined(_FP_SEG) && defined(FP_SEG) +# define _FP_SEG FP_SEG +# endif +# if !defined(_FP_OFF) && defined(FP_OFF) +# define _FP_OFF FP_OFF +# endif +#endif + +#if !defined(lzo_ptrdiff_t) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef ptrdiff_t lzo_ptrdiff_t; +# else + typedef long lzo_ptrdiff_t; +# endif +#endif + +#if !defined(__LZO_HAVE_PTR_T) +# if defined(lzo_ptr_t) +# define __LZO_HAVE_PTR_T +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) +# error "no suitable type for lzo_ptr_t" +# else + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_ptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#if !defined(lzo_moff_t) +#define lzo_moff_t lzo_uint +#endif + +#endif + +LZO_PUBLIC(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_ptr_t p; + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) + p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); +#else + p = PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ + lzo_ptr_t p, s, n; + + assert(size > 0); + + p = __lzo_ptr_linear(ptr); + s = (lzo_ptr_t) (size - 1); +#if 0 + assert((size & (size - 1)) == 0); + n = ((p + s) & ~s) - p; +#else + n = (((p + s) / size) * size) - p; +#endif + + assert((long)n >= 0); + assert(n <= s); + + return (unsigned)n; +} + +#ifndef __LZO_UTIL_H +#define __LZO_UTIL_H + +#ifndef __LZO_CONF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 && defined(HAVE_MEMCPY) +#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) + +#define MEMCPY8_DS(dest,src,len) \ + memcpy(dest,src,len); \ + dest += len; \ + src += len + +#endif +#endif + +#if 0 && !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + len -= 8; \ + } while (len > 0); } + +#endif + +#if !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { register lzo_uint __l = (len) / 8; \ + do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + } while (--__l > 0); } + +#endif + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#define MEMMOVE_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) + +#define BZERO8_PTR(s,l,n) \ +__asm__ __volatile__( \ + "movl %0,%%eax \n" \ + "movl %1,%%edi \n" \ + "movl %2,%%ecx \n" \ + "cld \n" \ + "rep \n" \ + "stosl %%eax,(%%edi) \n" \ + : \ + :"g" (0),"g" (s),"g" (n) \ + :"eax","edi","ecx", "memory", "cc" \ +) + +#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + +#if 1 +#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) +#else +#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) +#endif + +#else + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#endif + +#if 0 +#if defined(__GNUC__) && defined(__i386__) + +unsigned char lzo_rotr8(unsigned char value, int shift); +extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) +{ + unsigned char result; + + __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +unsigned short lzo_rotr16(unsigned short value, int shift); +extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) +{ + unsigned short result; + + __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +LZO_PUBLIC(lzo_bool) +lzo_assert(int expr) +{ + return (expr) ? 1 : 0; +} + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +const lzo_byte __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\n\n\n" + "LZO real-time data compression library.\n" + "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com/opensource/lzo/\n" + "\n" + "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" + "LZO build date: " __DATE__ " " __TIME__ "\n\n" + "LZO special compilation options:\n" +#ifdef __cplusplus + " __cplusplus\n" +#endif +#if defined(__PIC__) + " __PIC__\n" +#elif defined(__pic__) + " __pic__\n" +#endif +#if (UINT_MAX < LZO_0xffffffffL) + " 16BIT\n" +#endif +#if defined(__LZO_STRICT_16BIT) + " __LZO_STRICT_16BIT\n" +#endif +#if (UINT_MAX > LZO_0xffffffffL) + " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" +#endif +#if (ULONG_MAX > LZO_0xffffffffL) + " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" +#endif +#if defined(LZO_BYTE_ORDER) + " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" +#endif +#if defined(LZO_UNALIGNED_OK_2) + " LZO_UNALIGNED_OK_2\n" +#endif +#if defined(LZO_UNALIGNED_OK_4) + " LZO_UNALIGNED_OK_4\n" +#endif +#if defined(LZO_ALIGNED_OK_4) + " LZO_ALIGNED_OK_4\n" +#endif +#if defined(LZO_DICT_USE_PTR) + " LZO_DICT_USE_PTR\n" +#endif +#if defined(__LZO_QUERY_COMPRESS) + " __LZO_QUERY_COMPRESS\n" +#endif +#if defined(__LZO_QUERY_DECOMPRESS) + " __LZO_QUERY_DECOMPRESS\n" +#endif +#if defined(__LZO_IN_MINILZO) + " __LZO_IN_MINILZO\n" +#endif + "\n\n" + "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ +#if defined(__GNUC__) && defined(__VERSION__) + " by gcc " __VERSION__ +#elif defined(__BORLANDC__) + " by Borland C " _LZO_MEXPAND(__BORLANDC__) +#elif defined(_MSC_VER) + " by Microsoft C " _LZO_MEXPAND(_MSC_VER) +#elif defined(__PUREC__) + " by Pure C " _LZO_MEXPAND(__PUREC__) +#elif defined(__SC__) + " by Symantec C " _LZO_MEXPAND(__SC__) +#elif defined(__TURBOC__) + " by Turbo C " _LZO_MEXPAND(__TURBOC__) +#elif defined(__WATCOMC__) + " by Watcom C " _LZO_MEXPAND(__WATCOMC__) +#endif + " $\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; +#endif + +LZO_PUBLIC(const lzo_byte *) +lzo_copyright(void) +{ + return __lzo_copyright; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (int) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +LZO_PUBLIC(int) +lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP) + return memcmp(s1,s2,len); +#else + const lzo_byte *p1 = (const lzo_byte *) s1; + const lzo_byte *p2 = (const lzo_byte *) s2; + int d; + + if (len > 0) do + { + d = *p1 - *p2; + if (d != 0) + return d; + p1++; + p2++; + } + while (--len > 0); + return 0; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY) + return memcpy(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + do + *p1++ = *p2++; + while (--len > 0); + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE) + return memmove(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + + if (p1 < p2) + { + do + *p1++ = *p2++; + while (--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while (--len > 0); + } + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memset(lzo_voidp s, int c, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + return memset(s,c,len); +#else + lzo_byte *p = (lzo_byte *) s; + + if (len > 0) do + *p++ = LZO_BYTE(c); + while (--len > 0); + return s; +#endif +} + +#if 0 +# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) +# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) +#else +# define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) +# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) +#endif + +#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +static lzo_bool schedule_insns_bug(void); +static lzo_bool strength_reduce_bug(int *); + +#if 0 || defined(LZO_DEBUG) +#include +static lzo_bool __lzo_assert_fail(const char *s, unsigned line) +{ +#if defined(__palmos__) + printf("LZO assertion failed in line %u: '%s'\n",line,s); +#else + fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); +#endif + return 0; +} +# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) +#else +# define __lzo_assert(x) ((x) ? 1 : 0) +#endif + +#undef COMPILE_TIME_ASSERT +#if 0 +# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) +#else +# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif + +static lzo_bool basic_integral_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(CHAR_BIT == 8); + COMPILE_TIME_ASSERT(sizeof(char) == 1); + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + COMPILE_TIME_ASSERT(sizeof(long) >= 4); + COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); + COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); +#if defined(__LZO_STRICT_16BIT) + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); +#else + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); +#endif + +#if (USHRT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(short) == 2); +#elif (USHRT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) == 4); +#elif (USHRT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) > 4); +#endif +#if (UINT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(int) == 2); +#elif (UINT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) == 4); +#elif (UINT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) > 4); +#endif +#if (ULONG_MAX == 65535ul) + COMPILE_TIME_ASSERT(sizeof(long) == 2); +#elif (ULONG_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) == 4); +#elif (ULONG_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) > 4); +#endif + +#if defined(SIZEOF_UNSIGNED) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); +#endif +#if defined(SIZEOF_UNSIGNED_LONG) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); +#endif +#if defined(SIZEOF_UNSIGNED_SHORT) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); +#endif +#if !defined(__LZO_IN_MINILZO) +#if defined(SIZEOF_SIZE_T) + COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); +#endif +#endif + + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); + COMPILE_TIME_ASSERT(IS_SIGNED(short)); + COMPILE_TIME_ASSERT(IS_SIGNED(int)); + COMPILE_TIME_ASSERT(IS_SIGNED(long)); + + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); + + COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); + COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); + COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); + COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); + COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); + COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); + COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); + COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); +#if !defined(__LZO_IN_MINILZO) + COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); +#endif + + r &= __lzo_assert(LZO_BYTE(257) == 1); + + return r; +} + +static lzo_bool basic_ptr_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); + COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); + + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); + + COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); + +#if defined(SIZEOF_CHAR_P) + COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); +#endif +#if defined(SIZEOF_PTRDIFF_T) + COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); +#endif + + COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); + + return r; +} + +static lzo_bool ptr_check(void) +{ + lzo_bool r = 1; + int i; + char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; + lzo_bytep wrkmem; + lzo_bytepp dict; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + long d; + lzo_full_align_t a; + lzo_full_align_t u; + + for (i = 0; i < (int) sizeof(x); i++) + x[i] = LZO_BYTE(i); + + wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t)); + +#if 0 + dict = (lzo_bytepp) wrkmem; +#else + + u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp; +#endif + + d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); + r &= __lzo_assert(d >= 0); + r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t)); + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_lzo_voidp == NULL); + + memset(&a,0xff,sizeof(a)); + r &= __lzo_assert(a.a_ushort == USHRT_MAX); + r &= __lzo_assert(a.a_uint == UINT_MAX); + r &= __lzo_assert(a.a_ulong == ULONG_MAX); + r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); + r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); + + if (r == 1) + { + for (i = 0; i < 8; i++) + r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); + } + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_char_p == NULL); + r &= __lzo_assert(a.a_lzo_bytep == NULL); + r &= __lzo_assert(NULL == (void *)0); + if (r == 1) + { + for (i = 0; i < 10; i++) + dict[i] = wrkmem; + BZERO8_PTR(dict+1,sizeof(dict[0]),8); + r &= __lzo_assert(dict[0] == wrkmem); + for (i = 1; i < 9; i++) + r &= __lzo_assert(dict[i] == NULL); + r &= __lzo_assert(dict[9] == wrkmem); + } + + if (r == 1) + { + unsigned k = 1; + const unsigned n = (unsigned) sizeof(lzo_uint32); + lzo_byte *p0; + lzo_byte *p1; + + k += __lzo_align_gap(&x[k],n); + p0 = (lzo_bytep) &x[k]; +#if defined(PTR_LINEAR) + r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); +#else + r &= __lzo_assert(n == 4); + r &= __lzo_assert(PTR_ALIGNED_4(p0)); +#endif + + r &= __lzo_assert(k >= 1); + p1 = (lzo_bytep) &x[1]; + r &= __lzo_assert(PTR_GE(p0,p1)); + + r &= __lzo_assert(k < 1+n); + p1 = (lzo_bytep) &x[1+n]; + r &= __lzo_assert(PTR_LT(p0,p1)); + + if (r == 1) + { + lzo_uint32 v0, v1; +#if 0 + v0 = * (lzo_uint32 *) &x[k]; + v1 = * (lzo_uint32 *) &x[k+n]; +#else + + u.a_uchar_p = &x[k]; + v0 = *u.a_lzo_uint32_p; + u.a_uchar_p = &x[k+n]; + v1 = *u.a_lzo_uint32_p; +#endif + r &= __lzo_assert(v0 > 0); + r &= __lzo_assert(v1 > 0); + } + } + + return r; +} + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + int i; + union { + lzo_uint32 a; + unsigned short b; + lzo_uint32 aa[4]; + unsigned char x[4*sizeof(lzo_full_align_t)]; + } u; + + COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255); + COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0); + +#if 0 + r &= __lzo_assert((const void *)&u == (const void *)&u.a); + r &= __lzo_assert((const void *)&u == (const void *)&u.b); + r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); + r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); +#endif + + r &= basic_integral_check(); + r &= basic_ptr_check(); + if (r != 1) + return LZO_E_ERROR; + + u.a = 0; u.b = 0; + for (i = 0; i < (int) sizeof(u.x); i++) + u.x[i] = LZO_BYTE(i); + +#if defined(LZO_BYTE_ORDER) + if (r == 1) + { +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); + unsigned short b = (unsigned short) (u.b & 0xffff); + r &= __lzo_assert(a == 0x03020100L); + r &= __lzo_assert(b == 0x0100); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); + unsigned short b = u.b >> (8 * sizeof(u.b) - 16); + r &= __lzo_assert(a == 0x00010203L); + r &= __lzo_assert(b == 0x0001); +# else +# error "invalid LZO_BYTE_ORDER" +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_2) + COMPILE_TIME_ASSERT(sizeof(short) == 2); + if (r == 1) + { + unsigned short b[4]; + + for (i = 0; i < 4; i++) + b[i] = * (const unsigned short *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(b[0] == 0x0100); + r &= __lzo_assert(b[1] == 0x0201); + r &= __lzo_assert(b[2] == 0x0302); + r &= __lzo_assert(b[3] == 0x0403); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(b[0] == 0x0001); + r &= __lzo_assert(b[1] == 0x0102); + r &= __lzo_assert(b[2] == 0x0203); + r &= __lzo_assert(b[3] == 0x0304); +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + if (r == 1) + { + lzo_uint32 a[4]; + + for (i = 0; i < 4; i++) + a[i] = * (const lzo_uint32 *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(a[0] == 0x03020100L); + r &= __lzo_assert(a[1] == 0x04030201L); + r &= __lzo_assert(a[2] == 0x05040302L); + r &= __lzo_assert(a[3] == 0x06050403L); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(a[0] == 0x00010203L); + r &= __lzo_assert(a[1] == 0x01020304L); + r &= __lzo_assert(a[2] == 0x02030405L); + r &= __lzo_assert(a[3] == 0x03040506L); +# endif + } +#endif + +#if defined(LZO_ALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); +#endif + + COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); + +#if defined(__LZO_IN_MINLZO) + if (r == 1) + { + lzo_uint32 adler; + adler = lzo_adler32(0, NULL, 0); + adler = lzo_adler32(adler, lzo_copyright(), 200); + r &= __lzo_assert(adler == 0xc76f1751L); + } +#endif + + if (r == 1) + { + r &= __lzo_assert(!schedule_insns_bug()); + } + + if (r == 1) + { + static int x[3]; + static unsigned xn = 3; + register unsigned j; + + for (j = 0; j < xn; j++) + x[j] = (int)j - 3; + r &= __lzo_assert(!strength_reduce_bug(x)); + } + + if (r == 1) + { + r &= ptr_check(); + } + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +static lzo_bool schedule_insns_bug(void) +{ +#if defined(__LZO_CHECKER) + return 0; +#else + const int clone[] = {1, 2, 0}; + const int *q; + q = clone; + return (*q) ? 0 : 1; +#endif +} + +static lzo_bool strength_reduce_bug(int *x) +{ + return x[0] != -3 || x[1] != -2 || x[2] != -1; +} + +#undef COMPILE_TIME_ASSERT + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +LZO_EXTERN(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); + +LZO_PUBLIC(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) +{ + if (v == 0 || v > 0x1010) + return LZO_E_ERROR; + return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); +} + +#endif + +#define do_compress _lzo1x_1_do_compress + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) +{ + lzo_uint32 df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR( \ + (PTR_LT(m_pos,in) || \ + (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset) )) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + ((lzo_moff_t) ((ip)-(in)) <= m_off || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static +lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *ip __asm__("%esi"); +#else + register const lzo_byte *ip; +#endif + lzo_byte *op; + const lzo_byte * const in_end = in + in_len; + const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *m_pos __asm__("%edi"); +#else + register const lzo_byte *m_pos; +#endif + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if (m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if (ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = ip - ii; + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if (ip >= ip_end) + break; + } + + *out_len = op - out; + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_byte *op = out; + lzo_uint t; + +#if defined(__LZO_QUERY_COMPRESS) + if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); +#endif + + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_byte *ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_DECOMPRESS_OVERRUN +#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#define LZO_TEST_DECOMPRESS_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +/***** End of minilzo.c *****/ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.h new file mode 100755 index 0000000..e3270f9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.h @@ -0,0 +1,100 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x1080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/private.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/private.h new file mode 100755 index 0000000..71370b5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/private.h @@ -0,0 +1,44 @@ +#ifndef RFB_PRIVATE_H +#define RFB_PRIVATE_H + +/* from cursor.c */ + +void rfbShowCursor(rfbClientPtr cl); +void rfbHideCursor(rfbClientPtr cl); +void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion); + +/* from main.c */ + +rfbClientPtr rfbClientIteratorHead(rfbClientIteratorPtr i); + +/* from tight.c */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +extern void rfbTightCleanup(rfbScreenInfoPtr screen); +#endif + +/* from zlib.c */ +extern void rfbZlibCleanup(rfbScreenInfoPtr screen); + +/* from zrle.c */ +void rfbFreeZrleData(rfbClientPtr cl); + +#endif + + +/* from ultra.c */ + +extern void rfbUltraCleanup(rfbScreenInfoPtr screen); +extern void rfbFreeUltraData(rfbClientPtr cl); + +/* from rre.c */ + +extern void rfbRRECleanup(rfbScreenInfoPtr screen); + +/* from corre.c */ + +extern void rfbCoRRECleanup(rfbScreenInfoPtr screen); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbregion.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbregion.c new file mode 100755 index 0000000..0ab8a12 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbregion.c @@ -0,0 +1,886 @@ +/* -=- sraRegion.c + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + * + * A general purpose region clipping library + * Only deals with rectangular regions, though. + */ + +#include +#include + +/* -=- Internal Span structure */ + +struct sraRegion; + +typedef struct sraSpan { + struct sraSpan *_next; + struct sraSpan *_prev; + int start; + int end; + struct sraRegion *subspan; +} sraSpan; + +typedef struct sraRegion { + sraSpan front; + sraSpan back; +} sraSpanList; + +/* -=- Span routines */ + +sraSpanList *sraSpanListDup(const sraSpanList *src); +void sraSpanListDestroy(sraSpanList *list); + +static sraSpan * +sraSpanCreate(int start, int end, const sraSpanList *subspan) { + sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan)); + item->_next = item->_prev = NULL; + item->start = start; + item->end = end; + item->subspan = sraSpanListDup(subspan); + return item; +} + +static sraSpan * +sraSpanDup(const sraSpan *src) { + sraSpan *span; + if (!src) return NULL; + span = sraSpanCreate(src->start, src->end, src->subspan); + return span; +} + +static void +sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) { + newspan->_next = after->_next; + newspan->_prev = after; + after->_next->_prev = newspan; + after->_next = newspan; +} + +static void +sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) { + newspan->_next = before; + newspan->_prev = before->_prev; + before->_prev->_next = newspan; + before->_prev = newspan; +} + +static void +sraSpanRemove(sraSpan *span) { + span->_prev->_next = span->_next; + span->_next->_prev = span->_prev; +} + +static void +sraSpanDestroy(sraSpan *span) { + if (span->subspan) sraSpanListDestroy(span->subspan); + free(span); +} + +#ifdef DEBUG +static void +sraSpanCheck(const sraSpan *span, const char *text) { + /* Check the span is valid! */ + if (span->start == span->end) { + printf(text); + printf(":%d-%d\n", span->start, span->end); + } +} +#endif + +/* -=- SpanList routines */ + +static void sraSpanPrint(const sraSpan *s); + +static void +sraSpanListPrint(const sraSpanList *l) { + sraSpan *curr; + if (!l) { + printf("NULL"); + return; + } + curr = l->front._next; + printf("["); + while (curr != &(l->back)) { + sraSpanPrint(curr); + curr = curr->_next; + } + printf("]"); +} + +void +sraSpanPrint(const sraSpan *s) { + printf("(%d-%d)", (s->start), (s->end)); + if (s->subspan) + sraSpanListPrint(s->subspan); +} + +static sraSpanList * +sraSpanListCreate(void) { + sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList)); + item->front._next = &(item->back); + item->front._prev = NULL; + item->back._prev = &(item->front); + item->back._next = NULL; + return item; +} + +sraSpanList * +sraSpanListDup(const sraSpanList *src) { + sraSpanList *newlist; + sraSpan *newspan, *curr; + + if (!src) return NULL; + newlist = sraSpanListCreate(); + curr = src->front._next; + while (curr != &(src->back)) { + newspan = sraSpanDup(curr); + sraSpanInsertBefore(newspan, &(newlist->back)); + curr = curr->_next; + } + + return newlist; +} + +void +sraSpanListDestroy(sraSpanList *list) { + sraSpan *curr, *next; + while (list->front._next != &(list->back)) { + curr = list->front._next; + next = curr->_next; + sraSpanRemove(curr); + sraSpanDestroy(curr); + curr = next; + } + free(list); +} + +static void +sraSpanListMakeEmpty(sraSpanList *list) { + sraSpan *curr, *next; + while (list->front._next != &(list->back)) { + curr = list->front._next; + next = curr->_next; + sraSpanRemove(curr); + sraSpanDestroy(curr); + curr = next; + } + list->front._next = &(list->back); + list->front._prev = NULL; + list->back._prev = &(list->front); + list->back._next = NULL; +} + +static rfbBool +sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) { + sraSpan *sp1, *sp2; + + if (!s1) { + if (!s2) { + return 1; + } else { + rfbErr("sraSpanListEqual:incompatible spans (only one NULL!)\n"); + return FALSE; + } + } + + sp1 = s1->front._next; + sp2 = s2->front._next; + while ((sp1 != &(s1->back)) && + (sp2 != &(s2->back))) { + if ((sp1->start != sp2->start) || + (sp1->end != sp2->end) || + (!sraSpanListEqual(sp1->subspan, sp2->subspan))) { + return 0; + } + sp1 = sp1->_next; + sp2 = sp2->_next; + } + + if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) { + return 1; + } else { + return 0; + } +} + +static rfbBool +sraSpanListEmpty(const sraSpanList *list) { + return (list->front._next == &(list->back)); +} + +static unsigned long +sraSpanListCount(const sraSpanList *list) { + sraSpan *curr = list->front._next; + unsigned long count = 0; + while (curr != &(list->back)) { + if (curr->subspan) { + count += sraSpanListCount(curr->subspan); + } else { + count += 1; + } + curr = curr->_next; + } + return count; +} + +static void +sraSpanMergePrevious(sraSpan *dest) { + sraSpan *prev = dest->_prev; + + while ((prev->_prev) && + (prev->end == dest->start) && + (sraSpanListEqual(prev->subspan, dest->subspan))) { + /* + printf("merge_prev:"); + sraSpanPrint(prev); + printf(" & "); + sraSpanPrint(dest); + printf("\n"); + */ + dest->start = prev->start; + sraSpanRemove(prev); + sraSpanDestroy(prev); + prev = dest->_prev; + } +} + +static void +sraSpanMergeNext(sraSpan *dest) { + sraSpan *next = dest->_next; + while ((next->_next) && + (next->start == dest->end) && + (sraSpanListEqual(next->subspan, dest->subspan))) { +/* + printf("merge_next:"); + sraSpanPrint(dest); + printf(" & "); + sraSpanPrint(next); + printf("\n"); + */ + dest->end = next->end; + sraSpanRemove(next); + sraSpanDestroy(next); + next = dest->_next; + } +} + +static void +sraSpanListOr(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr; + int s_start, s_end; + + if (!dest) { + if (!src) { + return; + } else { + rfbErr("sraSpanListOr:incompatible spans (only one NULL!)\n"); + return; + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + s_start = s_curr->start; + s_end = s_curr->end; + while (s_curr != &(src->back)) { + + /* - If we are at end of destination list OR + If the new span comes before the next destination one */ + if ((d_curr == &(dest->back)) || + (d_curr->start >= s_end)) { + /* - Add the span */ + sraSpanInsertBefore(sraSpanCreate(s_start, s_end, + s_curr->subspan), + d_curr); + if (d_curr != &(dest->back)) + sraSpanMergePrevious(d_curr); + s_curr = s_curr->_next; + s_start = s_curr->start; + s_end = s_curr->end; + } else { + + /* - If the new span overlaps the existing one */ + if ((s_start < d_curr->end) && + (s_end > d_curr->start)) { + + /* - Insert new span before the existing destination one? */ + if (s_start < d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(s_start, + d_curr->start, + s_curr->subspan), + d_curr); + sraSpanMergePrevious(d_curr); + } + + /* Split the existing span if necessary */ + if (s_end < d_curr->end) { + sraSpanInsertAfter(sraSpanCreate(s_end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_end; + } + if (s_start > d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(d_curr->start, + s_start, + d_curr->subspan), + d_curr); + d_curr->start = s_start; + } + + /* Recursively OR subspans */ + sraSpanListOr(d_curr->subspan, s_curr->subspan); + + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + if (d_curr->_next != &(dest->back)) + sraSpanMergeNext(d_curr); + + /* Move onto the next pair to compare */ + if (s_end > d_curr->end) { + s_start = d_curr->end; + d_curr = d_curr->_next; + } else { + s_curr = s_curr->_next; + s_start = s_curr->start; + s_end = s_curr->end; + } + } else { + /* - No overlap. Move to the next destination span */ + d_curr = d_curr->_next; + } + } + } +} + +static rfbBool +sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr, *d_next; + + if (!dest) { + if (!src) { + return 1; + } else { + rfbErr("sraSpanListAnd:incompatible spans (only one NULL!)\n"); + return FALSE; + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { + + /* - If we haven't reached a destination span yet then move on */ + if (d_curr->start >= s_curr->end) { + s_curr = s_curr->_next; + continue; + } + + /* - If we are beyond the current destination span then remove it */ + if (d_curr->end <= s_curr->start) { + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + continue; + } + + /* - If we partially overlap a span then split it up or remove bits */ + if (s_curr->start > d_curr->start) { + /* - The top bit of the span does not match */ + d_curr->start = s_curr->start; + } + if (s_curr->end < d_curr->end) { + /* - The end of the span does not match */ + sraSpanInsertAfter(sraSpanCreate(s_curr->end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_curr->end; + } + + /* - Now recursively process the affected span */ + if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) { + /* - The destination subspan is now empty, so we should remove it */ + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + } else { + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + + /* - Move on to the next span */ + d_next = d_curr; + if (s_curr->end >= d_curr->end) { + d_next = d_curr->_next; + } + if (s_curr->end <= d_curr->end) { + s_curr = s_curr->_next; + } + d_curr = d_next; + } + } + + while (d_curr != &(dest->back)) { + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr=next; + } + + return !sraSpanListEmpty(dest); +} + +static rfbBool +sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr; + + if (!dest) { + if (!src) { + return 1; + } else { + rfbErr("sraSpanListSubtract:incompatible spans (only one NULL!)\n"); + return FALSE; + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { + + /* - If we haven't reached a destination span yet then move on */ + if (d_curr->start >= s_curr->end) { + s_curr = s_curr->_next; + continue; + } + + /* - If we are beyond the current destination span then skip it */ + if (d_curr->end <= s_curr->start) { + d_curr = d_curr->_next; + continue; + } + + /* - If we partially overlap the current span then split it up */ + if (s_curr->start > d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(d_curr->start, + s_curr->start, + d_curr->subspan), + d_curr); + d_curr->start = s_curr->start; + } + if (s_curr->end < d_curr->end) { + sraSpanInsertAfter(sraSpanCreate(s_curr->end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_curr->end; + } + + /* - Now recursively process the affected span */ + if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) { + /* - The destination subspan is now empty, so we should remove it */ + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + } else { + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + if (d_curr->_next != &(dest->back)) + sraSpanMergeNext(d_curr); + + /* - Move on to the next span */ + if (s_curr->end > d_curr->end) { + d_curr = d_curr->_next; + } else { + s_curr = s_curr->_next; + } + } + } + + return !sraSpanListEmpty(dest); +} + +/* -=- Region routines */ + +sraRegion * +sraRgnCreate(void) { + return (sraRegion*)sraSpanListCreate(); +} + +sraRegion * +sraRgnCreateRect(int x1, int y1, int x2, int y2) { + sraSpanList *vlist, *hlist; + sraSpan *vspan, *hspan; + + /* - Build the horizontal portion of the span */ + hlist = sraSpanListCreate(); + hspan = sraSpanCreate(x1, x2, NULL); + sraSpanInsertAfter(hspan, &(hlist->front)); + + /* - Build the vertical portion of the span */ + vlist = sraSpanListCreate(); + vspan = sraSpanCreate(y1, y2, hlist); + sraSpanInsertAfter(vspan, &(vlist->front)); + + sraSpanListDestroy(hlist); + + return (sraRegion*)vlist; +} + +sraRegion * +sraRgnCreateRgn(const sraRegion *src) { + return (sraRegion*)sraSpanListDup((sraSpanList*)src); +} + +void +sraRgnDestroy(sraRegion *rgn) { + sraSpanListDestroy((sraSpanList*)rgn); +} + +void +sraRgnMakeEmpty(sraRegion *rgn) { + sraSpanListMakeEmpty((sraSpanList*)rgn); +} + +/* -=- Boolean Region ops */ + +rfbBool +sraRgnAnd(sraRegion *dst, const sraRegion *src) { + return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src); +} + +void +sraRgnOr(sraRegion *dst, const sraRegion *src) { + sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src); +} + +rfbBool +sraRgnSubtract(sraRegion *dst, const sraRegion *src) { + return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src); +} + +void +sraRgnOffset(sraRegion *dst, int dx, int dy) { + sraSpan *vcurr, *hcurr; + + vcurr = ((sraSpanList*)dst)->front._next; + while (vcurr != &(((sraSpanList*)dst)->back)) { + vcurr->start += dy; + vcurr->end += dy; + + hcurr = vcurr->subspan->front._next; + while (hcurr != &(vcurr->subspan->back)) { + hcurr->start += dx; + hcurr->end += dx; + hcurr = hcurr->_next; + } + + vcurr = vcurr->_next; + } +} + +sraRegion *sraRgnBBox(const sraRegion *src) { + int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax; + sraSpan *vcurr, *hcurr; + + if(!src) + return sraRgnCreate(); + + vcurr = ((sraSpanList*)src)->front._next; + while (vcurr != &(((sraSpanList*)src)->back)) { + if(vcurr->startstart; + if(vcurr->end>ymax) + ymax=vcurr->end; + + hcurr = vcurr->subspan->front._next; + while (hcurr != &(vcurr->subspan->back)) { + if(hcurr->startstart; + if(hcurr->end>xmax) + xmax=hcurr->end; + hcurr = hcurr->_next; + } + + vcurr = vcurr->_next; + } + + if(xmaxback._prev; + vend = &(((sraSpanList*)rgn)->front); + } else { + vcurr = ((sraSpanList*)rgn)->front._next; + vend = &(((sraSpanList*)rgn)->back); + } + + if (vcurr != vend) { + rect->y1 = vcurr->start; + rect->y2 = vcurr->end; + + /* - Pick correct order */ + if (right2left) { + hcurr = vcurr->subspan->back._prev; + hend = &(vcurr->subspan->front); + } else { + hcurr = vcurr->subspan->front._next; + hend = &(vcurr->subspan->back); + } + + if (hcurr != hend) { + rect->x1 = hcurr->start; + rect->x2 = hcurr->end; + + sraSpanRemove(hcurr); + sraSpanDestroy(hcurr); + + if (sraSpanListEmpty(vcurr->subspan)) { + sraSpanRemove(vcurr); + sraSpanDestroy(vcurr); + } + +#if 0 + printf("poprect:(%dx%d)-(%dx%d)\n", + rect->x1, rect->y1, rect->x2, rect->y2); +#endif + return 1; + } + } + + return 0; +} + +unsigned long +sraRgnCountRects(const sraRegion *rgn) { + unsigned long count = sraSpanListCount((sraSpanList*)rgn); + return count; +} + +rfbBool +sraRgnEmpty(const sraRegion *rgn) { + return sraSpanListEmpty((sraSpanList*)rgn); +} + +/* iterator stuff */ +sraRectangleIterator *sraRgnGetIterator(sraRegion *s) +{ + /* these values have to be multiples of 4 */ +#define DEFSIZE 4 +#define DEFSTEP 8 + sraRectangleIterator *i = + (sraRectangleIterator*)malloc(sizeof(sraRectangleIterator)); + if(!i) + return NULL; + + /* we have to recurse eventually. So, the first sPtr is the pointer to + the sraSpan in the first level. the second sPtr is the pointer to + the sraRegion.back. The third and fourth sPtr are for the second + recursion level and so on. */ + i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE); + if(!i->sPtrs) { + free(i); + return NULL; + } + i->ptrSize = DEFSIZE; + i->sPtrs[0] = &(s->front); + i->sPtrs[1] = &(s->back); + i->ptrPos = 0; + i->reverseX = 0; + i->reverseY = 0; + return i; +} + +sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY) +{ + sraRectangleIterator *i = sraRgnGetIterator(s); + if(reverseY) { + i->sPtrs[1] = &(s->front); + i->sPtrs[0] = &(s->back); + } + i->reverseX = reverseX; + i->reverseY = reverseY; + return(i); +} + +static rfbBool sraReverse(sraRectangleIterator *i) +{ + return( ((i->ptrPos&2) && i->reverseX) || + (!(i->ptrPos&2) && i->reverseY)); +} + +static sraSpan* sraNextSpan(sraRectangleIterator *i) +{ + if(sraReverse(i)) + return(i->sPtrs[i->ptrPos]->_prev); + else + return(i->sPtrs[i->ptrPos]->_next); +} + +rfbBool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r) +{ + /* is the subspan finished? */ + while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) { + i->ptrPos -= 2; + if(i->ptrPos < 0) /* the end */ + return(0); + } + + i->sPtrs[i->ptrPos] = sraNextSpan(i); + + /* is this a new subspan? */ + while(i->sPtrs[i->ptrPos]->subspan) { + if(i->ptrPos+2 > i->ptrSize) { /* array is too small */ + i->ptrSize += DEFSTEP; + i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize); + } + i->ptrPos =+ 2; + if(sraReverse(i)) { + i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev; + i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front); + } else { + i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next; + i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back); + } + } + + if((i->ptrPos%4)!=2) { + rfbErr("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos); + return FALSE; + } + + r->y1 = i->sPtrs[i->ptrPos-2]->start; + r->y2 = i->sPtrs[i->ptrPos-2]->end; + r->x1 = i->sPtrs[i->ptrPos]->start; + r->x2 = i->sPtrs[i->ptrPos]->end; + + return(-1); +} + +void sraRgnReleaseIterator(sraRectangleIterator* i) +{ + free(i->sPtrs); + free(i); +} + +void +sraRgnPrint(const sraRegion *rgn) { + sraSpanListPrint((sraSpanList*)rgn); +} + +rfbBool +sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch) { + if (*x < cx) { + *w -= (cx-*x); + *x = cx; + } + if (*y < cy) { + *h -= (cy-*y); + *y = cy; + } + if (*x+*w > cx+cw) { + *w = (cx+cw)-*x; + } + if (*y+*h > cy+ch) { + *h = (cy+ch)-*y; + } + return (*w>0) && (*h>0); +} + +rfbBool +sraClipRect2(int *x, int *y, int *x2, int *y2, + int cx, int cy, int cx2, int cy2) { + if (*x < cx) + *x = cx; + if (*y < cy) + *y = cy; + if (*x >= cx2) + *x = cx2-1; + if (*y >= cy2) + *y = cy2-1; + if (*x2 <= cx) + *x2 = cx+1; + if (*y2 <= cy) + *y2 = cy+1; + if (*x2 > cx2) + *x2 = cx2; + if (*y2 > cy2) + *y2 = cy2; + return (*x2>*x) && (*y2>*y); +} + +/* test */ + +#ifdef SRA_TEST +/* pipe the output to sort|uniq -u and you'll get the errors. */ +int main(int argc, char** argv) +{ + sraRegionPtr region, region1, region2; + sraRectangleIterator* i; + sraRect rect; + rfbBool b; + + region = sraRgnCreateRect(10, 10, 600, 300); + region1 = sraRgnCreateRect(40, 50, 350, 200); + region2 = sraRgnCreateRect(0, 0, 20, 40); + + sraRgnPrint(region); + printf("\n[(10-300)[(10-600)]]\n\n"); + + b = sraRgnSubtract(region, region1); + printf("%s ",b?"true":"false"); + sraRgnPrint(region); + printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n"); + + sraRgnOr(region, region2); + printf("%ld\n6\n\n", sraRgnCountRects(region)); + + i = sraRgnGetIterator(region); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n"); + + i = sraRgnGetReverseIterator(region,1,0); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n"); + + i = sraRgnGetReverseIterator(region,1,1); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n"); + + sraRgnDestroy(region); + sraRgnDestroy(region1); + sraRgnDestroy(region2); + + return(0); +} +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbserver.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbserver.c new file mode 100755 index 0000000..9c8bb9d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbserver.c @@ -0,0 +1,3383 @@ +/* + * rfbserver.c - deal with server-side of the RFB protocol. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include "private.h" + +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif + +#ifdef WIN32 +#define write(sock,buf,len) send(sock,buf,len,0) +#else +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#endif +#endif + +#ifdef CORBA +#include +#endif + +#ifdef DEBUGPROTO +#undef DEBUGPROTO +#define DEBUGPROTO(x) x +#else +#define DEBUGPROTO(x) +#endif +#include +#include +/* stst() */ +#include +#include +#include +/* readdir() */ +#include +/* errno */ +#include +/* strftime() */ +#include + +#ifdef __MINGW32__ +static int compat_mkdir(const char *path, int mode) +{ + return mkdir(path); +} +#define mkdir compat_mkdir +#endif + +static void rfbProcessClientProtocolVersion(rfbClientPtr cl); +static void rfbProcessClientNormalMessage(rfbClientPtr cl); +static void rfbProcessClientInitMessage(rfbClientPtr cl); + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +void rfbIncrClientRef(rfbClientPtr cl) +{ + LOCK(cl->refCountMutex); + cl->refCount++; + UNLOCK(cl->refCountMutex); +} + +void rfbDecrClientRef(rfbClientPtr cl) +{ + LOCK(cl->refCountMutex); + cl->refCount--; + if(cl->refCount<=0) /* just to be sure also < 0 */ + TSIGNAL(cl->deleteCond); + UNLOCK(cl->refCountMutex); +} +#else +void rfbIncrClientRef(rfbClientPtr cl) {} +void rfbDecrClientRef(rfbClientPtr cl) {} +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +static MUTEX(rfbClientListMutex); +#endif + +struct rfbClientIterator { + rfbClientPtr next; + rfbScreenInfoPtr screen; + rfbBool closedToo; +}; + +void +rfbClientListInit(rfbScreenInfoPtr rfbScreen) +{ + if(sizeof(rfbBool)!=1) { + /* a sanity check */ + fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",(int)sizeof(rfbBool)); + /* we cannot continue, because rfbBool is supposed to be char everywhere */ + exit(1); + } + rfbScreen->clientHead = NULL; + INIT_MUTEX(rfbClientListMutex); +} + +rfbClientIteratorPtr +rfbGetClientIterator(rfbScreenInfoPtr rfbScreen) +{ + rfbClientIteratorPtr i = + (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator)); + i->next = NULL; + i->screen = rfbScreen; + i->closedToo = FALSE; + return i; +} + +rfbClientIteratorPtr +rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen) +{ + rfbClientIteratorPtr i = + (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator)); + i->next = NULL; + i->screen = rfbScreen; + i->closedToo = TRUE; + return i; +} + +rfbClientPtr +rfbClientIteratorHead(rfbClientIteratorPtr i) +{ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if(i->next != 0) { + rfbDecrClientRef(i->next); + rfbIncrClientRef(i->screen->clientHead); + } +#endif + LOCK(rfbClientListMutex); + i->next = i->screen->clientHead; + UNLOCK(rfbClientListMutex); + return i->next; +} + +rfbClientPtr +rfbClientIteratorNext(rfbClientIteratorPtr i) +{ + if(i->next == 0) { + LOCK(rfbClientListMutex); + i->next = i->screen->clientHead; + UNLOCK(rfbClientListMutex); + } else { + IF_PTHREADS(rfbClientPtr cl = i->next); + i->next = i->next->next; + IF_PTHREADS(rfbDecrClientRef(cl)); + } + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if(!i->closedToo) + while(i->next && i->next->sock<0) + i->next = i->next->next; + if(i->next) + rfbIncrClientRef(i->next); +#endif + + return i->next; +} + +void +rfbReleaseClientIterator(rfbClientIteratorPtr iterator) +{ + IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next)); + free(iterator); +} + + +/* + * rfbNewClientConnection is called from sockets.c when a new connection + * comes in. + */ + +void +rfbNewClientConnection(rfbScreenInfoPtr rfbScreen, + int sock) +{ + rfbClientPtr cl; + + cl = rfbNewClient(rfbScreen,sock); +#ifdef CORBA + if(cl!=NULL) + newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1); +#endif +} + + +/* + * rfbReverseConnection is called by the CORBA stuff to make an outward + * connection to a "listening" RFB client. + */ + +rfbClientPtr +rfbReverseConnection(rfbScreenInfoPtr rfbScreen, + char *host, + int port) +{ + int sock; + rfbClientPtr cl; + + if ((sock = rfbConnect(rfbScreen, host, port)) < 0) + return (rfbClientPtr)NULL; + + cl = rfbNewClient(rfbScreen, sock); + + if (cl) { + cl->reverseConnection = TRUE; + } + + return cl; +} + + +void +rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_) +{ + /* Permit the server to set the version to report */ + /* TODO: sanity checking */ + if ((major_==3) && (minor_ > 2 && minor_ < 9)) + { + rfbScreen->protocolMajorVersion = major_; + rfbScreen->protocolMinorVersion = minor_; + } + else + rfbLog("rfbSetProtocolVersion(%d,%d) set to invalid values\n", major_, minor_); +} + +/* + * rfbNewClient is called when a new connection has been made by whatever + * means. + */ + +static rfbClientPtr +rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, + int sock, + rfbBool isUDP) +{ + rfbProtocolVersionMsg pv; + rfbClientIteratorPtr iterator; + rfbClientPtr cl,cl_; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(struct sockaddr_in); + rfbProtocolExtension* extension; + + cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1); + + cl->screen = rfbScreen; + cl->sock = sock; + cl->viewOnly = FALSE; + /* setup pseudo scaling */ + cl->scaledScreen = rfbScreen; + cl->scaledScreen->scaledScreenRefCount++; + + rfbResetStats(cl); + + cl->clientData = NULL; + cl->clientGoneHook = rfbDoNothingWithClient; + + if(isUDP) { + rfbLog(" accepted UDP client\n"); + } else { + int one=1; + + getpeername(sock, (struct sockaddr *)&addr, &addrlen); + cl->host = strdup(inet_ntoa(addr.sin_addr)); + + rfbLog(" other clients:\n"); + iterator = rfbGetClientIterator(rfbScreen); + while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) { + rfbLog(" %s\n",cl_->host); + } + rfbReleaseClientIterator(iterator); + +#ifndef WIN32 + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("fcntl failed"); + close(sock); + return NULL; + } +#endif + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("setsockopt failed"); + close(sock); + return NULL; + } + + FD_SET(sock,&(rfbScreen->allFds)); + rfbScreen->maxFd = max(sock,rfbScreen->maxFd); + + INIT_MUTEX(cl->outputMutex); + INIT_MUTEX(cl->refCountMutex); + INIT_MUTEX(cl->sendMutex); + INIT_COND(cl->deleteCond); + + cl->state = RFB_PROTOCOL_VERSION; + + cl->reverseConnection = FALSE; + cl->readyForSetColourMapEntries = FALSE; + cl->useCopyRect = FALSE; + cl->preferredEncoding = -1; + cl->correMaxWidth = 48; + cl->correMaxHeight = 48; +#ifdef LIBVNCSERVER_HAVE_LIBZ + cl->zrleData = NULL; +#endif + + cl->copyRegion = sraRgnCreate(); + cl->copyDX = 0; + cl->copyDY = 0; + + cl->modifiedRegion = + sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height); + + INIT_MUTEX(cl->updateMutex); + INIT_COND(cl->updateCond); + + cl->requestedRegion = sraRgnCreate(); + + cl->format = cl->screen->serverFormat; + cl->translateFn = rfbTranslateNone; + cl->translateLookupTable = NULL; + + LOCK(rfbClientListMutex); + + IF_PTHREADS(cl->refCount = 0); + cl->next = rfbScreen->clientHead; + cl->prev = NULL; + if (rfbScreen->clientHead) + rfbScreen->clientHead->prev = cl; + + rfbScreen->clientHead = cl; + UNLOCK(rfbClientListMutex); + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + cl->webSockets = FALSE; + cl->webSocketsSSL = FALSE; + cl->webSocketsBase64 = FALSE; + cl->dblen= 0; + cl->carrylen = 0; +#endif + +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + cl->tightQualityLevel = -1; +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) + cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + { + int i; + for (i = 0; i < 4; i++) + cl->zsActive[i] = FALSE; + } +#endif +#endif + + cl->fileTransfer.fd = -1; + + cl->enableCursorShapeUpdates = FALSE; + cl->enableCursorPosUpdates = FALSE; + cl->useRichCursorEncoding = FALSE; + cl->enableLastRectEncoding = FALSE; + cl->enableKeyboardLedState = FALSE; + cl->enableSupportedMessages = FALSE; + cl->enableSupportedEncodings = FALSE; + cl->enableServerIdentity = FALSE; + cl->lastKeyboardLedState = -1; + cl->cursorX = rfbScreen->cursorX; + cl->cursorY = rfbScreen->cursorY; + cl->useNewFBSize = FALSE; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + cl->compStreamInited = FALSE; + cl->compStream.total_in = 0; + cl->compStream.total_out = 0; + cl->compStream.zalloc = Z_NULL; + cl->compStream.zfree = Z_NULL; + cl->compStream.opaque = Z_NULL; + + cl->zlibCompressLevel = 5; +#endif + + cl->progressiveSliceY = 0; + + cl->extensions = NULL; + + cl->lastPtrX = -1; + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + /* + * Wait a few ms for the client to send one of: + * - Flash policy request + * - WebSockets connection (TLS/SSL or plain) + */ + + if (!webSocketsCheck(cl)) { + // Error reporting handled in webSocketsHandshake + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return NULL; + } + +#endif + + sprintf(pv,rfbProtocolVersionFormat,rfbScreen->protocolMajorVersion, + rfbScreen->protocolMinorVersion); + + if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return NULL; + } + } + + for(extension = rfbGetExtensionIterator(); extension; + extension=extension->next) { + void* data = NULL; + /* if the extension does not have a newClient method, it wants + * to be initialized later. */ + if(extension->newClient && extension->newClient(cl, &data)) + rfbEnableExtension(cl, extension, data); + } + rfbReleaseExtensionIterator(); + + printf("--------\n"); + switch (cl->screen->newClientHook(cl)) { + case RFB_CLIENT_ON_HOLD: + cl->onHold = TRUE; + break; + case RFB_CLIENT_ACCEPT: + cl->onHold = FALSE; + break; + case RFB_CLIENT_REFUSE: + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + cl = NULL; + break; + } + + return cl; +} + +rfbClientPtr +rfbNewClient(rfbScreenInfoPtr rfbScreen, + int sock) +{ + return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE)); +} + +rfbClientPtr +rfbNewUDPClient(rfbScreenInfoPtr rfbScreen) +{ + return((rfbScreen->udpClient= + rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE))); +} + +/* + * rfbClientConnectionGone is called from sockets.c just after a connection + * has gone away. + */ + +void +rfbClientConnectionGone(rfbClientPtr cl) +{ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + int i; +#endif + + LOCK(rfbClientListMutex); + + if (cl->prev) + cl->prev->next = cl->next; + else + cl->screen->clientHead = cl->next; + if (cl->next) + cl->next->prev = cl->prev; + + if(cl->sock>=0) + close(cl->sock); + + if (cl->scaledScreen!=NULL) + cl->scaledScreen->scaledScreenRefCount--; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbFreeZrleData(cl); +#endif + + rfbFreeUltraData(cl); + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if(cl->screen->backgroundLoop != FALSE) { + int i; + do { + LOCK(cl->refCountMutex); + i=cl->refCount; + if(i>0) + WAIT(cl->deleteCond,cl->refCountMutex); + UNLOCK(cl->refCountMutex); + } while(i>0); + } +#endif + + UNLOCK(rfbClientListMutex); + + if(cl->sock>=0) + FD_CLR(cl->sock,&(cl->screen->allFds)); + + cl->clientGoneHook(cl); + + rfbLog("Client %s gone\n",cl->host); + free(cl->host); + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* Release the compression state structures if any. */ + if ( cl->compStreamInited ) { + deflateEnd( &(cl->compStream) ); + } + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + for (i = 0; i < 4; i++) { + if (cl->zsActive[i]) + deflateEnd(&cl->zsStruct[i]); + } +#endif +#endif + + if (cl->screen->pointerClient == cl) + cl->screen->pointerClient = NULL; + + sraRgnDestroy(cl->modifiedRegion); + sraRgnDestroy(cl->requestedRegion); + sraRgnDestroy(cl->copyRegion); + + if (cl->translateLookupTable) free(cl->translateLookupTable); + + TINI_COND(cl->updateCond); + TINI_MUTEX(cl->updateMutex); + + /* make sure outputMutex is unlocked before destroying */ + LOCK(cl->outputMutex); + UNLOCK(cl->outputMutex); + TINI_MUTEX(cl->outputMutex); + + LOCK(cl->sendMutex); + UNLOCK(cl->sendMutex); + TINI_MUTEX(cl->sendMutex); + +#ifdef CORBA + destroyConnection(cl); +#endif + + rfbPrintStats(cl); + + free(cl); +} + + +/* + * rfbProcessClientMessage is called when there is data to read from a client. + */ + +void +rfbProcessClientMessage(rfbClientPtr cl) +{ + switch (cl->state) { + case RFB_PROTOCOL_VERSION: + rfbProcessClientProtocolVersion(cl); + return; + case RFB_SECURITY_TYPE: + rfbProcessClientSecurityType(cl); + return; + case RFB_AUTHENTICATION: + rfbAuthProcessClientMessage(cl); + return; + case RFB_INITIALISATION: + rfbProcessClientInitMessage(cl); + return; + default: + rfbProcessClientNormalMessage(cl); + return; + } +} + + +/* + * rfbProcessClientProtocolVersion is called when the client sends its + * protocol version. + */ + +static void +rfbProcessClientProtocolVersion(rfbClientPtr cl) +{ + rfbProtocolVersionMsg pv; + int n, major_, minor_; + + if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) { + if (n == 0) + rfbLog("rfbProcessClientProtocolVersion: client gone\n"); + else + rfbLogPerror("rfbProcessClientProtocolVersion: read"); + rfbCloseClient(cl); + return; + } + + pv[sz_rfbProtocolVersionMsg] = 0; + if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) { + char name[1024]; + if(sscanf(pv,"RFB %03d.%03d %1023s\n",&major_,&minor_,name) != 3) { + rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client: %s\n", pv); + rfbCloseClient(cl); + return; + } + free(cl->host); + cl->host=strdup(name); + } + rfbLog("Client Protocol Version %d.%d\n", major_, minor_); + + if (major_ != rfbProtocolMajorVersion) { + rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d", + cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion, + major_,minor_); + rfbCloseClient(cl); + return; + } + + /* Check for the minor version use either of the two standard version of RFB */ + /* + * UltraVNC Viewer detects FileTransfer compatible servers via rfb versions + * 3.4, 3.6, 3.14, 3.16 + * It's a bad method, but it is what they use to enable features... + * maintaining RFB version compatibility across multiple servers is a pain + * Should use something like ServerIdentity encoding + */ + cl->protocolMajorVersion = major_; + cl->protocolMinorVersion = minor_; + + rfbLog("Protocol version sent %d.%d, using %d.%d\n", + major_, minor_, rfbProtocolMajorVersion, cl->protocolMinorVersion); + + rfbAuthNewClient(cl); +} + + +void +rfbClientSendString(rfbClientPtr cl, char *reason) +{ + char *buf; + int len = strlen(reason); + + rfbLog("rfbClientSendString(\"%s\")\n", reason); + + buf = (char *)malloc(4 + len); + ((uint32_t *)buf)[0] = Swap32IfLE(len); + memcpy(buf + 4, reason, len); + + if (rfbWriteExact(cl, buf, 4 + len) < 0) + rfbLogPerror("rfbClientSendString: write"); + free(buf); + + rfbCloseClient(cl); +} + +/* + * rfbClientConnFailed is called when a client connection has failed either + * because it talks the wrong protocol or it has failed authentication. + */ + +void +rfbClientConnFailed(rfbClientPtr cl, + char *reason) +{ + char *buf; + int len = strlen(reason); + + rfbLog("rfbClientConnFailed(\"%s\")\n", reason); + + buf = (char *)malloc(8 + len); + ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed); + ((uint32_t *)buf)[1] = Swap32IfLE(len); + memcpy(buf + 8, reason, len); + + if (rfbWriteExact(cl, buf, 8 + len) < 0) + rfbLogPerror("rfbClientConnFailed: write"); + free(buf); + + rfbCloseClient(cl); +} + + +/* + * rfbProcessClientInitMessage is called when the client sends its + * initialisation message. + */ + +static void +rfbProcessClientInitMessage(rfbClientPtr cl) +{ + rfbClientInitMsg ci; + union { + char buf[256]; + rfbServerInitMsg si; + } u; + int len, n; + rfbClientIteratorPtr iterator; + rfbClientPtr otherCl; + rfbExtensionData* extension; + + if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) { + if (n == 0) + rfbLog("rfbProcessClientInitMessage: client gone\n"); + else + rfbLogPerror("rfbProcessClientInitMessage: read"); + rfbCloseClient(cl); + return; + } + + memset(u.buf,0,sizeof(u.buf)); + + u.si.framebufferWidth = Swap16IfLE(cl->screen->width); + u.si.framebufferHeight = Swap16IfLE(cl->screen->height); + u.si.format = cl->screen->serverFormat; + u.si.format.redMax = Swap16IfLE(u.si.format.redMax); + u.si.format.greenMax = Swap16IfLE(u.si.format.greenMax); + u.si.format.blueMax = Swap16IfLE(u.si.format.blueMax); + + strncpy(u.buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127); + len = strlen(u.buf + sz_rfbServerInitMsg); + u.si.nameLength = Swap32IfLE(len); + + if (rfbWriteExact(cl, u.buf, sz_rfbServerInitMsg + len) < 0) { + rfbLogPerror("rfbProcessClientInitMessage: write"); + rfbCloseClient(cl); + return; + } + + for(extension = cl->extensions; extension;) { + rfbExtensionData* next = extension->next; + if(extension->extension->init && + !extension->extension->init(cl, extension->data)) + /* extension requested that it be removed */ + rfbDisableExtension(cl, extension->extension); + extension = next; + } + + cl->state = RFB_NORMAL; + + if (!cl->reverseConnection && + (cl->screen->neverShared || (!cl->screen->alwaysShared && !ci.shared))) { + + if (cl->screen->dontDisconnect) { + iterator = rfbGetClientIterator(cl->screen); + while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) { + if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { + rfbLog("-dontdisconnect: Not shared & existing client\n"); + rfbLog(" refusing new client %s\n", cl->host); + rfbCloseClient(cl); + rfbReleaseClientIterator(iterator); + return; + } + } + rfbReleaseClientIterator(iterator); + } else { + iterator = rfbGetClientIterator(cl->screen); + while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) { + if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { + rfbLog("Not shared - closing connection to client %s\n", + otherCl->host); + rfbCloseClient(otherCl); + } + } + rfbReleaseClientIterator(iterator); + } + } +} + +/* The values come in based on the scaled screen, we need to convert them to + * values based on the man screen's coordinate system + */ +static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h, + rfbClientPtr cl) +{ + int x1=Swap16IfLE(*x); + int y1=Swap16IfLE(*y); + int w1=Swap16IfLE(*w); + int h1=Swap16IfLE(*h); + + rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1, "rectSwapIfLEAndClip"); + *x = x1; + *y = y1; + *w = w1; + *h = h1; + + if(*w>cl->screen->width-*x) + *w=cl->screen->width-*x; + /* possible underflow */ + if(*w>cl->screen->width-*x) + return FALSE; + if(*h>cl->screen->height-*y) + *h=cl->screen->height-*y; + if(*h>cl->screen->height-*y) + return FALSE; + + return TRUE; +} + +/* + * Send keyboard state (PointerPos pseudo-encoding). + */ + +rfbBool +rfbSendKeyboardLedState(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState); + rect.r.x = Swap16IfLE(cl->lastKeyboardLedState); + rect.r.y = 0; + rect.r.w = 0; + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, rfbEncodingKeyboardLedState, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + + +#define rfbSetBit(buffer, position) (buffer[(position & 255) / 8] |= (1 << (position % 8))) + +/* + * Send rfbEncodingSupportedMessages. + */ + +rfbBool +rfbSendSupportedMessages(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + rfbSupportedMessages msgs; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(sz_rfbSupportedMessages); + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + memset((char *)&msgs, 0, sz_rfbSupportedMessages); + rfbSetBit(msgs.client2server, rfbSetPixelFormat); + rfbSetBit(msgs.client2server, rfbFixColourMapEntries); + rfbSetBit(msgs.client2server, rfbSetEncodings); + rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest); + rfbSetBit(msgs.client2server, rfbKeyEvent); + rfbSetBit(msgs.client2server, rfbPointerEvent); + rfbSetBit(msgs.client2server, rfbClientCutText); + rfbSetBit(msgs.client2server, rfbFileTransfer); + rfbSetBit(msgs.client2server, rfbSetScale); + /*rfbSetBit(msgs.client2server, rfbSetServerInput); */ + /*rfbSetBit(msgs.client2server, rfbSetSW); */ + /*rfbSetBit(msgs.client2server, rfbTextChat); */ + /*rfbSetBit(msgs.client2server, rfbKeyFrameRequest); */ + rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor); + + rfbSetBit(msgs.server2client, rfbFramebufferUpdate); + rfbSetBit(msgs.server2client, rfbSetColourMapEntries); + rfbSetBit(msgs.server2client, rfbBell); + rfbSetBit(msgs.server2client, rfbServerCutText); + rfbSetBit(msgs.server2client, rfbResizeFrameBuffer); + /*rfbSetBit(msgs.server2client, rfbKeyFrameUpdate); */ + rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages); + cl->ublen += sz_rfbSupportedMessages; + + rfbStatRecordEncodingSent(cl, rfbEncodingSupportedMessages, + sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages, + sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages); + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + + + +/* + * Send rfbEncodingSupportedEncodings. + */ + +rfbBool +rfbSendSupportedEncodings(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + static uint32_t supported[] = { + rfbEncodingRaw, + rfbEncodingCopyRect, + rfbEncodingRRE, + rfbEncodingCoRRE, + rfbEncodingHextile, +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbEncodingZlib, + rfbEncodingZRLE, + rfbEncodingZYWRLE, +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + rfbEncodingTight, +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + rfbEncodingTightPng, +#endif + rfbEncodingUltra, + rfbEncodingUltraZip, + rfbEncodingXCursor, + rfbEncodingRichCursor, + rfbEncodingPointerPos, + rfbEncodingLastRect, + rfbEncodingNewFBSize, + rfbEncodingKeyboardLedState, + rfbEncodingSupportedMessages, + rfbEncodingSupportedEncodings, + rfbEncodingServerIdentity, + }; + uint32_t nEncodings = sizeof(supported) / sizeof(supported[0]), i; + + /* think rfbSetEncodingsMsg */ + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + + (nEncodings * sizeof(uint32_t)) > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t)); + rect.r.h = Swap16IfLE(nEncodings); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + for (i = 0; i < nEncodings; i++) { + uint32_t encoding = Swap32IfLE(supported[i]); + memcpy(&cl->updateBuf[cl->ublen], (char *)&encoding, sizeof(encoding)); + cl->ublen += sizeof(encoding); + } + + rfbStatRecordEncodingSent(cl, rfbEncodingSupportedEncodings, + sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)), + sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t))); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + + +void +rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...) +{ + char buffer[256]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buffer, sizeof(buffer)-1, fmt, ap); + va_end(ap); + + if (screen->versionString!=NULL) free(screen->versionString); + screen->versionString = strdup(buffer); +} + +/* + * Send rfbEncodingServerIdentity. + */ + +rfbBool +rfbSendServerIdentity(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + char buffer[512]; + + /* tack on our library version */ + snprintf(buffer,sizeof(buffer)-1, "%s (%s)", + (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString), + LIBVNCSERVER_PACKAGE_STRING); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + + (strlen(buffer)+1) > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingServerIdentity); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(strlen(buffer)+1); + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1); + cl->ublen += strlen(buffer)+1; + + rfbStatRecordEncodingSent(cl, rfbEncodingServerIdentity, + sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1, + sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1); + + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + +rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer) +{ + rfbTextChatMsg tc; + int bytesToSend=0; + + memset((char *)&tc, 0, sizeof(tc)); + tc.type = rfbTextChat; + tc.length = Swap32IfLE(length); + + switch(length) { + case rfbTextChatOpen: + case rfbTextChatClose: + case rfbTextChatFinished: + bytesToSend=0; + break; + default: + bytesToSend=length; + if (bytesToSend>rfbTextMaxSize) + bytesToSend=rfbTextMaxSize; + } + + if (cl->ublen + sz_rfbTextChatMsg + bytesToSend > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + memcpy(&cl->updateBuf[cl->ublen], (char *)&tc, sz_rfbTextChatMsg); + cl->ublen += sz_rfbTextChatMsg; + if (bytesToSend>0) { + memcpy(&cl->updateBuf[cl->ublen], buffer, bytesToSend); + cl->ublen += bytesToSend; + } + rfbStatRecordMessageSent(cl, rfbTextChat, sz_rfbTextChatMsg+bytesToSend, sz_rfbTextChatMsg+bytesToSend); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + +#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \ + if ((cl->screen->getFileTransferPermission != NULL \ + && cl->screen->getFileTransferPermission(cl) != TRUE) \ + || cl->screen->permitFileTransfer != TRUE) { \ + rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \ + rfbCloseClient(cl); \ + return ret; \ + } + +int DB = 1; + +rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, char *buffer) +{ + rfbFileTransferMsg ft; + ft.type = rfbFileTransfer; + ft.contentType = contentType; + ft.contentParam = contentParam; + ft.pad = 0; /* UltraVNC did not Swap16LE(ft.contentParam) (Looks like it might be BigEndian) */ + ft.size = Swap32IfLE(size); + ft.length = Swap32IfLE(length); + + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE); + /* + rfbLog("rfbSendFileTransferMessage( %dtype, %dparam, %dsize, %dlen, %p)\n", contentType, contentParam, size, length, buffer); + */ + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&ft, sz_rfbFileTransferMsg) < 0) { + rfbLogPerror("rfbSendFileTransferMessage: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + return FALSE; + } + + if (length>0) + { + if (rfbWriteExact(cl, buffer, length) < 0) { + rfbLogPerror("rfbSendFileTransferMessage: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + return FALSE; + } + } + UNLOCK(cl->sendMutex); + + rfbStatRecordMessageSent(cl, rfbFileTransfer, sz_rfbFileTransferMsg+length, sz_rfbFileTransferMsg+length); + + return TRUE; +} + + +/* + * UltraVNC uses Windows Structures + */ +#define MAX_PATH 260 + +typedef struct { + uint32_t dwLowDateTime; + uint32_t dwHighDateTime; +} RFB_FILETIME; + +typedef struct { + uint32_t dwFileAttributes; + RFB_FILETIME ftCreationTime; + RFB_FILETIME ftLastAccessTime; + RFB_FILETIME ftLastWriteTime; + uint32_t nFileSizeHigh; + uint32_t nFileSizeLow; + uint32_t dwReserved0; + uint32_t dwReserved1; + uint8_t cFileName[ MAX_PATH ]; + uint8_t cAlternateFileName[ 14 ]; +} RFB_FIND_DATA; + +#define RFB_FILE_ATTRIBUTE_READONLY 0x1 +#define RFB_FILE_ATTRIBUTE_HIDDEN 0x2 +#define RFB_FILE_ATTRIBUTE_SYSTEM 0x4 +#define RFB_FILE_ATTRIBUTE_DIRECTORY 0x10 +#define RFB_FILE_ATTRIBUTE_ARCHIVE 0x20 +#define RFB_FILE_ATTRIBUTE_NORMAL 0x80 +#define RFB_FILE_ATTRIBUTE_TEMPORARY 0x100 +#define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800 + +rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath) +{ + int x; + char *home=NULL; + + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE); + + /* C: */ + if (path[0]=='C' && path[1]==':') + strcpy(unixPath, &path[2]); + else + { + home = getenv("HOME"); + if (home!=NULL) + { + strcpy(unixPath, home); + strcat(unixPath,"/"); + strcat(unixPath, path); + } + else + strcpy(unixPath, path); + } + for (x=0;x\"%s\"\n",buffer, path); + + dirp=opendir(path); + if (dirp==NULL) + return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL); + /* send back the path name (necessary for links) */ + if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE; + for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp)) + { + /* get stats */ + snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name); + retval = stat(retfilename, &statbuf); + + if (retval==0) + { + memset((char *)&win32filename, 0, sizeof(win32filename)); + win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL); + if (S_ISDIR(statbuf.st_mode)) + win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY); + win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime); /* Intel Order */ + win32filename.ftCreationTime.dwHighDateTime = 0; + win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */ + win32filename.ftLastAccessTime.dwHighDateTime = 0; + win32filename.ftLastWriteTime.dwLowDateTime = Swap32IfBE(statbuf.st_mtime); /* Intel Order */ + win32filename.ftLastWriteTime.dwHighDateTime = 0; + win32filename.nFileSizeLow = Swap32IfBE(statbuf.st_size); /* Intel Order */ + win32filename.nFileSizeHigh = 0; + win32filename.dwReserved0 = 0; + win32filename.dwReserved1 = 0; + + /* If this had the full path, we would need to translate to DOS format ("C:\") */ + /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */ + strcpy((char *)win32filename.cFileName, direntp->d_name); + + /* Do not show hidden files (but show how to move up the tree) */ + if ((strcmp(direntp->d_name, "..")==0) || (direntp->d_name[0]!='.')) + { + nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName); + /* + rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName); + */ + if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE) return FALSE; + } + } + } + closedir(dirp); + /* End of the transfer */ + return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL); +} + + +char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length) +{ + char *buffer=NULL; + int n=0; + + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL); + /* + rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length); + */ + if (length>0) { + buffer=malloc(length+1); + if (buffer!=NULL) { + if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessFileTransferReadBuffer: read"); + rfbCloseClient(cl); + /* NOTE: don't forget to free(buffer) if you return early! */ + if (buffer!=NULL) free(buffer); + return NULL; + } + /* Null Terminate */ + buffer[length]=0; + } + } + return buffer; +} + + +rfbBool rfbSendFileTransferChunk(rfbClientPtr cl) +{ + /* Allocate buffer for compression */ + unsigned char readBuf[sz_rfbBlockSize]; + int bytesRead=0; + int retval=0; + fd_set wfds; + struct timeval tv; + int n; +#ifdef LIBVNCSERVER_HAVE_LIBZ + unsigned char compBuf[sz_rfbBlockSize + 1024]; + unsigned long nMaxCompSize = sizeof(compBuf); + int nRetC = 0; +#endif + + /* + * Don't close the client if we get into this one because + * it is called from many places to service file transfers. + * Note that permitFileTransfer is checked first. + */ + if (cl->screen->permitFileTransfer != TRUE || + (cl->screen->getFileTransferPermission != NULL + && cl->screen->getFileTransferPermission(cl) != TRUE)) { + return TRUE; + } + + /* If not sending, or no file open... Return as if we sent something! */ + if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1)) + { + FD_ZERO(&wfds); + FD_SET(cl->sock, &wfds); + + /* return immediately */ + tv.tv_sec = 0; + tv.tv_usec = 0; + n = select(cl->sock + 1, NULL, &wfds, NULL, &tv); + + if (n<0) { + rfbLog("rfbSendFileTransferChunk() select failed: %s\n", strerror(errno)); + } + /* We have space on the transmit queue */ + if (n > 0) + { + bytesRead = read(cl->fileTransfer.fd, readBuf, sz_rfbBlockSize); + switch (bytesRead) { + case 0: + /* + rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n"); + */ + retval = rfbSendFileTransferMessage(cl, rfbEndOfFile, 0, 0, 0, NULL); + close(cl->fileTransfer.fd); + cl->fileTransfer.fd = -1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + return retval; + case -1: + /* TODO : send an error msg to the client... */ + rfbLog("rfbSendFileTransferChunk(): %s\n",strerror(errno)); + retval = rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, 0, 0, NULL); + close(cl->fileTransfer.fd); + cl->fileTransfer.fd = -1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + return retval; + default: + /* + rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead); + */ + if (!cl->fileTransfer.compressionEnabled) + return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf); + else + { +#ifdef LIBVNCSERVER_HAVE_LIBZ + nRetC = compress(compBuf, &nMaxCompSize, readBuf, bytesRead); + /* + rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead); + */ + + if ((nRetC==0) && (nMaxCompSizeD:\....Z:\ + * + * We replace the "\" char following the drive letter and ":" + * with a char corresponding to the type of drive + * We obtain something like "C:lD:c....Z:n\" + * Isn't it ugly ? + * DRIVE_FIXED = 'l' (local?) + * DRIVE_REMOVABLE = 'f' (floppy?) + * DRIVE_CDROM = 'c' + * DRIVE_REMOTE = 'n' + */ + + /* in unix, there are no 'drives' (We could list mount points though) + * We fake the root as a "C:" for the Winblows users + */ + filename2[0]='C'; + filename2[1]=':'; + filename2[2]='l'; + filename2[3]=0; + filename2[4]=0; + retval = rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADrivesList, 0, 5, filename2); + if (buffer!=NULL) free(buffer); + return retval; + break; + case rfbRDirContent: /* Client requests the content of a directory */ + /* + rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + retval = rfbSendDirContent(cl, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + } + break; + + case rfbDirPacket: + rfbLog("rfbProcessFileTransfer() rfbDirPacket\n"); + break; + case rfbFileAcceptHeader: + rfbLog("rfbProcessFileTransfer() rfbFileAcceptHeader\n"); + break; + case rfbCommandReturn: + rfbLog("rfbProcessFileTransfer() rfbCommandReturn\n"); + break; + case rfbFileChecksums: + /* Destination file already exists - the viewer sends the checksums */ + rfbLog("rfbProcessFileTransfer() rfbFileChecksums\n"); + break; + case rfbFileTransferAccess: + rfbLog("rfbProcessFileTransfer() rfbFileTransferAccess\n"); + break; + + /* + * sending from the server to the viewer + */ + + case rfbFileTransferRequest: + /* + rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest:\n"); + */ + /* add some space to the end of the buffer as we will be adding a timespec to it */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + /* The client requests a File */ + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744); + + /* + */ + if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\") Open: %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), cl->fileTransfer.fd); + + if (cl->fileTransfer.fd!=-1) { + if (fstat(cl->fileTransfer.fd, &statbuf)!=0) { + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + } + else + { + /* Add the File Time Stamp to the filename */ + strftime(timespec, sizeof(timespec), "%m/%d/%Y %H:%M",gmtime(&statbuf.st_ctime)); + buffer=realloc(buffer, length + strlen(timespec) + 2); /* comma, and Null term */ + if (buffer==NULL) { + rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest: Failed to malloc %d bytes\n", length + strlen(timespec) + 2); + return FALSE; + } + strcat(buffer,","); + strcat(buffer, timespec); + length = strlen(buffer); + if (DB) rfbLog("rfbProcessFileTransfer() buffer is now: \"%s\"\n", buffer); + } + } + + /* The viewer supports compression if size==1 */ + cl->fileTransfer.compressionEnabled = (size==1); + + /* + rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\")%s\n", buffer, filename1, (size==1?" ":"")); + */ + + /* File Size in bytes, 0xFFFFFFFF (-1) means error */ + retval = rfbSendFileTransferMessage(cl, rfbFileHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : statbuf.st_size), length, buffer); + + if (cl->fileTransfer.fd==-1) + { + if (buffer!=NULL) free(buffer); + return retval; + } + /* setup filetransfer stuff */ + cl->fileTransfer.fileSize = statbuf.st_size; + cl->fileTransfer.numPackets = statbuf.st_size / sz_rfbBlockSize; + cl->fileTransfer.receiving = 0; + cl->fileTransfer.sending = 0; /* set when we receive a rfbFileHeader: */ + + /* TODO: finish 64-bit file size support */ + sizeHtmp = 0; + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&sizeHtmp, 4) < 0) { + rfbLogPerror("rfbProcessFileTransfer: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + if (buffer!=NULL) free(buffer); + return FALSE; + } + UNLOCK(cl->sendMutex); + break; + + case rfbFileHeader: + /* Destination file (viewer side) is ready for reception (size > 0) or not (size = -1) */ + if (size==-1) { + rfbLog("rfbProcessFileTransfer() rfbFileHeader (error, aborting)\n"); + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + return TRUE; + } + + /* + rfbLog("rfbProcessFileTransfer() rfbFileHeader (%d bytes of a file)\n", size); + */ + + /* Starts the transfer! */ + cl->fileTransfer.sending=1; + return rfbSendFileTransferChunk(cl); + break; + + + /* + * sending from the viewer to the server + */ + + case rfbFileTransferOffer: + /* client is sending a file to us */ + /* buffer contains full path name (plus FileTime) */ + /* size contains size of the file */ + /* + rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer:\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + + /* Parse the FileTime */ + p = strrchr(buffer, ','); + if (p!=NULL) { + *p = '\0'; + strcpy(szFileTime, p+1); + } else + szFileTime[0]=0; + + + + /* Need to read in sizeHtmp */ + if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessFileTransfer: read sizeHtmp"); + rfbCloseClient(cl); + /* NOTE: don't forget to free(buffer) if you return early! */ + if (buffer!=NULL) free(buffer); + return FALSE; + } + sizeHtmp = Swap32IfLE(sizeHtmp); + + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + + /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */ + /* TODO: Delta Transfer */ + + cl->fileTransfer.fd=open(filename1, O_CREAT|O_WRONLY|O_TRUNC, 0744); + if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer(\"%s\"->\"%s\") %s %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), (cl->fileTransfer.fd==-1?strerror(errno):""), cl->fileTransfer.fd); + /* + */ + + /* File Size in bytes, 0xFFFFFFFF (-1) means error */ + retval = rfbSendFileTransferMessage(cl, rfbFileAcceptHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : 0), length, buffer); + if (cl->fileTransfer.fd==-1) { + free(buffer); + return retval; + } + + /* setup filetransfer stuff */ + cl->fileTransfer.fileSize = size; + cl->fileTransfer.numPackets = size / sz_rfbBlockSize; + cl->fileTransfer.receiving = 1; + cl->fileTransfer.sending = 0; + break; + + case rfbFilePacket: + /* + rfbLog("rfbProcessFileTransfer() rfbFilePacket:\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + if (cl->fileTransfer.fd!=-1) { + /* buffer contains the contents of the file */ + if (size==0) + retval=write(cl->fileTransfer.fd, buffer, length); + else + { +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* compressed packet */ + nRet = uncompress(compBuff,&nRawBytes,(const unsigned char*)buffer, length); + retval=write(cl->fileTransfer.fd, compBuff, nRawBytes); +#else + /* Write the file out as received... */ + retval=write(cl->fileTransfer.fd, buffer, length); +#endif + } + if (retval==-1) + { + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + } + } + break; + + case rfbEndOfFile: + if (DB) rfbLog("rfbProcessFileTransfer() rfbEndOfFile\n"); + /* + */ + if (cl->fileTransfer.fd!=-1) + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + break; + + case rfbAbortFileTransfer: + if (DB) rfbLog("rfbProcessFileTransfer() rfbAbortFileTransfer\n"); + /* + */ + if (cl->fileTransfer.fd!=-1) + { + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + } + else + { + /* We use this message for FileTransfer rights (<=RC18 versions) + * The client asks for FileTransfer permission + */ + if (contentParam == 0) + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED! (Client Version <=RC18)\n"); + /* Old method for FileTransfer handshake perimssion (<=RC18) (Deny it)*/ + return rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, -1, 0, ""); + } + /* New method is allowed */ + if (cl->screen->getFileTransferPermission!=NULL) + { + if (cl->screen->getFileTransferPermission(cl)==TRUE) + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */ + } + else + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* Deny */ + } + } + else + { + if (cl->screen->permitFileTransfer) + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */ + } + else + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED by default!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* DEFAULT: DENY (for security) */ + } + + } + } + break; + + + case rfbCommand: + /* + rfbLog("rfbProcessFileTransfer() rfbCommand:\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + switch (contentParam) { + case rfbCDirCreate: /* Client requests the creation of a directory */ + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + retval = mkdir(filename1, 0755); + if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success")); + /* + */ + retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbADirCreate, retval, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + case rfbCFileDelete: /* Client requests the deletion of a file */ + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + if (stat(filename1,&statbuf)==0) + { + if (S_ISDIR(statbuf.st_mode)) + retval = rmdir(filename1); + else + retval = unlink(filename1); + } + else retval=-1; + retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileDelete, retval, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + case rfbCFileRename: /* Client requests the Renaming of a file/directory */ + p = strrchr(buffer, '*'); + if (p != NULL) + { + /* Split into 2 filenames ('*' is a seperator) */ + *p = '\0'; + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + rfbFilenameTranslate2UNIX(cl, p+1, filename2); + retval = rename(filename1,filename2); + if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success")); + /* + */ + /* Restore the buffer so the reply is good */ + *p = '*'; + retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileRename, retval, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + } + break; + } + + break; + } + + /* NOTE: don't forget to free(buffer) if you return early! */ + if (buffer!=NULL) free(buffer); + return TRUE; +} + +/* + * rfbProcessClientNormalMessage is called when the client has sent a normal + * protocol message. + */ + +static void +rfbProcessClientNormalMessage(rfbClientPtr cl) +{ + + int n=0; + rfbClientToServerMsg msg; + char *str; + int i; + uint32_t enc=0; + uint32_t lastPreferredEncoding = -1; + char encBuf[64]; + char encBuf2[64]; + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->webSockets) { + + if (cl->ssl) + n = SSL_peek(cl->ssl, encBuf, 4); + else + n = recv(cl->sock, encBuf, 4, MSG_PEEK); + + if (cl->webSocketsBase64) { + /* With Base64 encoding we need at least 4 bytes */ + if ((n > 0) && (n < 4)) { + if (encBuf[0] == '\xff') { + /* Make sure we don't miss a client disconnect on an end frame + * marker */ + if (cl->ssl) + n = SSL_read(cl->ssl, encBuf, 1); + else + n = read(cl->sock, encBuf, 1); + } + return; + } + } else { + /* With UTF-8 encoding we need at least 3 bytes (framing + 1) */ + if ((n == 1) || (n == 2)) { + if (encBuf[0] == '\xff') { + /* Make sure we don't miss a client disconnect on an end frame + * marker */ + if (cl->ssl) + n = SSL_read(cl->ssl, encBuf, 1); + else + n = read(cl->sock, encBuf, 1); + } + return; + } + } + } +#endif + + if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + switch (msg.type) { + + case rfbSetPixelFormat: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetPixelFormatMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel; + cl->format.depth = msg.spf.format.depth; + cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE); + cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE); + cl->format.redMax = Swap16IfLE(msg.spf.format.redMax); + cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax); + cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax); + cl->format.redShift = msg.spf.format.redShift; + cl->format.greenShift = msg.spf.format.greenShift; + cl->format.blueShift = msg.spf.format.blueShift; + + cl->readyForSetColourMapEntries = TRUE; + cl->screen->setTranslateFunction(cl); + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg); + + return; + + + case rfbFixColourMapEntries: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbFixColourMapEntriesMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg); + rfbLog("rfbProcessClientNormalMessage: %s", + "FixColourMapEntries unsupported\n"); + rfbCloseClient(cl); + return; + + + /* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features... + * We may want to look into this... + * Example: + * case rfbEncodingXCursor: + * cl->enableCursorShapeUpdates = TRUE; + * + * Currently: cl->enableCursorShapeUpdates can *never* be turned off... + */ + case rfbSetEncodings: + { + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetEncodingsMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings); + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4),sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4)); + + /* + * UltraVNC Client has the ability to adapt to changing network environments + * So, let's give it a change to tell us what it wants now! + */ + if (cl->preferredEncoding!=-1) + lastPreferredEncoding = cl->preferredEncoding; + + /* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */ + cl->preferredEncoding=-1; + cl->useCopyRect = FALSE; + cl->useNewFBSize = FALSE; + cl->cursorWasChanged = FALSE; + cl->useRichCursorEncoding = FALSE; + cl->enableCursorPosUpdates = FALSE; + cl->enableCursorShapeUpdates = FALSE; + cl->enableCursorShapeUpdates = FALSE; + cl->enableLastRectEncoding = FALSE; + cl->enableKeyboardLedState = FALSE; + cl->enableSupportedMessages = FALSE; + cl->enableSupportedEncodings = FALSE; + cl->enableServerIdentity = FALSE; + + +int j; + for (j = 0; j < msg.se.nEncodings; j++) { + + if ((n = rfbReadExact(cl, (char *)&enc, 4)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + printf("close\n"); + rfbCloseClient(cl); + return; + } + enc = Swap32IfLE(enc); + + + switch (enc) { + + case rfbEncodingCopyRect: + cl->useCopyRect = TRUE; + break; + case rfbEncodingRaw: + case rfbEncodingRRE: + case rfbEncodingCoRRE: + case rfbEncodingHextile: + case rfbEncodingUltra: +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZlib: + case rfbEncodingZRLE: + case rfbEncodingZYWRLE: +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + case rfbEncodingTight: +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + case rfbEncodingTightPng: +#endif + + /* The first supported encoding is the 'preferred' encoding */ + if (cl->preferredEncoding == -1) + cl->preferredEncoding = enc; + + + break; + case rfbEncodingXCursor: + if(!cl->screen->dontConvertRichCursorToXCursor) { + rfbLog("Enabling X-style cursor updates for client %s\n", + cl->host); + /* if cursor was drawn, hide the cursor */ + if(!cl->enableCursorShapeUpdates) + rfbRedrawAfterHideCursor(cl,NULL); + + cl->enableCursorShapeUpdates = TRUE; + cl->cursorWasChanged = TRUE; + } + break; + case rfbEncodingRichCursor: + rfbLog("Enabling full-color cursor updates for client %s\n", + cl->host); + /* if cursor was drawn, hide the cursor */ + if(!cl->enableCursorShapeUpdates) + rfbRedrawAfterHideCursor(cl,NULL); + + cl->enableCursorShapeUpdates = TRUE; + cl->useRichCursorEncoding = TRUE; + cl->cursorWasChanged = TRUE; + break; + case rfbEncodingPointerPos: + if (!cl->enableCursorPosUpdates) { + rfbLog("Enabling cursor position updates for client %s\n", + cl->host); + cl->enableCursorPosUpdates = TRUE; + cl->cursorWasMoved = TRUE; + } + break; + case rfbEncodingLastRect: + if (!cl->enableLastRectEncoding) { + rfbLog("Enabling LastRect protocol extension for client " + "%s\n", cl->host); + cl->enableLastRectEncoding = TRUE; + } + break; + case rfbEncodingNewFBSize: + if (!cl->useNewFBSize) { + rfbLog("Enabling NewFBSize protocol extension for client " + "%s\n", cl->host); + cl->useNewFBSize = TRUE; + } + break; + case rfbEncodingKeyboardLedState: + if (!cl->enableKeyboardLedState) { + rfbLog("Enabling KeyboardLedState protocol extension for client " + "%s\n", cl->host); + cl->enableKeyboardLedState = TRUE; + } + break; + case rfbEncodingSupportedMessages: + if (!cl->enableSupportedMessages) { + rfbLog("Enabling SupportedMessages protocol extension for client " + "%s\n", cl->host); + cl->enableSupportedMessages = TRUE; + } + break; + case rfbEncodingSupportedEncodings: + if (!cl->enableSupportedEncodings) { + rfbLog("Enabling SupportedEncodings protocol extension for client " + "%s\n", cl->host); + cl->enableSupportedEncodings = TRUE; + } + break; + case rfbEncodingServerIdentity: + if (!cl->enableServerIdentity) { + rfbLog("Enabling ServerIdentity protocol extension for client " + "%s\n", cl->host); + cl->enableServerIdentity = TRUE; + } + break; + default: +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + if ( enc >= (uint32_t)rfbEncodingCompressLevel0 && + enc <= (uint32_t)rfbEncodingCompressLevel9 ) { + cl->zlibCompressLevel = enc & 0x0F; +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) + cl->tightCompressLevel = enc & 0x0F; + rfbLog("Using compression level %d for client %s\n", + cl->tightCompressLevel, cl->host); +#endif + } else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 && + enc <= (uint32_t)rfbEncodingQualityLevel9 ) { + cl->tightQualityLevel = enc & 0x0F; + rfbLog("Using image quality level %d for client %s\n", + cl->tightQualityLevel, cl->host); + } else +#endif + { + rfbExtensionData* e; + for(e = cl->extensions; e;) { + rfbExtensionData* next = e->next; + if(e->extension->enablePseudoEncoding && + e->extension->enablePseudoEncoding(cl, + &e->data, (int)enc)) + /* ext handles this encoding */ + break; + e = next; + } + if(e == NULL) { + rfbBool handled = FALSE; + /* if the pseudo encoding is not handled by the + enabled extensions, search through all + extensions. */ + rfbProtocolExtension* e; + + for(e = rfbGetExtensionIterator(); e;) { + int* encs = e->pseudoEncodings; + while(encs && *encs!=0) { + if(*encs==(int)enc) { + void* data = NULL; + if(!e->enablePseudoEncoding(cl, &data, (int)enc)) { + rfbLog("Installed extension pretends to handle pseudo encoding 0x%x, but does not!\n",(int)enc); + } else { + rfbEnableExtension(cl, e, data); + handled = TRUE; + e = NULL; + break; + } + } + encs++; + } + + if(e) + e = e->next; + } + rfbReleaseExtensionIterator(); + + if(!handled) + rfbLog("rfbProcessClientNormalMessage: " + "ignoring unsupported encoding type %s\n", + encodingName(enc,encBuf,sizeof(encBuf))); + } + } + } + } + + + if (cl->preferredEncoding == -1) { + if (lastPreferredEncoding==-1) { + cl->preferredEncoding = rfbEncodingRaw; + rfbLog("Defaulting to %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host); + } + else { + cl->preferredEncoding = lastPreferredEncoding; + rfbLog("Sticking with %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host); + } + } + else + { + if (lastPreferredEncoding==-1) { + rfbLog("Using %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host); + } else { + rfbLog("Switching from %s to %s Encoding for client %s\n", + encodingName(lastPreferredEncoding,encBuf2,sizeof(encBuf2)), + encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)), cl->host); + } + } + + if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) { + rfbLog("Disabling cursor position updates for client %s\n", + cl->host); + cl->enableCursorPosUpdates = FALSE; + } + + return; + } + + + case rfbFramebufferUpdateRequest: + { + sraRegionPtr tmpRegion; + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbFramebufferUpdateRequestMsg,sz_rfbFramebufferUpdateRequestMsg); + + /* The values come in based on the scaled screen, we need to convert them to + * values based on the main screen's coordinate system + */ + if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,cl)) + { + rfbLog("Warning, ignoring rfbFramebufferUpdateRequest: %dXx%dY-%dWx%dH\n",msg.fur.x, msg.fur.y, msg.fur.w, msg.fur.h); + return; + } + + + tmpRegion = + sraRgnCreateRect(msg.fur.x, + msg.fur.y, + msg.fur.x+msg.fur.w, + msg.fur.y+msg.fur.h); + + LOCK(cl->updateMutex); + sraRgnOr(cl->requestedRegion,tmpRegion); + + if (!cl->readyForSetColourMapEntries) { + /* client hasn't sent a SetPixelFormat so is using server's */ + cl->readyForSetColourMapEntries = TRUE; + if (!cl->format.trueColour) { + if (!rfbSetClientColourMap(cl, 0, 0)) { + sraRgnDestroy(tmpRegion); + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + return; + } + } + } + + if (!msg.fur.incremental) { + sraRgnOr(cl->modifiedRegion,tmpRegion); + sraRgnSubtract(cl->copyRegion,tmpRegion); + } + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + + sraRgnDestroy(tmpRegion); + + return; + } + + case rfbKeyEvent: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbKeyEventMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbKeyEventMsg, sz_rfbKeyEventMsg); + + if(!cl->viewOnly) { + cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl); + } + + return; + + + case rfbPointerEvent: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbPointerEventMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbPointerEventMsg, sz_rfbPointerEventMsg); + + if (cl->screen->pointerClient && cl->screen->pointerClient != cl) + return; + + if (msg.pe.buttonMask == 0) + cl->screen->pointerClient = NULL; + else + cl->screen->pointerClient = cl; + + if(!cl->viewOnly) { + if (msg.pe.buttonMask != cl->lastPtrButtons || + cl->screen->deferPtrUpdateTime == 0) { + cl->screen->ptrAddEvent(msg.pe.buttonMask, + ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x)), + ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y)), + cl); + cl->lastPtrButtons = msg.pe.buttonMask; + } else { + cl->lastPtrX = ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x)); + cl->lastPtrY = ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y)); + cl->lastPtrButtons = msg.pe.buttonMask; + } + } + return; + + + case rfbFileTransfer: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbFileTransferMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + msg.ft.size = Swap32IfLE(msg.ft.size); + msg.ft.length = Swap32IfLE(msg.ft.length); + /* record statistics in rfbProcessFileTransfer as length is filled with garbage when it is not valid */ + rfbProcessFileTransfer(cl, msg.ft.contentType, msg.ft.contentParam, msg.ft.size, msg.ft.length); + return; + + case rfbSetSW: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetSWMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + msg.sw.x = Swap16IfLE(msg.sw.x); + msg.sw.y = Swap16IfLE(msg.sw.y); + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetSWMsg, sz_rfbSetSWMsg); + /* msg.sw.status is not initialized in the ultraVNC viewer and contains random numbers (why???) */ + + rfbLog("Received a rfbSetSingleWindow(%d x, %d y)\n", msg.sw.x, msg.sw.y); + if (cl->screen->setSingleWindow!=NULL) + cl->screen->setSingleWindow(cl, msg.sw.x, msg.sw.y); + return; + + case rfbSetServerInput: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetServerInputMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetServerInputMsg, sz_rfbSetServerInputMsg); + + /* msg.sim.pad is not initialized in the ultraVNC viewer and contains random numbers (why???) */ + /* msg.sim.pad = Swap16IfLE(msg.sim.pad); */ + + rfbLog("Received a rfbSetServerInput(%d status)\n", msg.sim.status); + if (cl->screen->setServerInput!=NULL) + cl->screen->setServerInput(cl, msg.sim.status); + return; + + case rfbTextChat: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbTextChatMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + msg.tc.pad2 = Swap16IfLE(msg.tc.pad2); + msg.tc.length = Swap32IfLE(msg.tc.length); + + switch (msg.tc.length) { + case rfbTextChatOpen: + case rfbTextChatClose: + case rfbTextChatFinished: + /* commands do not have text following */ + /* Why couldn't they have used the pad byte??? */ + str=NULL; + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg, sz_rfbTextChatMsg); + break; + default: + if ((msg.tc.length>0) && (msg.tc.length%d\n", msg.tc.length, rfbTextMaxSize); + rfbCloseClient(cl); + return; + } + } + + /* Note: length can be commands: rfbTextChatOpen, rfbTextChatClose, and rfbTextChatFinished + * at which point, the str is NULL (as it is not sent) + */ + if (cl->screen->setTextChat!=NULL) + cl->screen->setTextChat(cl, msg.tc.length, str); + + free(str); + return; + + + case rfbClientCutText: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbClientCutTextMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + msg.cct.length = Swap32IfLE(msg.cct.length); + + str = (char *)malloc(msg.cct.length); + + if ((n = rfbReadExact(cl, str, msg.cct.length)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + free(str); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbClientCutTextMsg+msg.cct.length, sz_rfbClientCutTextMsg+msg.cct.length); + if(!cl->viewOnly) { + cl->screen->setXCutText(str, msg.cct.length, cl); + } + free(str); + + return; + + case rfbPalmVNCSetScaleFactor: + cl->PalmVNC = TRUE; + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetScaleMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg); + rfbLog("rfbSetScale(%d)\n", msg.ssc.scale); + rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale); + + rfbSendNewScaleSize(cl); + return; + + case rfbSetScale: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetScaleMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg); + rfbLog("rfbSetScale(%d)\n", msg.ssc.scale); + rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale); + + rfbSendNewScaleSize(cl); + return; + + default: + { + rfbExtensionData *e,*next; + + for(e=cl->extensions; e;) { + next = e->next; + if(e->extension->handleMessage && + e->extension->handleMessage(cl, e->data, &msg)) + { + rfbStatRecordMessageRcvd(cl, msg.type, 0, 0); /* Extension should handle this */ + return; + } + e = next; + } + + rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", + msg.type); + rfbLog(" ... closing connection\n"); + rfbCloseClient(cl); + return; + } + } +} + + + +/* + * rfbSendFramebufferUpdate - send the currently pending framebuffer update to + * the RFB client. + * givenUpdateRegion is not changed. + */ + +rfbBool +rfbSendFramebufferUpdate(rfbClientPtr cl, + sraRegionPtr givenUpdateRegion) +{ + sraRectangleIterator* i=NULL; + sraRect rect; + int nUpdateRegionRects; + rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf; + sraRegionPtr updateRegion,updateCopyRegion,tmpRegion; + int dx, dy; + rfbBool sendCursorShape = FALSE; + rfbBool sendCursorPos = FALSE; + rfbBool sendKeyboardLedState = FALSE; + rfbBool sendSupportedMessages = FALSE; + rfbBool sendSupportedEncodings = FALSE; + rfbBool sendServerIdentity = FALSE; + rfbBool result = TRUE; + + + if(cl->screen->displayHook) + cl->screen->displayHook(cl); + + /* + * If framebuffer size was changed and the client supports NewFBSize + * encoding, just send NewFBSize marker and return. + */ + + if (cl->useNewFBSize && cl->newFBSizePending) { + LOCK(cl->updateMutex); + cl->newFBSizePending = FALSE; + UNLOCK(cl->updateMutex); + fu->type = rfbFramebufferUpdate; + fu->nRects = Swap16IfLE(1); + cl->ublen = sz_rfbFramebufferUpdateMsg; + if (!rfbSendNewFBSize(cl, cl->scaledScreen->width, cl->scaledScreen->height)) { + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, FALSE); + return FALSE; + } + result = rfbSendUpdateBuf(cl); + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, result); + return result; + } + + /* + * If this client understands cursor shape updates, cursor should be + * removed from the framebuffer. Otherwise, make sure it's put up. + */ + + if (cl->enableCursorShapeUpdates) { + if (cl->cursorWasChanged && cl->readyForSetColourMapEntries) + sendCursorShape = TRUE; + } + + /* + * Do we plan to send cursor position update? + */ + + if (cl->enableCursorPosUpdates && cl->cursorWasMoved) + sendCursorPos = TRUE; + + /* + * Do we plan to send a keyboard state update? + */ + if ((cl->enableKeyboardLedState) && + (cl->screen->getKeyboardLedStateHook!=NULL)) + { + int x; + x=cl->screen->getKeyboardLedStateHook(cl->screen); + if (x!=cl->lastKeyboardLedState) + { + sendKeyboardLedState = TRUE; + cl->lastKeyboardLedState=x; + } + } + + /* + * Do we plan to send a rfbEncodingSupportedMessages? + */ + if (cl->enableSupportedMessages) + { + sendSupportedMessages = TRUE; + /* We only send this message ONCE + * (We disable it here) + */ + cl->enableSupportedMessages = FALSE; + } + /* + * Do we plan to send a rfbEncodingSupportedEncodings? + */ + if (cl->enableSupportedEncodings) + { + sendSupportedEncodings = TRUE; + /* We only send this message ONCE + * (We disable it here) + */ + cl->enableSupportedEncodings = FALSE; + } + /* + * Do we plan to send a rfbEncodingServerIdentity? + */ + if (cl->enableServerIdentity) + { + sendServerIdentity = TRUE; + /* We only send this message ONCE + * (We disable it here) + */ + cl->enableServerIdentity = FALSE; + } + + LOCK(cl->updateMutex); + + /* + * The modifiedRegion may overlap the destination copyRegion. We remove + * any overlapping bits from the copyRegion (since they'd only be + * overwritten anyway). + */ + + sraRgnSubtract(cl->copyRegion,cl->modifiedRegion); + + /* + * The client is interested in the region requestedRegion. The region + * which should be updated now is the intersection of requestedRegion + * and the union of modifiedRegion and copyRegion. If it's empty then + * no update is needed. + */ + + updateRegion = sraRgnCreateRgn(givenUpdateRegion); + if(cl->screen->progressiveSliceHeight>0) { + int height=cl->screen->progressiveSliceHeight, + y=cl->progressiveSliceY; + sraRegionPtr bbox=sraRgnBBox(updateRegion); + sraRect rect; + if(sraRgnPopRect(bbox,&rect,0)) { + sraRegionPtr slice; + if(y=rect.y2) + y=rect.y1; + slice=sraRgnCreateRect(0,y,cl->screen->width,y+height); + sraRgnAnd(updateRegion,slice); + sraRgnDestroy(slice); + } + sraRgnDestroy(bbox); + y+=height; + if(y>=cl->screen->height) + y=0; + cl->progressiveSliceY=y; + } + + sraRgnOr(updateRegion,cl->copyRegion); + if(!sraRgnAnd(updateRegion,cl->requestedRegion) && + sraRgnEmpty(updateRegion) && + (cl->enableCursorShapeUpdates || + (cl->cursorX == cl->screen->cursorX && cl->cursorY == cl->screen->cursorY)) && + !sendCursorShape && !sendCursorPos && !sendKeyboardLedState && + !sendSupportedMessages && !sendSupportedEncodings && !sendServerIdentity) { + sraRgnDestroy(updateRegion); + UNLOCK(cl->updateMutex); + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, TRUE); + return TRUE; + } + + /* + * We assume that the client doesn't have any pixel data outside the + * requestedRegion. In other words, both the source and destination of a + * copy must lie within requestedRegion. So the region we can send as a + * copy is the intersection of the copyRegion with both the requestedRegion + * and the requestedRegion translated by the amount of the copy. We set + * updateCopyRegion to this. + */ + + updateCopyRegion = sraRgnCreateRgn(cl->copyRegion); + sraRgnAnd(updateCopyRegion,cl->requestedRegion); + tmpRegion = sraRgnCreateRgn(cl->requestedRegion); + sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY); + sraRgnAnd(updateCopyRegion,tmpRegion); + sraRgnDestroy(tmpRegion); + dx = cl->copyDX; + dy = cl->copyDY; + + /* + * Next we remove updateCopyRegion from updateRegion so that updateRegion + * is the part of this update which is sent as ordinary pixel data (i.e not + * a copy). + */ + + sraRgnSubtract(updateRegion,updateCopyRegion); + + /* + * Finally we leave modifiedRegion to be the remainder (if any) of parts of + * the screen which are modified but outside the requestedRegion. We also + * empty both the requestedRegion and the copyRegion - note that we never + * carry over a copyRegion for a future update. + */ + + sraRgnOr(cl->modifiedRegion,cl->copyRegion); + sraRgnSubtract(cl->modifiedRegion,updateRegion); + sraRgnSubtract(cl->modifiedRegion,updateCopyRegion); + + sraRgnMakeEmpty(cl->requestedRegion); + sraRgnMakeEmpty(cl->copyRegion); + cl->copyDX = 0; + cl->copyDY = 0; + + UNLOCK(cl->updateMutex); + + if (!cl->enableCursorShapeUpdates) { + if(cl->cursorX != cl->screen->cursorX || cl->cursorY != cl->screen->cursorY) { + rfbRedrawAfterHideCursor(cl,updateRegion); + LOCK(cl->screen->cursorMutex); + cl->cursorX = cl->screen->cursorX; + cl->cursorY = cl->screen->cursorY; + UNLOCK(cl->screen->cursorMutex); + rfbRedrawAfterHideCursor(cl,updateRegion); + } + rfbShowCursor(cl); + } + + /* + * Now send the update. + */ + + rfbStatRecordMessageSent(cl, rfbFramebufferUpdate, 0, 0); + if (cl->preferredEncoding == rfbEncodingCoRRE) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + int rectsPerRow, rows; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + rectsPerRow = (w-1)/cl->correMaxWidth+1; + rows = (h-1)/cl->correMaxHeight+1; + nUpdateRegionRects += rectsPerRow*rows; + } + sraRgnReleaseIterator(i); i=NULL; + } else if (cl->preferredEncoding == rfbEncodingUltra) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + nUpdateRegionRects += (((h-1) / (ULTRA_MAX_SIZE( w ) / w)) + 1); + } + sraRgnReleaseIterator(i); i=NULL; +#ifdef LIBVNCSERVER_HAVE_LIBZ + } else if (cl->preferredEncoding == rfbEncodingZlib) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1); + } + sraRgnReleaseIterator(i); i=NULL; +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + } else if (cl->preferredEncoding == rfbEncodingTight) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + int n; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + n = rfbNumCodedRectsTight(cl, x, y, w, h); + if (n == 0) { + nUpdateRegionRects = 0xFFFF; + break; + } + nUpdateRegionRects += n; + } + sraRgnReleaseIterator(i); i=NULL; +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + } else if (cl->preferredEncoding == rfbEncodingTightPng) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + int n; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + n = rfbNumCodedRectsTight(cl, x, y, w, h); + if (n == 0) { + nUpdateRegionRects = 0xFFFF; + break; + } + nUpdateRegionRects += n; + } + sraRgnReleaseIterator(i); i=NULL; +#endif + } else { + nUpdateRegionRects = sraRgnCountRects(updateRegion); + } + + fu->type = rfbFramebufferUpdate; + if (nUpdateRegionRects != 0xFFFF) { + if(cl->screen->maxRectsPerUpdate>0 + /* CoRRE splits the screen into smaller squares */ + && cl->preferredEncoding != rfbEncodingCoRRE + /* Ultra encoding splits rectangles up into smaller chunks */ + && cl->preferredEncoding != rfbEncodingUltra +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* Zlib encoding splits rectangles up into smaller chunks */ + && cl->preferredEncoding != rfbEncodingZlib +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* Tight encoding counts the rectangles differently */ + && cl->preferredEncoding != rfbEncodingTight +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + /* Tight encoding counts the rectangles differently */ + && cl->preferredEncoding != rfbEncodingTightPng +#endif + && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) { + sraRegion* newUpdateRegion = sraRgnBBox(updateRegion); + sraRgnDestroy(updateRegion); + updateRegion = newUpdateRegion; + nUpdateRegionRects = sraRgnCountRects(updateRegion); + } + fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) + + nUpdateRegionRects + + !!sendCursorShape + !!sendCursorPos + !!sendKeyboardLedState + + !!sendSupportedMessages + !!sendSupportedEncodings + !!sendServerIdentity)); + } else { + fu->nRects = 0xFFFF; + } + cl->ublen = sz_rfbFramebufferUpdateMsg; + + if (sendCursorShape) { + cl->cursorWasChanged = FALSE; + if (!rfbSendCursorShape(cl)) + goto updateFailed; + } + + if (sendCursorPos) { + cl->cursorWasMoved = FALSE; + if (!rfbSendCursorPos(cl)) + goto updateFailed; + } + + if (sendKeyboardLedState) { + if (!rfbSendKeyboardLedState(cl)) + goto updateFailed; + } + + if (sendSupportedMessages) { + if (!rfbSendSupportedMessages(cl)) + goto updateFailed; + } + if (sendSupportedEncodings) { + if (!rfbSendSupportedEncodings(cl)) + goto updateFailed; + } + if (sendServerIdentity) { + if (!rfbSendServerIdentity(cl)) + goto updateFailed; + } + + if (!sraRgnEmpty(updateCopyRegion)) { + if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy)) + goto updateFailed; + } + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + + switch (cl->preferredEncoding) { + case -1: + case rfbEncodingRaw: + if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingRRE: + if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingCoRRE: + if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingHextile: + if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingUltra: + if (!rfbSendRectEncodingUltra(cl, x, y, w, h)) + goto updateFailed; + break; +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZlib: + if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) + goto updateFailed; + break; +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + case rfbEncodingTight: + if (!rfbSendRectEncodingTight(cl, x, y, w, h)) + goto updateFailed; + break; +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + case rfbEncodingTightPng: + if (!rfbSendRectEncodingTightPng(cl, x, y, w, h)) + goto updateFailed; + break; +#endif +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZRLE: + case rfbEncodingZYWRLE: + if (!rfbSendRectEncodingZRLE(cl, x, y, w, h)) + goto updateFailed; + break; +#endif + } + } + if (i) { + sraRgnReleaseIterator(i); + i = NULL; + } + + if ( nUpdateRegionRects == 0xFFFF && + !rfbSendLastRectMarker(cl) ) + goto updateFailed; + + if (!rfbSendUpdateBuf(cl)) { +updateFailed: + result = FALSE; + } + + if (!cl->enableCursorShapeUpdates) { + rfbHideCursor(cl); + } + + if(i) + sraRgnReleaseIterator(i); + sraRgnDestroy(updateRegion); + sraRgnDestroy(updateCopyRegion); + + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, result); + return result; +} + + +/* + * Send the copy region as a string of CopyRect encoded rectangles. + * The only slightly tricky thing is that we should send the messages in + * the correct order so that an earlier CopyRect will not corrupt the source + * of a later one. + */ + +rfbBool +rfbSendCopyRegion(rfbClientPtr cl, + sraRegionPtr reg, + int dx, + int dy) +{ + int x, y, w, h; + rfbFramebufferUpdateRectHeader rect; + rfbCopyRect cr; + sraRectangleIterator* i; + sraRect rect1; + + /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */ + i = sraRgnGetReverseIterator(reg,dx>0,dy>0); + + /* correct for the scale of the screen */ + dx = ScaleX(cl->screen, cl->scaledScreen, dx); + dy = ScaleX(cl->screen, cl->scaledScreen, dy); + + while(sraRgnIteratorNext(i,&rect1)) { + x = rect1.x1; + y = rect1.y1; + w = rect1.x2 - x; + h = rect1.y2 - y; + + /* correct for scaling (if necessary) */ + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "copyrect"); + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingCopyRect); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + cr.srcX = Swap16IfLE(x - dx); + cr.srcY = Swap16IfLE(y - dy); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect); + cl->ublen += sz_rfbCopyRect; + + rfbStatRecordEncodingSent(cl, rfbEncodingCopyRect, sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect, + w * h * (cl->scaledScreen->bitsPerPixel / 8)); + } + sraRgnReleaseIterator(i); + + return TRUE; +} + +/* + * Send a given rectangle in raw encoding (rfbEncodingRaw). + */ + +rfbBool +rfbSendRectEncodingRaw(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + int nlines; + int bytesPerLine = w * (cl->format.bitsPerPixel / 8); + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + /* Flush the buffer to guarantee correct alignment for translateFn(). */ + if (cl->ublen > 0) { + 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(rfbEncodingRaw); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + + rfbStatRecordEncodingSent(cl, rfbEncodingRaw, sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h, + sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h); + + nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine; + + while (TRUE) { + if (nlines > h) + nlines = h; + + (*cl->translateFn)(cl->translateLookupTable, + &(cl->screen->serverFormat), + &cl->format, fbptr, &cl->updateBuf[cl->ublen], + cl->scaledScreen->paddedWidthInBytes, w, nlines); + + cl->ublen += nlines * bytesPerLine; + h -= nlines; + + if (h == 0) /* rect fitted in buffer, do next one */ + return TRUE; + + /* buffer full - flush partial rect and do another nlines */ + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + fbptr += (cl->scaledScreen->paddedWidthInBytes * nlines); + + nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine; + if (nlines == 0) { + rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d " + "bytes per line\n", bytesPerLine); + rfbCloseClient(cl); + return FALSE; + } + } +} + + + +/* + * Send an empty rectangle with encoding field set to value of + * rfbEncodingLastRect to notify client that this is the last + * rectangle in framebuffer update ("LastRect" extension of RFB + * protocol). + */ + +rfbBool +rfbSendLastRectMarker(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingLastRect); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = 0; + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + + rfbStatRecordEncodingSent(cl, rfbEncodingLastRect, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader); + + return TRUE; +} + + +/* + * Send NewFBSize pseudo-rectangle. This tells the client to change + * its framebuffer size. + */ + +rfbBool +rfbSendNewFBSize(rfbClientPtr cl, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + if (cl->PalmVNC==TRUE) + rfbLog("Sending rfbEncodingNewFBSize in response to a PalmVNC style framebuffer resize (%dx%d)\n", w, h); + else + rfbLog("Sending rfbEncodingNewFBSize for resize to (%dx%d)\n", w, h); + + rect.encoding = Swap32IfLE(rfbEncodingNewFBSize); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, rfbEncodingNewFBSize, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader); + + return TRUE; +} + + +/* + * Send the contents of cl->updateBuf. Returns 1 if successful, -1 if + * not (errno should be set). + */ + +rfbBool +rfbSendUpdateBuf(rfbClientPtr cl) +{ + if(cl->sock<0) + return FALSE; + + if (rfbWriteExact(cl, cl->updateBuf, cl->ublen) < 0) { + rfbLogPerror("rfbSendUpdateBuf: write"); + rfbCloseClient(cl); + return FALSE; + } + + cl->ublen = 0; + return TRUE; +} + +/* + * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the + * client, using values from the currently installed colormap. + */ + +rfbBool +rfbSendSetColourMapEntries(rfbClientPtr cl, + int firstColour, + int nColours) +{ + char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; + char *wbuf = buf; + rfbSetColourMapEntriesMsg *scme; + uint16_t *rgb; + rfbColourMap* cm = &cl->screen->colourMap; + int i, len; + + if (nColours > 256) { + /* some rare hardware has, e.g., 4096 colors cells: PseudoColor:12 */ + wbuf = (char *) malloc(sz_rfbSetColourMapEntriesMsg + nColours * 3 * 2); + } + + scme = (rfbSetColourMapEntriesMsg *)wbuf; + rgb = (uint16_t *)(&wbuf[sz_rfbSetColourMapEntriesMsg]); + + scme->type = rfbSetColourMapEntries; + + scme->firstColour = Swap16IfLE(firstColour); + scme->nColours = Swap16IfLE(nColours); + + len = sz_rfbSetColourMapEntriesMsg; + + for (i = 0; i < nColours; i++) { + if(i<(int)cm->count) { + if(cm->is16) { + rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]); + rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]); + rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]); + } else { + rgb[i*3] = Swap16IfLE((unsigned short)cm->data.bytes[i*3]); + rgb[i*3+1] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+1]); + rgb[i*3+2] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+2]); + } + } + } + + len += nColours * 3 * 2; + + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, wbuf, len) < 0) { + rfbLogPerror("rfbSendSetColourMapEntries: write"); + rfbCloseClient(cl); + if (wbuf != buf) free(wbuf); + UNLOCK(cl->sendMutex); + return FALSE; + } + UNLOCK(cl->sendMutex); + + rfbStatRecordMessageSent(cl, rfbSetColourMapEntries, len, len); + if (wbuf != buf) free(wbuf); + return TRUE; +} + +/* + * rfbSendBell sends a Bell message to all the clients. + */ + +void +rfbSendBell(rfbScreenInfoPtr rfbScreen) +{ + rfbClientIteratorPtr i; + rfbClientPtr cl; + rfbBellMsg b; + + i = rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(i))) { + b.type = rfbBell; + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) { + rfbLogPerror("rfbSendBell: write"); + rfbCloseClient(cl); + } + UNLOCK(cl->sendMutex); + } + rfbStatRecordMessageSent(cl, rfbBell, sz_rfbBellMsg, sz_rfbBellMsg); + rfbReleaseClientIterator(i); +} + + +/* + * rfbSendServerCutText sends a ServerCutText message to all the clients. + */ + +void +rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len) +{ + rfbClientPtr cl; + rfbServerCutTextMsg sct; + rfbClientIteratorPtr iterator; + + iterator = rfbGetClientIterator(rfbScreen); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) { + sct.type = rfbServerCutText; + sct.length = Swap32IfLE(len); + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&sct, + sz_rfbServerCutTextMsg) < 0) { + rfbLogPerror("rfbSendServerCutText: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + continue; + } + if (rfbWriteExact(cl, str, len) < 0) { + rfbLogPerror("rfbSendServerCutText: write"); + rfbCloseClient(cl); + } + UNLOCK(cl->sendMutex); + rfbStatRecordMessageSent(cl, rfbServerCutText, sz_rfbServerCutTextMsg+len, sz_rfbServerCutTextMsg+len); + } + rfbReleaseClientIterator(iterator); +} + +/***************************************************************************** + * + * UDP can be used for keyboard and pointer events when the underlying + * network is highly reliable. This is really here to support ORL's + * videotile, whose TCP implementation doesn't like sending lots of small + * packets (such as 100s of pen readings per second!). + */ + +static unsigned char ptrAcceleration = 50; + +void +rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen, + int sock) +{ + if (write(sock, &ptrAcceleration, 1) < 0) { + rfbLogPerror("rfbNewUDPConnection: write"); + } +} + +/* + * Because UDP is a message based service, we can't read the first byte and + * then the rest of the packet separately like we do with TCP. We will always + * get a whole packet delivered in one go, so we ask read() for the maximum + * number of bytes we can possibly get. + */ + +void +rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen) +{ + int n; + rfbClientPtr cl=rfbScreen->udpClient; + rfbClientToServerMsg msg; + + if((!cl) || cl->onHold) + return; + + if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) { + if (n < 0) { + rfbLogPerror("rfbProcessUDPInput: read"); + } + rfbDisconnectUDPSock(rfbScreen); + return; + } + + switch (msg.type) { + + case rfbKeyEvent: + if (n != sz_rfbKeyEventMsg) { + rfbErr("rfbProcessUDPInput: key event incorrect length\n"); + rfbDisconnectUDPSock(rfbScreen); + return; + } + cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl); + break; + + case rfbPointerEvent: + if (n != sz_rfbPointerEventMsg) { + rfbErr("rfbProcessUDPInput: ptr event incorrect length\n"); + rfbDisconnectUDPSock(rfbScreen); + return; + } + cl->screen->ptrAddEvent(msg.pe.buttonMask, + Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl); + break; + + default: + rfbErr("rfbProcessUDPInput: unknown message type %d\n", + msg.type); + rfbDisconnectUDPSock(rfbScreen); + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rre.c new file mode 100755 index 0000000..b43561a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rre.c @@ -0,0 +1,329 @@ +/* + * rre.c + * + * Routines to implement Rise-and-Run-length Encoding (RRE). This + * code is based on krw's original javatel rfbserver. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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 + +/* + * rreBeforeBuf contains pixel data in the client's format. + * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is + * larger than the raw data or if it exceeds rreAfterBufSize then + * raw encoding is used instead. + */ + +static int rreBeforeBufSize = 0; +static char *rreBeforeBuf = NULL; + +static int rreAfterBufSize = 0; +static char *rreAfterBuf = NULL; +static int rreAfterBufLen=0; + +static int subrectEncode8(uint8_t *data, int w, int h); +static int subrectEncode16(uint16_t *data, int w, int h); +static int subrectEncode32(uint32_t *data, int w, int h); +static uint32_t getBgColour(char *data, int size, int bpp); + + +void rfbRRECleanup(rfbScreenInfoPtr screen) +{ + if (rreBeforeBufSize) { + free(rreBeforeBuf); + rreBeforeBufSize=0; + } + if (rreAfterBufSize) { + free(rreAfterBuf); + rreAfterBufSize=0; + } +} + + +/* + * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding. + */ + +rfbBool +rfbSendRectEncodingRRE(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 (rreBeforeBufSize < maxRawSize) { + rreBeforeBufSize = maxRawSize; + if (rreBeforeBuf == NULL) + rreBeforeBuf = (char *)malloc(rreBeforeBufSize); + else + rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize); + } + + if (rreAfterBufSize < maxRawSize) { + rreAfterBufSize = maxRawSize; + if (rreAfterBuf == NULL) + rreAfterBuf = (char *)malloc(rreAfterBufSize); + else + rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize); + } + + (*cl->translateFn)(cl->translateLookupTable, + &(cl->screen->serverFormat), + &cl->format, fbptr, rreBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + switch (cl->format.bitsPerPixel) { + case 8: + nSubrects = subrectEncode8((uint8_t *)rreBeforeBuf, w, h); + break; + case 16: + nSubrects = subrectEncode16((uint16_t *)rreBeforeBuf, w, h); + break; + case 32: + nSubrects = subrectEncode32((uint32_t *)rreBeforeBuf, 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, rfbEncodingRRE, + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + rreAfterBufLen, + 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(rfbEncodingRRE); + + 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 < rreAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > rreAfterBufLen) { + bytesToCopy = rreAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[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 rreAfterBuf. 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 [...] where each + * is []. + */ + +#define DEFINE_SUBRECT_ENCODE(bpp) \ +static int \ +subrectEncode##bpp(uint##bpp##_t *data, int w, int h) { \ + uint##bpp##_t cl; \ + rfbRectangle 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*)rreAfterBuf) = bg; \ + \ + rreAfterBufLen = (bpp/8); \ + \ + for (y=0; y 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 = Swap16IfLE(thex); \ + subrect.y = Swap16IfLE(they); \ + subrect.w = Swap16IfLE(thew); \ + subrect.h = Swap16IfLE(theh); \ + \ + newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \ + if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ + return -1; \ + \ + numsubs += 1; \ + *((uint##bpp##_t*)(rreAfterBuf + rreAfterBufLen)) = cl; \ + rreAfterBufLen += (bpp/8); \ + memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \ + rreAfterBufLen += sz_rfbRectangle; \ + \ + /* \ + * 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) { + rfbErr("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; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.c new file mode 100755 index 0000000..55598fa --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.c @@ -0,0 +1,420 @@ +/* + * scale.c - deal with server-side scaling. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include "private.h" + +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif + +#ifdef WIN32 +#define write(sock,buf,len) send(sock,buf,len,0) +#else +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#endif +#endif + +#ifdef CORBA +#include +#endif + +#ifdef DEBUGPROTO +#undef DEBUGPROTO +#define DEBUGPROTO(x) x +#else +#define DEBUGPROTO(x) +#endif + +/****************************/ +#define CEIL(x) ( (double) ((int) (x)) == (x) ? \ + (double) ((int) (x)) : (double) ((int) (x) + 1) ) +#define FLOOR(x) ( (double) ((int) (x)) ) + + +int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x) +{ + if ((from==to) || (from==NULL) || (to==NULL)) return x; + return ((int)(((double) x / (double)from->width) * (double)to->width )); +} + +int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y) +{ + if ((from==to) || (from==NULL) || (to==NULL)) return y; + return ((int)(((double) y / (double)from->height) * (double)to->height )); +} + +/* So, all of the encodings point to the ->screen->frameBuffer, + * We need to change this! + */ +void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, char *function) +{ + double x1,y1,w1,h1, x2, y2, w2, h2; + double scaleW = ((double) to->width) / ((double) from->width); + double scaleH = ((double) to->height) / ((double) from->height); + + + /* + * rfbLog("rfbScaledCorrection(%p -> %p, %dx%d->%dx%d (%dXx%dY-%dWx%dH)\n", + * from, to, from->width, from->height, to->width, to->height, *x, *y, *w, *h); + */ + + /* If it's the original framebuffer... */ + if (from==to) return; + + x1 = ((double) *x) * scaleW; + y1 = ((double) *y) * scaleH; + w1 = ((double) *w) * scaleW; + h1 = ((double) *h) * scaleH; + + + /*cast from double to int is same as "*x = floor(x1);" */ + x2 = FLOOR(x1); + y2 = FLOOR(y1); + + /* include into W and H the jitter of scaling X and Y */ + w2 = CEIL(w1 + ( x1 - x2 )); + h2 = CEIL(h1 + ( y1 - y2 )); + + /* + * rfbLog("%s (%dXx%dY-%dWx%dH -> %fXx%fY-%fWx%fH) {%dWx%dH -> %dWx%dH}\n", + * function, *x, *y, *w, *h, x2, y2, w2, h2, + * from->width, from->height, to->width, to->height); + */ + + /* simulate ceil() without math library */ + *x = (int)x2; + *y = (int)y2; + *w = (int)w2; + *h = (int)h2; + + /* Small changes for a thumbnail may be scaled to zero */ + if (*w==0) (*w)++; + if (*h==0) (*h)++; + /* scaling from small to big may overstep the size a bit */ + if (*x+*w > to->width) *w=to->width - *x; + if (*y+*h > to->height) *h=to->height - *y; +} + +void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0) +{ + int x,y,w,v,z; + int x1, y1, w1, h1; + int bitsPerPixel, bytesPerPixel, bytesPerLine, areaX, areaY, area2; + unsigned char *srcptr, *dstptr; + + /* Nothing to do!!! */ + if (screen==ptr) return; + + x1 = x0; + y1 = y0; + w1 = w0; + h1 = h0; + + rfbScaledCorrection(screen, ptr, &x1, &y1, &w1, &h1, "rfbScaledScreenUpdateRect"); + x0 = ScaleX(ptr, screen, x1); + y0 = ScaleY(ptr, screen, y1); + w0 = ScaleX(ptr, screen, w1); + h0 = ScaleY(ptr, screen, h1); + + bitsPerPixel = screen->bitsPerPixel; + bytesPerPixel = bitsPerPixel / 8; + bytesPerLine = w1 * bytesPerPixel; + srcptr = (unsigned char *)(screen->frameBuffer + + (y0 * screen->paddedWidthInBytes + x0 * bytesPerPixel)); + dstptr = (unsigned char *)(ptr->frameBuffer + + ( y1 * ptr->paddedWidthInBytes + x1 * bytesPerPixel)); + /* The area of the source framebuffer for each destination pixel */ + areaX = ScaleX(ptr,screen,1); + areaY = ScaleY(ptr,screen,1); + area2 = areaX*areaY; + + + /* Ensure that we do not go out of bounds */ + if ((x1+w1) > (ptr->width)) + { + if (x1==0) w1=ptr->width; else x1 = ptr->width - w1; + } + if ((y1+h1) > (ptr->height)) + { + if (y1==0) h1=ptr->height; else y1 = ptr->height - h1; + } + /* + * rfbLog("rfbScaledScreenUpdateRect(%dXx%dY-%dWx%dH -> %dXx%dY-%dWx%dH <%dx%d>) {%dWx%dH -> %dWx%dH} 0x%p\n", + * x0, y0, w0, h0, x1, y1, w1, h1, areaX, areaY, + * screen->width, screen->height, ptr->width, ptr->height, ptr->frameBuffer); + */ + + if (screen->serverFormat.trueColour) { /* Blend neighbouring pixels together */ + unsigned char *srcptr2; + unsigned long pixel_value, red, green, blue; + unsigned int redShift = screen->serverFormat.redShift; + unsigned int greenShift = screen->serverFormat.greenShift; + unsigned int blueShift = screen->serverFormat.blueShift; + unsigned long redMax = screen->serverFormat.redMax; + unsigned long greenMax = screen->serverFormat.greenMax; + unsigned long blueMax = screen->serverFormat.blueMax; + + /* for each *destination* pixel... */ + for (y = 0; y < h1; y++) { + for (x = 0; x < w1; x++) { + red = green = blue = 0; + /* Get the totals for rgb from the source grid... */ + for (w = 0; w < areaX; w++) { + for (v = 0; v < areaY; v++) { + srcptr2 = &srcptr[(((x * areaX) + w) * bytesPerPixel) + + (v * screen->paddedWidthInBytes)]; + pixel_value = 0; + + + switch (bytesPerPixel) { + case 4: pixel_value = *((unsigned int *)srcptr2); break; + case 2: pixel_value = *((unsigned short *)srcptr2); break; + case 1: pixel_value = *((unsigned char *)srcptr2); break; + default: + /* fixme: endianess problem? */ + for (z = 0; z < bytesPerPixel; z++) + pixel_value += (srcptr2[z] << (8 * z)); + break; + } + /* + srcptr2 += bytesPerPixel; + */ + + red += ((pixel_value >> redShift) & redMax); + green += ((pixel_value >> greenShift) & greenMax); + blue += ((pixel_value >> blueShift) & blueMax); + + } + } + /* We now have a total for all of the colors, find the average! */ + red /= area2; + green /= area2; + blue /= area2; + /* Stuff the new value back into memory */ + pixel_value = ((red & redMax) << redShift) | ((green & greenMax) << greenShift) | ((blue & blueMax) << blueShift); + + switch (bytesPerPixel) { + case 4: *((unsigned int *)dstptr) = (unsigned int) pixel_value; break; + case 2: *((unsigned short *)dstptr) = (unsigned short) pixel_value; break; + case 1: *((unsigned char *)dstptr) = (unsigned char) pixel_value; break; + default: + /* fixme: endianess problem? */ + for (z = 0; z < bytesPerPixel; z++) + dstptr[z]=(pixel_value >> (8 * z)) & 0xff; + break; + } + dstptr += bytesPerPixel; + } + srcptr += (screen->paddedWidthInBytes * areaY); + dstptr += (ptr->paddedWidthInBytes - bytesPerLine); + } + } else + { /* Not truecolour, so we can't blend. Just use the top-left pixel instead */ + for (y = y1; y < (y1+h1); y++) { + for (x = x1; x < (x1+w1); x++) + memcpy (&ptr->frameBuffer[(y *ptr->paddedWidthInBytes) + (x * bytesPerPixel)], + &screen->frameBuffer[(y * areaY * screen->paddedWidthInBytes) + (x *areaX * bytesPerPixel)], bytesPerPixel); + } + } +} + +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2) +{ + /* ok, now the task is to update each and every scaled version of the framebuffer + * and we only have to do this for this specific changed rectangle! + */ + rfbScreenInfoPtr ptr; + int count=0; + + /* We don't point to cl->screen as it is the original */ + for (ptr=screen->scaledScreenNext;ptr!=NULL;ptr=ptr->scaledScreenNext) + { + /* Only update if it has active clients... */ + if (ptr->scaledScreenRefCount>0) + { + rfbScaledScreenUpdateRect(screen, ptr, x1, y1, x2-x1, y2-y1); + count++; + } + } +} + +/* Create a new scaled version of the framebuffer */ +rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + ptr = malloc(sizeof(rfbScreenInfo)); + if (ptr!=NULL) + { + /* copy *everything* (we don't use most of it, but just in case) */ + memcpy(ptr, cl->screen, sizeof(rfbScreenInfo)); + ptr->width = width; + ptr->height = height; + ptr->paddedWidthInBytes = (ptr->bitsPerPixel/8)*ptr->width; + + /* Need to by multiples of 4 for Sparc systems */ + ptr->paddedWidthInBytes += (ptr->paddedWidthInBytes % 4); + + /* Reset the reference count to 0! */ + ptr->scaledScreenRefCount = 0; + + ptr->sizeInBytes = ptr->paddedWidthInBytes * ptr->height; + ptr->serverFormat = cl->screen->serverFormat; + + ptr->frameBuffer = malloc(ptr->sizeInBytes); + if (ptr->frameBuffer!=NULL) + { + /* Reset to a known condition: scale the entire framebuffer */ + rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); + /* Now, insert into the chain */ + LOCK(cl->updateMutex); + ptr->scaledScreenNext = cl->screen->scaledScreenNext; + cl->screen->scaledScreenNext = ptr; + UNLOCK(cl->updateMutex); + } + else + { + /* Failed to malloc the new frameBuffer, cleanup */ + free(ptr); + ptr=NULL; + } + } + return ptr; +} + +/* Find an active scaled version of the framebuffer + * TODO: implement a refcount per scaled screen to prevent + * unreferenced scaled screens from hanging around + */ +rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + /* include the original in the search (ie: fine 1:1 scaled version of the frameBuffer) */ + for (ptr=cl->screen; ptr!=NULL; ptr=ptr->scaledScreenNext) + { + if ((ptr->width==width) && (ptr->height==height)) + return ptr; + } + return NULL; +} + +/* Future needs "scale to 320x240, as that's the client's screen size */ +void rfbScalingSetup(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + + ptr = rfbScalingFind(cl,width,height); + if (ptr==NULL) + ptr = rfbScaledScreenAllocate(cl,width,height); + /* Now, there is a new screen available (if ptr is not NULL) */ + if (ptr!=NULL) + { + /* Update it! */ + if (ptr->scaledScreenRefCount<1) + rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); + /* + * rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n", + * cl->scaledScreen->width, cl->scaledScreen->height, + * cl->scaledScreen->scaledScreenRefCount, + * ptr->width, ptr->height, ptr->scaledScreenRefCount); + */ + + LOCK(cl->updateMutex); + cl->scaledScreen->scaledScreenRefCount--; + ptr->scaledScreenRefCount++; + cl->scaledScreen=ptr; + cl->newFBSizePending = TRUE; + UNLOCK(cl->updateMutex); + + rfbLog("Scaling to %dx%d (refcount=%d)\n",width,height,ptr->scaledScreenRefCount); + } + else + rfbLog("Scaling to %dx%d failed, leaving things alone\n",width,height); +} + +int rfbSendNewScaleSize(rfbClientPtr cl) +{ + /* if the client supports newFBsize Encoding, use it */ + if (cl->useNewFBSize && cl->newFBSizePending) + return FALSE; + + LOCK(cl->updateMutex); + cl->newFBSizePending = FALSE; + UNLOCK(cl->updateMutex); + + if (cl->PalmVNC==TRUE) + { + rfbPalmVNCReSizeFrameBufferMsg pmsg; + pmsg.type = rfbPalmVNCReSizeFrameBuffer; + pmsg.pad1 = 0; + pmsg.desktop_w = Swap16IfLE(cl->screen->width); + pmsg.desktop_h = Swap16IfLE(cl->screen->height); + pmsg.buffer_w = Swap16IfLE(cl->scaledScreen->width); + pmsg.buffer_h = Swap16IfLE(cl->scaledScreen->height); + pmsg.pad2 = 0; + + rfbLog("Sending a response to a PalmVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); + if (rfbWriteExact(cl, (char *)&pmsg, sz_rfbPalmVNCReSizeFrameBufferMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return FALSE; + } + } + else + { + rfbResizeFrameBufferMsg rmsg; + rmsg.type = rfbResizeFrameBuffer; + rmsg.pad1=0; + rmsg.framebufferWidth = Swap16IfLE(cl->scaledScreen->width); + rmsg.framebufferHeigth = Swap16IfLE(cl->scaledScreen->height); + rfbLog("Sending a response to a UltraVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); + if (rfbWriteExact(cl, (char *)&rmsg, sz_rfbResizeFrameBufferMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return FALSE; + } + } + return TRUE; +} +/****************************/ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.h new file mode 100755 index 0000000..13dd942 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.h @@ -0,0 +1,10 @@ + +int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x); +int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y); +void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, char *function); +void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0); +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2); +rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height); +rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height); +void rfbScalingSetup(rfbClientPtr cl, int width, int height); +int rfbSendNewScaleSize(rfbClientPtr cl); diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/selbox.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/selbox.c new file mode 100755 index 0000000..bbc6d52 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/selbox.c @@ -0,0 +1,300 @@ +#include +#include +#include + +typedef struct { + rfbScreenInfoPtr screen; + rfbFontDataPtr font; + char** list; + int listSize; + int selected; + int displayStart; + int x1,y1,x2,y2,textH,pageH; + int xhot,yhot; + int buttonWidth,okBX,cancelBX,okX,cancelX,okY; + rfbBool okInverted,cancelInverted; + int lastButtons; + rfbPixel colour,backColour; + SelectionChangedHookPtr selChangedHook; + enum { SELECTING, OK, CANCEL } state; +} rfbSelectData; + +static const char* okStr="OK"; +static const char* cancelStr="Cancel"; + +static void selPaintButtons(rfbSelectData* m,rfbBool invertOk,rfbBool invertCancel) +{ + rfbScreenInfoPtr s = m->screen; + rfbPixel bcolour = m->backColour; + rfbPixel colour = m->colour; + + rfbFillRect(s,m->x1,m->okY-m->textH,m->x2,m->okY,bcolour); + + if(invertOk) { + rfbFillRect(s,m->okBX,m->okY-m->textH,m->okBX+m->buttonWidth,m->okY,colour); + rfbDrawStringWithClip(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr, + m->x1,m->okY-m->textH,m->x2,m->okY, + bcolour,colour); + } else + rfbDrawString(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,colour); + + if(invertCancel) { + rfbFillRect(s,m->cancelBX,m->okY-m->textH, + m->cancelBX+m->buttonWidth,m->okY,colour); + rfbDrawStringWithClip(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot, + cancelStr,m->x1,m->okY-m->textH,m->x2,m->okY, + bcolour,colour); + } else + rfbDrawString(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,cancelStr,colour); + + m->okInverted = invertOk; + m->cancelInverted = invertCancel; +} + +/* line is relative to displayStart */ +static void selPaintLine(rfbSelectData* m,int line,rfbBool invert) +{ + int y1 = m->y1+line*m->textH, y2 = y1+m->textH; + if(y2>m->y2) + y2=m->y2; + rfbFillRect(m->screen,m->x1,y1,m->x2,y2,invert?m->colour:m->backColour); + if(m->displayStart+linelistSize) + rfbDrawStringWithClip(m->screen,m->font,m->x1+m->xhot,y2-1+m->yhot, + m->list[m->displayStart+line], + m->x1,y1,m->x2,y2, + invert?m->backColour:m->colour, + invert?m->backColour:m->colour); +} + +static void selSelect(rfbSelectData* m,int _index) +{ + int delta; + + if(_index==m->selected || _index<0 || _index>=m->listSize) + return; + + if(m->selected>=0) + selPaintLine(m,m->selected-m->displayStart,FALSE); + + if(_indexdisplayStart || _index>=m->displayStart+m->pageH) { + /* targetLine is the screen line in which the selected line will + be displayed. + targetLine = m->pageH/2 doesn't look so nice */ + int targetLine = m->selected-m->displayStart; + int lineStart,lineEnd; + + /* scroll */ + if(_indexpageH-targetLine>=m->listSize) + targetLine = _index+m->pageH-m->listSize; + delta = _index-(m->displayStart+targetLine); + + if(delta>-m->pageH && deltapageH) { + if(delta>0) { + lineStart = m->pageH-delta; + lineEnd = m->pageH; + rfbDoCopyRect(m->screen,m->x1,m->y1,m->x2,m->y1+lineStart*m->textH, + 0,-delta*m->textH); + } else { + lineStart = 0; + lineEnd = -delta; + rfbDoCopyRect(m->screen, + m->x1,m->y1+lineEnd*m->textH,m->x2,m->y2, + 0,-delta*m->textH); + } + } else { + lineStart = 0; + lineEnd = m->pageH; + } + m->displayStart += delta; + for(delta=lineStart;deltaselected = _index; + selPaintLine(m,m->selected-m->displayStart,TRUE); + + if(m->selChangedHook) + m->selChangedHook(_index); + + /* todo: scrollbars */ +} + +static void selKbdAddEvent(rfbBool down,rfbKeySym keySym,rfbClientPtr cl) +{ + if(down) { + if(keySym>' ' && keySym<0xff) { + int i; + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + char c = tolower(keySym); + + for(i=m->selected+1;m->list[i] && tolower(m->list[i][0])!=c;i++); + if(!m->list[i]) + for(i=0;iselected && tolower(m->list[i][0])!=c;i++); + selSelect(m,i); + } else if(keySym==XK_Escape) { + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + m->state = CANCEL; + } else if(keySym==XK_Return) { + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + m->state = OK; + } else { + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + int curSel=m->selected; + if(keySym==XK_Up) { + if(curSel>0) + selSelect(m,curSel-1); + } else if(keySym==XK_Down) { + if(curSel+1listSize) + selSelect(m,curSel+1); + } else { + if(keySym==XK_Page_Down) { + if(curSel+m->pageHlistSize) + selSelect(m,curSel+m->pageH); + else + selSelect(m,m->listSize-1); + } else if(keySym==XK_Page_Up) { + if(curSel-m->pageH>=0) + selSelect(m,curSel-m->pageH); + else + selSelect(m,0); + } + } + } + } +} + +static void selPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl) +{ + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + if(yokY && y>=m->okY-m->textH) { + if(x>=m->okBX && xokBX+m->buttonWidth) { + if(!m->okInverted) + selPaintButtons(m,TRUE,FALSE); + if(buttonMask) + m->state = OK; + } else if(x>=m->cancelBX && xcancelBX+m->buttonWidth) { + if(!m->cancelInverted) + selPaintButtons(m,FALSE,TRUE); + if(buttonMask) + m->state = CANCEL; + } else if(m->okInverted || m->cancelInverted) + selPaintButtons(m,FALSE,FALSE); + } else { + if(m->okInverted || m->cancelInverted) + selPaintButtons(m,FALSE,FALSE); + if(!m->lastButtons && buttonMask) { + if(x>=m->x1 && xx2 && y>=m->y1 && yy2) + selSelect(m,m->displayStart+(y-m->y1)/m->textH); + } + } + m->lastButtons = buttonMask; + + /* todo: scrollbars */ +} + +static rfbCursorPtr selGetCursorPtr(rfbClientPtr cl) +{ + return NULL; +} + +int rfbSelectBox(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + char** list, + int x1,int y1,int x2,int y2, + rfbPixel colour,rfbPixel backColour, + int border,SelectionChangedHookPtr selChangedHook) +{ + int bpp = rfbScreen->bitsPerPixel/8; + char* frameBufferBackup; + void* screenDataBackup = rfbScreen->screenData; + rfbKbdAddEventProcPtr kbdAddEventBackup = rfbScreen->kbdAddEvent; + rfbPtrAddEventProcPtr ptrAddEventBackup = rfbScreen->ptrAddEvent; + rfbGetCursorProcPtr getCursorPtrBackup = rfbScreen->getCursorPtr; + rfbDisplayHookPtr displayHookBackup = rfbScreen->displayHook; + rfbSelectData selData; + int i,j,k; + int fx1,fy1,fx2,fy2; /* for font bbox */ + + if(list==0 || *list==0) + return(-1); + + rfbWholeFontBBox(font, &fx1, &fy1, &fx2, &fy2); + selData.textH = fy2-fy1; + /* I need at least one line for the choice and one for the buttons */ + if(y2-y1screenData = &selData; + rfbScreen->kbdAddEvent = selKbdAddEvent; + rfbScreen->ptrAddEvent = selPtrAddEvent; + rfbScreen->getCursorPtr = selGetCursorPtr; + rfbScreen->displayHook = NULL; + + /* backup screen */ + for(j=0;jframeBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp, + (x2-x1)*bpp); + + /* paint list and buttons */ + rfbFillRect(rfbScreen,x1,y1,x2,y2,colour); + selPaintButtons(&selData,FALSE,FALSE); + selSelect(&selData,0); + + /* modal loop */ + while(selData.state == SELECTING) + rfbProcessEvents(rfbScreen,20000); + + /* copy back screen data */ + for(j=0;jframeBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp, + frameBufferBackup+j*(x2-x1)*bpp, + (x2-x1)*bpp); + free(frameBufferBackup); + rfbMarkRectAsModified(rfbScreen,x1,y1,x2,y2); + rfbScreen->screenData = screenDataBackup; + rfbScreen->kbdAddEvent = kbdAddEventBackup; + rfbScreen->ptrAddEvent = ptrAddEventBackup; + rfbScreen->getCursorPtr = getCursorPtrBackup; + rfbScreen->displayHook = displayHookBackup; + + if(selData.state==CANCEL) + selData.selected=-1; + return(selData.selected); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/sockets.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/sockets.c new file mode 100755 index 0000000..c95225f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/sockets.c @@ -0,0 +1,822 @@ +/* + * sockets.c - deal with TCP & UDP sockets. + * + * This code should be independent of any changes in the RFB protocol. It just + * deals with the X server scheduling stuff, calling rfbNewClientConnection and + * rfbProcessClientMessage to actually deal with the protocol. If a socket + * needs to be closed for any reason then rfbCloseClient should be called, and + * this in turn will call rfbClientConnectionGone. To make an active + * connection out, call rfbConnect - note that this does _not_ call + * rfbNewClientConnection. + * + * This file is divided into two types of function. Those beginning with + * "rfb" are specific to sockets using the RFB protocol. Those without the + * "rfb" prefix are more general socket routines (which are used by the http + * code). + * + * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN + * not EWOULDBLOCK. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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 + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#include +#endif +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif + +#if defined(__linux__) && defined(NEED_TIMEVAL) +struct timeval +{ + long int tv_sec,tv_usec; +} +; +#endif + +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif + +#include + +#ifdef USE_LIBWRAP +#include +#include +int allow_severity=LOG_INFO; +int deny_severity=LOG_WARNING; +#endif + +#if defined(WIN32) +#ifndef __MINGW32__ +#pragma warning (disable: 4018 4761) +#endif +#define read(sock,buf,len) recv(sock,buf,len,0) +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ETIMEDOUT WSAETIMEDOUT +#define write(sock,buf,len) send(sock,buf,len,0) +#else +#define closesocket close +#endif + +int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has + gone away - needed to stop us hanging */ + +/* + * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB + * connections. It does nothing if called again. + */ + +void +rfbInitSockets(rfbScreenInfoPtr rfbScreen) +{ + in_addr_t iface = rfbScreen->listenInterface; + + if (rfbScreen->socketState!=RFB_SOCKET_INIT) + return; + + rfbScreen->socketState = RFB_SOCKET_READY; + + if (rfbScreen->inetdSock != -1) { + const int one = 1; + +#ifndef WIN32 + if (fcntl(rfbScreen->inetdSock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("fcntl"); + return; + } +#endif + + if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("setsockopt"); + return; + } + + FD_ZERO(&(rfbScreen->allFds)); + FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->inetdSock; + return; + } + + if(rfbScreen->autoPort) { + int i; + rfbLog("Autoprobing TCP port \n"); + for (i = 5900; i < 6000; i++) { + if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) { + rfbScreen->port = i; + break; + } + } + + if (i >= 6000) { + rfbLogPerror("Failure autoprobing"); + return; + } + + rfbLog("Autoprobing selected port %d\n", rfbScreen->port); + FD_ZERO(&(rfbScreen->allFds)); + FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->listenSock; + } + else if(rfbScreen->port>0) { + rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port); + + if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) { + rfbLogPerror("ListenOnTCPPort"); + return; + } + + FD_ZERO(&(rfbScreen->allFds)); + FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->listenSock; + } + + if (rfbScreen->udpPort != 0) { + rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort); + + if ((rfbScreen->udpSock = rfbListenOnUDPPort(rfbScreen->udpPort, iface)) < 0) { + rfbLogPerror("ListenOnUDPPort"); + return; + } + FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd); + } +} + +void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen) +{ + if (rfbScreen->socketState!=RFB_SOCKET_READY) + return; + + rfbScreen->socketState = RFB_SOCKET_SHUTDOWN; + + if(rfbScreen->inetdSock>-1) { + closesocket(rfbScreen->inetdSock); + FD_CLR(rfbScreen->inetdSock,&rfbScreen->allFds); + rfbScreen->inetdSock=-1; + } + + if(rfbScreen->listenSock>-1) { + closesocket(rfbScreen->listenSock); + FD_CLR(rfbScreen->listenSock,&rfbScreen->allFds); + rfbScreen->listenSock=-1; + } + + if(rfbScreen->udpSock>-1) { + closesocket(rfbScreen->udpSock); + FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds); + rfbScreen->udpSock=-1; + } +} + +/* + * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB + * socket(s). If there is input to process, the appropriate function in the + * RFB server code will be called (rfbNewClientConnection, + * rfbProcessClientMessage, etc). + */ + +int +rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) +{ + int nfds; + fd_set fds; + struct timeval tv; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + char buf[6]; + const int one = 1; + int sock; + rfbClientIteratorPtr i; + rfbClientPtr cl; + int result = 0; + + if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { + rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); + rfbScreen->inetdInitDone = TRUE; + } + + do { + memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set)); + tv.tv_sec = 0; + tv.tv_usec = usec; + nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv); + if (nfds == 0) { + /* timed out, check for async events */ + i = rfbGetClientIterator(rfbScreen); + while((cl = rfbClientIteratorNext(i))) { + if (cl->onHold) + continue; + if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) + rfbSendFileTransferChunk(cl); + } + rfbReleaseClientIterator(i); + return result; + } + + if (nfds < 0) { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno != EINTR) + rfbLogPerror("rfbCheckFds: select"); + return -1; + } + + result += nfds; + + if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) { + + if ((sock = accept(rfbScreen->listenSock, + (struct sockaddr *)&addr, &addrlen)) < 0) { + rfbLogPerror("rfbCheckFds: accept"); + return -1; + } + +#ifndef WIN32 + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("rfbCheckFds: fcntl"); + closesocket(sock); + return -1; + } +#endif + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("rfbCheckFds: setsockopt"); + closesocket(sock); + return -1; + } + +#ifdef USE_LIBWRAP + if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), + STRING_UNKNOWN)) { + rfbLog("Rejected connection from client %s\n", + inet_ntoa(addr.sin_addr)); + closesocket(sock); + return -1; + } +#endif + + rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); + + rfbNewClient(rfbScreen,sock); + + FD_CLR(rfbScreen->listenSock, &fds); + if (--nfds == 0) + return result; + } + + if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) { + if(!rfbScreen->udpClient) + rfbNewUDPClient(rfbScreen); + if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK, + (struct sockaddr *)&addr, &addrlen) < 0) { + rfbLogPerror("rfbCheckFds: UDP: recvfrom"); + rfbDisconnectUDPSock(rfbScreen); + rfbScreen->udpSockConnected = FALSE; + } else { + if (!rfbScreen->udpSockConnected || + (memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0)) + { + /* new remote end */ + rfbLog("rfbCheckFds: UDP: got connection\n"); + + memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen); + rfbScreen->udpSockConnected = TRUE; + + if (connect(rfbScreen->udpSock, + (struct sockaddr *)&addr, addrlen) < 0) { + rfbLogPerror("rfbCheckFds: UDP: connect"); + rfbDisconnectUDPSock(rfbScreen); + return -1; + } + + rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock); + } + + rfbProcessUDPInput(rfbScreen); + } + + FD_CLR(rfbScreen->udpSock, &fds); + if (--nfds == 0) + return result; + } + + i = rfbGetClientIterator(rfbScreen); + while((cl = rfbClientIteratorNext(i))) { + + if (cl->onHold) + continue; + + if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) + { + if (FD_ISSET(cl->sock, &fds)) + rfbProcessClientMessage(cl); + else + rfbSendFileTransferChunk(cl); + } + } + rfbReleaseClientIterator(i); + } while(rfbScreen->handleEventsEagerly); + return result; +} + + +void +rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen) +{ + rfbScreen->udpSockConnected = FALSE; +} + + + +void +rfbCloseClient(rfbClientPtr cl) +{ + rfbExtensionData* extension; + + for(extension=cl->extensions; extension; extension=extension->next) + if(extension->extension->close) + extension->extension->close(cl, extension->data); + + LOCK(cl->updateMutex); +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if (cl->sock != -1) +#endif + { + FD_CLR(cl->sock,&(cl->screen->allFds)); + if(cl->sock==cl->screen->maxFd) + while(cl->screen->maxFd>0 + && !FD_ISSET(cl->screen->maxFd,&(cl->screen->allFds))) + cl->screen->maxFd--; +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) { + SSL_free(cl->ssl); + } + if (cl->ssl_ctx) { + SSL_CTX_free(cl->ssl_ctx); + } +#endif +#ifndef __MINGW32__ + shutdown(cl->sock,SHUT_RDWR); +#endif + closesocket(cl->sock); + cl->sock = -1; + } + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); +} + + +/* + * rfbConnect is called to make a connection out to a given TCP address. + */ + +int +rfbConnect(rfbScreenInfoPtr rfbScreen, + char *host, + int port) +{ + int sock; + int one = 1; + + rfbLog("Making connection to client on host %s port %d\n", + host,port); + + if ((sock = rfbConnectToTcpAddr(host, port)) < 0) { + rfbLogPerror("connection failed"); + return -1; + } + +#ifndef WIN32 + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("fcntl failed"); + closesocket(sock); + return -1; + } +#endif + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("setsockopt failed"); + closesocket(sock); + return -1; + } + + /* AddEnabledDevice(sock); */ + FD_SET(sock, &rfbScreen->allFds); + rfbScreen->maxFd = max(sock,rfbScreen->maxFd); + + return sock; +} + +/* + * ReadExact reads an exact number of bytes from a client. Returns 1 if + * those bytes have been read, 0 if the other end has closed, or -1 if an error + * occurred (errno is set to ETIMEDOUT if it timed out). + */ + +int +rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout) +{ +// rfbLog(">> rfbReadExactTimeout, len: %d\n", len); + int sock = cl->sock; + int n; + char *end; + fd_set fds; + struct timeval tv; + + while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->webSockets) { + n = webSocketsDecode(cl, buf, len); + } else if (cl->ssl) { + n = SSL_read(cl->ssl, buf, len); + } else { + n = read(sock, buf, len); + } +#else + n = read(sock, buf, len); +#endif + + if (n > 0) { + + buf += n; + len -= n; + + } else if (n == 0) { + + return 0; + + } else { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno == EINTR) + continue; + +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + if (errno != ENOENT) +#endif + if (errno != EWOULDBLOCK && errno != EAGAIN) { + return n; + } + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) { + if (SSL_pending(cl->ssl)) + continue; + } +#endif + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + n = select(sock+1, &fds, NULL, &fds, &tv); + if (n < 0) { + rfbLogPerror("ReadExact: select"); + return n; + } + if (n == 0) { + errno = ETIMEDOUT; + return -1; + } + } + } + +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + rfbLog("ReadExact %d bytes\n",len); + for(n=0;nsock; + int n; + fd_set fds; + struct timeval tv; + + while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) + n = SSL_peek(cl->ssl, buf, len); + else + n = recv(sock, buf, len, MSG_PEEK); +#endif + if (n == len) { + + break; + + } else if (n == 0) { + + return 0; + + } else { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno == EINTR) + continue; + +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + if (errno != ENOENT) +#endif + if (errno != EWOULDBLOCK && errno != EAGAIN) { + return n; + } + + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + n = select(sock+1, &fds, NULL, &fds, &tv); + if (n < 0) { + rfbLogPerror("ReadExact: select"); + return n; + } + if (n == 0) { + errno = ETIMEDOUT; + return -1; + } + } + } +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + rfbLog("ReadExact %d bytes\n",len); + for(n=0;n> rfbWriteExact, len: %d\n", len); + int sock = cl->sock; + int n; + fd_set fds; + struct timeval tv; + int totalTimeWaited = 0; + +#undef DEBUG_WRITE_EXACT +#ifdef DEBUG_WRITE_EXACT + rfbLog("WriteExact %d bytes\n",len); + for(n=0;nwebSockets) { + if ((len = webSocketsEncode(cl, buf, len)) < 0) { + rfbErr("WriteExact: WebSockets encode error\n"); + return -1; + } + buf = cl->encodeBuf; + } +#endif + + LOCK(cl->outputMutex); + while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) { + n = SSL_write(cl->ssl, buf, len); + } else { + n = write(sock, buf, len); + } +#endif + + if (n > 0) { + + buf += n; + len -= n; + + } else if (n == 0) { + + rfbErr("WriteExact: write returned 0?\n"); + return 0; + + } else { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno == EINTR) + continue; + + if (errno != EWOULDBLOCK && errno != EAGAIN) { + UNLOCK(cl->outputMutex); + return n; + } + + /* Retry every 5 seconds until we exceed rfbMaxClientWait. We + need to do this because select doesn't necessarily return + immediately when the other end has gone away */ + + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = 5; + tv.tv_usec = 0; + n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv); + if (n < 0) { + if(errno==EINTR) + continue; + rfbLogPerror("WriteExact: select"); + UNLOCK(cl->outputMutex); + return n; + } + if (n == 0) { + totalTimeWaited += 5000; + if (totalTimeWaited >= rfbMaxClientWait) { + errno = ETIMEDOUT; + UNLOCK(cl->outputMutex); + return -1; + } + } else { + totalTimeWaited = 0; + } + } + } + UNLOCK(cl->outputMutex); +// rfbLog("<< rfbWriteExact, len: %d\n", len); + return 1; +} + +/* currently private, called by rfbProcessArguments() */ +int +rfbStringToAddr(char *str, in_addr_t *addr) { + if (str == NULL || *str == '\0' || strcmp(str, "any") == 0) { + *addr = htonl(INADDR_ANY); + } else if (strcmp(str, "localhost") == 0) { + *addr = htonl(INADDR_LOOPBACK); + } else { + struct hostent *hp; + if ((*addr = inet_addr(str)) == htonl(INADDR_NONE)) { + if (!(hp = gethostbyname(str))) { + return 0; + } + *addr = *(unsigned long *)hp->h_addr; + } + } + return 1; +} + +int +rfbListenOnTCPPort(int port, + in_addr_t iface) +{ + struct sockaddr_in addr; + int sock; + int one = 1; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = iface; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return -1; + } + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&one, sizeof(one)) < 0) { + closesocket(sock); + return -1; + } + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + closesocket(sock); + return -1; + } + if (listen(sock, 32) < 0) { + closesocket(sock); + return -1; + } + + return sock; +} + +int +rfbConnectToTcpAddr(char *host, + int port) +{ + struct hostent *hp; + int sock; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if ((addr.sin_addr.s_addr = inet_addr(host)) == htonl(INADDR_NONE)) + { + if (!(hp = gethostbyname(host))) { + errno = EINVAL; + return -1; + } + addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr; + } + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) { + closesocket(sock); + return -1; + } + + return sock; +} + +int +rfbListenOnUDPPort(int port, + in_addr_t iface) +{ + struct sockaddr_in addr; + int sock; + int one = 1; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = iface; + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + return -1; + } + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&one, sizeof(one)) < 0) { + return -1; + } + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + return -1; + } + + return sock; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/stats.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/stats.c new file mode 100755 index 0000000..9763ce4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/stats.c @@ -0,0 +1,479 @@ +/* + * stats.c + */ + +/* + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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 + +char *messageNameServer2Client(uint32_t type, char *buf, int len); +char *messageNameClient2Server(uint32_t type, char *buf, int len); +char *encodingName(uint32_t enc, char *buf, int len); + +rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type); +rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type); + +void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbResetStats(rfbClientPtr cl); +void rfbPrintStats(rfbClientPtr cl); + + + + +char *messageNameServer2Client(uint32_t type, char *buf, int len) { + if (buf==NULL) return "error"; + switch (type) { + case rfbFramebufferUpdate: snprintf(buf, len, "FramebufferUpdate"); break; + case rfbSetColourMapEntries: snprintf(buf, len, "SetColourMapEntries"); break; + case rfbBell: snprintf(buf, len, "Bell"); break; + case rfbServerCutText: snprintf(buf, len, "ServerCutText"); break; + case rfbResizeFrameBuffer: snprintf(buf, len, "ResizeFrameBuffer"); break; + case rfbKeyFrameUpdate: snprintf(buf, len, "KeyFrameUpdate"); break; + case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break; + case rfbTextChat: snprintf(buf, len, "TextChat"); break; + case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break; + default: + snprintf(buf, len, "svr2cli-0x%08X", 0xFF); + } + return buf; +} + +char *messageNameClient2Server(uint32_t type, char *buf, int len) { + if (buf==NULL) return "error"; + switch (type) { + case rfbSetPixelFormat: snprintf(buf, len, "SetPixelFormat"); break; + case rfbFixColourMapEntries: snprintf(buf, len, "FixColourMapEntries"); break; + case rfbSetEncodings: snprintf(buf, len, "SetEncodings"); break; + case rfbFramebufferUpdateRequest: snprintf(buf, len, "FramebufferUpdate"); break; + case rfbKeyEvent: snprintf(buf, len, "KeyEvent"); break; + case rfbPointerEvent: snprintf(buf, len, "PointerEvent"); break; + case rfbClientCutText: snprintf(buf, len, "ClientCutText"); break; + case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break; + case rfbSetScale: snprintf(buf, len, "SetScale"); break; + case rfbSetServerInput: snprintf(buf, len, "SetServerInput"); break; + case rfbSetSW: snprintf(buf, len, "SetSingleWindow"); break; + case rfbTextChat: snprintf(buf, len, "TextChat"); break; + case rfbKeyFrameRequest: snprintf(buf, len, "KeyFrameRequest"); break; + case rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break; + default: + snprintf(buf, len, "cli2svr-0x%08X", type); + + + } + return buf; +} + +/* Encoding name must be <=16 characters to fit nicely on the status output in + * an 80 column terminal window + */ +char *encodingName(uint32_t type, char *buf, int len) { + if (buf==NULL) return "error"; + + switch (type) { + case rfbEncodingRaw: snprintf(buf, len, "raw"); break; + case rfbEncodingCopyRect: snprintf(buf, len, "copyRect"); break; + case rfbEncodingRRE: snprintf(buf, len, "RRE"); break; + case rfbEncodingCoRRE: snprintf(buf, len, "CoRRE"); break; + case rfbEncodingHextile: snprintf(buf, len, "hextile"); break; + case rfbEncodingZlib: snprintf(buf, len, "zlib"); break; + case rfbEncodingTight: snprintf(buf, len, "tight"); break; + case rfbEncodingTightPng: snprintf(buf, len, "tightPng"); break; + case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break; + case rfbEncodingUltra: snprintf(buf, len, "ultra"); break; + case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break; + case rfbEncodingZYWRLE: snprintf(buf, len, "ZYWRLE"); break; + case rfbEncodingCache: snprintf(buf, len, "cache"); break; + case rfbEncodingCacheEnable: snprintf(buf, len, "cacheEnable"); break; + case rfbEncodingXOR_Zlib: snprintf(buf, len, "xorZlib"); break; + case rfbEncodingXORMonoColor_Zlib: snprintf(buf, len, "xorMonoZlib"); break; + case rfbEncodingXORMultiColor_Zlib: snprintf(buf, len, "xorColorZlib"); break; + case rfbEncodingSolidColor: snprintf(buf, len, "solidColor"); break; + case rfbEncodingXOREnable: snprintf(buf, len, "xorEnable"); break; + case rfbEncodingCacheZip: snprintf(buf, len, "cacheZip"); break; + case rfbEncodingSolMonoZip: snprintf(buf, len, "monoZip"); break; + case rfbEncodingUltraZip: snprintf(buf, len, "ultraZip"); break; + + case rfbEncodingXCursor: snprintf(buf, len, "Xcursor"); break; + case rfbEncodingRichCursor: snprintf(buf, len, "RichCursor"); break; + case rfbEncodingPointerPos: snprintf(buf, len, "PointerPos"); break; + + case rfbEncodingLastRect: snprintf(buf, len, "LastRect"); break; + case rfbEncodingNewFBSize: snprintf(buf, len, "NewFBSize"); break; + case rfbEncodingKeyboardLedState: snprintf(buf, len, "LedState"); break; + case rfbEncodingSupportedMessages: snprintf(buf, len, "SupportedMessage"); break; + case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncoding"); break; + case rfbEncodingServerIdentity: snprintf(buf, len, "ServerIdentify"); break; + + /* The following lookups do not report in stats */ + case rfbEncodingCompressLevel0: snprintf(buf, len, "CompressLevel0"); break; + case rfbEncodingCompressLevel1: snprintf(buf, len, "CompressLevel1"); break; + case rfbEncodingCompressLevel2: snprintf(buf, len, "CompressLevel2"); break; + case rfbEncodingCompressLevel3: snprintf(buf, len, "CompressLevel3"); break; + case rfbEncodingCompressLevel4: snprintf(buf, len, "CompressLevel4"); break; + case rfbEncodingCompressLevel5: snprintf(buf, len, "CompressLevel5"); break; + case rfbEncodingCompressLevel6: snprintf(buf, len, "CompressLevel6"); break; + case rfbEncodingCompressLevel7: snprintf(buf, len, "CompressLevel7"); break; + case rfbEncodingCompressLevel8: snprintf(buf, len, "CompressLevel8"); break; + case rfbEncodingCompressLevel9: snprintf(buf, len, "CompressLevel9"); break; + + case rfbEncodingQualityLevel0: snprintf(buf, len, "QualityLevel0"); break; + case rfbEncodingQualityLevel1: snprintf(buf, len, "QualityLevel1"); break; + case rfbEncodingQualityLevel2: snprintf(buf, len, "QualityLevel2"); break; + case rfbEncodingQualityLevel3: snprintf(buf, len, "QualityLevel3"); break; + case rfbEncodingQualityLevel4: snprintf(buf, len, "QualityLevel4"); break; + case rfbEncodingQualityLevel5: snprintf(buf, len, "QualityLevel5"); break; + case rfbEncodingQualityLevel6: snprintf(buf, len, "QualityLevel6"); break; + case rfbEncodingQualityLevel7: snprintf(buf, len, "QualityLevel7"); break; + case rfbEncodingQualityLevel8: snprintf(buf, len, "QualityLevel8"); break; + case rfbEncodingQualityLevel9: snprintf(buf, len, "QualityLevel9"); break; + + + default: + snprintf(buf, len, "Enc(0x%08X)", type); + } + + return buf; +} + + + + + +rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr; + if (cl==NULL) return NULL; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + { + if (ptr->type==type) return ptr; + } + /* Well, we are here... need to *CREATE* an entry */ + ptr = (rfbStatList *)malloc(sizeof(rfbStatList)); + if (ptr!=NULL) + { + memset((char *)ptr, 0, sizeof(rfbStatList)); + ptr->type = type; + /* add to the top of the list */ + ptr->Next = cl->statEncList; + cl->statEncList = ptr; + } + return ptr; +} + + +rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr; + if (cl==NULL) return NULL; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + { + if (ptr->type==type) return ptr; + } + /* Well, we are here... need to *CREATE* an entry */ + ptr = (rfbStatList *)malloc(sizeof(rfbStatList)); + if (ptr!=NULL) + { + memset((char *)ptr, 0, sizeof(rfbStatList)); + ptr->type = type; + /* add to the top of the list */ + ptr->Next = cl->statMsgList; + cl->statMsgList = ptr; + } + return ptr; +} + +void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */ +{ + rfbStatList *ptr; + + ptr = rfbStatLookupEncoding(cl, type); + if (ptr!=NULL) + ptr->bytesSent += byteCount; +} + + +void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupEncoding(cl, type); + if (ptr!=NULL) + { + ptr->sentCount++; + ptr->bytesSent += byteCount; + ptr->bytesSentIfRaw += byteIfRaw; + } +} + +void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupEncoding(cl, type); + if (ptr!=NULL) + { + ptr->rcvdCount++; + ptr->bytesRcvd += byteCount; + ptr->bytesRcvdIfRaw += byteIfRaw; + } +} + +void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupMessage(cl, type); + if (ptr!=NULL) + { + ptr->sentCount++; + ptr->bytesSent += byteCount; + ptr->bytesSentIfRaw += byteIfRaw; + } +} + +void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupMessage(cl, type); + if (ptr!=NULL) + { + ptr->rcvdCount++; + ptr->bytesRcvd += byteCount; + ptr->bytesRcvdIfRaw += byteIfRaw; + } +} + + +int rfbStatGetSentBytes(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSent; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSent; + return bytes; +} + +int rfbStatGetSentBytesIfRaw(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSentIfRaw; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSentIfRaw; + return bytes; +} + +int rfbStatGetRcvdBytes(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvd; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvd; + return bytes; +} + +int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvdIfRaw; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvdIfRaw; + return bytes; +} + +int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->sentCount; + return 0; +} +int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->rcvdCount; + return 0; +} + +int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->sentCount; + return 0; +} +int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->rcvdCount; + return 0; +} + + + + +void rfbResetStats(rfbClientPtr cl) +{ + rfbStatList *ptr; + if (cl==NULL) return; + while (cl->statEncList!=NULL) + { + ptr = cl->statEncList; + cl->statEncList = ptr->Next; + free(ptr); + } + while (cl->statMsgList!=NULL) + { + ptr = cl->statMsgList; + cl->statMsgList = ptr->Next; + free(ptr); + } +} + + +void rfbPrintStats(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + char encBuf[64]; + double savings=0.0; + int totalRects=0; + double totalBytes=0.0; + double totalBytesIfRaw=0.0; + + char *name=NULL; + int bytes=0; + int bytesIfRaw=0; + int count=0; + + if (cl==NULL) return; + + rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Transmit","RawEquiv","saved"); + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + { + name = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->sentCount; + bytes = ptr->bytesSent; + bytesIfRaw = ptr->bytesSentIfRaw; + + savings = 0.0; + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + { + name = encodingName(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->sentCount; + bytes = ptr->bytesSent; + bytesIfRaw = ptr->bytesSentIfRaw; + savings = 0.0; + + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + savings=0.0; + if (totalBytesIfRaw>0.0) + savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); + rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", + "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); + + totalRects=0.0; + totalBytes=0.0; + totalBytesIfRaw=0.0; + + rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Received","RawEquiv","saved"); + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + { + name = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->rcvdCount; + bytes = ptr->bytesRcvd; + bytesIfRaw = ptr->bytesRcvdIfRaw; + savings = 0.0; + + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + { + name = encodingName(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->rcvdCount; + bytes = ptr->bytesRcvd; + bytesIfRaw = ptr->bytesRcvdIfRaw; + savings = 0.0; + + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + savings=0.0; + if (totalBytesIfRaw>0.0) + savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); + rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", + "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); + +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinit24.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinit24.c new file mode 100755 index 0000000..39e9920 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinit24.c @@ -0,0 +1,157 @@ +/* + 24 bit + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +static void +rfbInitOneRGBTable24 (uint8_t *table, int inMax, int outMax, int outShift,int swap); + + +static void +rfbInitColourMapSingleTable24(char **table, rfbPixelFormat *in, + rfbPixelFormat *out,rfbColourMap* colourMap) +{ + uint32_t i, r, g, b, outValue; + uint8_t *t; + uint8_t c; + unsigned int nEntries = 1 << in->bitsPerPixel; + int shift = colourMap->is16?16:8; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * 3 + 1); + t = (uint8_t *)*table; + + for (i = 0; i < nEntries; i++) { + r = g = b = 0; + if(i < colourMap->count) { + if(colourMap->is16) { + r = colourMap->data.shorts[3*i+0]; + g = colourMap->data.shorts[3*i+1]; + b = colourMap->data.shorts[3*i+2]; + } else { + r = colourMap->data.bytes[3*i+0]; + g = colourMap->data.bytes[3*i+1]; + b = colourMap->data.bytes[3*i+2]; + } + } + outValue = ((((r * (1 + out->redMax)) >> shift) << out->redShift) | + (((g * (1 + out->greenMax)) >> shift) << out->greenShift) | + (((b * (1 + out->blueMax)) >> shift) << out->blueShift)); + *(uint32_t*)&t[3*i] = outValue; + if(!rfbEndianTest) + memmove(t+3*i,t+3*i+1,3); + if (out->bigEndian != in->bigEndian) { + c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c; + } + } +} + +/* + * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour + * translation. + */ + +static void +rfbInitTrueColourSingleTable24 (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + int i,outValue; + int inRed, inGreen, inBlue, outRed, outGreen, outBlue; + uint8_t *t; + uint8_t c; + int nEntries = 1 << in->bitsPerPixel; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * 3 + 1); + t = (uint8_t *)*table; + + for (i = 0; i < nEntries; i++) { + inRed = (i >> in->redShift) & in->redMax; + inGreen = (i >> in->greenShift) & in->greenMax; + inBlue = (i >> in->blueShift) & in->blueMax; + + outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; + outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; + outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; + + outValue = ((outRed << out->redShift) | + (outGreen << out->greenShift) | + (outBlue << out->blueShift)); + *(uint32_t*)&t[3*i] = outValue; + if(!rfbEndianTest) + memmove(t+3*i,t+3*i+1,3); + if (out->bigEndian != in->bigEndian) { + c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c; + } + } +} + + +/* + * rfbInitTrueColourRGBTables sets up three separate lookup tables for the + * red, green and blue values. + */ + +static void +rfbInitTrueColourRGBTables24 (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + uint8_t *redTable; + uint8_t *greenTable; + uint8_t *blueTable; + + if (*table) free(*table); + *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) + * 3 + 1); + redTable = (uint8_t *)*table; + greenTable = redTable + 3*(in->redMax + 1); + blueTable = greenTable + 3*(in->greenMax + 1); + + rfbInitOneRGBTable24 (redTable, in->redMax, out->redMax, + out->redShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTable24 (greenTable, in->greenMax, out->greenMax, + out->greenShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTable24 (blueTable, in->blueMax, out->blueMax, + out->blueShift, (out->bigEndian != in->bigEndian)); +} + +static void +rfbInitOneRGBTable24 (uint8_t *table, int inMax, int outMax, int outShift, + int swap) +{ + int i; + int nEntries = inMax + 1; + uint32_t outValue; + uint8_t c; + + for (i = 0; i < nEntries; i++) { + outValue = ((i * outMax + inMax / 2) / inMax) << outShift; + *(uint32_t *)&table[3*i] = outValue; + if(!rfbEndianTest) + memmove(table+3*i,table+3*i+1,3); + if (swap) { + c = table[3*i]; table[3*i] = table[3*i+2]; + table[3*i+2] = c; + } + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinitcmtemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinitcmtemplate.c new file mode 100755 index 0000000..df01b23 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinitcmtemplate.c @@ -0,0 +1,84 @@ +/* + * tableinitcmtemplate.c - template for initialising lookup tables for + * translation from a colour map to true colour. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with a different definition of the macro OUT. + * For each value of OUT, this file defines a function which allocates an + * appropriately sized lookup table and initialises it. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +#if !defined(OUT) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#define OUT_T CONCAT3E(uint,OUT,_t) +#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) +#define rfbInitColourMapSingleTableOUT \ + CONCAT2E(rfbInitColourMapSingleTable,OUT) + +static void +rfbInitColourMapSingleTableOUT(char **table, rfbPixelFormat *in, + rfbPixelFormat *out,rfbColourMap* colourMap) +{ + uint32_t i, r, g, b; + OUT_T *t; + uint32_t nEntries = 1 << in->bitsPerPixel; + int shift = colourMap->is16?16:8; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * sizeof(OUT_T)); + t = (OUT_T *)*table; + + for (i = 0; i < nEntries; i++) { + r = g = b = 0; + if(i < colourMap->count) { + if(colourMap->is16) { + r = colourMap->data.shorts[3*i+0]; + g = colourMap->data.shorts[3*i+1]; + b = colourMap->data.shorts[3*i+2]; + } else { + r = colourMap->data.bytes[3*i+0]; + g = colourMap->data.bytes[3*i+1]; + b = colourMap->data.bytes[3*i+2]; + } + } + t[i] = ((((r * (1 + out->redMax)) >> shift) << out->redShift) | + (((g * (1 + out->greenMax)) >> shift) << out->greenShift) | + (((b * (1 + out->blueMax)) >> shift) << out->blueShift)); +#if (OUT != 8) + if (out->bigEndian != in->bigEndian) { + t[i] = SwapOUT(t[i]); + } +#endif + } +} + +#undef OUT_T +#undef SwapOUT +#undef rfbInitColourMapSingleTableOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinittctemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinittctemplate.c new file mode 100755 index 0000000..8d4f742 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinittctemplate.c @@ -0,0 +1,142 @@ +/* + * tableinittctemplate.c - template for initialising lookup tables for + * truecolour to truecolour translation. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with a different definition of the macro OUT. + * For each value of OUT, this file defines two functions for initialising + * lookup tables. One is for truecolour translation using a single lookup + * table, the other is for truecolour translation using three separate + * lookup tables for the red, green and blue values. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +#if !defined(OUT) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#define OUT_T CONCAT3E(uint,OUT,_t) +#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) +#define rfbInitTrueColourSingleTableOUT \ + CONCAT2E(rfbInitTrueColourSingleTable,OUT) +#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT) +#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT) + +static void +rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, + int swap); + + +/* + * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour + * translation. + */ + +static void +rfbInitTrueColourSingleTableOUT (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + int i; + int inRed, inGreen, inBlue, outRed, outGreen, outBlue; + OUT_T *t; + int nEntries = 1 << in->bitsPerPixel; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * sizeof(OUT_T)); + t = (OUT_T *)*table; + + for (i = 0; i < nEntries; i++) { + inRed = (i >> in->redShift) & in->redMax; + inGreen = (i >> in->greenShift) & in->greenMax; + inBlue = (i >> in->blueShift) & in->blueMax; + + outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; + outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; + outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; + + t[i] = ((outRed << out->redShift) | + (outGreen << out->greenShift) | + (outBlue << out->blueShift)); +#if (OUT != 8) + if (out->bigEndian != in->bigEndian) { + t[i] = SwapOUT(t[i]); + } +#endif + } +} + + +/* + * rfbInitTrueColourRGBTables sets up three separate lookup tables for the + * red, green and blue values. + */ + +static void +rfbInitTrueColourRGBTablesOUT (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + OUT_T *redTable; + OUT_T *greenTable; + OUT_T *blueTable; + + if (*table) free(*table); + *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) + * sizeof(OUT_T)); + redTable = (OUT_T *)*table; + greenTable = redTable + in->redMax + 1; + blueTable = greenTable + in->greenMax + 1; + + rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax, + out->redShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax, + out->greenShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax, + out->blueShift, (out->bigEndian != in->bigEndian)); +} + +static void +rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, + int swap) +{ + int i; + int nEntries = inMax + 1; + + for (i = 0; i < nEntries; i++) { + table[i] = ((i * outMax + inMax / 2) / inMax) << outShift; +#if (OUT != 8) + if (swap) { + table[i] = SwapOUT(table[i]); + } +#endif + } +} + +#undef OUT_T +#undef SwapOUT +#undef rfbInitTrueColourSingleTableOUT +#undef rfbInitTrueColourRGBTablesOUT +#undef rfbInitOneRGBTableOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletrans24template.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletrans24template.c new file mode 100755 index 0000000..4b3a0a0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletrans24template.c @@ -0,0 +1,281 @@ +/* + * tabletranstemplate.c - template for translation using lookup tables. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with different definitions of the macros IN and OUT. + * + * For each pair of values IN and OUT, this file defines two functions for + * translating a given rectangle of pixel data. One uses a single lookup + * table, and the other uses three separate lookup tables for the red, green + * and blue values. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +#if !defined(BPP) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#if BPP == 24 + +/* + * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTable24to24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines - width * 3; + uint8_t *opLineEnd; + uint8_t *t = (uint8_t *)table; + int shift = rfbEndianTest?0:8; + uint8_t c; + + while (height > 0) { + opLineEnd = op + width*3; + + while (op < opLineEnd) { + *(uint32_t*)op = t[((*(uint32_t *)ip)>>shift)&0x00ffffff]; + if(!rfbEndianTest) + memmove(op,op+1,3); + if (out->bigEndian != in->bigEndian) { + c = op[0]; op[0] = op[2]; op[2] = c; + } + op += 3; + ip += 3; + } + + ip += ipextra; + height--; + } +} + +/* + * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTables24to24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines - width*3; + uint8_t *opLineEnd; + uint8_t *redTable = (uint8_t *)table; + uint8_t *greenTable = redTable + 3*(in->redMax + 1); + uint8_t *blueTable = greenTable + 3*(in->greenMax + 1); + uint32_t outValue,inValue; + int shift = rfbEndianTest?0:8; + + while (height > 0) { + opLineEnd = op+3*width; + + while (op < opLineEnd) { + inValue = ((*(uint32_t *)ip)>>shift)&0x00ffffff; + outValue = (redTable[(inValue >> in->redShift) & in->redMax] | + greenTable[(inValue >> in->greenShift) & in->greenMax] | + blueTable[(inValue >> in->blueShift) & in->blueMax]); + memcpy(op,&outValue,3); + op += 3; + ip+=3; + } + ip += ipextra; + height--; + } +} + +#else + +#define IN_T CONCAT3E(uint,BPP,_t) +#define OUT_T CONCAT3E(uint,BPP,_t) +#define rfbTranslateWithSingleTable24toOUT \ + CONCAT4E(rfbTranslateWithSingleTable,24,to,BPP) +#define rfbTranslateWithSingleTableINto24 \ + CONCAT4E(rfbTranslateWithSingleTable,BPP,to,24) +#define rfbTranslateWithRGBTables24toOUT \ + CONCAT4E(rfbTranslateWithRGBTables,24,to,BPP) +#define rfbTranslateWithRGBTablesINto24 \ + CONCAT4E(rfbTranslateWithRGBTables,BPP,to,24) + +/* + * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTable24toOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines - width*3; + OUT_T *opLineEnd; + OUT_T *t = (OUT_T *)table; + int shift = rfbEndianTest?0:8; + + while (height > 0) { + opLineEnd = op + width; + + while (op < opLineEnd) { + *(op++) = t[((*(uint32_t *)ip)>>shift)&0x00ffffff]; + ip+=3; + } + + ip += ipextra; + height--; + } +} + + +/* + * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTables24toOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines - width*3; + OUT_T *opLineEnd; + OUT_T *redTable = (OUT_T *)table; + OUT_T *greenTable = redTable + in->redMax + 1; + OUT_T *blueTable = greenTable + in->greenMax + 1; + uint32_t inValue; + int shift = rfbEndianTest?0:8; + + while (height > 0) { + opLineEnd = &op[width]; + + while (op < opLineEnd) { + inValue = ((*(uint32_t *)ip)>>shift)&0x00ffffff; + *(op++) = (redTable[(inValue >> in->redShift) & in->redMax] | + greenTable[(inValue >> in->greenShift) & in->greenMax] | + blueTable[(inValue >> in->blueShift) & in->blueMax]); + ip+=3; + } + ip += ipextra; + height--; + } +} + +/* + * rfbTranslateWithSingleTableINto24 translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTableINto24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + uint8_t *opLineEnd; + uint8_t *t = (uint8_t *)table; + + while (height > 0) { + opLineEnd = op + width * 3; + + while (op < opLineEnd) { + memcpy(op,&t[3*(*(ip++))],3); + op += 3; + } + + ip += ipextra; + height--; + } +} + + +/* + * rfbTranslateWithRGBTablesINto24 translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTablesINto24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + uint8_t *opLineEnd; + uint8_t *redTable = (uint8_t *)table; + uint8_t *greenTable = redTable + 3*(in->redMax + 1); + uint8_t *blueTable = greenTable + 3*(in->greenMax + 1); + uint32_t outValue; + + while (height > 0) { + opLineEnd = op+3*width; + + while (op < opLineEnd) { + outValue = (redTable[(*ip >> in->redShift) & in->redMax] | + greenTable[(*ip >> in->greenShift) & in->greenMax] | + blueTable[(*ip >> in->blueShift) & in->blueMax]); + memcpy(op,&outValue,3); + op += 3; + ip++; + } + ip += ipextra; + height--; + } +} + +#undef IN_T +#undef OUT_T +#undef rfbTranslateWithSingleTable24toOUT +#undef rfbTranslateWithRGBTables24toOUT +#undef rfbTranslateWithSingleTableINto24 +#undef rfbTranslateWithRGBTablesINto24 + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletranstemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletranstemplate.c new file mode 100755 index 0000000..e83c623 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletranstemplate.c @@ -0,0 +1,117 @@ +/* + * tabletranstemplate.c - template for translation using lookup tables. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with different definitions of the macros IN and OUT. + * + * For each pair of values IN and OUT, this file defines two functions for + * translating a given rectangle of pixel data. One uses a single lookup + * table, and the other uses three separate lookup tables for the red, green + * and blue values. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +#if !defined(IN) || !defined(OUT) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#define IN_T CONCAT3E(uint,IN,_t) +#define OUT_T CONCAT3E(uint,OUT,_t) +#define rfbTranslateWithSingleTableINtoOUT \ + CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT) +#define rfbTranslateWithRGBTablesINtoOUT \ + CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT) + +/* + * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTableINtoOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + OUT_T *opLineEnd; + OUT_T *t = (OUT_T *)table; + + while (height > 0) { + opLineEnd = op + width; + + while (op < opLineEnd) { + *(op++) = t[*(ip++)]; + } + + ip += ipextra; + height--; + } +} + + +/* + * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTablesINtoOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + OUT_T *opLineEnd; + OUT_T *redTable = (OUT_T *)table; + OUT_T *greenTable = redTable + in->redMax + 1; + OUT_T *blueTable = greenTable + in->greenMax + 1; + + while (height > 0) { + opLineEnd = &op[width]; + + while (op < opLineEnd) { + *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] | + greenTable[(*ip >> in->greenShift) & in->greenMax] | + blueTable[(*ip >> in->blueShift) & in->blueMax]); + ip++; + } + ip += ipextra; + height--; + } +} + +#undef IN_T +#undef OUT_T +#undef rfbTranslateWithSingleTableINtoOUT +#undef rfbTranslateWithRGBTablesINtoOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tight.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tight.c new file mode 100755 index 0000000..9423ba5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tight.c @@ -0,0 +1,2053 @@ +/* + * tight.c + * + * Routines to implement Tight Encoding + */ + +/* + * 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 */ +#include +#include "private.h" + +#ifdef WIN32 +#define XMD_H +#undef FAR +#define NEEDFAR_POINTERS +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBPNG +#include +#endif +#include + +/* Note: The following constant should not be changed. */ +#define TIGHT_MIN_TO_COMPRESS 12 + +/* The parameters below may be adjusted. */ +#define MIN_SPLIT_RECT_SIZE 4096 +#define MIN_SOLID_SUBRECT_SIZE 2048 +#define MAX_SPLIT_TILE_SIZE 16 + +/* May be set to TRUE with "-lazytight" Xvnc option. */ +rfbBool rfbTightDisableGradient = FALSE; + +/* + * There is so much access of the Tight encoding static data buffers + * that we resort to using thread local storage instead of having + * per-client data. + */ +#if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__) +#define TLS __thread +#endif +#ifndef TLS +#define TLS +#endif + +/* This variable is set on every rfbSendRectEncodingTight() call. */ +static TLS rfbBool usePixelFormat24 = FALSE; + +/* Compression level stuff. The following array contains various + encoder parameters for each of 10 compression levels (0..9). + Last three parameters correspond to JPEG quality levels (0..9). */ + +typedef struct TIGHT_CONF_s { + int maxRectSize, maxRectWidth; + int monoMinRectSize, gradientMinRectSize; + int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel; + int gradientThreshold, gradientThreshold24; + int idxMaxColorsDivisor; + int jpegQuality, jpegThreshold, jpegThreshold24; +} TIGHT_CONF; + +static TIGHT_CONF tightConf[10] = { + { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 }, + { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 }, + { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 }, + { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 }, + { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 }, + { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 }, + { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 }, + { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 }, + { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 }, + { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } +}; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG +typedef struct TIGHT_PNG_CONF_s { + int png_zlib_level, png_filters; +} TIGHT_PNG_CONF; + +static TIGHT_PNG_CONF tightPngConf[10] = { + { 0, PNG_NO_FILTERS }, + { 1, PNG_NO_FILTERS }, + { 2, PNG_NO_FILTERS }, + { 3, PNG_NO_FILTERS }, + { 4, PNG_NO_FILTERS }, + { 5, PNG_ALL_FILTERS }, + { 6, PNG_ALL_FILTERS }, + { 7, PNG_ALL_FILTERS }, + { 8, PNG_ALL_FILTERS }, + { 9, PNG_ALL_FILTERS }, +}; +#endif + +static TLS int compressLevel = 0; +static TLS int qualityLevel = 0; + +/* Stuff dealing with palettes. */ + +typedef struct COLOR_LIST_s { + struct COLOR_LIST_s *next; + int idx; + uint32_t rgb; +} COLOR_LIST; + +typedef struct PALETTE_ENTRY_s { + COLOR_LIST *listNode; + int numPixels; +} PALETTE_ENTRY; + +typedef struct PALETTE_s { + PALETTE_ENTRY entry[256]; + COLOR_LIST *hash[256]; + COLOR_LIST list[256]; +} PALETTE; + +/* TODO: move into rfbScreen struct */ +static TLS int paletteNumColors = 0; +static TLS int paletteMaxColors = 0; +static TLS uint32_t monoBackground = 0; +static TLS uint32_t monoForeground = 0; +static TLS PALETTE palette; + +/* Pointers to dynamically-allocated buffers. */ + +static TLS int tightBeforeBufSize = 0; +static TLS char *tightBeforeBuf = NULL; + +static TLS int tightAfterBufSize = 0; +static TLS char *tightAfterBuf = NULL; + +static TLS int *prevRowBuf = NULL; + +void rfbTightCleanup(rfbScreenInfoPtr screen) +{ + if(tightBeforeBufSize) { + free(tightBeforeBuf); + tightBeforeBufSize=0; + tightBeforeBuf = NULL; + } + if(tightAfterBufSize) { + free(tightAfterBuf); + tightAfterBufSize=0; + tightAfterBuf = NULL; + } +} + +/* Prototypes for static functions. */ + +static rfbBool SendRectEncodingTight(rfbClientPtr cl, int x, int y, + int w, int h); +static void FindBestSolidArea (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t colorValue, int *w_ptr, int *h_ptr); +static void ExtendSolidArea (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t colorValue, + int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr); +static rfbBool CheckSolidTile (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); +static rfbBool CheckSolidTile8 (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); +static rfbBool CheckSolidTile16 (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); +static rfbBool CheckSolidTile32 (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); + +static rfbBool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); + +static rfbBool SendSolidRect (rfbClientPtr cl); +static rfbBool SendMonoRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendIndexedRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendFullColorRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendGradientRect (rfbClientPtr cl, int x, int y, int w, int h); + +static rfbBool CompressData(rfbClientPtr cl, int streamId, int dataLen, + int zlibLevel, int zlibStrategy); +static rfbBool SendCompressedData(rfbClientPtr cl, int compressedLen); + +static void FillPalette8(int count); +static void FillPalette16(int count); +static void FillPalette32(int count); + +static void PaletteReset(void); +static int PaletteInsert(uint32_t rgb, int numPixels, int bpp); + +static void Pack24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int count); + +static void EncodeIndexedRect16(uint8_t *buf, int count); +static void EncodeIndexedRect32(uint8_t *buf, int count); + +static void EncodeMonoRect8(uint8_t *buf, int w, int h); +static void EncodeMonoRect16(uint8_t *buf, int w, int h); +static void EncodeMonoRect32(uint8_t *buf, int w, int h); + +static void FilterGradient24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int w, int h); +static void FilterGradient16(rfbClientPtr cl, uint16_t *buf, rfbPixelFormat *fmt, int w, int h); +static void FilterGradient32(rfbClientPtr cl, uint32_t *buf, rfbPixelFormat *fmt, int w, int h); + +static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); +static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); +static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); +static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); + +static rfbBool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, + int quality); +static void PrepareRowForImg(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg24(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg16(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg32(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); + +static void JpegInitDestination(j_compress_ptr cinfo); +static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); +static void JpegTermDestination(j_compress_ptr cinfo); +static void JpegSetDstManager(j_compress_ptr cinfo); + +#ifdef LIBVNCSERVER_HAVE_LIBPNG +static rfbBool SendPngRect(rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool CanSendPngRect(rfbClientPtr cl, int w, int h); +#endif + +/* + * Tight encoding implementation. + */ + +int +rfbNumCodedRectsTight(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int maxRectSize, maxRectWidth; + int subrectMaxWidth, subrectMaxHeight; + + /* No matter how many rectangles we will send if LastRect markers + are used to terminate rectangle stream. */ + if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE) + return 0; + + maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; + maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; + + if (w > maxRectWidth || w * h > maxRectSize) { + subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; + subrectMaxHeight = maxRectSize / subrectMaxWidth; + return (((w - 1) / maxRectWidth + 1) * + ((h - 1) / subrectMaxHeight + 1)); + } else { + return 1; + } +} + +rfbBool +rfbSendRectEncodingTight(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + cl->tightEncoding = rfbEncodingTight; + return SendRectEncodingTight(cl, x, y, w, h); +} + +rfbBool +rfbSendRectEncodingTightPng(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + cl->tightEncoding = rfbEncodingTightPng; + return SendRectEncodingTight(cl, x, y, w, h); +} + + +rfbBool +SendRectEncodingTight(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int nMaxRows; + uint32_t colorValue; + int dx, dy, dw, dh; + int x_best, y_best, w_best, h_best; + char *fbptr; + + rfbSendUpdateBuf(cl); + + compressLevel = cl->tightCompressLevel; + qualityLevel = cl->tightQualityLevel; + + if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && + cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { + usePixelFormat24 = TRUE; + } else { + usePixelFormat24 = FALSE; + } + + if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) + return SendRectSimple(cl, x, y, w, h); + + /* Make sure we can write at least one pixel into tightBeforeBuf. */ + + if (tightBeforeBufSize < 4) { + tightBeforeBufSize = 4; + if (tightBeforeBuf == NULL) + tightBeforeBuf = (char *)malloc(tightBeforeBufSize); + else + tightBeforeBuf = (char *)realloc(tightBeforeBuf, + tightBeforeBufSize); + } + + /* Calculate maximum number of rows in one non-solid rectangle. */ + + { + int maxRectSize, maxRectWidth, nMaxWidth; + + maxRectSize = tightConf[compressLevel].maxRectSize; + maxRectWidth = tightConf[compressLevel].maxRectWidth; + nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; + nMaxRows = maxRectSize / nMaxWidth; + } + + /* Try to find large solid-color areas and send them separately. */ + + for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { + + /* If a rectangle becomes too large, send its upper part now. */ + + if (dy - y >= nMaxRows) { + if (!SendRectSimple(cl, x, y, w, nMaxRows)) + return 0; + y += nMaxRows; + h -= nMaxRows; + } + + dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? + MAX_SPLIT_TILE_SIZE : (y + h - dy); + + for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) { + + dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ? + MAX_SPLIT_TILE_SIZE : (x + w - dx); + + if (CheckSolidTile(cl, dx, dy, dw, dh, &colorValue, FALSE)) { + + /* Get dimensions of solid-color area. */ + + FindBestSolidArea(cl, dx, dy, w - (dx - x), h - (dy - y), + colorValue, &w_best, &h_best); + + /* Make sure a solid rectangle is large enough + (or the whole rectangle is of the same color). */ + + if ( w_best * h_best != w * h && + w_best * h_best < MIN_SOLID_SUBRECT_SIZE ) + continue; + + /* Try to extend solid rectangle to maximum size. */ + + x_best = dx; y_best = dy; + ExtendSolidArea(cl, x, y, w, h, colorValue, + &x_best, &y_best, &w_best, &h_best); + + /* Send rectangles at top and left to solid-color area. */ + + if ( y_best != y && + !SendRectSimple(cl, x, y, w, y_best-y) ) + return FALSE; + if ( x_best != x && + !SendRectEncodingTight(cl, x, y_best, + x_best-x, h_best) ) + return FALSE; + + /* Send solid-color rectangle. */ + + if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) + return FALSE; + + fbptr = (cl->scaledScreen->frameBuffer + + (cl->scaledScreen->paddedWidthInBytes * y_best) + + (x_best * (cl->scaledScreen->bitsPerPixel / 8))); + + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, tightBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, 1, 1); + + if (!SendSolidRect(cl)) + return FALSE; + + /* Send remaining rectangles (at right and bottom). */ + + if ( x_best + w_best != x + w && + !SendRectEncodingTight(cl, x_best+w_best, y_best, + w-(x_best-x)-w_best, h_best) ) + return FALSE; + if ( y_best + h_best != y + h && + !SendRectEncodingTight(cl, x, y_best+h_best, + w, h-(y_best-y)-h_best) ) + return FALSE; + + /* Return after all recursive calls are done. */ + + return TRUE; + } + + } + + } + + /* No suitable solid-color rectangles found. */ + + return SendRectSimple(cl, x, y, w, h); +} + +static void +FindBestSolidArea(rfbClientPtr cl, + int x, + int y, + int w, + int h, + uint32_t colorValue, + int *w_ptr, + int *h_ptr) +{ + int dx, dy, dw, dh; + int w_prev; + int w_best = 0, h_best = 0; + + w_prev = w; + + for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { + + dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? + MAX_SPLIT_TILE_SIZE : (y + h - dy); + dw = (w_prev > MAX_SPLIT_TILE_SIZE) ? + MAX_SPLIT_TILE_SIZE : w_prev; + + if (!CheckSolidTile(cl, x, dy, dw, dh, &colorValue, TRUE)) + break; + + for (dx = x + dw; dx < x + w_prev;) { + dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ? + MAX_SPLIT_TILE_SIZE : (x + w_prev - dx); + if (!CheckSolidTile(cl, dx, dy, dw, dh, &colorValue, TRUE)) + break; + dx += dw; + } + + w_prev = dx - x; + if (w_prev * (dy + dh - y) > w_best * h_best) { + w_best = w_prev; + h_best = dy + dh - y; + } + } + + *w_ptr = w_best; + *h_ptr = h_best; +} + +static void +ExtendSolidArea(rfbClientPtr cl, + int x, + int y, + int w, + int h, + uint32_t colorValue, + int *x_ptr, + int *y_ptr, + int *w_ptr, + int *h_ptr) +{ + int cx, cy; + + /* Try to extend the area upwards. */ + for ( cy = *y_ptr - 1; + cy >= y && CheckSolidTile(cl, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); + cy-- ); + *h_ptr += *y_ptr - (cy + 1); + *y_ptr = cy + 1; + + /* ... downwards. */ + for ( cy = *y_ptr + *h_ptr; + cy < y + h && + CheckSolidTile(cl, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); + cy++ ); + *h_ptr += cy - (*y_ptr + *h_ptr); + + /* ... to the left. */ + for ( cx = *x_ptr - 1; + cx >= x && CheckSolidTile(cl, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); + cx-- ); + *w_ptr += *x_ptr - (cx + 1); + *x_ptr = cx + 1; + + /* ... to the right. */ + for ( cx = *x_ptr + *w_ptr; + cx < x + w && + CheckSolidTile(cl, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); + cx++ ); + *w_ptr += cx - (*x_ptr + *w_ptr); +} + +/* + * Check if a rectangle is all of the same color. If needSameColor is + * set to non-zero, then also check that its color equals to the + * *colorPtr value. The result is 1 if the test is successfull, and in + * that case new color will be stored in *colorPtr. + */ + +static rfbBool CheckSolidTile(rfbClientPtr cl, int x, int y, int w, int h, uint32_t* colorPtr, rfbBool needSameColor) +{ + switch(cl->screen->serverFormat.bitsPerPixel) { + case 32: + return CheckSolidTile32(cl, x, y, w, h, colorPtr, needSameColor); + case 16: + return CheckSolidTile16(cl, x, y, w, h, colorPtr, needSameColor); + default: + return CheckSolidTile8(cl, x, y, w, h, colorPtr, needSameColor); + } +} + +#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ + \ +static rfbBool \ +CheckSolidTile##bpp(rfbClientPtr cl, int x, int y, int w, int h, \ + uint32_t* colorPtr, rfbBool needSameColor) \ +{ \ + uint##bpp##_t *fbptr; \ + uint##bpp##_t colorValue; \ + int dx, dy; \ + \ + fbptr = (uint##bpp##_t *) \ + &cl->scaledScreen->frameBuffer[y * cl->scaledScreen->paddedWidthInBytes + x * (bpp/8)]; \ + \ + colorValue = *fbptr; \ + if (needSameColor && (uint32_t)colorValue != *colorPtr) \ + return FALSE; \ + \ + for (dy = 0; dy < h; dy++) { \ + for (dx = 0; dx < w; dx++) { \ + if (colorValue != fbptr[dx]) \ + return FALSE; \ + } \ + fbptr = (uint##bpp##_t *)((uint8_t *)fbptr + cl->scaledScreen->paddedWidthInBytes); \ + } \ + \ + *colorPtr = (uint32_t)colorValue; \ + return TRUE; \ +} + +DEFINE_CHECK_SOLID_FUNCTION(8) +DEFINE_CHECK_SOLID_FUNCTION(16) +DEFINE_CHECK_SOLID_FUNCTION(32) + +static rfbBool +SendRectSimple(rfbClientPtr cl, int x, int y, int w, int h) +{ + int maxBeforeSize, maxAfterSize; + int maxRectSize, maxRectWidth; + int subrectMaxWidth, subrectMaxHeight; + int dx, dy; + int rw, rh; + + maxRectSize = tightConf[compressLevel].maxRectSize; + maxRectWidth = tightConf[compressLevel].maxRectWidth; + + maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8); + maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12; + + if (tightBeforeBufSize < maxBeforeSize) { + tightBeforeBufSize = maxBeforeSize; + if (tightBeforeBuf == NULL) + tightBeforeBuf = (char *)malloc(tightBeforeBufSize); + else + tightBeforeBuf = (char *)realloc(tightBeforeBuf, + tightBeforeBufSize); + } + + if (tightAfterBufSize < maxAfterSize) { + tightAfterBufSize = maxAfterSize; + if (tightAfterBuf == NULL) + tightAfterBuf = (char *)malloc(tightAfterBufSize); + else + tightAfterBuf = (char *)realloc(tightAfterBuf, + tightAfterBufSize); + } + + if (w > maxRectWidth || w * h > maxRectSize) { + subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; + subrectMaxHeight = maxRectSize / subrectMaxWidth; + + for (dy = 0; dy < h; dy += subrectMaxHeight) { + for (dx = 0; dx < w; dx += maxRectWidth) { + rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx; + rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy; + if (!SendSubrect(cl, x+dx, y+dy, rw, rh)) + return FALSE; + } + } + } else { + if (!SendSubrect(cl, x, y, w, h)) + return FALSE; + } + + return TRUE; +} + +static rfbBool +SendSubrect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + char *fbptr; + rfbBool success = FALSE; + + /* Send pending data if there is more than 128 bytes. */ + if (cl->ublen > 128) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + if (!SendTightHeader(cl, x, y, w, h)) + return FALSE; + + fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, tightBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + paletteMaxColors = w * h / tightConf[compressLevel].idxMaxColorsDivisor; + if ( paletteMaxColors < 2 && + w * h >= tightConf[compressLevel].monoMinRectSize ) { + paletteMaxColors = 2; + } + switch (cl->format.bitsPerPixel) { + case 8: + FillPalette8(w * h); + break; + case 16: + FillPalette16(w * h); + break; + default: + FillPalette32(w * h); + } + + switch (paletteNumColors) { + case 0: + /* Truecolor image */ + if (DetectSmoothImage(cl, &cl->format, w, h)) { + if (qualityLevel != -1) { + success = SendJpegRect(cl, x, y, w, h, + tightConf[qualityLevel].jpegQuality); + } else { + success = SendGradientRect(cl, x, y, w, h); + } + } else { + success = SendFullColorRect(cl, x, y, w, h); + } + break; + case 1: + /* Solid rectangle */ + success = SendSolidRect(cl); + break; + case 2: + /* Two-color rectangle */ + success = SendMonoRect(cl, x, y, w, h); + break; + default: + /* Up to 256 different colors */ + if ( paletteNumColors > 96 && + qualityLevel != -1 && qualityLevel <= 3 && + DetectSmoothImage(cl, &cl->format, w, h) ) { + success = SendJpegRect(cl, x, y, w, h, + tightConf[qualityLevel].jpegQuality); + } else { + success = SendIndexedRect(cl, x, y, w, h); + } + } + return success; +} + +static rfbBool +SendTightHeader(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > 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(cl->tightEncoding); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, cl->tightEncoding, sz_rfbFramebufferUpdateRectHeader, + sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h); + + return TRUE; +} + +/* + * Subencoding implementations. + */ + +static rfbBool +SendSolidRect(rfbClientPtr cl) +{ + int len; + + if (usePixelFormat24) { + Pack24(cl, tightBeforeBuf, &cl->format, 1); + len = 3; + } else + len = cl->format.bitsPerPixel / 8; + + if (cl->ublen + 1 + len > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = (char)(rfbTightFill << 4); + memcpy (&cl->updateBuf[cl->ublen], tightBeforeBuf, len); + cl->ublen += len; + + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, len+1); + + return TRUE; +} + +static rfbBool +SendMonoRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 1; + int paletteLen, dataLen; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + // TODO: setup palette maybe + return SendPngRect(cl, x, y, w, h); + // TODO: destroy palette maybe + } +#endif + + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + + 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + /* Prepare tight encoding header. */ + dataLen = (w + 7) / 8; + dataLen *= h; + + cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; + cl->updateBuf[cl->ublen++] = rfbTightFilterPalette; + cl->updateBuf[cl->ublen++] = 1; + + /* Prepare palette, convert image. */ + switch (cl->format.bitsPerPixel) { + + case 32: + EncodeMonoRect32((uint8_t *)tightBeforeBuf, w, h); + + ((uint32_t *)tightAfterBuf)[0] = monoBackground; + ((uint32_t *)tightAfterBuf)[1] = monoForeground; + if (usePixelFormat24) { + Pack24(cl, tightAfterBuf, &cl->format, 2); + paletteLen = 6; + } else + paletteLen = 8; + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteLen); + cl->ublen += paletteLen; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteLen); + break; + + case 16: + EncodeMonoRect16((uint8_t *)tightBeforeBuf, w, h); + + ((uint16_t *)tightAfterBuf)[0] = (uint16_t)monoBackground; + ((uint16_t *)tightAfterBuf)[1] = (uint16_t)monoForeground; + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, 4); + cl->ublen += 4; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 7); + break; + + default: + EncodeMonoRect8((uint8_t *)tightBeforeBuf, w, h); + + cl->updateBuf[cl->ublen++] = (char)monoBackground; + cl->updateBuf[cl->ublen++] = (char)monoForeground; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 5); + } + + return CompressData(cl, streamId, dataLen, + tightConf[compressLevel].monoZlibLevel, + Z_DEFAULT_STRATEGY); +} + +static rfbBool +SendIndexedRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 2; + int i, entryLen; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + + paletteNumColors * cl->format.bitsPerPixel / 8 > + UPDATE_BUF_SIZE ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + /* Prepare tight encoding header. */ + cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; + cl->updateBuf[cl->ublen++] = rfbTightFilterPalette; + cl->updateBuf[cl->ublen++] = (char)(paletteNumColors - 1); + + /* Prepare palette, convert image. */ + switch (cl->format.bitsPerPixel) { + + case 32: + EncodeIndexedRect32((uint8_t *)tightBeforeBuf, w * h); + + for (i = 0; i < paletteNumColors; i++) { + ((uint32_t *)tightAfterBuf)[i] = + palette.entry[i].listNode->rgb; + } + if (usePixelFormat24) { + Pack24(cl, tightAfterBuf, &cl->format, paletteNumColors); + entryLen = 3; + } else + entryLen = 4; + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * entryLen); + cl->ublen += paletteNumColors * entryLen; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * entryLen); + break; + + case 16: + EncodeIndexedRect16((uint8_t *)tightBeforeBuf, w * h); + + for (i = 0; i < paletteNumColors; i++) { + ((uint16_t *)tightAfterBuf)[i] = + (uint16_t)palette.entry[i].listNode->rgb; + } + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * 2); + cl->ublen += paletteNumColors * 2; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * 2); + break; + + default: + return FALSE; /* Should never happen. */ + } + + return CompressData(cl, streamId, w * h, + tightConf[compressLevel].idxZlibLevel, + Z_DEFAULT_STRATEGY); +} + +static rfbBool +SendFullColorRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 0; + int len; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + + if (usePixelFormat24) { + Pack24(cl, tightBeforeBuf, &cl->format, w * h); + len = 3; + } else + len = cl->format.bitsPerPixel / 8; + + return CompressData(cl, streamId, w * h * len, + tightConf[compressLevel].rawZlibLevel, + Z_DEFAULT_STRATEGY); +} + +static rfbBool +SendGradientRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 3; + int len; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + + if (cl->format.bitsPerPixel == 8) + return SendFullColorRect(cl, x, y, w, h); + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + if (prevRowBuf == NULL) + prevRowBuf = (int *)malloc(2048 * 3 * sizeof(int)); + + cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; + cl->updateBuf[cl->ublen++] = rfbTightFilterGradient; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 2); + + if (usePixelFormat24) { + FilterGradient24(cl, tightBeforeBuf, &cl->format, w, h); + len = 3; + } else if (cl->format.bitsPerPixel == 32) { + FilterGradient32(cl, (uint32_t *)tightBeforeBuf, &cl->format, w, h); + len = 4; + } else { + FilterGradient16(cl, (uint16_t *)tightBeforeBuf, &cl->format, w, h); + len = 2; + } + + return CompressData(cl, streamId, w * h * len, + tightConf[compressLevel].gradientZlibLevel, + Z_FILTERED); +} + +static rfbBool +CompressData(rfbClientPtr cl, + int streamId, + int dataLen, + int zlibLevel, + int zlibStrategy) +{ + z_streamp pz; + int err; + + if (dataLen < TIGHT_MIN_TO_COMPRESS) { + memcpy(&cl->updateBuf[cl->ublen], tightBeforeBuf, dataLen); + cl->ublen += dataLen; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, dataLen); + return TRUE; + } + + pz = &cl->zsStruct[streamId]; + + /* Initialize compression stream if needed. */ + if (!cl->zsActive[streamId]) { + pz->zalloc = Z_NULL; + pz->zfree = Z_NULL; + pz->opaque = Z_NULL; + + err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS, + MAX_MEM_LEVEL, zlibStrategy); + if (err != Z_OK) + return FALSE; + + cl->zsActive[streamId] = TRUE; + cl->zsLevel[streamId] = zlibLevel; + } + + /* Prepare buffer pointers. */ + pz->next_in = (Bytef *)tightBeforeBuf; + pz->avail_in = dataLen; + pz->next_out = (Bytef *)tightAfterBuf; + pz->avail_out = tightAfterBufSize; + + /* Change compression parameters if needed. */ + if (zlibLevel != cl->zsLevel[streamId]) { + if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) { + return FALSE; + } + cl->zsLevel[streamId] = zlibLevel; + } + + /* Actual compression. */ + if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK || + pz->avail_in != 0 || pz->avail_out == 0 ) { + return FALSE; + } + + return SendCompressedData(cl, tightAfterBufSize - pz->avail_out); +} + +static rfbBool SendCompressedData(rfbClientPtr cl, + int compressedLen) +{ + int i, portionLen; + + cl->updateBuf[cl->ublen++] = compressedLen & 0x7F; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + if (compressedLen > 0x7F) { + cl->updateBuf[cl->ublen-1] |= 0x80; + cl->updateBuf[cl->ublen++] = compressedLen >> 7 & 0x7F; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + if (compressedLen > 0x3FFF) { + cl->updateBuf[cl->ublen-1] |= 0x80; + cl->updateBuf[cl->ublen++] = compressedLen >> 14 & 0xFF; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + } + } + + portionLen = UPDATE_BUF_SIZE; + for (i = 0; i < compressedLen; i += portionLen) { + if (i + portionLen > compressedLen) { + portionLen = compressedLen - i; + } + if (cl->ublen + portionLen > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen); + cl->ublen += portionLen; + } + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, compressedLen); + + return TRUE; +} + +/* + * Code to determine how many different colors used in rectangle. + */ + +static void +FillPalette8(int count) +{ + uint8_t *data = (uint8_t *)tightBeforeBuf; + uint8_t c0, c1; + int i, n0, n1; + + paletteNumColors = 0; + + c0 = data[0]; + for (i = 1; i < count && data[i] == c0; i++); + if (i == count) { + paletteNumColors = 1; + return; /* Solid rectangle */ + } + + if (paletteMaxColors < 2) + return; + + n0 = i; + c1 = data[i]; + n1 = 0; + for (i++; i < count; i++) { + if (data[i] == c0) { + n0++; + } else if (data[i] == c1) { + n1++; + } else + break; + } + if (i == count) { + if (n0 > n1) { + monoBackground = (uint32_t)c0; + monoForeground = (uint32_t)c1; + } else { + monoBackground = (uint32_t)c1; + monoForeground = (uint32_t)c0; + } + paletteNumColors = 2; /* Two colors */ + } +} + +#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \ + \ +static void \ +FillPalette##bpp(int count) { \ + uint##bpp##_t *data = (uint##bpp##_t *)tightBeforeBuf; \ + uint##bpp##_t c0, c1, ci; \ + int i, n0, n1, ni; \ + \ + c0 = data[0]; \ + for (i = 1; i < count && data[i] == c0; i++); \ + if (i >= count) { \ + paletteNumColors = 1; /* Solid rectangle */ \ + return; \ + } \ + \ + if (paletteMaxColors < 2) { \ + paletteNumColors = 0; /* Full-color encoding preferred */ \ + return; \ + } \ + \ + n0 = i; \ + c1 = data[i]; \ + n1 = 0; \ + for (i++; i < count; i++) { \ + ci = data[i]; \ + if (ci == c0) { \ + n0++; \ + } else if (ci == c1) { \ + n1++; \ + } else \ + break; \ + } \ + if (i >= count) { \ + if (n0 > n1) { \ + monoBackground = (uint32_t)c0; \ + monoForeground = (uint32_t)c1; \ + } else { \ + monoBackground = (uint32_t)c1; \ + monoForeground = (uint32_t)c0; \ + } \ + paletteNumColors = 2; /* Two colors */ \ + return; \ + } \ + \ + PaletteReset(); \ + PaletteInsert (c0, (uint32_t)n0, bpp); \ + PaletteInsert (c1, (uint32_t)n1, bpp); \ + \ + ni = 1; \ + for (i++; i < count; i++) { \ + if (data[i] == ci) { \ + ni++; \ + } else { \ + if (!PaletteInsert (ci, (uint32_t)ni, bpp)) \ + return; \ + ci = data[i]; \ + ni = 1; \ + } \ + } \ + PaletteInsert (ci, (uint32_t)ni, bpp); \ +} + +DEFINE_FILL_PALETTE_FUNCTION(16) +DEFINE_FILL_PALETTE_FUNCTION(32) + + +/* + * Functions to operate with palette structures. + */ + +#define HASH_FUNC16(rgb) ((int)(((rgb >> 8) + rgb) & 0xFF)) +#define HASH_FUNC32(rgb) ((int)(((rgb >> 16) + (rgb >> 8)) & 0xFF)) + +static void +PaletteReset(void) +{ + paletteNumColors = 0; + memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *)); +} + +static int +PaletteInsert(uint32_t rgb, + int numPixels, + int bpp) +{ + COLOR_LIST *pnode; + COLOR_LIST *prev_pnode = NULL; + int hash_key, idx, new_idx, count; + + hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb); + + pnode = palette.hash[hash_key]; + + while (pnode != NULL) { + if (pnode->rgb == rgb) { + /* Such palette entry already exists. */ + new_idx = idx = pnode->idx; + count = palette.entry[idx].numPixels + numPixels; + if (new_idx && palette.entry[new_idx-1].numPixels < count) { + do { + palette.entry[new_idx] = palette.entry[new_idx-1]; + palette.entry[new_idx].listNode->idx = new_idx; + new_idx--; + } + while (new_idx && palette.entry[new_idx-1].numPixels < count); + palette.entry[new_idx].listNode = pnode; + pnode->idx = new_idx; + } + palette.entry[new_idx].numPixels = count; + return paletteNumColors; + } + prev_pnode = pnode; + pnode = pnode->next; + } + + /* Check if palette is full. */ + if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) { + paletteNumColors = 0; + return 0; + } + + /* Move palette entries with lesser pixel counts. */ + for ( idx = paletteNumColors; + idx > 0 && palette.entry[idx-1].numPixels < numPixels; + idx-- ) { + palette.entry[idx] = palette.entry[idx-1]; + palette.entry[idx].listNode->idx = idx; + } + + /* Add new palette entry into the freed slot. */ + pnode = &palette.list[paletteNumColors]; + if (prev_pnode != NULL) { + prev_pnode->next = pnode; + } else { + palette.hash[hash_key] = pnode; + } + pnode->next = NULL; + pnode->idx = idx; + pnode->rgb = rgb; + palette.entry[idx].listNode = pnode; + palette.entry[idx].numPixels = numPixels; + + return (++paletteNumColors); +} + + +/* + * Converting 32-bit color samples into 24-bit colors. + * Should be called only when redMax, greenMax and blueMax are 255. + * Color components assumed to be byte-aligned. + */ + +static void Pack24(rfbClientPtr cl, + char *buf, + rfbPixelFormat *fmt, + int count) +{ + uint32_t *buf32; + uint32_t pix; + int r_shift, g_shift, b_shift; + + buf32 = (uint32_t *)buf; + + if (!cl->screen->serverFormat.bigEndian == !fmt->bigEndian) { + r_shift = fmt->redShift; + g_shift = fmt->greenShift; + b_shift = fmt->blueShift; + } else { + r_shift = 24 - fmt->redShift; + g_shift = 24 - fmt->greenShift; + b_shift = 24 - fmt->blueShift; + } + + while (count--) { + pix = *buf32++; + *buf++ = (char)(pix >> r_shift); + *buf++ = (char)(pix >> g_shift); + *buf++ = (char)(pix >> b_shift); + } +} + + +/* + * Converting truecolor samples into palette indices. + */ + +#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \ + \ +static void \ +EncodeIndexedRect##bpp(uint8_t *buf, int count) { \ + COLOR_LIST *pnode; \ + uint##bpp##_t *src; \ + uint##bpp##_t rgb; \ + int rep = 0; \ + \ + src = (uint##bpp##_t *) buf; \ + \ + while (count--) { \ + rgb = *src++; \ + while (count && *src == rgb) { \ + rep++, src++, count--; \ + } \ + pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \ + while (pnode != NULL) { \ + if ((uint##bpp##_t)pnode->rgb == rgb) { \ + *buf++ = (uint8_t)pnode->idx; \ + while (rep) { \ + *buf++ = (uint8_t)pnode->idx; \ + rep--; \ + } \ + break; \ + } \ + pnode = pnode->next; \ + } \ + } \ +} + +DEFINE_IDX_ENCODE_FUNCTION(16) +DEFINE_IDX_ENCODE_FUNCTION(32) + +#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \ + \ +static void \ +EncodeMonoRect##bpp(uint8_t *buf, int w, int h) { \ + uint##bpp##_t *ptr; \ + uint##bpp##_t bg; \ + unsigned int value, mask; \ + int aligned_width; \ + int x, y, bg_bits; \ + \ + ptr = (uint##bpp##_t *) buf; \ + bg = (uint##bpp##_t) monoBackground; \ + aligned_width = w - w % 8; \ + \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < aligned_width; x += 8) { \ + for (bg_bits = 0; bg_bits < 8; bg_bits++) { \ + if (*ptr++ != bg) \ + break; \ + } \ + if (bg_bits == 8) { \ + *buf++ = 0; \ + continue; \ + } \ + mask = 0x80 >> bg_bits; \ + value = mask; \ + for (bg_bits++; bg_bits < 8; bg_bits++) { \ + mask >>= 1; \ + if (*ptr++ != bg) { \ + value |= mask; \ + } \ + } \ + *buf++ = (uint8_t)value; \ + } \ + \ + mask = 0x80; \ + value = 0; \ + if (x >= w) \ + continue; \ + \ + for (; x < w; x++) { \ + if (*ptr++ != bg) { \ + value |= mask; \ + } \ + mask >>= 1; \ + } \ + *buf++ = (uint8_t)value; \ + } \ +} + +DEFINE_MONO_ENCODE_FUNCTION(8) +DEFINE_MONO_ENCODE_FUNCTION(16) +DEFINE_MONO_ENCODE_FUNCTION(32) + + +/* + * ``Gradient'' filter for 24-bit color samples. + * Should be called only when redMax, greenMax and blueMax are 255. + * Color components assumed to be byte-aligned. + */ + +static void +FilterGradient24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int w, int h) +{ + uint32_t *buf32; + uint32_t pix32; + int *prevRowPtr; + int shiftBits[3]; + int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; + int prediction; + int x, y, c; + + buf32 = (uint32_t *)buf; + memset (prevRowBuf, 0, w * 3 * sizeof(int)); + + if (!cl->screen->serverFormat.bigEndian == !fmt->bigEndian) { + shiftBits[0] = fmt->redShift; + shiftBits[1] = fmt->greenShift; + shiftBits[2] = fmt->blueShift; + } else { + shiftBits[0] = 24 - fmt->redShift; + shiftBits[1] = 24 - fmt->greenShift; + shiftBits[2] = 24 - fmt->blueShift; + } + + for (y = 0; y < h; y++) { + for (c = 0; c < 3; c++) { + pixUpper[c] = 0; + pixHere[c] = 0; + } + prevRowPtr = prevRowBuf; + for (x = 0; x < w; x++) { + pix32 = *buf32++; + for (c = 0; c < 3; c++) { + pixUpperLeft[c] = pixUpper[c]; + pixLeft[c] = pixHere[c]; + pixUpper[c] = *prevRowPtr; + pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF); + *prevRowPtr++ = pixHere[c]; + + prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; + if (prediction < 0) { + prediction = 0; + } else if (prediction > 0xFF) { + prediction = 0xFF; + } + *buf++ = (char)(pixHere[c] - prediction); + } + } + } +} + + +/* + * ``Gradient'' filter for other color depths. + */ + +#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \ + \ +static void \ +FilterGradient##bpp(rfbClientPtr cl, uint##bpp##_t *buf, \ + rfbPixelFormat *fmt, int w, int h) { \ + uint##bpp##_t pix, diff; \ + rfbBool endianMismatch; \ + int *prevRowPtr; \ + int maxColor[3], shiftBits[3]; \ + int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \ + int prediction; \ + int x, y, c; \ + \ + memset (prevRowBuf, 0, w * 3 * sizeof(int)); \ + \ + endianMismatch = (!cl->screen->serverFormat.bigEndian != !fmt->bigEndian); \ + \ + maxColor[0] = fmt->redMax; \ + maxColor[1] = fmt->greenMax; \ + maxColor[2] = fmt->blueMax; \ + shiftBits[0] = fmt->redShift; \ + shiftBits[1] = fmt->greenShift; \ + shiftBits[2] = fmt->blueShift; \ + \ + for (y = 0; y < h; y++) { \ + for (c = 0; c < 3; c++) { \ + pixUpper[c] = 0; \ + pixHere[c] = 0; \ + } \ + prevRowPtr = prevRowBuf; \ + for (x = 0; x < w; x++) { \ + pix = *buf; \ + if (endianMismatch) { \ + pix = Swap##bpp(pix); \ + } \ + diff = 0; \ + for (c = 0; c < 3; c++) { \ + pixUpperLeft[c] = pixUpper[c]; \ + pixLeft[c] = pixHere[c]; \ + pixUpper[c] = *prevRowPtr; \ + pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ + *prevRowPtr++ = pixHere[c]; \ + \ + prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \ + if (prediction < 0) { \ + prediction = 0; \ + } else if (prediction > maxColor[c]) { \ + prediction = maxColor[c]; \ + } \ + diff |= ((pixHere[c] - prediction) & maxColor[c]) \ + << shiftBits[c]; \ + } \ + if (endianMismatch) { \ + diff = Swap##bpp(diff); \ + } \ + *buf++ = diff; \ + } \ + } \ +} + +DEFINE_GRADIENT_FILTER_FUNCTION(16) +DEFINE_GRADIENT_FILTER_FUNCTION(32) + + +/* + * Code to guess if given rectangle is suitable for smooth image + * compression (by applying "gradient" filter or JPEG coder). + */ + +#define JPEG_MIN_RECT_SIZE 4096 + +#define DETECT_SUBROW_WIDTH 7 +#define DETECT_MIN_WIDTH 8 +#define DETECT_MIN_HEIGHT 8 + +static int +DetectSmoothImage (rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h) +{ + long avgError; + + if ( cl->screen->serverFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 || + w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) { + return 0; + } + + if (qualityLevel != -1) { + if (w * h < JPEG_MIN_RECT_SIZE) { + return 0; + } + } else { + if ( rfbTightDisableGradient || + w * h < tightConf[compressLevel].gradientMinRectSize ) { + return 0; + } + } + + if (fmt->bitsPerPixel == 32) { + if (usePixelFormat24) { + avgError = DetectSmoothImage24(cl, fmt, w, h); + if (qualityLevel != -1) { + return (avgError < tightConf[qualityLevel].jpegThreshold24); + } + return (avgError < tightConf[compressLevel].gradientThreshold24); + } else { + avgError = DetectSmoothImage32(cl, fmt, w, h); + } + } else { + avgError = DetectSmoothImage16(cl, fmt, w, h); + } + if (qualityLevel != -1) { + return (avgError < tightConf[qualityLevel].jpegThreshold); + } + return (avgError < tightConf[compressLevel].gradientThreshold); +} + +static unsigned long +DetectSmoothImage24 (rfbClientPtr cl, + rfbPixelFormat *fmt, + int w, + int h) +{ + int off; + int x, y, d, dx, c; + int diffStat[256]; + int pixelCount = 0; + int pix, left[3]; + unsigned long avgError; + + /* If client is big-endian, color samples begin from the second + byte (offset 1) of a 32-bit pixel value. */ + off = (fmt->bigEndian != 0); + + memset(diffStat, 0, 256*sizeof(int)); + + y = 0, x = 0; + while (y < h && x < w) { + for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { + for (c = 0; c < 3; c++) { + left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF; + } + for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { + for (c = 0; c < 3; c++) { + pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF; + diffStat[abs(pix - left[c])]++; + left[c] = pix; + } + pixelCount++; + } + } + if (w > h) { + x += h; + y = 0; + } else { + x = 0; + y += w; + } + } + + if (diffStat[0] * 33 / pixelCount >= 95) + return 0; + + avgError = 0; + for (c = 1; c < 8; c++) { + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); + if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) + return 0; + } + for (; c < 256; c++) { + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); + } + avgError /= (pixelCount * 3 - diffStat[0]); + + return avgError; +} + +#define DEFINE_DETECT_FUNCTION(bpp) \ + \ +static unsigned long \ +DetectSmoothImage##bpp (rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h) {\ + rfbBool endianMismatch; \ + uint##bpp##_t pix; \ + int maxColor[3], shiftBits[3]; \ + int x, y, d, dx, c; \ + int diffStat[256]; \ + int pixelCount = 0; \ + int sample, sum, left[3]; \ + unsigned long avgError; \ + \ + endianMismatch = (!cl->screen->serverFormat.bigEndian != !fmt->bigEndian); \ + \ + maxColor[0] = fmt->redMax; \ + maxColor[1] = fmt->greenMax; \ + maxColor[2] = fmt->blueMax; \ + shiftBits[0] = fmt->redShift; \ + shiftBits[1] = fmt->greenShift; \ + shiftBits[2] = fmt->blueShift; \ + \ + memset(diffStat, 0, 256*sizeof(int)); \ + \ + y = 0, x = 0; \ + while (y < h && x < w) { \ + for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \ + pix = ((uint##bpp##_t *)tightBeforeBuf)[(y+d)*w+x+d]; \ + if (endianMismatch) { \ + pix = Swap##bpp(pix); \ + } \ + for (c = 0; c < 3; c++) { \ + left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ + } \ + for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \ + pix = ((uint##bpp##_t *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \ + if (endianMismatch) { \ + pix = Swap##bpp(pix); \ + } \ + sum = 0; \ + for (c = 0; c < 3; c++) { \ + sample = (int)(pix >> shiftBits[c] & maxColor[c]); \ + sum += abs(sample - left[c]); \ + left[c] = sample; \ + } \ + if (sum > 255) \ + sum = 255; \ + diffStat[sum]++; \ + pixelCount++; \ + } \ + } \ + if (w > h) { \ + x += h; \ + y = 0; \ + } else { \ + x = 0; \ + y += w; \ + } \ + } \ + \ + if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \ + return 0; \ + \ + avgError = 0; \ + for (c = 1; c < 8; c++) { \ + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ + if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \ + return 0; \ + } \ + for (; c < 256; c++) { \ + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ + } \ + avgError /= (pixelCount - diffStat[0]); \ + \ + return avgError; \ +} + +DEFINE_DETECT_FUNCTION(16) +DEFINE_DETECT_FUNCTION(32) + + +/* + * JPEG compression stuff. + */ + +static TLS struct jpeg_destination_mgr jpegDstManager; +static TLS rfbBool jpegError = FALSE; +static TLS int jpegDstDataLen = 0; + +static rfbBool +SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + uint8_t *srcBuf; + JSAMPROW rowPointer[1]; + int dy; + + if (cl->screen->serverFormat.bitsPerPixel == 8) + return SendFullColorRect(cl, x, y, w, h); + + srcBuf = (uint8_t *)malloc(w * 3); + if (srcBuf == NULL) { + return SendFullColorRect(cl, x, y, w, h); + } + rowPointer[0] = srcBuf; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + cinfo.image_width = w; + cinfo.image_height = h; + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + + JpegSetDstManager (&cinfo); + + jpeg_start_compress(&cinfo, TRUE); + + for (dy = 0; dy < h; dy++) { + PrepareRowForImg(cl, srcBuf, x, y + dy, w); + jpeg_write_scanlines(&cinfo, rowPointer, 1); + if (jpegError) + break; + } + + if (!jpegError) + jpeg_finish_compress(&cinfo); + + jpeg_destroy_compress(&cinfo); + free(srcBuf); + + if (jpegError) + return SendFullColorRect(cl, x, y, w, h); + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + + return SendCompressedData(cl, jpegDstDataLen); +} + +static void +PrepareRowForImg(rfbClientPtr cl, + uint8_t *dst, + int x, + int y, + int count) +{ + if (cl->screen->serverFormat.bitsPerPixel == 32) { + if ( cl->screen->serverFormat.redMax == 0xFF && + cl->screen->serverFormat.greenMax == 0xFF && + cl->screen->serverFormat.blueMax == 0xFF ) { + PrepareRowForImg24(cl, dst, x, y, count); + } else { + PrepareRowForImg32(cl, dst, x, y, count); + } + } else { + /* 16 bpp assumed. */ + PrepareRowForImg16(cl, dst, x, y, count); + } +} + +static void +PrepareRowForImg24(rfbClientPtr cl, + uint8_t *dst, + int x, + int y, + int count) +{ + uint32_t *fbptr; + uint32_t pix; + + fbptr = (uint32_t *) + &cl->scaledScreen->frameBuffer[y * cl->scaledScreen->paddedWidthInBytes + x * 4]; + + while (count--) { + pix = *fbptr++; + *dst++ = (uint8_t)(pix >> cl->screen->serverFormat.redShift); + *dst++ = (uint8_t)(pix >> cl->screen->serverFormat.greenShift); + *dst++ = (uint8_t)(pix >> cl->screen->serverFormat.blueShift); + } +} + +#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ + \ +static void \ +PrepareRowForImg##bpp(rfbClientPtr cl, uint8_t *dst, int x, int y, int count) { \ + uint##bpp##_t *fbptr; \ + uint##bpp##_t pix; \ + int inRed, inGreen, inBlue; \ + \ + fbptr = (uint##bpp##_t *) \ + &cl->scaledScreen->frameBuffer[y * cl->scaledScreen->paddedWidthInBytes + \ + x * (bpp / 8)]; \ + \ + while (count--) { \ + pix = *fbptr++; \ + \ + inRed = (int) \ + (pix >> cl->screen->serverFormat.redShift & cl->screen->serverFormat.redMax); \ + inGreen = (int) \ + (pix >> cl->screen->serverFormat.greenShift & cl->screen->serverFormat.greenMax); \ + inBlue = (int) \ + (pix >> cl->screen->serverFormat.blueShift & cl->screen->serverFormat.blueMax); \ + \ + *dst++ = (uint8_t)((inRed * 255 + cl->screen->serverFormat.redMax / 2) / \ + cl->screen->serverFormat.redMax); \ + *dst++ = (uint8_t)((inGreen * 255 + cl->screen->serverFormat.greenMax / 2) / \ + cl->screen->serverFormat.greenMax); \ + *dst++ = (uint8_t)((inBlue * 255 + cl->screen->serverFormat.blueMax / 2) / \ + cl->screen->serverFormat.blueMax); \ + } \ +} + +DEFINE_JPEG_GET_ROW_FUNCTION(16) +DEFINE_JPEG_GET_ROW_FUNCTION(32) + +/* + * Destination manager implementation for JPEG library. + */ + +static void +JpegInitDestination(j_compress_ptr cinfo) +{ + jpegError = FALSE; + jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; + jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; +} + +static boolean +JpegEmptyOutputBuffer(j_compress_ptr cinfo) +{ + jpegError = TRUE; + jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; + jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; + + return TRUE; +} + +static void +JpegTermDestination(j_compress_ptr cinfo) +{ + jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer; +} + +static void +JpegSetDstManager(j_compress_ptr cinfo) +{ + jpegDstManager.init_destination = JpegInitDestination; + jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer; + jpegDstManager.term_destination = JpegTermDestination; + cinfo->dest = &jpegDstManager; +} + +/* + * PNG compression stuff. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + +static TLS int pngDstDataLen = 0; + +static rfbBool CanSendPngRect(rfbClientPtr cl, int w, int h) { + if (cl->tightEncoding != rfbEncodingTightPng) { + return FALSE; + } + + if ( cl->screen->serverFormat.bitsPerPixel == 8 || + cl->format.bitsPerPixel == 8) { + return FALSE; + } + + return TRUE; +} + +static void pngWriteData(png_structp png_ptr, png_bytep data, + png_size_t length) +{ + //rfbClientPtr cl = png_get_io_ptr(png_ptr); + + //buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); + //memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); + memcpy(tightAfterBuf + pngDstDataLen, data, length); + + pngDstDataLen += length; +} + +static void pngFlushData(png_structp png_ptr) +{ +} + + +static void *pngMalloc(png_structp png_ptr, png_size_t size) +{ + return malloc(size); +} + +static void pngFree(png_structp png_ptr, png_voidp ptr) +{ + free(ptr); +} + +static rfbBool SendPngRect(rfbClientPtr cl, int x, int y, int w, int h) { + //rfbLog(">> SendPngRect x:%d, y:%d, w:%d, h:%d\n", x, y, w, h); + + png_byte color_type; + png_structp png_ptr; + png_infop info_ptr; + png_colorp png_palette = NULL; + int level = tightPngConf[cl->tightCompressLevel].png_zlib_level; + int filters = tightPngConf[cl->tightCompressLevel].png_filters; + uint8_t *buf; + int dy; + + pngDstDataLen = 0; + + png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, + NULL, pngMalloc, pngFree); + + if (png_ptr == NULL) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, NULL); + return FALSE; + } + + png_set_write_fn(png_ptr, (void *) cl, pngWriteData, pngFlushData); + png_set_compression_level(png_ptr, level); + png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, filters); + +// TODO: +// if (palette) { +// color_type = PNG_COLOR_TYPE_PALETTE; +// } else { + color_type = PNG_COLOR_TYPE_RGB; +// } + + png_set_IHDR(png_ptr, info_ptr, w, h, + 8, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + +// if (color_type == PNG_COLOR_TYPE_PALETTE) { +// struct palette_cb_priv priv; +// +// png_palette = pngMalloc(png_ptr, sizeof(*png_palette) * +// palette_size(palette)); +// +// priv.vs = vs; +// priv.png_palette = png_palette; +// palette_iter(palette, write_png_palette, &priv); +// +// png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); +// +// offset = vs->tight.tight.offset; +// if (vs->clientds.pf.bytes_per_pixel == 4) { +// tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); +// } else { +// tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); +// } +// } + + png_write_info(png_ptr, info_ptr); + + ////buffer_reserve(&vs->tight.png, 2048); + buf = malloc(w * 3); + for (dy = 0; dy < h; dy++) + { +// if (color_type == PNG_COLOR_TYPE_PALETTE) { +// memcpy(buf, vs->tight.tight.buffer + (dy * w), w); +// } else { + PrepareRowForImg(cl, buf, x, y + dy, w); +// } + png_write_row(png_ptr, buf); + } + free(buf); + + png_write_end(png_ptr, NULL); + + if (color_type == PNG_COLOR_TYPE_PALETTE) { + pngFree(png_ptr, png_palette); + } + + png_destroy_write_struct(&png_ptr, &info_ptr); + + // done v + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = (char)(rfbTightPng << 4); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + + //rfbLog("<< SendPngRect\n"); + return SendCompressedData(cl, pngDstDataLen); +} +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/.cvsignore new file mode 100755 index 0000000..22a4e72 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.c new file mode 100755 index 0000000..c08e506 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#include +#include "rfb/rfb.h" +#include "filelistinfo.h" + + +/* This method is used for debugging purpose */ +void +DisplayFileList(FileListInfo fli) +{ + int i = 0; + if((fli.pEntries == NULL) || (fli.numEntries == 0)) return; + + rfbLog("DISPLAYING FILE NAMES IN THE LIST ...START\n\n"); + rfbLog("Numer of entries:: %d\n", fli.numEntries); + for(i = 0; i < fli.numEntries; i++) + rfbLog("file[%d]\t<%s>\n", i, fli.pEntries[i].name); + rfbLog("DISPLAYING FILE NAMES IN THE LIST ...END\n\n"); +} + +#ifndef __GNUC__ +#define __FUNCTION__ "unknown" +#endif + +int +AddFileListItemInfo(FileListInfoPtr fileListInfoPtr, char* name, + unsigned int size, unsigned int data) +{ + FileListItemInfoPtr fileListItemInfoPtr = (FileListItemInfoPtr) + calloc((fileListInfoPtr->numEntries + 1), + sizeof(FileListItemInfo)); + if(fileListItemInfoPtr == NULL) { + rfbLog("File [%s]: Method [%s]: fileListItemInfoPtr is NULL\n", + __FILE__, __FUNCTION__); + return FAILURE; + } + + if(fileListInfoPtr->numEntries != 0) { + memcpy(fileListItemInfoPtr, fileListInfoPtr->pEntries, + fileListInfoPtr->numEntries * sizeof(FileListItemInfo)); + } + + strcpy(fileListItemInfoPtr[fileListInfoPtr->numEntries].name, name); + fileListItemInfoPtr[fileListInfoPtr->numEntries].size = size; + fileListItemInfoPtr[fileListInfoPtr->numEntries].data = data; + + if(fileListInfoPtr->pEntries != NULL) { + free(fileListInfoPtr->pEntries); + fileListInfoPtr->pEntries = NULL; + } + + fileListInfoPtr->pEntries = fileListItemInfoPtr; + fileListItemInfoPtr = NULL; + fileListInfoPtr->numEntries++; + + return SUCCESS; +} + + +char* +GetFileNameAt(FileListInfo fileListInfo, int number) +{ + char* name = NULL; + if(number >= 0 && number < fileListInfo.numEntries) + name = fileListInfo.pEntries[number].name; + return name; +} + + +unsigned int +GetFileSizeAt(FileListInfo fileListInfo, int number) +{ + unsigned int size = 0; + if(number >= 0 && number < fileListInfo.numEntries) + size = fileListInfo.pEntries[number].size; + return size; +} + + +unsigned int +GetFileDataAt(FileListInfo fileListInfo, int number) +{ + unsigned int data = 0; + if(number >= 0 && number < fileListInfo.numEntries) + data = fileListInfo.pEntries[number].data; + return data; +} + + +unsigned int +GetSumOfFileNamesLength(FileListInfo fileListInfo) +{ + int i = 0, sumLen = 0; + for(i = 0; i < fileListInfo.numEntries; i++) + sumLen += strlen(fileListInfo.pEntries[i].name); + return sumLen; +} + + +void +FreeFileListInfo(FileListInfo fileListInfo) +{ + if(fileListInfo.pEntries != NULL) { + free(fileListInfo.pEntries); + fileListInfo.pEntries = NULL; + } + fileListInfo.numEntries = 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.h new file mode 100755 index 0000000..a53964c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#ifndef FILE_LIST_INFO_H +#define FILE_LIST_INFO_H + +#include + +#if !defined(NAME_MAX) +#define NAME_MAX 255 +#endif + + +#define SUCCESS 1 +#define FAILURE 0 + +typedef struct _FileListItemInfo { + char name[NAME_MAX]; + unsigned int size; + unsigned int data; +} FileListItemInfo, *FileListItemInfoPtr; + +typedef struct _FileListItemSize { + unsigned int size; + unsigned int data; +} FileListItemSize, *FileListItemSizePtr; + +typedef struct _FileListInfo { + FileListItemInfoPtr pEntries; + int numEntries; +} FileListInfo, *FileListInfoPtr; + +int AddFileListItemInfo(FileListInfoPtr fileListInfoPtr, char* name, unsigned int size, unsigned int data); +char* GetFileNameAt(FileListInfo fileListInfo, int number); +unsigned int GetFileSizeAt(FileListInfo fileListInfo, int number); +unsigned int GetFileDataAt(FileListInfo fileListInfo, int number); +unsigned int GetSumOfFileNamesLength(FileListInfo fileListInfo); +void FreeFileListInfo(FileListInfo fileListInfo); + +void DisplayFileList(FileListInfo fli); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.c new file mode 100755 index 0000000..7dae2cd --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rfbtightproto.h" +#include "filelistinfo.h" +#include "filetransfermsg.h" +#include "handlefiletransferrequest.h" + +#define SZ_RFBBLOCKSIZE 8192 + + +void +FreeFileTransferMsg(FileTransferMsg ftm) +{ + + if(ftm.data != NULL) { + free(ftm.data); + ftm.data = NULL; + } + + ftm.length = 0; + +} + + +/****************************************************************************** + * Methods to handle file list request. + ******************************************************************************/ + +int CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag); +FileTransferMsg CreateFileListErrMsg(char flags); +FileTransferMsg CreateFileListMsg(FileListInfo fileListInfo, char flags); + + +/* + * This is the method called by HandleFileListRequest to get the file list + */ + +FileTransferMsg +GetFileListResponseMsg(char* path, char flags) +{ + FileTransferMsg fileListMsg; + FileListInfo fileListInfo; + int status = -1; + + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + memset(&fileListInfo, 0, sizeof(FileListInfo)); + + + /* fileListInfo can have null data if the folder is Empty + or if some error condition has occured. + The return value is 'failure' only if some error condition has occured. + */ + status = CreateFileListInfo(&fileListInfo, path, !(flags & 0x10)); + + if(status == FAILURE) { + fileListMsg = CreateFileListErrMsg(flags); + } + else { + /* DisplayFileList(fileListInfo); For Debugging */ + + fileListMsg = CreateFileListMsg(fileListInfo, flags); + FreeFileListInfo(fileListInfo); + } + + return fileListMsg; +} + +#ifndef __GNUC__ +#define __FUNCTION__ "unknown" +#endif + +int +CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag) +{ + DIR* pDir = NULL; + struct dirent* pDirent = NULL; + + if((path == NULL) || (strlen(path) == 0)) { + /* In this case we will send the list of entries in ftp root*/ + sprintf(path, "%s%s", GetFtpRoot(), "/"); + } + + if((pDir = opendir(path)) == NULL) { + rfbLog("File [%s]: Method [%s]: not able to open the dir\n", + __FILE__, __FUNCTION__); + return FAILURE; + } + + while((pDirent = readdir(pDir))) { + if(strcmp(pDirent->d_name, ".") && strcmp(pDirent->d_name, "..")) { + struct stat stat_buf; + /* + int fpLen = sizeof(char)*(strlen(pDirent->d_name)+strlen(path)+2); + */ + char fullpath[PATH_MAX]; + + memset(fullpath, 0, PATH_MAX); + + strcpy(fullpath, path); + if(path[strlen(path)-1] != '/') + strcat(fullpath, "/"); + strcat(fullpath, pDirent->d_name); + + if(stat(fullpath, &stat_buf) < 0) { + rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n", + __FILE__, __FUNCTION__, fullpath); + continue; + } + + if(S_ISDIR(stat_buf.st_mode)) { + if(AddFileListItemInfo(pFileListInfo, pDirent->d_name, -1, 0) == 0) { + rfbLog("File [%s]: Method [%s]: Add directory %s in the" + " list failed\n", __FILE__, __FUNCTION__, fullpath); + continue; + } + } + else { + if(flag) { + if(AddFileListItemInfo(pFileListInfo, pDirent->d_name, + stat_buf.st_size, + stat_buf.st_mtime) == 0) { + rfbLog("File [%s]: Method [%s]: Add file %s in the " + "list failed\n", __FILE__, __FUNCTION__, fullpath); + continue; + } + } + } + } + } + if(closedir(pDir) < 0) { + rfbLog("File [%s]: Method [%s]: ERROR Couldn't close dir\n", + __FILE__, __FUNCTION__); + } + + return SUCCESS; +} + + +FileTransferMsg +CreateFileListErrMsg(char flags) +{ + FileTransferMsg fileListMsg; + rfbFileListDataMsg* pFLD = NULL; + char* data = NULL; + unsigned int length = 0; + + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + + data = (char*) calloc(sizeof(rfbFileListDataMsg), sizeof(char)); + if(data == NULL) { + return fileListMsg; + } + length = sizeof(rfbFileListDataMsg) * sizeof(char); + pFLD = (rfbFileListDataMsg*) data; + + pFLD->type = rfbFileListData; + pFLD->numFiles = Swap16IfLE(0); + pFLD->dataSize = Swap16IfLE(0); + pFLD->compressedSize = Swap16IfLE(0); + pFLD->flags = flags | 0x80; + + fileListMsg.data = data; + fileListMsg.length = length; + + return fileListMsg; +} + + +FileTransferMsg +CreateFileListMsg(FileListInfo fileListInfo, char flags) +{ + FileTransferMsg fileListMsg; + rfbFileListDataMsg* pFLD = NULL; + char *data = NULL, *pFileNames = NULL; + unsigned int length = 0, dsSize = 0, i = 0; + FileListItemSizePtr pFileListItemSize = NULL; + + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + dsSize = fileListInfo.numEntries * 8; + length = sz_rfbFileListDataMsg + dsSize + + GetSumOfFileNamesLength(fileListInfo) + + fileListInfo.numEntries; + + data = (char*) calloc(length, sizeof(char)); + if(data == NULL) { + return fileListMsg; + } + pFLD = (rfbFileListDataMsg*) data; + pFileListItemSize = (FileListItemSizePtr) &data[sz_rfbFileListDataMsg]; + pFileNames = &data[sz_rfbFileListDataMsg + dsSize]; + + pFLD->type = rfbFileListData; + pFLD->flags = flags & 0xF0; + pFLD->numFiles = Swap16IfLE(fileListInfo.numEntries); + pFLD->dataSize = Swap16IfLE(GetSumOfFileNamesLength(fileListInfo) + + fileListInfo.numEntries); + pFLD->compressedSize = pFLD->dataSize; + + for(i =0; i rcft.rcfd.fName; + + memset(pBuf, 0, SZ_RFBBLOCKSIZE); + + if((rtcp->rcft.rcfd.downloadInProgress == FALSE) && (rtcp->rcft.rcfd.downloadFD == -1)) { + if((rtcp->rcft.rcfd.downloadFD = open(path, O_RDONLY)) == -1) { + rfbLog("File [%s]: Method [%s]: Error: Couldn't open file\n", + __FILE__, __FUNCTION__); + return GetFileDownloadReadDataErrMsg(); + } + rtcp->rcft.rcfd.downloadInProgress = TRUE; + } + if((rtcp->rcft.rcfd.downloadInProgress == TRUE) && (rtcp->rcft.rcfd.downloadFD != -1)) { + if( (numOfBytesRead = read(rtcp->rcft.rcfd.downloadFD, pBuf, SZ_RFBBLOCKSIZE)) <= 0) { + close(rtcp->rcft.rcfd.downloadFD); + rtcp->rcft.rcfd.downloadFD = -1; + rtcp->rcft.rcfd.downloadInProgress = FALSE; + if(numOfBytesRead == 0) { + return CreateFileDownloadZeroSizeDataMsg(rtcp->rcft.rcfd.mTime); + } + return GetFileDownloadReadDataErrMsg(); + } + return CreateFileDownloadBlockSizeDataMsg(numOfBytesRead, pBuf); + } + return GetFileDownLoadErrMsg(); +} + + +FileTransferMsg +ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + FileTransferMsg fileDownloadMsg; + struct stat stat_buf; + int sz_rfbFileSize = 0; + char* path = rtcp->rcft.rcfd.fName; + + memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg)); + + if( (path == NULL) || (strlen(path) == 0) || + (stat(path, &stat_buf) < 0) || (!(S_ISREG(stat_buf.st_mode))) ) { + + char reason[] = "Cannot open file, perhaps it is absent or is not a regular file"; + int reasonLen = strlen(reason); + + rfbLog("File [%s]: Method [%s]: Reading stat for path %s failed\n", + __FILE__, __FUNCTION__, path); + + fileDownloadMsg = CreateFileDownloadErrMsg(reason, reasonLen); + } + else { + rtcp->rcft.rcfd.mTime = stat_buf.st_mtime; + sz_rfbFileSize = stat_buf.st_size; + if(sz_rfbFileSize <= 0) { + fileDownloadMsg = CreateFileDownloadZeroSizeDataMsg(stat_buf.st_mtime); + } + + } + return fileDownloadMsg; +} + + +FileTransferMsg +CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen) +{ + FileTransferMsg fileDownloadErrMsg; + int length = sz_rfbFileDownloadFailedMsg + reasonLen + 1; + rfbFileDownloadFailedMsg *pFDF = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg)); + if(pData == NULL) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileDownloadErrMsg; + } + + pFDF = (rfbFileDownloadFailedMsg *) pData; + pFollow = &pData[sz_rfbFileDownloadFailedMsg]; + + pFDF->type = rfbFileDownloadFailed; + pFDF->reasonLen = Swap16IfLE(reasonLen); + memcpy(pFollow, reason, reasonLen); + + fileDownloadErrMsg.data = pData; + fileDownloadErrMsg.length = length; + + return fileDownloadErrMsg; +} + + +FileTransferMsg +CreateFileDownloadZeroSizeDataMsg(unsigned long mTime) +{ + FileTransferMsg fileDownloadZeroSizeDataMsg; + int length = sz_rfbFileDownloadDataMsg + sizeof(int); + rfbFileDownloadDataMsg *pFDD = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileDownloadZeroSizeDataMsg, 0, sizeof(FileTransferMsg)); + if(pData == NULL) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileDownloadZeroSizeDataMsg; + } + + pFDD = (rfbFileDownloadDataMsg *) pData; + pFollow = &pData[sz_rfbFileDownloadDataMsg]; + + pFDD->type = rfbFileDownloadData; + pFDD->compressLevel = 0; + pFDD->compressedSize = Swap16IfLE(0); + pFDD->realSize = Swap16IfLE(0); + + memcpy(pFollow, &mTime, sizeof(unsigned long)); + + fileDownloadZeroSizeDataMsg.data = pData; + fileDownloadZeroSizeDataMsg.length = length; + + return fileDownloadZeroSizeDataMsg; + +} + + +FileTransferMsg +CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile) +{ + FileTransferMsg fileDownloadBlockSizeDataMsg; + int length = sz_rfbFileDownloadDataMsg + sizeFile; + rfbFileDownloadDataMsg *pFDD = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileDownloadBlockSizeDataMsg, 0, sizeof(FileTransferMsg)); + if(NULL == pData) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileDownloadBlockSizeDataMsg; + } + + pFDD = (rfbFileDownloadDataMsg *) pData; + pFollow = &pData[sz_rfbFileDownloadDataMsg]; + + pFDD->type = rfbFileDownloadData; + pFDD->compressLevel = 0; + pFDD->compressedSize = Swap16IfLE(sizeFile); + pFDD->realSize = Swap16IfLE(sizeFile); + + memcpy(pFollow, pFile, sizeFile); + + fileDownloadBlockSizeDataMsg.data = pData; + fileDownloadBlockSizeDataMsg.length = length; + + return fileDownloadBlockSizeDataMsg; + +} + + +/****************************************************************************** + * Methods to handle file upload request + ******************************************************************************/ + +FileTransferMsg CreateFileUploadErrMsg(char* reason, unsigned int reasonLen); + +FileTransferMsg +GetFileUploadLengthErrResponseMsg() +{ + char reason [] = "Path length exceeds PATH_MAX (4096) bytes"; + int reasonLen = strlen(reason); + + return CreateFileUploadErrMsg(reason, reasonLen); +} + + +FileTransferMsg +ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + FileTransferMsg fileUploadErrMsg; + + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + if( (rtcp->rcft.rcfu.fName == NULL) || + (strlen(rtcp->rcft.rcfu.fName) == 0) || + ((rtcp->rcft.rcfu.uploadFD = creat(rtcp->rcft.rcfu.fName, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1)) { + + char reason[] = "Could not create file"; + int reasonLen = strlen(reason); + fileUploadErrMsg = CreateFileUploadErrMsg(reason, reasonLen); + } + else + rtcp->rcft.rcfu.uploadInProgress = TRUE; + + return fileUploadErrMsg; +} + + +FileTransferMsg +GetFileUploadCompressedLevelErrMsg() +{ + char reason[] = "Server does not support data compression on upload"; + int reasonLen = strlen(reason); + + return CreateFileUploadErrMsg(reason, reasonLen); +} + + +FileTransferMsg +ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf) +{ + FileTransferMsg ftm; + unsigned long numOfBytesWritten = 0; + + memset(&ftm, 0, sizeof(FileTransferMsg)); + + numOfBytesWritten = write(rtcp->rcft.rcfu.uploadFD, pBuf, rtcp->rcft.rcfu.fSize); + + if(numOfBytesWritten != rtcp->rcft.rcfu.fSize) { + char reason[] = "Error writing file data"; + int reasonLen = strlen(reason); + ftm = CreateFileUploadErrMsg(reason, reasonLen); + CloseUndoneFileTransfer(cl, rtcp); + } + return ftm; +} + + +void +FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + /* Here we are settimg the modification and access time of the file */ + /* Windows code stes mod/access/creation time of the file */ + struct utimbuf utb; + + utb.actime = utb.modtime = rtcp->rcft.rcfu.mTime; + if(utime(rtcp->rcft.rcfu.fName, &utb) == -1) { + rfbLog("File [%s]: Method [%s]: Setting the modification/access" + " time for the file <%s> failed\n", __FILE__, + __FUNCTION__, rtcp->rcft.rcfu.fName); + } + + if(rtcp->rcft.rcfu.uploadFD != -1) { + close(rtcp->rcft.rcfu.uploadFD); + rtcp->rcft.rcfu.uploadFD = -1; + rtcp->rcft.rcfu.uploadInProgress = FALSE; + } +} + + +FileTransferMsg +CreateFileUploadErrMsg(char* reason, unsigned int reasonLen) +{ + FileTransferMsg fileUploadErrMsg; + int length = sz_rfbFileUploadCancelMsg + reasonLen; + rfbFileUploadCancelMsg *pFDF = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + if(pData == NULL) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileUploadErrMsg; + } + + pFDF = (rfbFileUploadCancelMsg *) pData; + pFollow = &pData[sz_rfbFileUploadCancelMsg]; + + pFDF->type = rfbFileUploadCancel; + pFDF->reasonLen = Swap16IfLE(reasonLen); + memcpy(pFollow, reason, reasonLen); + + fileUploadErrMsg.data = pData; + fileUploadErrMsg.length = length; + + return fileUploadErrMsg; +} + + +/****************************************************************************** + * Method to cancel File Transfer operation. + ******************************************************************************/ + +void +CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + /* TODO :: File Upload case is not handled currently */ + /* TODO :: In case of concurrency we need to use Critical Section */ + + if(cl == NULL) + return; + + + if(rtcp->rcft.rcfu.uploadInProgress == TRUE) { + rtcp->rcft.rcfu.uploadInProgress = FALSE; + + if(rtcp->rcft.rcfu.uploadFD != -1) { + close(rtcp->rcft.rcfu.uploadFD); + rtcp->rcft.rcfu.uploadFD = -1; + } + + if(unlink(rtcp->rcft.rcfu.fName) == -1) { + rfbLog("File [%s]: Method [%s]: Delete operation on file <%s> failed\n", + __FILE__, __FUNCTION__, rtcp->rcft.rcfu.fName); + } + + memset(rtcp->rcft.rcfu.fName, 0 , PATH_MAX); + } + + if(rtcp->rcft.rcfd.downloadInProgress == TRUE) { + rtcp->rcft.rcfd.downloadInProgress = FALSE; + + if(rtcp->rcft.rcfd.downloadFD != -1) { + close(rtcp->rcft.rcfd.downloadFD); + rtcp->rcft.rcfd.downloadFD = -1; + } + memset(rtcp->rcft.rcfd.fName, 0 , PATH_MAX); + } +} + + +/****************************************************************************** + * Method to handle create directory request. + ******************************************************************************/ + +void +CreateDirectory(char* dirName) +{ + if(dirName == NULL) return; + + if(mkdir(dirName, 0700) == -1) { + rfbLog("File [%s]: Method [%s]: Create operation for directory <%s> failed\n", + __FILE__, __FUNCTION__, dirName); + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.h new file mode 100755 index 0000000..30e58df --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#ifndef FILE_TRANSFER_MSG_H +#define FILE_TRANSFER_MSG_H + +typedef struct _FileTransferMsg { + char* data; + unsigned int length; +} FileTransferMsg; + +FileTransferMsg GetFileListResponseMsg(char* path, char flag); + +FileTransferMsg GetFileDownloadResponseMsg(char* path); +FileTransferMsg GetFileDownloadLengthErrResponseMsg(); +FileTransferMsg GetFileDownLoadErrMsg(); +FileTransferMsg GetFileDownloadResponseMsgInBlocks(rfbClientPtr cl, rfbTightClientPtr data); +FileTransferMsg ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr data); + +FileTransferMsg GetFileUploadLengthErrResponseMsg(); +FileTransferMsg GetFileUploadCompressedLevelErrMsg(); +FileTransferMsg ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr data); +FileTransferMsg ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr data, char* pBuf); + +void CreateDirectory(char* dirName); +void FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr data); +void CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr data); + +void FreeFileTransferMsg(FileTransferMsg ftm); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c new file mode 100755 index 0000000..2bd5ba1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c @@ -0,0 +1,993 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rfbtightproto.h" +#include "filetransfermsg.h" +#include "handlefiletransferrequest.h" + + +pthread_mutex_t fileDownloadMutex = PTHREAD_MUTEX_INITIALIZER; + +rfbBool fileTransferEnabled = TRUE; +rfbBool fileTransferInitted = FALSE; +char ftproot[PATH_MAX]; + + +/****************************************************************************** + * File Transfer Init methods. These methods are called for initializating + * File Transfer and setting ftproot. + ******************************************************************************/ + +void InitFileTransfer(); +int SetFtpRoot(char* path); +char* GetHomeDir(uid_t uid); +void FreeHomeDir(char *homedir); + +/* + * InitFileTransfer method is called before parsing the command-line options + * for Xvnc. This sets the ftproot to the Home dir of the user running the Xvnc + * server. In case of error ftproot is set to '\0' char. + */ + +void +InitFileTransfer() +{ + char* userHome = NULL; + uid_t uid = geteuid(); + + if(fileTransferInitted) + return; + + rfbLog("tightvnc-filetransfer/InitFileTransfer\n"); + + memset(ftproot, 0, sizeof(ftproot)); + + userHome = GetHomeDir(uid); + + if((userHome != NULL) && (strlen(userHome) != 0)) { + SetFtpRoot(userHome); + FreeHomeDir(userHome); + } + + fileTransferEnabled = TRUE; + fileTransferInitted = TRUE; +} + +#ifndef __GNUC__ +#define __FUNCTION__ "unknown" +#endif + +/* + * This method is called from InitFileTransfer method and + * if the command line option for ftproot is provided. + */ +int +SetFtpRoot(char* path) +{ + struct stat stat_buf; + DIR* dir = NULL; + + rfbLog("tightvnc-filetransfer/SetFtpRoot\n"); + + if((path == NULL) || (strlen(path) == 0) || (strlen(path) > (PATH_MAX - 1))) { + rfbLog("File [%s]: Method [%s]: parameter passed is improper, ftproot" + " not changed\n", __FILE__, __FUNCTION__); + return FALSE; + } + + if(stat(path, &stat_buf) < 0) { + rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n", + __FILE__, __FUNCTION__, path); + return FALSE; + } + + if(S_ISDIR(stat_buf.st_mode) == 0) { + rfbLog("File [%s]: Method [%s]: path specified is not a directory\n", + __FILE__, __FUNCTION__); + return FALSE; + } + + if((dir = opendir(path)) == NULL) { + rfbLog("File [%s]: Method [%s]: Not able to open the directory\n", + __FILE__, __FUNCTION__); + return FALSE; + } + else { + closedir(dir); + dir = NULL; + } + + + memset(ftproot, 0, PATH_MAX); + if(path[strlen(path)-1] == '/') { + memcpy(ftproot, path, strlen(path)-1); + } + else + memcpy(ftproot, path, strlen(path)); + + + return TRUE; +} + + +/* + * Get the home directory for the user name + * param: username - name of the user for whom the home directory is required. + * returns: returns the home directory for the user, or null in case the entry + * is not found or any error. The returned string must be freed by calling the + * freehomedir function. +*/ +char* +GetHomeDir(uid_t uid) +{ + struct passwd *pwEnt = NULL; + char *homedir = NULL; + + pwEnt = getpwuid (uid); + if (pwEnt == NULL) + return NULL; + + if(pwEnt->pw_dir != NULL) { + homedir = strdup (pwEnt->pw_dir); + } + + return homedir; +} + + +/* + * Free the home directory allocated by a previous call to retrieve the home + * directory. param: homedir - the string returned by a previous call to + * retrieve home directory for a user. + */ +void +FreeHomeDir(char *homedir) +{ + free (homedir); +} + + +/****************************************************************************** + * General methods. + ******************************************************************************/ + +/* + * When the console sends the File Transfer Request, it sends the file path with + * ftproot as "/". So on Agent, to get the absolute file path we need to prepend + * the ftproot to it. + */ +char* +ConvertPath(char* path) +{ + char p[PATH_MAX]; + memset(p, 0, PATH_MAX); + + if( (path == NULL) || + (strlen(path) == 0) || + (strlen(path)+strlen(ftproot) > PATH_MAX - 1) ) { + + rfbLog("File [%s]: Method [%s]: cannot create path for file transfer\n", + __FILE__, __FUNCTION__); + return NULL; + } + + memcpy(p, path, strlen(path)); + memset(path, 0, PATH_MAX); + sprintf(path, "%s%s", ftproot, p); + + return path; +} + + +void +EnableFileTransfer(rfbBool enable) +{ + fileTransferEnabled = enable; +} + + +rfbBool +IsFileTransferEnabled() +{ + return fileTransferEnabled; +} + + +char* +GetFtpRoot() +{ + return ftproot; +} + + +/****************************************************************************** + * Methods to Handle File List Request. + ******************************************************************************/ + +/* + * HandleFileListRequest method is called when the server receives + * FileListRequest. In case of success a file list is sent to the client. + * For File List Request there is no failure reason sent.So here in case of any + * "unexpected" error no information will be sent. As these conditions should + * never come. Lets hope it never arrives :) + * In case of dir open failure an empty list will be sent, just the header of + * the message filled up. So on console you will get an Empty listing. + */ +void +HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data) +{ + rfbClientToServerTightMsg msg; + int n = 0; + char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */ + FileTransferMsg fileListMsg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + memset(path, 0, PATH_MAX); + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileListRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Socket error while reading dir name" + " length\n", __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.flr.dirNameSize = Swap16IfLE(msg.flr.dirNameSize); + if ((msg.flr.dirNameSize == 0) || + (msg.flr.dirNameSize > (PATH_MAX - 1))) { + + rfbLog("File [%s]: Method [%s]: Unexpected error:: path length is " + "greater that PATH_MAX\n", __FILE__, __FUNCTION__); + + return; + } + + if((n = rfbReadExact(cl, path, msg.flr.dirNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Socket error while reading dir name\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + if(ConvertPath(path) == NULL) { + + /* The execution should never reach here */ + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL", + __FILE__, __FUNCTION__); + return; + } + + fileListMsg = GetFileListResponseMsg(path, (char) (msg.flr.flags)); + + if((fileListMsg.data == NULL) || (fileListMsg.length == 0)) { + + rfbLog("File [%s]: Method [%s]: Unexpected error:: Data to be sent is " + "of Zero length\n", __FILE__, __FUNCTION__); + return; + } + + rfbWriteExact(cl, fileListMsg.data, fileListMsg.length); + + FreeFileTransferMsg(fileListMsg); +} + + +/****************************************************************************** + * Methods to Handle File Download Request. + ******************************************************************************/ + +void HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize); +void SendFileDownloadLengthErrMsg(rfbClientPtr cl); +void HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr data); +#ifdef TODO +void HandleFileDownloadRequest(rfbClientPtr cl); +void SendFileDownloadErrMsg(rfbClientPtr cl); +void* RunFileDownloadThread(void* client); +#endif + +/* + * HandleFileDownloadRequest method is called when the server receives + * rfbFileDownload request message. + */ +void +HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */ + rfbClientToServerTightMsg msg; + + memset(path, 0, sizeof(path)); + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + + rfbLog("File [%s]: Method [%s]: Unexpected error:: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fdr.fNameSize = Swap16IfLE(msg.fdr.fNameSize); + msg.fdr.position = Swap16IfLE(msg.fdr.position); + + if ((msg.fdr.fNameSize == 0) || + (msg.fdr.fNameSize > (PATH_MAX - 1))) { + + rfbLog("File [%s]: Method [%s]: Error: path length is greater than" + " PATH_MAX\n", __FILE__, __FUNCTION__); + + HandleFileDownloadLengthError(cl, msg.fdr.fNameSize); + return; + } + + if((n = rfbReadExact(cl, rtcp->rcft.rcfd.fName, msg.fdr.fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + rtcp->rcft.rcfd.fName[msg.fdr.fNameSize] = '\0'; + + if(ConvertPath(rtcp->rcft.rcfd.fName) == NULL) { + + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL", + __FILE__, __FUNCTION__); + + + /* This condition can come only if the file path is greater than + PATH_MAX. So sending file path length error msg back to client. + */ + + SendFileDownloadLengthErrMsg(cl); + return; + } + + HandleFileDownload(cl, rtcp); + +} + + +void +HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize) +{ + char *path = NULL; + int n = 0; + + if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) { + rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n", + __FILE__, __FUNCTION__); + return; + } + if((n = rfbReadExact(cl, path, fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(path != NULL) { + free(path); + path = NULL; + } + + return; + } + + if(path != NULL) { + free(path); + path = NULL; + } + + SendFileDownloadLengthErrMsg(cl); +} + + +void +SendFileDownloadLengthErrMsg(rfbClientPtr cl) +{ + FileTransferMsg fileDownloadErrMsg; + + memset(&fileDownloadErrMsg, 0 , sizeof(FileTransferMsg)); + + fileDownloadErrMsg = GetFileDownloadLengthErrResponseMsg(); + + if((fileDownloadErrMsg.data == NULL) || (fileDownloadErrMsg.length == 0)) { + rfbLog("File [%s]: Method [%s]: Unexpected error: fileDownloadErrMsg " + "is null\n", __FILE__, __FUNCTION__); + return; + } + + rfbWriteExact(cl, fileDownloadErrMsg.data, fileDownloadErrMsg.length); + + FreeFileTransferMsg(fileDownloadErrMsg); +} + +extern rfbTightClientPtr rfbGetTightClientData(rfbClientPtr cl); + +void* +RunFileDownloadThread(void* client) +{ + rfbClientPtr cl = (rfbClientPtr) client; + rfbTightClientPtr rtcp = rfbGetTightClientData(cl); + FileTransferMsg fileDownloadMsg; + + if(rtcp == NULL) + return NULL; + + memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg)); + do { + pthread_mutex_lock(&fileDownloadMutex); + fileDownloadMsg = GetFileDownloadResponseMsgInBlocks(cl, rtcp); + pthread_mutex_unlock(&fileDownloadMutex); + + if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) { + if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0) { + rfbLog("File [%s]: Method [%s]: Error while writing to socket \n" + , __FILE__, __FUNCTION__); + + if(cl != NULL) { + rfbCloseClient(cl); + CloseUndoneFileTransfer(cl, rtcp); + } + + FreeFileTransferMsg(fileDownloadMsg); + return NULL; + } + FreeFileTransferMsg(fileDownloadMsg); + } + } while(rtcp->rcft.rcfd.downloadInProgress == TRUE); + return NULL; +} + + +void +HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + pthread_t fileDownloadThread; + FileTransferMsg fileDownloadMsg; + + memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg)); + fileDownloadMsg = ChkFileDownloadErr(cl, rtcp); + if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) { + rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length); + FreeFileTransferMsg(fileDownloadMsg); + return; + } + rtcp->rcft.rcfd.downloadInProgress = FALSE; + rtcp->rcft.rcfd.downloadFD = -1; + + if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*) + cl) != 0) { + FileTransferMsg ftm = GetFileDownLoadErrMsg(); + + rfbLog("File [%s]: Method [%s]: Download thread creation failed\n", + __FILE__, __FUNCTION__); + + if((ftm.data != NULL) && (ftm.length != 0)) { + rfbWriteExact(cl, ftm.data, ftm.length); + FreeFileTransferMsg(ftm); + return; + } + + } + +} + + +/****************************************************************************** + * Methods to Handle File Download Cancel Request. + ******************************************************************************/ + + +void +HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char *reason = NULL; + rfbClientToServerTightMsg msg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadCancelMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading " + "FileDownloadCancelMsg\n", __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fdc.reasonLen = Swap16IfLE(msg.fdc.reasonLen); + + if(msg.fdc.reasonLen == 0) { + rfbLog("File [%s]: Method [%s]: reason length received is Zero\n", + __FILE__, __FUNCTION__); + return; + } + + reason = (char*) calloc(msg.fdc.reasonLen + 1, sizeof(char)); + if(reason == NULL) { + rfbLog("File [%s]: Method [%s]: Fatal Error: Memory alloc failed\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, reason, msg.fdc.reasonLen)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading " + "FileDownloadCancelMsg\n", __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + } + + rfbLog("File [%s]: Method [%s]: File Download Cancel Request received:" + " reason <%s>\n", __FILE__, __FUNCTION__, reason); + + pthread_mutex_lock(&fileDownloadMutex); + CloseUndoneFileTransfer(cl, rtcp); + pthread_mutex_unlock(&fileDownloadMutex); + + if(reason != NULL) { + free(reason); + reason = NULL; + } + +} + + +/****************************************************************************** + * Methods to Handle File upload request + ******************************************************************************/ + +#ifdef TODO +void HandleFileUploadRequest(rfbClientPtr cl); +#endif +void HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr data); +void HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize); +void SendFileUploadLengthErrMsg(rfbClientPtr cl); + + +void +HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */ + rfbClientToServerTightMsg msg; + + memset(path, 0, PATH_MAX); + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fupr.fNameSize = Swap16IfLE(msg.fupr.fNameSize); + msg.fupr.position = Swap16IfLE(msg.fupr.position); + + if ((msg.fupr.fNameSize == 0) || + (msg.fupr.fNameSize > (PATH_MAX - 1))) { + + rfbLog("File [%s]: Method [%s]: error: path length is greater than PATH_MAX\n", + __FILE__, __FUNCTION__); + HandleFileUploadLengthError(cl, msg.fupr.fNameSize); + return; + } + + if((n = rfbReadExact(cl, rtcp->rcft.rcfu.fName, msg.fupr.fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n" + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + rtcp->rcft.rcfu.fName[msg.fupr.fNameSize] = '\0'; + + if(ConvertPath(rtcp->rcft.rcfu.fName) == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n", + __FILE__, __FUNCTION__); + + /* This may come if the path length exceeds PATH_MAX. + So sending path length error to client + */ + SendFileUploadLengthErrMsg(cl); + return; + } + + HandleFileUpload(cl, rtcp); +} + + +void +HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize) +{ + char *path = NULL; + int n = 0; + + if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) { + rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n", + __FILE__, __FUNCTION__); + return; + } + if((n = rfbReadExact(cl, path, fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(path != NULL) { + free(path); + path = NULL; + } + + return; + } + + rfbLog("File [%s]: Method [%s]: File Upload Length Error occured" + "file path requested is <%s>\n", __FILE__, __FUNCTION__, path); + + if(path != NULL) { + free(path); + path = NULL; + } + + SendFileUploadLengthErrMsg(cl); +} + +void +SendFileUploadLengthErrMsg(rfbClientPtr cl) +{ + + FileTransferMsg fileUploadErrMsg; + + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + fileUploadErrMsg = GetFileUploadLengthErrResponseMsg(); + + if((fileUploadErrMsg.data == NULL) || (fileUploadErrMsg.length == 0)) { + rfbLog("File [%s]: Method [%s]: Unexpected error: fileUploadErrMsg is null\n", + __FILE__, __FUNCTION__); + return; + } + + rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length); + FreeFileTransferMsg(fileUploadErrMsg); +} + +void +HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + FileTransferMsg fileUploadErrMsg; + + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + + rtcp->rcft.rcfu.uploadInProgress = FALSE; + rtcp->rcft.rcfu.uploadFD = -1; + + fileUploadErrMsg = ChkFileUploadErr(cl, rtcp); + if((fileUploadErrMsg.data != NULL) && (fileUploadErrMsg.length != 0)) { + rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length); + FreeFileTransferMsg(fileUploadErrMsg); + } +} + + +/****************************************************************************** + * Methods to Handle File Upload Data Request + *****************************************************************************/ + +void HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf); + + +void +HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char* pBuf = NULL; + rfbClientToServerTightMsg msg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadDataMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fud.realSize = Swap16IfLE(msg.fud.realSize); + msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize); + if((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) { + if((n = rfbReadExact(cl, (char*)&(rtcp->rcft.rcfu.mTime), sizeof(unsigned + long))) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + FileUpdateComplete(cl, rtcp); + return; + } + + pBuf = (char*) calloc(msg.fud.compressedSize, sizeof(char)); + if(pBuf == NULL) { + rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__); + return; + } + if((n = rfbReadExact(cl, pBuf, msg.fud.compressedSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(pBuf != NULL) { + free(pBuf); + pBuf = NULL; + } + + return; + } + if(msg.fud.compressedLevel != 0) { + FileTransferMsg ftm; + memset(&ftm, 0, sizeof(FileTransferMsg)); + + ftm = GetFileUploadCompressedLevelErrMsg(); + + if((ftm.data != NULL) && (ftm.length != 0)) { + rfbWriteExact(cl, ftm.data, ftm.length); + FreeFileTransferMsg(ftm); + } + + CloseUndoneFileTransfer(cl, rtcp); + + if(pBuf != NULL) { + free(pBuf); + pBuf = NULL; + } + + return; + } + + rtcp->rcft.rcfu.fSize = msg.fud.compressedSize; + + HandleFileUploadWrite(cl, rtcp, pBuf); + + if(pBuf != NULL) { + free(pBuf); + pBuf = NULL; + } + +} + + +void +HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf) +{ + FileTransferMsg ftm; + memset(&ftm, 0, sizeof(FileTransferMsg)); + + ftm = ChkFileUploadWriteErr(cl, rtcp, pBuf); + + if((ftm.data != NULL) && (ftm.length != 0)) { + rfbWriteExact(cl, ftm.data, ftm.length); + FreeFileTransferMsg(ftm); + } +} + + +/****************************************************************************** + * Methods to Handle File Upload Failed Request. + ******************************************************************************/ + + +void +HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char* reason = NULL; + rfbClientToServerTightMsg msg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadFailedMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fuf.reasonLen = Swap16IfLE(msg.fuf.reasonLen); + if(msg.fuf.reasonLen == 0) { + rfbLog("File [%s]: Method [%s]: reason length received is Zero\n", + __FILE__, __FUNCTION__); + return; + } + + + reason = (char*) calloc(msg.fuf.reasonLen + 1, sizeof(char)); + if(reason == NULL) { + rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, reason, msg.fuf.reasonLen)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(reason != NULL) { + free(reason); + reason = NULL; + } + + return; + } + + rfbLog("File [%s]: Method [%s]: File Upload Failed Request received:" + " reason <%s>\n", __FILE__, __FUNCTION__, reason); + + CloseUndoneFileTransfer(cl, rtcp); + + if(reason != NULL) { + free(reason); + reason = NULL; + } + +} + + +/****************************************************************************** + * Methods to Handle File Create Request. + ******************************************************************************/ + + +void +HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char dirName[PATH_MAX]; + rfbClientToServerTightMsg msg; + + memset(dirName, 0, PATH_MAX); + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileCreateDirRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileCreateDirRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fcdr.dNameLen = Swap16IfLE(msg.fcdr.dNameLen); + + /* TODO :: chk if the dNameLen is greater than PATH_MAX */ + + if((n = rfbReadExact(cl, dirName, msg.fcdr.dNameLen)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + if(ConvertPath(dirName) == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n", + __FILE__, __FUNCTION__); + + return; + } + + CreateDirectory(dirName); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.h new file mode 100755 index 0000000..74c0e8a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + +#ifndef HANDLE_FILE_TRANSFER_REQUEST_H +#define HANDLE_FILE_TRANSFER_REQUEST_H + + +#include + + +void InitFileTransfer(); +int SetFtpRoot(char* path); +void EnableFileTransfer(rfbBool enable); +rfbBool IsFileTransferEnabled(); +char* GetFtpRoot(); + +void HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientRec* data); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightproto.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightproto.h new file mode 100755 index 0000000..ef683ae --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightproto.h @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 25th August 2005 + */ + +#ifndef RFBTIGHTPROTO_H +#define RFBTIGHTPROTO_H + +#include +#include + +/* PATH_MAX is not defined in limits.h on some platforms */ +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + + +#define rfbSecTypeTight 16 + +void rfbTightUsage(void); +int rfbTightProcessArgs(int argc, char *argv[]); + +/*----------------------------------------------------------------------------- + * Negotiation of Tunneling Capabilities (protocol version 3.7t) + * + * If the chosen security type is rfbSecTypeTight, the server sends a list of + * supported tunneling methods ("tunneling" refers to any additional layer of + * data transformation, such as encryption or external compression.) + * + * nTunnelTypes specifies the number of following rfbCapabilityInfo structures + * that list all supported tunneling methods in the order of preference. + * + * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be + * used, and the client should not send a response requesting a tunneling + * method. + */ + +typedef struct _rfbTunnelingCapsMsg { + uint32_t nTunnelTypes; + /* followed by nTunnelTypes * rfbCapabilityInfo structures */ +} rfbTunnelingCapsMsg; + +#define sz_rfbTunnelingCapsMsg 4 + +/*----------------------------------------------------------------------------- + * Tunneling Method Request (protocol version 3.7t) + * + * If the list of tunneling capabilities sent by the server was not empty, the + * client should reply with a 32-bit code specifying a particular tunneling + * method. The following code should be used for no tunneling. + */ + +#define rfbNoTunneling 0 +#define sig_rfbNoTunneling "NOTUNNEL" + + +/*----------------------------------------------------------------------------- + * Negotiation of Authentication Capabilities (protocol version 3.7t) + * + * After setting up tunneling, the server sends a list of supported + * authentication schemes. + * + * nAuthTypes specifies the number of following rfbCapabilityInfo structures + * that list all supported authentication schemes in the order of preference. + * + * NOTE: If nAuthTypes is 0, that tells the client that no authentication is + * necessary, and the client should not send a response requesting an + * authentication scheme. + */ + +typedef struct _rfbAuthenticationCapsMsg { + uint32_t nAuthTypes; + /* followed by nAuthTypes * rfbCapabilityInfo structures */ +} rfbAuthenticationCapsMsg; + +#define sz_rfbAuthenticationCapsMsg 4 + +/*----------------------------------------------------------------------------- + * Authentication Scheme Request (protocol version 3.7t) + * + * If the list of authentication capabilities sent by the server was not empty, + * the client should reply with a 32-bit code specifying a particular + * authentication scheme. The following codes are supported. + */ + +#define rfbAuthNone 1 +#define rfbAuthVNC 2 +#define rfbAuthUnixLogin 129 +#define rfbAuthExternal 130 + +#define sig_rfbAuthNone "NOAUTH__" +#define sig_rfbAuthVNC "VNCAUTH_" +#define sig_rfbAuthUnixLogin "ULGNAUTH" +#define sig_rfbAuthExternal "XTRNAUTH" + +/*----------------------------------------------------------------------------- + * Structure used to describe protocol options such as tunneling methods, + * authentication schemes and message types (protocol version 3.7t). + */ + +typedef struct _rfbCapabilityInfo { + + uint32_t code; /* numeric identifier */ + uint8_t vendorSignature[4]; /* vendor identification */ + uint8_t nameSignature[8]; /* abbreviated option name */ + +} rfbCapabilityInfo; + +#define sz_rfbCapabilityInfoVendor 4 +#define sz_rfbCapabilityInfoName 8 +#define sz_rfbCapabilityInfo 16 + +/* + * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC. + */ + +#define rfbStandardVendor "STDV" +#define rfbTridiaVncVendor "TRDV" +#define rfbTightVncVendor "TGHT" + + +/* It's a good idea to keep these values a bit greater than required. */ +#define MAX_TIGHT_ENCODINGS 10 +#define MAX_TUNNELING_CAPS 16 +#define MAX_AUTH_CAPS 16 + +typedef struct _rfbClientFileDownload { + char fName[PATH_MAX]; + int downloadInProgress; + unsigned long mTime; + int downloadFD; +} rfbClientFileDownload ; + +typedef struct _rfbClientFileUpload { + char fName[PATH_MAX]; + int uploadInProgress; + unsigned long mTime; + unsigned long fSize; + int uploadFD; +} rfbClientFileUpload ; + +typedef struct _rfbClientFileTransfer { + rfbClientFileDownload rcfd; + rfbClientFileUpload rcfu; +} rfbClientFileTransfer; + + +typedef struct _rfbTightClientRec { + + /* Lists of capability codes sent to clients. We remember these + lists to restrict clients from choosing those tunneling and + authentication types that were not advertised. */ + + int nAuthCaps; + uint32_t authCaps[MAX_AUTH_CAPS]; + + /* This is not useful while we don't support tunneling: + int nTunnelingCaps; + uint32_t tunnelingCaps[MAX_TUNNELING_CAPS]; */ + + rfbClientFileTransfer rcft; + +} rfbTightClientRec, *rfbTightClientPtr; + +/* + * Macro to fill in an rfbCapabilityInfo structure (protocol 3.7t). + * Normally, using macros is no good, but this macro saves us from + * writing constants twice -- it constructs signature names from codes. + * Note that "code_sym" argument should be a single symbol, not an expression. + */ + +#define SetCapInfo(cap_ptr, code_sym, vendor) \ +{ \ + rfbCapabilityInfo *pcap; \ + pcap = (cap_ptr); \ + pcap->code = Swap32IfLE(code_sym); \ + memcpy(pcap->vendorSignature, (vendor), \ + sz_rfbCapabilityInfoVendor); \ + memcpy(pcap->nameSignature, sig_##code_sym, \ + sz_rfbCapabilityInfoName); \ +} + +void rfbHandleSecTypeTight(rfbClientPtr cl); + + +/*----------------------------------------------------------------------------- + * Server Interaction Capabilities Message (protocol version 3.7t) + * + * In the protocol version 3.7t, the server informs the client what message + * types it supports in addition to ones defined in the protocol version 3.7. + * Also, the server sends the list of all supported encodings (note that it's + * not necessary to advertise the "raw" encoding sinse it MUST be supported in + * RFB 3.x protocols). + * + * This data immediately follows the server initialisation message. + */ + +typedef struct _rfbInteractionCapsMsg { + uint16_t nServerMessageTypes; + uint16_t nClientMessageTypes; + uint16_t nEncodingTypes; + uint16_t pad; /* reserved, must be 0 */ + /* followed by nServerMessageTypes * rfbCapabilityInfo structures */ + /* followed by nClientMessageTypes * rfbCapabilityInfo structures */ +} rfbInteractionCapsMsg; + +#define sz_rfbInteractionCapsMsg 8 + +#define rfbFileListData 130 +#define rfbFileDownloadData 131 +#define rfbFileUploadCancel 132 +#define rfbFileDownloadFailed 133 + +/* signatures for non-standard messages */ +#define sig_rfbFileListData "FTS_LSDT" +#define sig_rfbFileDownloadData "FTS_DNDT" +#define sig_rfbFileUploadCancel "FTS_UPCN" +#define sig_rfbFileDownloadFailed "FTS_DNFL" + + + +#define rfbFileListRequest 130 +#define rfbFileDownloadRequest 131 +#define rfbFileUploadRequest 132 +#define rfbFileUploadData 133 +#define rfbFileDownloadCancel 134 +#define rfbFileUploadFailed 135 +#define rfbFileCreateDirRequest 136 + +/* signatures for non-standard messages */ +#define sig_rfbFileListRequest "FTC_LSRQ" +#define sig_rfbFileDownloadRequest "FTC_DNRQ" +#define sig_rfbFileUploadRequest "FTC_UPRQ" +#define sig_rfbFileUploadData "FTC_UPDT" +#define sig_rfbFileDownloadCancel "FTC_DNCN" +#define sig_rfbFileUploadFailed "FTC_UPFL" +#define sig_rfbFileCreateDirRequest "FTC_FCDR" + + +/* signatures for basic encoding types */ +#define sig_rfbEncodingRaw "RAW_____" +#define sig_rfbEncodingCopyRect "COPYRECT" +#define sig_rfbEncodingRRE "RRE_____" +#define sig_rfbEncodingCoRRE "CORRE___" +#define sig_rfbEncodingHextile "HEXTILE_" +#define sig_rfbEncodingZlib "ZLIB____" +#define sig_rfbEncodingTight "TIGHT___" +#define sig_rfbEncodingZlibHex "ZLIBHEX_" + + +/* signatures for "fake" encoding types */ +#define sig_rfbEncodingCompressLevel0 "COMPRLVL" +#define sig_rfbEncodingXCursor "X11CURSR" +#define sig_rfbEncodingRichCursor "RCHCURSR" +#define sig_rfbEncodingPointerPos "POINTPOS" +#define sig_rfbEncodingLastRect "LASTRECT" +#define sig_rfbEncodingNewFBSize "NEWFBSIZ" +#define sig_rfbEncodingQualityLevel0 "JPEGQLVL" + + +/*----------------------------------------------------------------------------- + * FileListRequest + */ + +typedef struct _rfbFileListRequestMsg { + uint8_t type; + uint8_t flags; + uint16_t dirNameSize; + /* Followed by char Dirname[dirNameSize] */ +} rfbFileListRequestMsg; + +#define sz_rfbFileListRequestMsg 4 + +/*----------------------------------------------------------------------------- + * FileDownloadRequest + */ + +typedef struct _rfbFileDownloadRequestMsg { + uint8_t type; + uint8_t compressedLevel; + uint16_t fNameSize; + uint32_t position; + /* Followed by char Filename[fNameSize] */ +} rfbFileDownloadRequestMsg; + +#define sz_rfbFileDownloadRequestMsg 8 + +/*----------------------------------------------------------------------------- + * FileUploadRequest + */ + +typedef struct _rfbFileUploadRequestMsg { + uint8_t type; + uint8_t compressedLevel; + uint16_t fNameSize; + uint32_t position; + /* Followed by char Filename[fNameSize] */ +} rfbFileUploadRequestMsg; + +#define sz_rfbFileUploadRequestMsg 8 + + +/*----------------------------------------------------------------------------- + * FileUploadData + */ + +typedef struct _rfbFileUploadDataMsg { + uint8_t type; + uint8_t compressedLevel; + uint16_t realSize; + uint16_t compressedSize; + /* Followed by File[compressedSize], + but if (realSize = compressedSize = 0) followed by uint32_t modTime */ +} rfbFileUploadDataMsg; + +#define sz_rfbFileUploadDataMsg 6 + +/*----------------------------------------------------------------------------- + * FileDownloadCancel + */ + +typedef struct _rfbFileDownloadCancelMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileDownloadCancelMsg; + +#define sz_rfbFileDownloadCancelMsg 4 + +/*----------------------------------------------------------------------------- + * FileUploadFailed + */ + +typedef struct _rfbFileUploadFailedMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileUploadFailedMsg; + +#define sz_rfbFileUploadFailedMsg 4 + +/*----------------------------------------------------------------------------- + * FileCreateDirRequest + */ + +typedef struct _rfbFileCreateDirRequestMsg { + uint8_t type; + uint8_t unused; + uint16_t dNameLen; + /* Followed by dName[dNameLen] */ +} rfbFileCreateDirRequestMsg; + +#define sz_rfbFileCreateDirRequestMsg 4 + + +/*----------------------------------------------------------------------------- + * Union of all client->server messages. + */ + +typedef union _rfbClientToServerTightMsg { + rfbFileListRequestMsg flr; + rfbFileDownloadRequestMsg fdr; + rfbFileUploadRequestMsg fupr; + rfbFileUploadDataMsg fud; + rfbFileDownloadCancelMsg fdc; + rfbFileUploadFailedMsg fuf; + rfbFileCreateDirRequestMsg fcdr; +} rfbClientToServerTightMsg; + + + +/*----------------------------------------------------------------------------- + * FileListData + */ + +typedef struct _rfbFileListDataMsg { + uint8_t type; + uint8_t flags; + uint16_t numFiles; + uint16_t dataSize; + uint16_t compressedSize; + /* Followed by SizeData[numFiles] */ + /* Followed by Filenames[compressedSize] */ +} rfbFileListDataMsg; + +#define sz_rfbFileListDataMsg 8 + +/*----------------------------------------------------------------------------- + * FileDownloadData + */ + +typedef struct _rfbFileDownloadDataMsg { + uint8_t type; + uint8_t compressLevel; + uint16_t realSize; + uint16_t compressedSize; + /* Followed by File[copressedSize], + but if (realSize = compressedSize = 0) followed by uint32_t modTime */ +} rfbFileDownloadDataMsg; + +#define sz_rfbFileDownloadDataMsg 6 + + +/*----------------------------------------------------------------------------- + * FileUploadCancel + */ + +typedef struct _rfbFileUploadCancelMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileUploadCancelMsg; + +#define sz_rfbFileUploadCancelMsg 4 + +/*----------------------------------------------------------------------------- + * FileDownloadFailed + */ + +typedef struct _rfbFileDownloadFailedMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileDownloadFailedMsg; + +#define sz_rfbFileDownloadFailedMsg 4 + + + + +#endif + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightserver.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightserver.c new file mode 100755 index 0000000..d43d3f3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightserver.c @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 25th August 2005 + */ + + +#include +#include "rfbtightproto.h" +#include "handlefiletransferrequest.h" + +/* + * Get my data! + * + * This gets the extension specific data from the client structure. If + * the data is not found, the client connection is closed, a complaint + * is logged, and NULL is returned. + */ + +extern rfbProtocolExtension tightVncFileTransferExtension; + +rfbTightClientPtr +rfbGetTightClientData(rfbClientPtr cl) +{ + rfbTightClientPtr rtcp = (rfbTightClientPtr) + rfbGetExtensionClientData(cl, + &tightVncFileTransferExtension); + if(rtcp == NULL) { + rfbLog("Extension client data is null, closing the connection !\n"); + rfbCloseClient(cl); + } + + return rtcp; +} + +/* + * Send the authentication challenge. + */ + +static void +rfbVncAuthSendChallenge(rfbClientPtr cl) +{ + + rfbLog("tightvnc-filetransfer/rfbVncAuthSendChallenge\n"); + /* 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. */ + /* This methos is defined in auth.c file */ + rfbAuthProcessClientMessage(cl); + +} + +/* + * LibVNCServer has a bug WRT Tight SecurityType and RFB 3.8 + * It should send auth result even for rfbAuthNone. + * See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=517422 + * For testing set USE_SECTYPE_TIGHT_FOR_RFB_3_8 when compiling + * or set it here. + */ +#define SECTYPE_TIGHT_FOR_RFB_3_8 \ + if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) { \ + uint32_t authResult; \ + 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; \ + } \ + } + +/* + Enabled by runge on 2010/01/02 + */ +#define USE_SECTYPE_TIGHT_FOR_RFB_3_8 + +/* + * Read client's preferred authentication type (protocol 3.7t). + */ + +void +rfbProcessClientAuthType(rfbClientPtr cl) +{ + uint32_t auth_type; + int n, i; + rfbTightClientPtr rtcp = rfbGetTightClientData(cl); + + rfbLog("tightvnc-filetransfer/rfbProcessClientAuthType\n"); + + if(rtcp == NULL) + return; + + /* Read authentication type selected by the client. */ + n = rfbReadExact(cl, (char *)&auth_type, sizeof(auth_type)); + if (n <= 0) { + if (n == 0) + rfbLog("rfbProcessClientAuthType: client gone\n"); + else + rfbLogPerror("rfbProcessClientAuthType: read"); + rfbCloseClient(cl); + return; + } + auth_type = Swap32IfLE(auth_type); + + /* Make sure it was present in the list sent by the server. */ + for (i = 0; i < rtcp->nAuthCaps; i++) { + if (auth_type == rtcp->authCaps[i]) + break; + } + if (i >= rtcp->nAuthCaps) { + rfbLog("rfbProcessClientAuthType: " + "wrong authentication type requested\n"); + rfbCloseClient(cl); + return; + } + + switch (auth_type) { + case rfbAuthNone: + /* Dispatch client input to rfbProcessClientInitMessage. */ +#ifdef USE_SECTYPE_TIGHT_FOR_RFB_3_8 + SECTYPE_TIGHT_FOR_RFB_3_8 +#endif + cl->state = RFB_INITIALISATION; + break; + case rfbAuthVNC: + rfbVncAuthSendChallenge(cl); + break; + default: + rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n"); + rfbCloseClient(cl); + } +} + + +/* + * Read tunneling type requested by the client (protocol 3.7t). + * NOTE: Currently, we don't support tunneling, and this function + * can never be called. + */ + +void +rfbProcessClientTunnelingType(rfbClientPtr cl) +{ + /* If we were called, then something's really wrong. */ + rfbLog("rfbProcessClientTunnelingType: not implemented\n"); + rfbCloseClient(cl); + return; +} + + +/* + * Send the list of our authentication capabilities to the client + * (protocol 3.7t). + */ + +static void +rfbSendAuthCaps(rfbClientPtr cl) +{ + rfbAuthenticationCapsMsg caps; + rfbCapabilityInfo caplist[MAX_AUTH_CAPS]; + int count = 0; + rfbTightClientPtr rtcp = rfbGetTightClientData(cl); + + rfbLog("tightvnc-filetransfer/rfbSendAuthCaps\n"); + + if(rtcp == NULL) + return; + + if (cl->screen->authPasswdData && !cl->reverseConnection) { + /* chk if this condition is valid or not. */ + SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor); + rtcp->authCaps[count++] = rfbAuthVNC; + } + + rtcp->nAuthCaps = count; + caps.nAuthTypes = Swap32IfLE((uint32_t)count); + if (rfbWriteExact(cl, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) { + rfbLogPerror("rfbSendAuthCaps: write"); + rfbCloseClient(cl); + return; + } + + if (count) { + if (rfbWriteExact(cl, (char *)&caplist[0], + count * sz_rfbCapabilityInfo) < 0) { + rfbLogPerror("rfbSendAuthCaps: write"); + rfbCloseClient(cl); + return; + } + /* Dispatch client input to rfbProcessClientAuthType. */ + /* Call the function for authentication from here */ + rfbProcessClientAuthType(cl); + } else { +#ifdef USE_SECTYPE_TIGHT_FOR_RFB_3_8 + SECTYPE_TIGHT_FOR_RFB_3_8 +#endif + /* Dispatch client input to rfbProcessClientInitMessage. */ + cl->state = RFB_INITIALISATION; + } +} + + +/* + * Send the list of our tunneling capabilities (protocol 3.7t). + */ + +static void +rfbSendTunnelingCaps(rfbClientPtr cl) +{ + rfbTunnelingCapsMsg caps; + uint32_t nTypes = 0; /* we don't support tunneling yet */ + + rfbLog("tightvnc-filetransfer/rfbSendTunnelingCaps\n"); + + caps.nTunnelTypes = Swap32IfLE(nTypes); + if (rfbWriteExact(cl, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) { + rfbLogPerror("rfbSendTunnelingCaps: write"); + rfbCloseClient(cl); + return; + } + + if (nTypes) { + /* Dispatch client input to rfbProcessClientTunnelingType(). */ + /* The flow should not reach here as tunneling is not implemented. */ + rfbProcessClientTunnelingType(cl); + } else { + rfbSendAuthCaps(cl); + } +} + + + +/* + * rfbSendInteractionCaps is called after sending the server + * initialisation message, only if TightVNC protocol extensions were + * enabled (protocol 3.7t). In this function, we send the lists of + * supported protocol messages and encodings. + */ + +/* Update these constants on changing capability lists below! */ +/* Values updated for FTP */ +#define N_SMSG_CAPS 4 +#define N_CMSG_CAPS 6 +#define N_ENC_CAPS 12 + +void +rfbSendInteractionCaps(rfbClientPtr cl) +{ + rfbInteractionCapsMsg intr_caps; + rfbCapabilityInfo smsg_list[N_SMSG_CAPS]; + rfbCapabilityInfo cmsg_list[N_CMSG_CAPS]; + rfbCapabilityInfo enc_list[N_ENC_CAPS]; + int i, n_enc_caps = N_ENC_CAPS; + + /* Fill in the header structure sent prior to capability lists. */ + intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS); + intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS); + intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS); + intr_caps.pad = 0; + + rfbLog("tightvnc-filetransfer/rfbSendInteractionCaps\n"); + + /* Supported server->client message types. */ + /* For file transfer support: */ + i = 0; + if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) { + SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor); + SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor); + SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor); + SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor); + if (i != N_SMSG_CAPS) { + rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n"); + rfbCloseClient(cl); + return; + } + } + + /* Supported client->server message types. */ + /* For file transfer support: */ + i = 0; + if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) { + SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor); + if (i != N_CMSG_CAPS) { + rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n"); + rfbCloseClient(cl); + return; + } + } + + /* Encoding types. */ + i = 0; + SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor); + SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor); + SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor); + SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor); +#ifdef LIBVNCSERVER_HAVE_LIBZ + SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor); +#else + n_enc_caps -= 2; +#endif + SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor); + if (i != n_enc_caps) { + rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n"); + rfbCloseClient(cl); + return; + } + + /* Send header and capability lists */ + if (rfbWriteExact(cl, (char *)&intr_caps, + sz_rfbInteractionCapsMsg) < 0 || + rfbWriteExact(cl, (char *)&smsg_list[0], + sz_rfbCapabilityInfo * N_SMSG_CAPS) < 0 || + rfbWriteExact(cl, (char *)&cmsg_list[0], + sz_rfbCapabilityInfo * N_CMSG_CAPS) < 0 || + rfbWriteExact(cl, (char *)&enc_list[0], + sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) { + rfbLogPerror("rfbSendInteractionCaps: write"); + rfbCloseClient(cl); + return; + } + + /* Dispatch client input to rfbProcessClientNormalMessage(). */ + cl->state = RFB_NORMAL; +} + + + +rfbBool +rfbTightExtensionInit(rfbClientPtr cl, void* data) +{ + + rfbSendInteractionCaps(cl); + + return TRUE; +} + +static rfbBool +handleMessage(rfbClientPtr cl, + const char* messageName, + void (*handler)(rfbClientPtr cl, rfbTightClientPtr data)) +{ + rfbTightClientPtr data; + + rfbLog("tightvnc-filetransfer: %s message received\n", messageName); + + if((IsFileTransferEnabled() == FALSE) || ( cl->viewOnly == TRUE)) { + rfbCloseClient(cl); + return FALSE; + } + + data = rfbGetTightClientData(cl); + if(data == NULL) + return FALSE; + + handler(cl, data); + return TRUE; +} + +rfbBool +rfbTightExtensionMsgHandler(struct _rfbClientRec* cl, void* data, + const rfbClientToServerMsg* msg) +{ + switch (msg->type) { + + case rfbFileListRequest: + + return handleMessage(cl, "rfbFileListRequest", HandleFileListRequest); + + case rfbFileDownloadRequest: + + return handleMessage(cl, "rfbFileDownloadRequest", HandleFileDownloadRequest); + + case rfbFileUploadRequest: + + return handleMessage(cl, "rfbFileUploadRequest", HandleFileUploadRequest); + + case rfbFileUploadData: + + return handleMessage(cl, "rfbFileUploadDataRequest", HandleFileUploadDataRequest); + + case rfbFileDownloadCancel: + + return handleMessage(cl, "rfbFileDownloadCancelRequest", HandleFileDownloadCancelRequest); + + case rfbFileUploadFailed: + + return handleMessage(cl, "rfbFileUploadFailedRequest", HandleFileUploadFailedRequest); + + case rfbFileCreateDirRequest: + + return handleMessage(cl, "rfbFileCreateDirRequest", HandleFileCreateDirRequest); + + default: + + rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", + msg->type); + + /* + + We shouldn't close the connection here for unhandled msg, + it should be left to libvncserver. + rfbLog(" ... closing connection\n"); + rfbCloseClient(cl); + + */ + + return FALSE; + + } +} + + +void +rfbTightExtensionClientClose(rfbClientPtr cl, void* data) { + + if(data != NULL) + free(data); + +} + +void +rfbTightUsage(void) { + fprintf(stderr, "\nlibvncserver-tight-extension options:\n"); + fprintf(stderr, "-disablefiletransfer disable file transfer\n"); + fprintf(stderr, "-ftproot string set ftp root\n"); + fprintf(stderr,"\n"); +} + +int +rfbTightProcessArg(int argc, char *argv[]) { + + rfbLog("tightvnc-filetransfer/rfbTightProcessArg\n"); + + InitFileTransfer(); + + if(argc<1) + return 0; + + if (strcmp(argv[0], "-ftproot") == 0) { /* -ftproot string */ + if (2 > argc) { + return 0; + } + rfbLog("ftproot is set to <%s>\n", argv[1]); + if(SetFtpRoot(argv[1]) == FALSE) { + rfbLog("ERROR:: Path specified for ftproot in invalid\n"); + return 0; + } + return 2; + } else if (strcmp(argv[0], "-disablefiletransfer") == 0) { + EnableFileTransfer(FALSE); + return 1; + } + return 0; +} + +/* + * This method should be registered to libvncserver to handle rfbSecTypeTight security type. + */ +void +rfbHandleSecTypeTight(rfbClientPtr cl) { + + rfbTightClientPtr rtcp = (rfbTightClientPtr) malloc(sizeof(rfbTightClientRec)); + + rfbLog("tightvnc-filetransfer/rfbHandleSecTypeTight\n"); + + if(rtcp == NULL) { + /* Error condition close socket */ + rfbLog("Memory error has occured while handling " + "Tight security type... closing connection.\n"); + rfbCloseClient(cl); + return; + } + + memset(rtcp, 0, sizeof(rfbTightClientRec)); + rtcp->rcft.rcfd.downloadFD = -1; + rtcp->rcft.rcfu.uploadFD = -1; + rfbEnableExtension(cl, &tightVncFileTransferExtension, rtcp); + + rfbSendTunnelingCaps(cl); + +} + +rfbProtocolExtension tightVncFileTransferExtension = { + NULL, + rfbTightExtensionInit, + NULL, + NULL, + rfbTightExtensionMsgHandler, + rfbTightExtensionClientClose, + rfbTightUsage, + rfbTightProcessArg, + NULL +}; + +static rfbSecurityHandler tightVncSecurityHandler = { + rfbSecTypeTight, + rfbHandleSecTypeTight, + NULL +}; + +void rfbRegisterTightVNCFileTransferExtension() { + rfbRegisterProtocolExtension(&tightVncFileTransferExtension); + rfbRegisterSecurityHandler(&tightVncSecurityHandler); +} + +void +rfbUnregisterTightVNCFileTransferExtension() { + rfbUnregisterProtocolExtension(&tightVncFileTransferExtension); + rfbUnregisterSecurityHandler(&tightVncSecurityHandler); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/translate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/translate.c new file mode 100755 index 0000000..7c341c2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/translate.c @@ -0,0 +1,477 @@ +/* + * translate.c - translate between different pixel formats + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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 +#include + +static void PrintPixelFormat(rfbPixelFormat *pf); +static rfbBool rfbSetClientColourMapBGR233(rfbClientPtr cl); + +rfbBool rfbEconomicTranslate = FALSE; + +/* + * Some standard pixel formats. + */ + +static const rfbPixelFormat BGR233Format = { + 8, 8, 0, 1, 7, 7, 3, 0, 3, 6, 0, 0 +}; + + +/* + * Macro to compare pixel formats. + */ + +#define PF_EQ(x,y) \ + ((x.bitsPerPixel == y.bitsPerPixel) && \ + (x.depth == y.depth) && \ + ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \ + (x.trueColour == y.trueColour) && \ + (!x.trueColour || ((x.redMax == y.redMax) && \ + (x.greenMax == y.greenMax) && \ + (x.blueMax == y.blueMax) && \ + (x.redShift == y.redShift) && \ + (x.greenShift == y.greenShift) && \ + (x.blueShift == y.blueShift)))) + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) +#define CONCAT4(a,b,c,d) a##b##c##d +#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d) + +#undef OUT +#undef IN + +#define OUT 8 +#include "tableinitcmtemplate.c" +#include "tableinittctemplate.c" +#define IN 8 +#include "tabletranstemplate.c" +#undef IN +#define IN 16 +#include "tabletranstemplate.c" +#undef IN +#define IN 32 +#include "tabletranstemplate.c" +#undef IN +#undef OUT + +#define OUT 16 +#include "tableinitcmtemplate.c" +#include "tableinittctemplate.c" +#define IN 8 +#include "tabletranstemplate.c" +#undef IN +#define IN 16 +#include "tabletranstemplate.c" +#undef IN +#define IN 32 +#include "tabletranstemplate.c" +#undef IN +#undef OUT + +#define OUT 32 +#include "tableinitcmtemplate.c" +#include "tableinittctemplate.c" +#define IN 8 +#include "tabletranstemplate.c" +#undef IN +#define IN 16 +#include "tabletranstemplate.c" +#undef IN +#define IN 32 +#include "tabletranstemplate.c" +#undef IN +#undef OUT + +#ifdef LIBVNCSERVER_ALLOW24BPP +#define COUNT_OFFSETS 4 +#define BPP2OFFSET(bpp) ((bpp)/8-1) +#include "tableinit24.c" +#define BPP 8 +#include "tabletrans24template.c" +#undef BPP +#define BPP 16 +#include "tabletrans24template.c" +#undef BPP +#define BPP 24 +#include "tabletrans24template.c" +#undef BPP +#define BPP 32 +#include "tabletrans24template.c" +#undef BPP +#else +#define COUNT_OFFSETS 3 +#define BPP2OFFSET(bpp) ((int)(bpp)/16) +#endif + +typedef void (*rfbInitCMTableFnType)(char **table, rfbPixelFormat *in, + rfbPixelFormat *out,rfbColourMap* cm); +typedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in, + rfbPixelFormat *out); + +static rfbInitCMTableFnType rfbInitColourMapSingleTableFns[COUNT_OFFSETS] = { + rfbInitColourMapSingleTable8, + rfbInitColourMapSingleTable16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbInitColourMapSingleTable24, +#endif + rfbInitColourMapSingleTable32 +}; + +static rfbInitTableFnType rfbInitTrueColourSingleTableFns[COUNT_OFFSETS] = { + rfbInitTrueColourSingleTable8, + rfbInitTrueColourSingleTable16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbInitTrueColourSingleTable24, +#endif + rfbInitTrueColourSingleTable32 +}; + +static rfbInitTableFnType rfbInitTrueColourRGBTablesFns[COUNT_OFFSETS] = { + rfbInitTrueColourRGBTables8, + rfbInitTrueColourRGBTables16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbInitTrueColourRGBTables24, +#endif + rfbInitTrueColourRGBTables32 +}; + +static rfbTranslateFnType rfbTranslateWithSingleTableFns[COUNT_OFFSETS][COUNT_OFFSETS] = { + { rfbTranslateWithSingleTable8to8, + rfbTranslateWithSingleTable8to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithSingleTable8to24, +#endif + rfbTranslateWithSingleTable8to32 }, + { rfbTranslateWithSingleTable16to8, + rfbTranslateWithSingleTable16to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithSingleTable16to24, +#endif + rfbTranslateWithSingleTable16to32 }, +#ifdef LIBVNCSERVER_ALLOW24BPP + { rfbTranslateWithSingleTable24to8, + rfbTranslateWithSingleTable24to16, + rfbTranslateWithSingleTable24to24, + rfbTranslateWithSingleTable24to32 }, +#endif + { rfbTranslateWithSingleTable32to8, + rfbTranslateWithSingleTable32to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithSingleTable32to24, +#endif + rfbTranslateWithSingleTable32to32 } +}; + +static rfbTranslateFnType rfbTranslateWithRGBTablesFns[COUNT_OFFSETS][COUNT_OFFSETS] = { + { rfbTranslateWithRGBTables8to8, + rfbTranslateWithRGBTables8to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithRGBTables8to24, +#endif + rfbTranslateWithRGBTables8to32 }, + { rfbTranslateWithRGBTables16to8, + rfbTranslateWithRGBTables16to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithRGBTables16to24, +#endif + rfbTranslateWithRGBTables16to32 }, +#ifdef LIBVNCSERVER_ALLOW24BPP + { rfbTranslateWithRGBTables24to8, + rfbTranslateWithRGBTables24to16, + rfbTranslateWithRGBTables24to24, + rfbTranslateWithRGBTables24to32 }, +#endif + { rfbTranslateWithRGBTables32to8, + rfbTranslateWithRGBTables32to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithRGBTables32to24, +#endif + rfbTranslateWithRGBTables32to32 } +}; + + + +/* + * rfbTranslateNone is used when no translation is required. + */ + +void +rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out, + char *iptr, char *optr, int bytesBetweenInputLines, + int width, int height) +{ + int bytesPerOutputLine = width * (out->bitsPerPixel / 8); + + while (height > 0) { + memcpy(optr, iptr, bytesPerOutputLine); + iptr += bytesBetweenInputLines; + optr += bytesPerOutputLine; + height--; + } +} + + +/* + * rfbSetTranslateFunction sets the translation function. + */ + +rfbBool +rfbSetTranslateFunction(rfbClientPtr cl) +{ + rfbLog("Pixel format for client %s:\n",cl->host); + PrintPixelFormat(&cl->format); + + /* + * Check that bits per pixel values are valid + */ + + if ((cl->screen->serverFormat.bitsPerPixel != 8) && + (cl->screen->serverFormat.bitsPerPixel != 16) && +#ifdef LIBVNCSERVER_ALLOW24BPP + (cl->screen->serverFormat.bitsPerPixel != 24) && +#endif + (cl->screen->serverFormat.bitsPerPixel != 32)) + { + rfbErr("%s: server bits per pixel not 8, 16 or 32 (is %d)\n", + "rfbSetTranslateFunction", + cl->screen->serverFormat.bitsPerPixel); + rfbCloseClient(cl); + return FALSE; + } + + if ((cl->format.bitsPerPixel != 8) && + (cl->format.bitsPerPixel != 16) && +#ifdef LIBVNCSERVER_ALLOW24BPP + (cl->format.bitsPerPixel != 24) && +#endif + (cl->format.bitsPerPixel != 32)) + { + rfbErr("%s: client bits per pixel not 8, 16 or 32\n", + "rfbSetTranslateFunction"); + rfbCloseClient(cl); + return FALSE; + } + + if (!cl->format.trueColour && (cl->format.bitsPerPixel != 8)) { + rfbErr("rfbSetTranslateFunction: client has colour map " + "but %d-bit - can only cope with 8-bit colour maps\n", + cl->format.bitsPerPixel); + rfbCloseClient(cl); + return FALSE; + } + + /* + * bpp is valid, now work out how to translate + */ + + if (!cl->format.trueColour) { + /* + * truecolour -> colour map + * + * Set client's colour map to BGR233, then effectively it's + * truecolour as well + */ + + if (!rfbSetClientColourMapBGR233(cl)) + return FALSE; + + cl->format = BGR233Format; + } + + /* truecolour -> truecolour */ + + if (PF_EQ(cl->format,cl->screen->serverFormat)) { + + /* client & server the same */ + + rfbLog("no translation needed\n"); + cl->translateFn = rfbTranslateNone; + return TRUE; + } + + if ((cl->screen->serverFormat.bitsPerPixel < 16) || + ((!cl->screen->serverFormat.trueColour || !rfbEconomicTranslate) && + (cl->screen->serverFormat.bitsPerPixel == 16))) { + + /* we can use a single lookup table for <= 16 bpp */ + + cl->translateFn = rfbTranslateWithSingleTableFns + [BPP2OFFSET(cl->screen->serverFormat.bitsPerPixel)] + [BPP2OFFSET(cl->format.bitsPerPixel)]; + + if(cl->screen->serverFormat.trueColour) + (*rfbInitTrueColourSingleTableFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &(cl->screen->serverFormat), &cl->format); + else + (*rfbInitColourMapSingleTableFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &(cl->screen->serverFormat), &cl->format,&cl->screen->colourMap); + + } else { + + /* otherwise we use three separate tables for red, green and blue */ + + cl->translateFn = rfbTranslateWithRGBTablesFns + [BPP2OFFSET(cl->screen->serverFormat.bitsPerPixel)] + [BPP2OFFSET(cl->format.bitsPerPixel)]; + + (*rfbInitTrueColourRGBTablesFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &(cl->screen->serverFormat), &cl->format); + } + + return TRUE; +} + + + +/* + * rfbSetClientColourMapBGR233 sets the client's colour map so that it's + * just like an 8-bit BGR233 true colour client. + */ + +static rfbBool +rfbSetClientColourMapBGR233(rfbClientPtr cl) +{ + char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; + rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; + uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]); + int i, len; + int r, g, b; + + if (cl->format.bitsPerPixel != 8 ) { + rfbErr("%s: client not 8 bits per pixel\n", + "rfbSetClientColourMapBGR233"); + rfbCloseClient(cl); + return FALSE; + } + + scme->type = rfbSetColourMapEntries; + + scme->firstColour = Swap16IfLE(0); + scme->nColours = Swap16IfLE(256); + + len = sz_rfbSetColourMapEntriesMsg; + + i = 0; + + for (b = 0; b < 4; b++) { + for (g = 0; g < 8; g++) { + for (r = 0; r < 8; r++) { + rgb[i++] = Swap16IfLE(r * 65535 / 7); + rgb[i++] = Swap16IfLE(g * 65535 / 7); + rgb[i++] = Swap16IfLE(b * 65535 / 3); + } + } + } + + len += 256 * 3 * 2; + + if (rfbWriteExact(cl, buf, len) < 0) { + rfbLogPerror("rfbSetClientColourMapBGR233: write"); + rfbCloseClient(cl); + return FALSE; + } + return TRUE; +} + +/* this function is not called very often, so it needn't be + efficient. */ + +/* + * rfbSetClientColourMap is called to set the client's colour map. If the + * client is a true colour client, we simply update our own translation table + * and mark the whole screen as having been modified. + */ + +rfbBool +rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours) +{ + if (cl->screen->serverFormat.trueColour || !cl->readyForSetColourMapEntries) { + return TRUE; + } + + if (nColours == 0) { + nColours = cl->screen->colourMap.count; + } + + if (cl->format.trueColour) { + LOCK(cl->updateMutex); + (*rfbInitColourMapSingleTableFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &cl->screen->serverFormat, &cl->format,&cl->screen->colourMap); + + sraRgnDestroy(cl->modifiedRegion); + cl->modifiedRegion = + sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height); + UNLOCK(cl->updateMutex); + + return TRUE; + } + + return rfbSendSetColourMapEntries(cl, firstColour, nColours); +} + + +/* + * rfbSetClientColourMaps sets the colour map for each RFB client. + */ + +void +rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours) +{ + rfbClientIteratorPtr i; + rfbClientPtr cl; + + i = rfbGetClientIterator(rfbScreen); + while((cl = rfbClientIteratorNext(i))) + rfbSetClientColourMap(cl, firstColour, nColours); + rfbReleaseClientIterator(i); +} + +static void +PrintPixelFormat(rfbPixelFormat *pf) +{ + if (pf->bitsPerPixel == 1) { + rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n", + (pf->bigEndian ? "most" : "least")); + } else { + rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth, + ((pf->bitsPerPixel == 8) ? "" + : (pf->bigEndian ? ", big endian" : ", little endian"))); + if (pf->trueColour) { + rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n", + pf->redMax, pf->greenMax, pf->blueMax, + pf->redShift, pf->greenShift, pf->blueShift); + } else { + rfbLog(" uses a colour map (not true colour).\n"); + } + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/ultra.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/ultra.c new file mode 100755 index 0000000..a802026 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/ultra.c @@ -0,0 +1,248 @@ +/* + * ultra.c + * + * Routines to implement ultra based encoding (minilzo). + * ultrazip supports packed rectangles if the rects are tiny... + * This improves performance as lzo has more data to work with at once + * This is 'UltraZip' and is currently not implemented. + */ + +#include +#include "minilzo.h" + +/* + * lzoBeforeBuf contains pixel data in the client's format. + * lzoAfterBuf contains the lzo (deflated) encoding version. + * If the lzo compressed/encoded version is + * larger than the raw data or if it exceeds lzoAfterBufSize then + * raw encoding is used instead. + */ + +static int lzoBeforeBufSize = 0; +static char *lzoBeforeBuf = NULL; + +static int lzoAfterBufSize = 0; +static char *lzoAfterBuf = NULL; +static int lzoAfterBufLen = 0; + +/* + * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib + * rectangle encoding. + */ + +#define MAX_WRKMEM ((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) + +void rfbUltraCleanup(rfbScreenInfoPtr screen) +{ + if (lzoBeforeBufSize) { + free(lzoBeforeBuf); + lzoBeforeBufSize=0; + } + if (lzoAfterBufSize) { + free(lzoAfterBuf); + lzoAfterBufSize=0; + } +} + +void rfbFreeUltraData(rfbClientPtr cl) { + if (cl->compStreamInitedLZO) { + free(cl->lzoWrkMem); + cl->compStreamInitedLZO=FALSE; + } +} + + +static rfbBool +rfbSendOneRectEncodingUltra(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + rfbZlibHeader hdr; + int deflateResult; + int i; + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + int maxRawSize; + int maxCompSize; + + maxRawSize = (w * h * (cl->format.bitsPerPixel / 8)); + + if (lzoBeforeBufSize < maxRawSize) { + lzoBeforeBufSize = maxRawSize; + if (lzoBeforeBuf == NULL) + lzoBeforeBuf = (char *)malloc(lzoBeforeBufSize); + else + lzoBeforeBuf = (char *)realloc(lzoBeforeBuf, lzoBeforeBufSize); + } + + /* + * lzo requires output buffer to be slightly larger than the input + * buffer, in the worst case. + */ + maxCompSize = (maxRawSize + maxRawSize / 16 + 64 + 3); + + if (lzoAfterBufSize < maxCompSize) { + lzoAfterBufSize = maxCompSize; + if (lzoAfterBuf == NULL) + lzoAfterBuf = (char *)malloc(lzoAfterBufSize); + else + lzoAfterBuf = (char *)realloc(lzoAfterBuf, lzoAfterBufSize); + } + + /* + * Convert pixel data to client format. + */ + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, lzoBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + if ( cl->compStreamInitedLZO == FALSE ) { + cl->compStreamInitedLZO = TRUE; + /* Work-memory needed for compression. Allocate memory in units + * of `lzo_align_t' (instead of `char') to make sure it is properly aligned. + */ + cl->lzoWrkMem = malloc(sizeof(lzo_align_t) * (((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t))); + } + + /* Perform the compression here. */ + deflateResult = lzo1x_1_compress((unsigned char *)lzoBeforeBuf, (lzo_uint)(w * h * (cl->format.bitsPerPixel / 8)), (unsigned char *)lzoAfterBuf, (lzo_uint *)&maxCompSize, cl->lzoWrkMem); + /* maxCompSize now contains the compressed size */ + + /* Find the total size of the resulting compressed data. */ + lzoAfterBufLen = maxCompSize; + + if ( deflateResult != LZO_E_OK ) { + rfbErr("lzo deflation error: %d\n", deflateResult); + return FALSE; + } + + /* Update statics */ + rfbStatRecordEncodingSent(cl, rfbEncodingUltra, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + lzoAfterBufLen, maxRawSize); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + > 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(rfbEncodingUltra); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.nBytes = Swap32IfLE(lzoAfterBufLen); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader); + cl->ublen += sz_rfbZlibHeader; + + /* We might want to try sending the data directly... */ + for (i = 0; i < lzoAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > lzoAfterBufLen) { + bytesToCopy = lzoAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &lzoAfterBuf[i], bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; + +} + +/* + * rfbSendRectEncodingUltra - send a given rectangle using one or more + * LZO encoding rectangles. + */ + +rfbBool +rfbSendRectEncodingUltra(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int maxLines; + int linesRemaining; + rfbRectangle partialRect; + + partialRect.x = x; + partialRect.y = y; + partialRect.w = w; + partialRect.h = h; + + /* Determine maximum pixel/scan lines allowed per rectangle. */ + maxLines = ( ULTRA_MAX_SIZE(w) / w ); + + /* Initialize number of scan lines left to do. */ + linesRemaining = h; + + /* Loop until all work is done. */ + while ( linesRemaining > 0 ) { + + int linesToComp; + + if ( maxLines < linesRemaining ) + linesToComp = maxLines; + else + linesToComp = linesRemaining; + + partialRect.h = linesToComp; + + /* Encode (compress) and send the next rectangle. */ + if ( ! rfbSendOneRectEncodingUltra( cl, + partialRect.x, + partialRect.y, + partialRect.w, + partialRect.h )) { + + return FALSE; + } + + /* Technically, flushing the buffer here is not extrememly + * efficient. However, this improves the overall throughput + * of the system over very slow networks. By flushing + * the buffer with every maximum size lzo rectangle, we + * improve the pipelining usage of the server CPU, network, + * and viewer CPU components. Insuring that these components + * are working in parallel actually improves the performance + * seen by the user. + * Since, lzo is most useful for slow networks, this flush + * is appropriate for the desired behavior of the lzo encoding. + */ + if (( cl->ublen > 0 ) && + ( linesToComp == maxLines )) { + if (!rfbSendUpdateBuf(cl)) { + + return FALSE; + } + } + + /* Update remaining and incremental rectangle location. */ + linesRemaining -= linesToComp; + partialRect.y += linesToComp; + + } + + return TRUE; + +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/vncauth.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/vncauth.c new file mode 100755 index 0000000..0b73531 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/vncauth.c @@ -0,0 +1,208 @@ +/* + * 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 program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncauth.c - Functions for VNC password management and authentication. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include +#include +#include "d3des.h" + +#include +#include + +#ifdef LIBVNCSERVER_HAVE_SYS_STAT_H +#include +#endif + +#include + +#ifdef WIN32 +#define srandom srand +#define random rand +#else +#include +#endif + + +/* libvncclient does not need this */ +#ifndef rfbEncryptBytes + +/* + * We use a fixed key to store passwords, since we assume that our local + * file system is secure but nonetheless don't want to store passwords + * as plaintext. + */ + +static unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7}; + + +/* + * Encrypt a password and store it in a file. Returns 0 if successful, + * 1 if the file could not be written. + */ + +int +rfbEncryptAndStorePasswd(char *passwd, char *fname) +{ + FILE *fp; + unsigned int i; + unsigned char encryptedPasswd[8]; + + if ((fp = fopen(fname,"w")) == NULL) return 1; + + /* windows security sux */ +#ifndef WIN32 + fchmod(fileno(fp), S_IRUSR|S_IWUSR); +#endif + + /* pad password with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + encryptedPasswd[i] = passwd[i]; + } else { + encryptedPasswd[i] = 0; + } + } + + /* Do encryption in-place - this way we overwrite our copy of the plaintext + password */ + + rfbDesKey(fixedkey, EN0); + rfbDes(encryptedPasswd, encryptedPasswd); + + for (i = 0; i < 8; i++) { + putc(encryptedPasswd[i], fp); + } + + fclose(fp); + return 0; +} + + +/* + * Decrypt a password from a file. Returns a pointer to a newly allocated + * string containing the password or a null pointer if the password could + * not be retrieved for some reason. + */ + +char * +rfbDecryptPasswdFromFile(char *fname) +{ + FILE *fp; + int i, ch; + unsigned char *passwd = (unsigned char *)malloc(9); + + if ((fp = fopen(fname,"r")) == NULL) return NULL; + + for (i = 0; i < 8; i++) { + ch = getc(fp); + if (ch == EOF) { + fclose(fp); + return NULL; + } + passwd[i] = ch; + } + + fclose(fp); + + rfbDesKey(fixedkey, DE1); + rfbDes(passwd, passwd); + + passwd[8] = 0; + + return (char *)passwd; +} + + +/* + * Generate CHALLENGESIZE random bytes for use in challenge-response + * authentication. + */ + +void +rfbRandomBytes(unsigned char *bytes) +{ + int i; + static rfbBool s_srandom_called = FALSE; + + if (!s_srandom_called) { + srandom((unsigned int)time(NULL) ^ (unsigned int)getpid()); + s_srandom_called = TRUE; + } + + for (i = 0; i < CHALLENGESIZE; i++) { + bytes[i] = (unsigned char)(random() & 255); + } +} + +#endif + +/* + * Encrypt CHALLENGESIZE bytes in memory using a password. + */ + +void +rfbEncryptBytes(unsigned char *bytes, char *passwd) +{ + unsigned char key[8]; + unsigned int i; + + /* key is simply password padded with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + key[i] = passwd[i]; + } else { + key[i] = 0; + } + } + + rfbDesKey(key, EN0); + + for (i = 0; i < CHALLENGESIZE; i += 8) { + rfbDes(bytes+i, bytes+i); + } +} + +void +rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) { + int i, j; + rfbDesKey(key, EN0); + for (i = 0; i< 8; i++) + where[i] ^= key[i]; + rfbDes(where, where); + for (i = 8; i < length; i += 8) { + for (j = 0; j < 8; j++) + where[i + j] ^= where[i + j - 8]; + rfbDes(where + i, where + i); + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/websockets.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/websockets.c new file mode 100755 index 0000000..46cc46f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/websockets.c @@ -0,0 +1,568 @@ +/* + * websockets.c - deal with WebSockets clients. + * + * This code should be independent of any changes in the RFB protocol. It is + * an additional handshake and framing of normal sockets: + * http://www.whatwg.org/specs/web-socket-protocol/ + * + */ + +/* + * Copyright (C) 2010 Joel Martin + * + * 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 + +/* errno */ +#include + +#include +#include +#include + +#define FLASH_POLICY_RESPONSE "\n" +#define SZ_FLASH_POLICY_RESPONSE 93 + +#define WEBSOCKETS_HANDSHAKE_RESPONSE "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\ +Upgrade: WebSocket\r\n\ +Connection: Upgrade\r\n\ +%sWebSocket-Origin: %s\r\n\ +%sWebSocket-Location: %s://%s%s\r\n\ +%sWebSocket-Protocol: %s\r\n\ +\r\n%s" + +#define WEBSOCKETS_CLIENT_CONNECT_WAIT_MS 100 +#define WEBSOCKETS_CLIENT_SEND_WAIT_MS 100 +#define WEBSOCKETS_MAX_HANDSHAKE_LEN 4096 + +#if defined(__linux__) && defined(NEED_TIMEVAL) +struct timeval +{ + long int tv_sec,tv_usec; +} +; +#endif + +static rfbBool webSocketsHandshake(rfbClientPtr cl, char *scheme); +void webSocketsGenMd5(char * target, char *key1, char *key2, char *key3); + +static int +min (int a, int b) { + return a < b ? a : b; +} + +int +webSocketsSSLInit(rfbClientPtr cl) +{ + char *keyfile; + int r, ret = -1; + + SSL_library_init(); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + + if (cl->screen->sslkeyfile && *cl->screen->sslkeyfile) { + keyfile = cl->screen->sslkeyfile; + } else { + keyfile = cl->screen->sslcertfile; + } + + if (!cl->screen->sslcertfile || !cl->screen->sslcertfile[0]) { + rfbErr("SSL connection but no cert specified\n"); + } else if (NULL == (cl->ssl_ctx = SSL_CTX_new(TLSv1_server_method()))) { + ERR_print_errors_fp(stderr); + } else if (SSL_CTX_use_PrivateKey_file(cl->ssl_ctx, keyfile, SSL_FILETYPE_PEM) <= 0) { + rfbErr("Unable to load private key file %s\n", keyfile); + } else if (SSL_CTX_use_certificate_file(cl->ssl_ctx, cl->screen->sslcertfile, SSL_FILETYPE_PEM) <= 0) { + rfbErr("Unable to load certificate file %s\n", cl->screen->sslcertfile); + } else if (NULL == (cl->ssl = SSL_new(cl->ssl_ctx))) { + rfbErr("SSL_new failed\n"); + ERR_print_errors_fp(stderr); + } else if (!(SSL_set_fd(cl->ssl, cl->sock))) { + rfbErr("SSL_set_fd failed\n"); + ERR_print_errors_fp(stderr); + } else { + while ((r = SSL_accept(cl->ssl)) < 0) { + if (SSL_get_error(cl->ssl, r) != SSL_ERROR_WANT_READ) + break; + } + if (r < 0) { + rfbErr("SSL_accept failed %d\n", SSL_get_error(cl->ssl, r)); + } else { + ret = 0; + } + } + return ret; +} + + +/* + * rfbWebSocketsHandshake is called to handle new WebSockets connections + */ + +rfbBool +webSocketsCheck (rfbClientPtr cl) +{ + char bbuf[4], *scheme; + int ret; + + ret = rfbPeekExactTimeout(cl, bbuf, 4, + WEBSOCKETS_CLIENT_CONNECT_WAIT_MS); + if ((ret < 0) && (errno == ETIMEDOUT)) { + rfbLog("Normal socket connection\n"); + return TRUE; + } else if (ret <= 0) { + rfbErr("webSocketsHandshake: unknown connection error\n"); + return FALSE; + } + + if (strncmp(bbuf, "<", 1) == 0) { + rfbLog("Got Flash policy request, sending response\n"); + if (rfbWriteExact(cl, FLASH_POLICY_RESPONSE, + SZ_FLASH_POLICY_RESPONSE) < 0) { + rfbErr("webSocketsHandshake: failed sending Flash policy response"); + } + return FALSE; + } else if (strncmp(bbuf, "\x16", 1) == 0 || strncmp(bbuf, "\x80", 1) == 0) { + rfbLog("Got TLS/SSL WebSockets connection\n"); + if (-1 == webSocketsSSLInit(cl)) { + rfbErr("webSocketsHandshake: webSocketsSSLInit failed\n"); + return FALSE; + } + ret = rfbPeekExactTimeout(cl, bbuf, 4, WEBSOCKETS_CLIENT_CONNECT_WAIT_MS); + cl->webSocketsSSL = TRUE; + scheme = "wss"; + } else { + cl->webSocketsSSL = FALSE; + scheme = "ws"; + } + + if (strncmp(bbuf, "GET ", 4) != 0) { + rfbErr("webSocketsHandshake: invalid client header\n"); + return FALSE; + } + + rfbLog("Got '%s' WebSockets handshake\n", scheme); + + if (!webSocketsHandshake(cl, scheme)) { + return FALSE; + } + cl->webSockets = TRUE; // Start WebSockets framing + return TRUE; +} + +static rfbBool +webSocketsHandshake(rfbClientPtr cl, char *scheme) +{ + char *buf, *response, *line; + int n, linestart = 0, len = 0, llen; + char prefix[5], trailer[17]; + char *path, *host, *origin, *protocol; + char *key1 = NULL, *key2 = NULL, *key3 = NULL; + + buf = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN); + if (!buf) { + rfbLogPerror("webSocketsHandshake: malloc"); + return FALSE; + } + response = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN); + if (!response) { + free(buf); + rfbLogPerror("webSocketsHandshake: malloc"); + return FALSE; + } + + while (len < WEBSOCKETS_MAX_HANDSHAKE_LEN-1) { + if ((n = rfbReadExactTimeout(cl, buf+len, 1, + WEBSOCKETS_CLIENT_SEND_WAIT_MS)) <= 0) { + if ((n < 0) && (errno == ETIMEDOUT)) { + break; + } + if (n == 0) + rfbLog("webSocketsHandshake: client gone\n"); + else + rfbLogPerror("webSocketsHandshake: read"); + return FALSE; + } + + len += 1; + llen = len - linestart; + if (((llen >= 2)) && (buf[len-1] == '\n')) { + line = buf+linestart; + if ((llen == 2) && (strncmp("\r\n", line, 2) == 0)) { + if (key1 && key2) { + if ((n = rfbReadExact(cl, buf+len, 8)) <= 0) { + if ((n < 0) && (errno == ETIMEDOUT)) { + break; + } + if (n == 0) + rfbLog("webSocketsHandshake: client gone\n"); + else + rfbLogPerror("webSocketsHandshake: read"); + return FALSE; + } + rfbLog("Got key3\n"); + key3 = buf+len; + len += 8; + } else { + buf[len] = '\0'; + } + break; + } else if ((llen >= 16) && ((strncmp("GET ", line, min(llen,4))) == 0)) { + // 16 = 4 ("GET ") + 1 ("/.*") + 11 (" HTTP/1.1\r\n") + path = line+4; + buf[len-11] = '\0'; // Trim trailing " HTTP/1.1\r\n" + cl->webSocketsBase64 = TRUE; + //rfbLog("Got path: %s\n", path); + } else if ((strncasecmp("host: ", line, min(llen,6))) == 0) { + host = line+6; + buf[len-2] = '\0'; + //rfbLog("Got host: %s\n", host); + } else if ((strncasecmp("origin: ", line, min(llen,8))) == 0) { + origin = line+8; + buf[len-2] = '\0'; + //rfbLog("Got origin: %s\n", origin); + } else if ((strncasecmp("sec-websocket-key1: ", line, min(llen,20))) == 0) { + key1 = line+20; + buf[len-2] = '\0'; + //rfbLog("Got key1: %s\n", key1); + } else if ((strncasecmp("sec-websocket-key2: ", line, min(llen,20))) == 0) { + key2 = line+20; + buf[len-2] = '\0'; + //rfbLog("Got key2: %s\n", key2); + } else if ((strncasecmp("sec-websocket-protocol: ", line, min(llen,24))) == 0) { + protocol = line+24; + buf[len-2] = '\0'; + //rfbLog("Got protocol: %s\n", protocol); + } + linestart = len; + } + } + + if (!(path && host && origin)) { + rfbErr("webSocketsHandshake: incomplete client handshake\n"); + free(response); + free(buf); + return FALSE; + } + + /* + if ((!protocol) || (!strcasestr(protocol, "base64"))) { + rfbErr("webSocketsHandshake: base64 subprotocol not supported by client\n"); + free(response); + free(buf); + return FALSE; + } + */ + + /* + * Generate the WebSockets server response based on the the headers sent + * by the client. + */ + + if (!(key1 && key2 && key3)) { + rfbLog(" - WebSockets client version 75\n"); + prefix[0] = '\0'; + trailer[0] = '\0'; + } else { + rfbLog(" - WebSockets client version 76\n"); + snprintf(prefix, 5, "Sec-"); + webSocketsGenMd5(trailer, key1, key2, key3); + } + + snprintf(response, WEBSOCKETS_MAX_HANDSHAKE_LEN, + WEBSOCKETS_HANDSHAKE_RESPONSE, prefix, origin, prefix, scheme, + host, path, prefix, protocol, trailer); + + if (rfbWriteExact(cl, response, strlen(response)) < 0) { + rfbErr("webSocketsHandshake: failed sending WebSockets response\n"); + free(response); + free(buf); + return FALSE; + } + //rfbLog("webSocketsHandshake: handshake complete\n"); + return TRUE; +} + +void +webSocketsGenMd5(char * target, char *key1, char *key2, char *key3) +{ + unsigned int i, spaces1 = 0, spaces2 = 0; + unsigned long num1 = 0, num2 = 0; + unsigned char buf[17]; + for (i=0; i < strlen(key1); i++) { + if (key1[i] == ' ') { + spaces1 += 1; + } + if ((key1[i] >= 48) && (key1[i] <= 57)) { + num1 = num1 * 10 + (key1[i] - 48); + } + } + num1 = num1 / spaces1; + + for (i=0; i < strlen(key2); i++) { + if (key2[i] == ' ') { + spaces2 += 1; + } + if ((key2[i] >= 48) && (key2[i] <= 57)) { + num2 = num2 * 10 + (key2[i] - 48); + } + } + num2 = num2 / spaces2; + + /* Pack it big-endian */ + buf[0] = (num1 & 0xff000000) >> 24; + buf[1] = (num1 & 0xff0000) >> 16; + buf[2] = (num1 & 0xff00) >> 8; + buf[3] = num1 & 0xff; + + buf[4] = (num2 & 0xff000000) >> 24; + buf[5] = (num2 & 0xff0000) >> 16; + buf[6] = (num2 & 0xff00) >> 8; + buf[7] = num2 & 0xff; + + strncpy((char *)buf+8, key3, 8); + buf[16] = '\0'; + + md5_buffer((char *)buf, 16, target); + target[16] = '\0'; + + return; +} + +int +webSocketsEncode(rfbClientPtr cl, const char *src, int len) +{ + int i, sz = 0; + unsigned char chr; + cl->encodeBuf[sz++] = '\x00'; + if (cl->webSocketsBase64) { + len = __b64_ntop(src, len, cl->encodeBuf+sz, UPDATE_BUF_SIZE*2); + if (len < 0) { + return len; + } + sz += len; + } else { + for (i=0; i < len; i++) { + chr = src[i]; + if (chr < 128) { + if (chr == 0x00) { + cl->encodeBuf[sz++] = '\xc4'; + cl->encodeBuf[sz++] = '\x80'; + } else { + cl->encodeBuf[sz++] = chr; + } + } else { + if (chr < 192) { + cl->encodeBuf[sz++] = '\xc2'; + cl->encodeBuf[sz++] = chr; + } else { + cl->encodeBuf[sz++] = '\xc3'; + cl->encodeBuf[sz++] = chr - 64; + } + } + } + } + cl->encodeBuf[sz++] = '\xff'; + //rfbLog("<< webSocketsEncode: %d\n", len); + return sz; +} + +static int +ws_read(rfbClientPtr cl, char *buf, int len) +{ + int n; + if (cl->ssl) { + while ((n = SSL_read(cl->ssl, buf, len)) <= 0) { + if (SSL_get_error(cl->ssl, n) != SSL_ERROR_WANT_READ) + return -1; + } + } else { + n = read(cl->sock, buf, len); + } + return n; +} + +static int +ws_peek(rfbClientPtr cl, char *buf, int len) +{ + int total = 0, n; + if (cl->ssl) { + while ((n = SSL_peek(cl->ssl, buf, len)) <= 0) { + if (SSL_get_error(cl->ssl, n) != SSL_ERROR_WANT_READ) + return -1; + } + } else { + n = recv(cl->sock, buf, len, MSG_PEEK); + } + return n; +} + +int +webSocketsDecode(rfbClientPtr cl, char *dst, int len) +{ + int retlen = 0, n, i, avail, modlen, needlen, actual; + char *buf, *end = NULL; + unsigned char chr, chr2; + + char debug[1024]; + + buf = cl->decodeBuf; + + n = ws_peek(cl, buf, len*2+2); + + if (n <= 0) { + rfbLog("recv of %d\n", n); + return n; + } + + + if (cl->webSocketsBase64) { + /* Base64 encoded WebSockets stream */ + + if (buf[0] == '\xff') { + i = ws_read(cl, buf, 1); // Consume marker + buf++; + n--; + } + if (n == 0) { + errno = EAGAIN; + return -1; + } + if (buf[0] == '\x00') { + i = ws_read(cl, buf, 1); // Consume marker + buf++; + n--; + } + if (n == 0) { + errno = EAGAIN; + return -1; + } + + //end = memchr(buf, '\xff', len*2+2); + end = memchr(buf, '\xff', n); + if (!end) { + end = buf + n; + } + avail = end - buf; + + len -= cl->carrylen; + + /* Determine how much base64 data we need */ + modlen = len + (len+2)/3; + needlen = modlen; + if (needlen % 4) { + needlen += 4 - (needlen % 4); + } + + if (needlen > avail) { + //rfbLog("Waiting for more base64 data\n"); + errno = EAGAIN; + return -1; + } + + /* Any carryover from previous decode */ + for (i=0; i < cl->carrylen; i++) { +// rfbLog("Adding carryover %d\n", cl->carryBuf[i]); + dst[i] = cl->carryBuf[i]; + retlen += 1; + } + + /* Decode the rest of what we need */ + buf[needlen] = '\x00'; // Replace end marker with end of string +// rfbLog("buf: %s\n", buf); + n = __b64_pton(buf, dst+retlen, 2+len); + if (n < len) { + rfbErr("Base64 decode error\n"); + errno = EIO; + return -1; + } + retlen += n; + + /* Consume the data from socket */ + i = ws_read(cl, buf, needlen); + + cl->carrylen = n - len; + retlen -= cl->carrylen; + for (i=0; i < cl->carrylen; i++) { +// rfbLog("Saving carryover %d\n", dst[retlen + i]); + cl->carryBuf[i] = dst[retlen + i]; + } + } else { + /* UTF-8 encoded WebSockets stream */ + + actual = 0; + for (needlen = 0; needlen < n && actual < len; needlen++) { + chr = buf[needlen]; + if ((chr > 0) && (chr < 128)) { + actual++; + } else if ((chr > 127) && (chr < 255)) { + if (needlen + 1 >= n) { + break; + } + needlen++; + actual++; + } + } + + if (actual < len) { + errno = EAGAIN; + return -1; + } + + /* Consume what we need */ + if ((n = ws_read(cl, buf, needlen)) < needlen) { + return n; + } + + while (retlen < len) { + chr = buf[0]; + buf += 1; + + if (chr == 0) { + /* Begin frame marker, just skip it */ + } else if (chr == 255) { + /* Begin frame marker, just skip it */ + } else if (chr < 128) { + dst[retlen++] = chr; + } else { + chr2 = buf[0]; + buf += 1; + + switch (chr) { + case (unsigned char) '\xc2': + dst[retlen++] = chr2; + break; + case (unsigned char) '\xc3': + dst[retlen++] = chr2 + 64; + break; + case (unsigned char) '\xc4': + dst[retlen++] = 0; + break; + default: + rfbErr("Invalid UTF-8 encoding\n"); + errno = EIO; + return -1; + } + } + } + } + +// rfbLog("<< webSocketsDecode, retlen: %d\n", retlen); + return retlen; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zlib.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zlib.c new file mode 100755 index 0000000..ac20c9c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zlib.c @@ -0,0 +1,331 @@ +/* + * zlib.c + * + * Routines to implement zlib based encoding (deflate). + */ + +/* + * Copyright (C) 2000 Tridia Corporation. 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. + * + * For the latest source code, please check: + * + * http://www.developVNC.org/ + * + * or send email to feedback@developvnc.org. + */ + +#include + +/* + * zlibBeforeBuf contains pixel data in the client's format. + * zlibAfterBuf contains the zlib (deflated) encoding version. + * If the zlib compressed/encoded version is + * larger than the raw data or if it exceeds zlibAfterBufSize then + * raw encoding is used instead. + */ + +/* + * Out of lazyiness, we use thread local storage for zlib as we did for + * tight. N.B. ZRLE does it the traditional way with per-client storage + * (and so at least ZRLE will work threaded on older systems.) + */ +#if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__) +#define TLS __thread +#endif +#ifndef TLS +#define TLS +#endif + +static TLS int zlibBeforeBufSize = 0; +static TLS char *zlibBeforeBuf = NULL; + +static TLS int zlibAfterBufSize = 0; +static TLS char *zlibAfterBuf = NULL; +static TLS int zlibAfterBufLen = 0; + +void rfbZlibCleanup(rfbScreenInfoPtr screen) +{ + if (zlibBeforeBufSize) { + free(zlibBeforeBuf); + zlibBeforeBufSize=0; + } + if (zlibAfterBufSize) { + zlibAfterBufSize=0; + free(zlibAfterBuf); + } +} + + +/* + * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib + * rectangle encoding. + */ + +static rfbBool +rfbSendOneRectEncodingZlib(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + rfbZlibHeader hdr; + int deflateResult; + int previousOut; + int i; + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + int maxRawSize; + int maxCompSize; + + maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height + * (cl->format.bitsPerPixel / 8)); + + if (zlibBeforeBufSize < maxRawSize) { + zlibBeforeBufSize = maxRawSize; + if (zlibBeforeBuf == NULL) + zlibBeforeBuf = (char *)malloc(zlibBeforeBufSize); + else + zlibBeforeBuf = (char *)realloc(zlibBeforeBuf, zlibBeforeBufSize); + } + + /* zlib compression is not useful for very small data sets. + * So, we just send these raw without any compression. + */ + if (( w * h * (cl->scaledScreen->bitsPerPixel / 8)) < + VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) { + + int result; + + /* The translation function (used also by the in raw encoding) + * requires 4/2/1 byte alignment in the output buffer (which is + * updateBuf for the raw encoding) based on the bitsPerPixel of + * the viewer/client. This prevents SIGBUS errors on some + * architectures like SPARC, PARISC... + */ + if (( cl->format.bitsPerPixel > 8 ) && + ( cl->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + result = rfbSendRectEncodingRaw(cl, x, y, w, h); + + return result; + + } + + /* + * zlib requires output buffer to be slightly larger than the input + * buffer, in the worst case. + */ + maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12; + + if (zlibAfterBufSize < maxCompSize) { + zlibAfterBufSize = maxCompSize; + if (zlibAfterBuf == NULL) + zlibAfterBuf = (char *)malloc(zlibAfterBufSize); + else + zlibAfterBuf = (char *)realloc(zlibAfterBuf, zlibAfterBufSize); + } + + + /* + * Convert pixel data to client format. + */ + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, zlibBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + cl->compStream.next_in = ( Bytef * )zlibBeforeBuf; + cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8); + cl->compStream.next_out = ( Bytef * )zlibAfterBuf; + cl->compStream.avail_out = maxCompSize; + cl->compStream.data_type = Z_BINARY; + + /* Initialize the deflation state. */ + if ( cl->compStreamInited == FALSE ) { + + cl->compStream.total_in = 0; + cl->compStream.total_out = 0; + cl->compStream.zalloc = Z_NULL; + cl->compStream.zfree = Z_NULL; + cl->compStream.opaque = Z_NULL; + + deflateInit2( &(cl->compStream), + cl->zlibCompressLevel, + Z_DEFLATED, + MAX_WBITS, + MAX_MEM_LEVEL, + Z_DEFAULT_STRATEGY ); + /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */ + /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */ + cl->compStreamInited = TRUE; + + } + + previousOut = cl->compStream.total_out; + + /* Perform the compression here. */ + deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH ); + + /* Find the total size of the resulting compressed data. */ + zlibAfterBufLen = cl->compStream.total_out - previousOut; + + if ( deflateResult != Z_OK ) { + rfbErr("zlib deflation error: %s\n", cl->compStream.msg); + return FALSE; + } + + /* Note that it is not possible to switch zlib parameters based on + * the results of the compression pass. The reason is + * that we rely on the compressor and decompressor states being + * in sync. Compressing and then discarding the results would + * cause lose of synchronization. + */ + + /* Update statics */ + rfbStatRecordEncodingSent(cl, rfbEncodingZlib, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + zlibAfterBufLen, + + w * (cl->format.bitsPerPixel / 8) * h); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + > 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(rfbEncodingZlib); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.nBytes = Swap32IfLE(zlibAfterBufLen); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader); + cl->ublen += sz_rfbZlibHeader; + + for (i = 0; i < zlibAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > zlibAfterBufLen) { + bytesToCopy = zlibAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &zlibAfterBuf[i], bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; + +} + + +/* + * rfbSendRectEncodingZlib - send a given rectangle using one or more + * Zlib encoding rectangles. + */ + +rfbBool +rfbSendRectEncodingZlib(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int maxLines; + int linesRemaining; + rfbRectangle partialRect; + + partialRect.x = x; + partialRect.y = y; + partialRect.w = w; + partialRect.h = h; + + /* Determine maximum pixel/scan lines allowed per rectangle. */ + maxLines = ( ZLIB_MAX_SIZE(w) / w ); + + /* Initialize number of scan lines left to do. */ + linesRemaining = h; + + /* Loop until all work is done. */ + while ( linesRemaining > 0 ) { + + int linesToComp; + + if ( maxLines < linesRemaining ) + linesToComp = maxLines; + else + linesToComp = linesRemaining; + + partialRect.h = linesToComp; + + /* Encode (compress) and send the next rectangle. */ + if ( ! rfbSendOneRectEncodingZlib( cl, + partialRect.x, + partialRect.y, + partialRect.w, + partialRect.h )) { + + return FALSE; + } + + /* Technically, flushing the buffer here is not extrememly + * efficient. However, this improves the overall throughput + * of the system over very slow networks. By flushing + * the buffer with every maximum size zlib rectangle, we + * improve the pipelining usage of the server CPU, network, + * and viewer CPU components. Insuring that these components + * are working in parallel actually improves the performance + * seen by the user. + * Since, zlib is most useful for slow networks, this flush + * is appropriate for the desired behavior of the zlib encoding. + */ + if (( cl->ublen > 0 ) && + ( linesToComp == maxLines )) { + if (!rfbSendUpdateBuf(cl)) { + + return FALSE; + } + } + + /* Update remaining and incremental rectangle location. */ + linesRemaining -= linesToComp; + partialRect.y += linesToComp; + + } + + return TRUE; + +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrle.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrle.c new file mode 100755 index 0000000..e1f1447 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrle.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * 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. + */ + +/* + * zrle.c + * + * Routines to implement Zlib Run-length Encoding (ZRLE). + */ + +#include "rfb/rfb.h" +#include "private.h" +#include "zrleoutstream.h" + + +#define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \ +{ char *fbptr = (cl->scaledScreen->frameBuffer \ + + (cl->scaledScreen->paddedWidthInBytes * ty) \ + + (tx * (cl->scaledScreen->bitsPerPixel / 8))); \ + \ + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,\ + &cl->format, fbptr, (char*)buf, \ + cl->scaledScreen->paddedWidthInBytes, tw, th); } + +#define EXTRA_ARGS , rfbClientPtr cl + +#define ENDIAN_LITTLE 0 +#define ENDIAN_BIG 1 +#define ENDIAN_NO 2 +#define BPP 8 +#define ZYWRLE_ENDIAN ENDIAN_NO +#include +#undef BPP +#define BPP 15 +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef BPP +#define BPP 16 +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef BPP +#define BPP 32 +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#define CPIXEL 24A +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef CPIXEL +#define CPIXEL 24B +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef CPIXEL +#undef BPP + + +/* + * zrleBeforeBuf contains pixel data in the client's format. It must be at + * least one pixel bigger than the largest tile of pixel data, since the + * ZRLE encoding algorithm writes to the position one past the end of the pixel + * data. + */ + +/* TODO: put into rfbClient struct */ + +static char zrleBeforeBuf[rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4]; + +/* + * rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding. + */ + +rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h) +{ + zrleOutStream* zos; + rfbFramebufferUpdateRectHeader rect; + rfbZRLEHeader hdr; + int i; + char *zrleBeforeBuf; + + if (cl->zrleBeforeBuf == NULL) { + cl->zrleBeforeBuf = (char *) malloc(rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4); + } + zrleBeforeBuf = cl->zrleBeforeBuf; + + if (cl->preferredEncoding == rfbEncodingZYWRLE) { + if (cl->tightQualityLevel < 0) { + cl->zywrleLevel = 1; + } else if (cl->tightQualityLevel < 3) { + cl->zywrleLevel = 3; + } else if (cl->tightQualityLevel < 6) { + cl->zywrleLevel = 2; + } else { + cl->zywrleLevel = 1; + } + } else + cl->zywrleLevel = 0; + + if (!cl->zrleData) + cl->zrleData = zrleOutStreamNew(); + zos = cl->zrleData; + zos->in.ptr = zos->in.start; + zos->out.ptr = zos->out.start; + + switch (cl->format.bitsPerPixel) { + + case 8: + zrleEncode8NE(x, y, w, h, zos, zrleBeforeBuf, cl); + break; + + case 16: + if (cl->format.greenMax > 0x1F) { + if (cl->format.bigEndian) + zrleEncode16BE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode16LE(x, y, w, h, zos, zrleBeforeBuf, cl); + } else { + if (cl->format.bigEndian) + zrleEncode15BE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode15LE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + break; + + case 32: { + rfbBool fitsInLS3Bytes + = ((cl->format.redMax << cl->format.redShift) < (1<<24) && + (cl->format.greenMax << cl->format.greenShift) < (1<<24) && + (cl->format.blueMax << cl->format.blueShift) < (1<<24)); + + rfbBool fitsInMS3Bytes = (cl->format.redShift > 7 && + cl->format.greenShift > 7 && + cl->format.blueShift > 7); + + if ((fitsInLS3Bytes && !cl->format.bigEndian) || + (fitsInMS3Bytes && cl->format.bigEndian)) { + if (cl->format.bigEndian) + zrleEncode24ABE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode24ALE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + else if ((fitsInLS3Bytes && cl->format.bigEndian) || + (fitsInMS3Bytes && !cl->format.bigEndian)) { + if (cl->format.bigEndian) + zrleEncode24BBE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode24BLE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + else { + if (cl->format.bigEndian) + zrleEncode32BE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode32LE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + } + break; + } + + rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out), + + w * (cl->format.bitsPerPixel / 8) * h); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + > 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(cl->preferredEncoding); + + memcpy(cl->updateBuf+cl->ublen, (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out)); + + memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader); + cl->ublen += sz_rfbZRLEHeader; + + /* copy into updateBuf and send from there. Maybe should send directly? */ + + for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) { + bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i; + } + + memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; +} + + +void rfbFreeZrleData(rfbClientPtr cl) +{ + if (cl->zrleData) { + zrleOutStreamFree(cl->zrleData); + } + cl->zrleData = NULL; + + if (cl->zrleBeforeBuf) { + free(cl->zrleBeforeBuf); + } + cl->zrleBeforeBuf = NULL; + + if (cl->paletteHelper) { + free(cl->paletteHelper); + } + cl->paletteHelper = NULL; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleencodetemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleencodetemplate.c new file mode 100755 index 0000000..3a6f117 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleencodetemplate.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * 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. + */ + +/* + * Before including this file, you must define a number of CPP macros. + * + * BPP should be 8, 16 or 32 depending on the bits per pixel. + * GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data + * into the given buffer. EXTRA_ARGS can be defined to pass any other + * arguments needed by GET_IMAGE_INTO_BUF. + * + * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel + * bigger than the largest tile of pixel data, since the ZRLE encoding + * algorithm writes to the position one past the end of the pixel data. + */ + +#include "zrleoutstream.h" +#include "zrlepalettehelper.h" +#include + +/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same + but also expands its arguments if they are macros */ + +#ifndef __RFB_CONCAT2E +#define __RFB_CONCAT2(a,b) a##b +#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b) +#endif + +#ifndef __RFB_CONCAT3E +#define __RFB_CONCAT3(a,b,c) a##b##c +#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c) +#endif + +#undef END_FIX +#if ZYWRLE_ENDIAN == ENDIAN_LITTLE +# define END_FIX LE +#elif ZYWRLE_ENDIAN == ENDIAN_BIG +# define END_FIX BE +#else +# define END_FIX NE +#endif + +#ifdef CPIXEL +#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL) +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX) +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX) +#define BPPOUT 24 +#elif BPP==15 +#define PIXEL_T __RFB_CONCAT2E(zrle_U,16) +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16) +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) +#define BPPOUT 16 +#else +#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP) +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) +#define BPPOUT BPP +#endif + +#ifndef ZRLE_ONCE +#define ZRLE_ONCE + +static const int bitsPerPackedPixel[] = { + 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 +}; + +static zrlePaletteHelper paletteHelper; + +#endif /* ZRLE_ONCE */ + +void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os, + int zywrle_level, int *zywrleBuf, void *paletteHelper); + +#if BPP!=8 +#define ZYWRLE_ENCODE +#include "zywrletemplate.c" +#endif + +static void ZRLE_ENCODE (int x, int y, int w, int h, + zrleOutStream* os, void* buf + EXTRA_ARGS + ) +{ + int ty; + for (ty = y; ty < y+h; ty += rfbZRLETileHeight) { + int tx, th = rfbZRLETileHeight; + if (th > y+h-ty) th = y+h-ty; + for (tx = x; tx < x+w; tx += rfbZRLETileWidth) { + int tw = rfbZRLETileWidth; + if (tw > x+w-tx) tw = x+w-tx; + + GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf); + + if (cl->paletteHelper == NULL) { + cl->paletteHelper = (void *) calloc(sizeof(zrlePaletteHelper), 1); + } + + ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os, + cl->zywrleLevel, cl->zywrleBuf, cl->paletteHelper); + } + } + zrleOutStreamFlush(os); +} + + +void ZRLE_ENCODE_TILE(PIXEL_T* data, int w, int h, zrleOutStream* os, + int zywrle_level, int *zywrleBuf, void *paletteHelper) +{ + /* First find the palette and the number of runs */ + + zrlePaletteHelper *ph; + + int runs = 0; + int singlePixels = 0; + + rfbBool useRle; + rfbBool usePalette; + + int estimatedBytes; + int plainRleBytes; + int i; + + PIXEL_T* ptr = data; + PIXEL_T* end = ptr + h * w; + *end = ~*(end-1); /* one past the end is different so the while loop ends */ + +#if 0 + ph = &paletteHelper; +#else + ph = (zrlePaletteHelper *) paletteHelper; +#endif + zrlePaletteHelperInit(ph); + + while (ptr < end) { + PIXEL_T pix = *ptr; + if (*++ptr != pix) { + singlePixels++; + } else { + while (*++ptr == pix) ; + runs++; + } + zrlePaletteHelperInsert(ph, pix); + } + + /* Solid tile is a special case */ + + if (ph->size == 1) { + zrleOutStreamWriteU8(os, 1); + zrleOutStreamWRITE_PIXEL(os, ph->palette[0]); + return; + } + + /* Try to work out whether to use RLE and/or a palette. We do this by + estimating the number of bytes which will be generated and picking the + method which results in the fewest bytes. Of course this may not result + in the fewest bytes after compression... */ + + useRle = FALSE; + usePalette = FALSE; + + estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */ + +#if BPP!=8 + if (zywrle_level > 0 && !(zywrle_level & 0x80)) + estimatedBytes >>= zywrle_level; +#endif + + plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels); + + if (plainRleBytes < estimatedBytes) { + useRle = TRUE; + estimatedBytes = plainRleBytes; + } + + if (ph->size < 128) { + int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels; + + if (paletteRleBytes < estimatedBytes) { + useRle = TRUE; + usePalette = TRUE; + estimatedBytes = paletteRleBytes; + } + + if (ph->size < 17) { + int packedBytes = ((BPPOUT/8) * ph->size + + w * h * bitsPerPackedPixel[ph->size-1] / 8); + + if (packedBytes < estimatedBytes) { + useRle = FALSE; + usePalette = TRUE; + estimatedBytes = packedBytes; + } + } + } + + if (!usePalette) ph->size = 0; + + zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size); + + for (i = 0; i < ph->size; i++) { + zrleOutStreamWRITE_PIXEL(os, ph->palette[i]); + } + + if (useRle) { + + PIXEL_T* ptr = data; + PIXEL_T* end = ptr + w * h; + PIXEL_T* runStart; + PIXEL_T pix; + while (ptr < end) { + int len; + runStart = ptr; + pix = *ptr++; + while (*ptr == pix && ptr < end) + ptr++; + len = ptr - runStart; + if (len <= 2 && usePalette) { + int index = zrlePaletteHelperLookup(ph, pix); + if (len == 2) + zrleOutStreamWriteU8(os, index); + zrleOutStreamWriteU8(os, index); + continue; + } + if (usePalette) { + int index = zrlePaletteHelperLookup(ph, pix); + zrleOutStreamWriteU8(os, index | 128); + } else { + zrleOutStreamWRITE_PIXEL(os, pix); + } + len -= 1; + while (len >= 255) { + zrleOutStreamWriteU8(os, 255); + len -= 255; + } + zrleOutStreamWriteU8(os, len); + } + + } else { + + /* no RLE */ + + if (usePalette) { + int bppp; + PIXEL_T* ptr = data; + + /* packed pixels */ + + assert (ph->size < 17); + + bppp = bitsPerPackedPixel[ph->size-1]; + + for (i = 0; i < h; i++) { + zrle_U8 nbits = 0; + zrle_U8 byte = 0; + + PIXEL_T* eol = ptr + w; + + while (ptr < eol) { + PIXEL_T pix = *ptr++; + zrle_U8 index = zrlePaletteHelperLookup(ph, pix); + byte = (byte << bppp) | index; + nbits += bppp; + if (nbits >= 8) { + zrleOutStreamWriteU8(os, byte); + nbits = 0; + } + } + if (nbits > 0) { + byte <<= 8 - nbits; + zrleOutStreamWriteU8(os, byte); + } + } + } else { + + /* raw */ + +#if BPP!=8 + if (zywrle_level > 0 && !(zywrle_level & 0x80)) { + ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, zywrleBuf); + ZRLE_ENCODE_TILE(data, w, h, os, zywrle_level | 0x80, zywrleBuf, paletteHelper); + } + else +#endif + { +#ifdef CPIXEL + PIXEL_T *ptr; + for (ptr = data; ptr < data+w*h; ptr++) + zrleOutStreamWRITE_PIXEL(os, *ptr); +#else + zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8)); +#endif + } + } + } +} + +#undef PIXEL_T +#undef zrleOutStreamWRITE_PIXEL +#undef ZRLE_ENCODE +#undef ZRLE_ENCODE_TILE +#undef ZYWRLE_ENCODE_TILE +#undef BPPOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.c new file mode 100755 index 0000000..4efe609 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * 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 "zrleoutstream.h" +#include + +#define ZRLE_IN_BUFFER_SIZE 16384 +#define ZRLE_OUT_BUFFER_SIZE 1024 +#undef ZRLE_DEBUG + +static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size) +{ + buffer->ptr = buffer->start = malloc(size); + if (buffer->start == NULL) { + buffer->end = NULL; + return FALSE; + } + + buffer->end = buffer->start + size; + + return TRUE; +} + +static void zrleBufferFree(zrleBuffer *buffer) +{ + if (buffer->start) + free(buffer->start); + buffer->start = buffer->ptr = buffer->end = NULL; +} + +static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size) +{ + int offset; + + size += buffer->end - buffer->start; + offset = ZRLE_BUFFER_LENGTH (buffer); + + buffer->start = realloc(buffer->start, size); + if (!buffer->start) { + return FALSE; + } + + buffer->end = buffer->start + size; + buffer->ptr = buffer->start + offset; + + return TRUE; +} + +zrleOutStream *zrleOutStreamNew(void) +{ + zrleOutStream *os; + + os = malloc(sizeof(zrleOutStream)); + if (os == NULL) + return NULL; + + if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) { + free(os); + return NULL; + } + + if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) { + zrleBufferFree(&os->in); + free(os); + return NULL; + } + + os->zs.zalloc = Z_NULL; + os->zs.zfree = Z_NULL; + os->zs.opaque = Z_NULL; + if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) { + zrleBufferFree(&os->in); + free(os); + return NULL; + } + + return os; +} + +void zrleOutStreamFree (zrleOutStream *os) +{ + deflateEnd(&os->zs); + zrleBufferFree(&os->in); + zrleBufferFree(&os->out); + free(os); +} + +rfbBool zrleOutStreamFlush(zrleOutStream *os) +{ + os->zs.next_in = os->in.start; + os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in); +#endif + + while (os->zs.avail_in != 0) { + do { + int ret; + + if (os->out.ptr >= os->out.end && + !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { + rfbLog("zrleOutStreamFlush: failed to grow output buffer\n"); + return FALSE; + } + + os->zs.next_out = os->out.ptr; + os->zs.avail_out = os->out.end - os->out.ptr; + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n", + os->zs.avail_in, os->zs.avail_out); +#endif + + if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) { + rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret); + return FALSE; + } + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n", + os->zs.next_out - os->out.ptr); +#endif + + os->out.ptr = os->zs.next_out; + } while (os->zs.avail_out == 0); + } + + os->in.ptr = os->in.start; + + return TRUE; +} + +static int zrleOutStreamOverrun(zrleOutStream *os, + int size) +{ +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamOverrun\n"); +#endif + + while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) { + os->zs.next_in = os->in.start; + os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); + + do { + int ret; + + if (os->out.ptr >= os->out.end && + !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { + rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n"); + return FALSE; + } + + os->zs.next_out = os->out.ptr; + os->zs.avail_out = os->out.end - os->out.ptr; + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n", + os->zs.avail_in, os->zs.avail_out); +#endif + + if ((ret = deflate(&os->zs, 0)) != Z_OK) { + rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret); + return 0; + } + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n", + os->zs.next_out - os->out.ptr); +#endif + + os->out.ptr = os->zs.next_out; + } while (os->zs.avail_out == 0); + + /* output buffer not full */ + + if (os->zs.avail_in == 0) { + os->in.ptr = os->in.start; + } else { + /* but didn't consume all the data? try shifting what's left to the + * start of the buffer. + */ + rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n"); + memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in); + os->in.ptr -= os->zs.next_in - os->in.start; + } + } + + if (size > os->in.end - os->in.ptr) + size = os->in.end - os->in.ptr; + + return size; +} + +static int zrleOutStreamCheck(zrleOutStream *os, int size) +{ + if (os->in.ptr + size > os->in.end) { + return zrleOutStreamOverrun(os, size); + } + return size; +} + +void zrleOutStreamWriteBytes(zrleOutStream *os, + const zrle_U8 *data, + int length) +{ + const zrle_U8* dataEnd = data + length; + while (data < dataEnd) { + int n = zrleOutStreamCheck(os, dataEnd - data); + memcpy(os->in.ptr, data, n); + os->in.ptr += n; + data += n; + } +} + +void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u) +{ + zrleOutStreamCheck(os, 1); + *os->in.ptr++ = u; +} + +void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u) +{ + zrleOutStreamCheck(os, 1); + *os->in.ptr++ = u; +} + +void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u) +{ + zrleOutStreamCheck(os, 2); + *os->in.ptr++ = ((zrle_U8*)&u)[0]; + *os->in.ptr++ = ((zrle_U8*)&u)[1]; +} + +void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u) +{ + zrleOutStreamCheck(os, 4); + *os->in.ptr++ = ((zrle_U8*)&u)[0]; + *os->in.ptr++ = ((zrle_U8*)&u)[1]; + *os->in.ptr++ = ((zrle_U8*)&u)[2]; + *os->in.ptr++ = ((zrle_U8*)&u)[3]; +} + +void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u) +{ + zrleOutStreamCheck(os, 3); + *os->in.ptr++ = ((zrle_U8*)&u)[0]; + *os->in.ptr++ = ((zrle_U8*)&u)[1]; + *os->in.ptr++ = ((zrle_U8*)&u)[2]; +} + +void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u) +{ + zrleOutStreamCheck(os, 3); + *os->in.ptr++ = ((zrle_U8*)&u)[1]; + *os->in.ptr++ = ((zrle_U8*)&u)[2]; + *os->in.ptr++ = ((zrle_U8*)&u)[3]; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.h new file mode 100755 index 0000000..9e4fe51 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __ZRLE_OUT_STREAM_H__ +#define __ZRLE_OUT_STREAM_H__ + +#include +#include "zrletypes.h" +#include "rfb/rfb.h" + +typedef struct { + zrle_U8 *start; + zrle_U8 *ptr; + zrle_U8 *end; +} zrleBuffer; + +typedef struct { + zrleBuffer in; + zrleBuffer out; + + z_stream zs; +} zrleOutStream; + +#define ZRLE_BUFFER_LENGTH(b) ((b)->ptr - (b)->start) + +zrleOutStream *zrleOutStreamNew (void); +void zrleOutStreamFree (zrleOutStream *os); +rfbBool zrleOutStreamFlush (zrleOutStream *os); +void zrleOutStreamWriteBytes (zrleOutStream *os, + const zrle_U8 *data, + int length); +void zrleOutStreamWriteU8 (zrleOutStream *os, + zrle_U8 u); +void zrleOutStreamWriteOpaque8 (zrleOutStream *os, + zrle_U8 u); +void zrleOutStreamWriteOpaque16 (zrleOutStream *os, + zrle_U16 u); +void zrleOutStreamWriteOpaque32 (zrleOutStream *os, + zrle_U32 u); +void zrleOutStreamWriteOpaque24A(zrleOutStream *os, + zrle_U32 u); +void zrleOutStreamWriteOpaque24B(zrleOutStream *os, + zrle_U32 u); + +#endif /* __ZRLE_OUT_STREAM_H__ */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.c new file mode 100755 index 0000000..d758a26 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * 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 "zrlepalettehelper.h" +#include +#include + +#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095) + +void zrlePaletteHelperInit(zrlePaletteHelper *helper) +{ + memset(helper->palette, 0, sizeof(helper->palette)); + memset(helper->index, 255, sizeof(helper->index)); + memset(helper->key, 0, sizeof(helper->key)); + helper->size = 0; +} + +void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix) +{ + if (helper->size < ZRLE_PALETTE_MAX_SIZE) { + int i = ZRLE_HASH(pix); + + while (helper->index[i] != 255 && helper->key[i] != pix) + i++; + if (helper->index[i] != 255) return; + + helper->index[i] = helper->size; + helper->key[i] = pix; + helper->palette[helper->size] = pix; + } + helper->size++; +} + +int zrlePaletteHelperLookup(zrlePaletteHelper *helper, zrle_U32 pix) +{ + int i = ZRLE_HASH(pix); + + assert(helper->size <= ZRLE_PALETTE_MAX_SIZE); + + while (helper->index[i] != 255 && helper->key[i] != pix) + i++; + if (helper->index[i] != 255) return helper->index[i]; + + return -1; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.h new file mode 100755 index 0000000..e1213d1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * 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. + */ + +/* + * The PaletteHelper class helps us build up the palette from pixel data by + * storing a reverse index using a simple hash-table + */ + +#ifndef __ZRLE_PALETTE_HELPER_H__ +#define __ZRLE_PALETTE_HELPER_H__ + +#include "zrletypes.h" + +#define ZRLE_PALETTE_MAX_SIZE 127 + +typedef struct { + zrle_U32 palette[ZRLE_PALETTE_MAX_SIZE]; + zrle_U8 index[ZRLE_PALETTE_MAX_SIZE + 4096]; + zrle_U32 key[ZRLE_PALETTE_MAX_SIZE + 4096]; + int size; +} zrlePaletteHelper; + +void zrlePaletteHelperInit (zrlePaletteHelper *helper); +void zrlePaletteHelperInsert(zrlePaletteHelper *helper, + zrle_U32 pix); +int zrlePaletteHelperLookup(zrlePaletteHelper *helper, + zrle_U32 pix); + +#endif /* __ZRLE_PALETTE_HELPER_H__ */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrletypes.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrletypes.h new file mode 100755 index 0000000..0df42c9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrletypes.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. 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. + */ + +#ifndef __ZRLE_TYPES_H__ +#define __ZRLE_TYPES_H__ + +typedef unsigned char zrle_U8; +typedef unsigned short zrle_U16; +typedef unsigned int zrle_U32; +typedef signed char zrle_S8; +typedef signed short zrle_S16; +typedef signed int zrle_S32; + +#endif /* __ZRLE_TYPES_H__ */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zywrletemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zywrletemplate.c new file mode 100755 index 0000000..52b2b0b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zywrletemplate.c @@ -0,0 +1,824 @@ + +/******************************************************************** + * * + * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE. * + * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 * + * BY Hitachi Systems & Services, Ltd. * + * (Noriaki Yamazaki, Research & Developement Center) * * + * * + ******************************************************************** +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Hitachi Systems & Services, Ltd. nor +the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``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 FOUNDATION +OR CONTRIBUTORS 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. + ********************************************************************/ + +/* Change Log: + V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline + (Thanks Johannes Schindelin, author of LibVNC + Server/Client) + V0.01 : 2007/02/06 : Initial release +*/ + +/* #define ZYWRLE_ENCODE */ +/* #define ZYWRLE_DECODE */ +#define ZYWRLE_QUANTIZE + +/* +[References] + PLHarr: + Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380. + EZW: + Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993). +*/ + + +/* Template Macro stuffs. */ +#undef ZYWRLE_ANALYZE +#undef ZYWRLE_SYNTHESIZE +#define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX) +#define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX) + +#define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX) +#define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX) +#define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP) +#define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP) +#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP) +#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP) + +/* Packing/Unpacking pixel stuffs. + Endian conversion stuffs. */ +#undef S_0 +#undef S_1 +#undef L_0 +#undef L_1 +#undef L_2 +#if ZYWRLE_ENDIAN == ENDIAN_BIG +# define S_0 1 +# define S_1 0 +# define L_0 3 +# define L_1 2 +# define L_2 1 +#else +# define S_0 0 +# define S_1 1 +# define L_0 0 +# define L_1 1 +# define L_2 2 +#endif + +/* Load/Save pixel stuffs. */ +#define ZYWRLE_YMASK15 0xFFFFFFF8 +#define ZYWRLE_UVMASK15 0xFFFFFFF8 +#define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \ + R = (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8; \ + G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8; \ + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ +} +#define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \ + R &= 0xF8; \ + G &= 0xF8; \ + B &= 0xF8; \ + ((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6) ); \ + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF); \ +} +#define ZYWRLE_YMASK16 0xFFFFFFFC +#define ZYWRLE_UVMASK16 0xFFFFFFF8 +#define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \ + R = ((unsigned char*)pSrc)[S_1] & 0xF8; \ + G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC; \ + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ +} +#define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \ + R &= 0xF8; \ + G &= 0xFC; \ + B &= 0xF8; \ + ((unsigned char*)pDst)[S_1] = (unsigned char)( R |(G>>5) ); \ + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF); \ +} +#define ZYWRLE_YMASK32 0xFFFFFFFF +#define ZYWRLE_UVMASK32 0xFFFFFFFF +#define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \ + R = ((unsigned char*)pSrc)[L_2]; \ + G = ((unsigned char*)pSrc)[L_1]; \ + B = ((unsigned char*)pSrc)[L_0]; \ +} +#define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \ + ((unsigned char*)pDst)[L_2] = (unsigned char)R; \ + ((unsigned char*)pDst)[L_1] = (unsigned char)G; \ + ((unsigned char*)pDst)[L_0] = (unsigned char)B; \ +} + +#ifndef ZYWRLE_ONCE +#define ZYWRLE_ONCE + +#ifdef WIN32 +#define InlineX __inline +#else +#define InlineX inline +#endif + +#ifdef ZYWRLE_ENCODE +/* Tables for Coefficients filtering. */ +# ifndef ZYWRLE_QUANTIZE +/* Type A:lower bit omitting of EZW style. */ +const static unsigned int zywrleParam[3][3]={ + {0x0000F000,0x00000000,0x00000000}, + {0x0000C000,0x00F0F0F0,0x00000000}, + {0x0000C000,0x00C0C0C0,0x00F0F0F0}, +/* {0x0000FF00,0x00000000,0x00000000}, + {0x0000FF00,0x00FFFFFF,0x00000000}, + {0x0000FF00,0x00FFFFFF,0x00FFFFFF}, */ +}; +# else +/* Type B:Non liner quantization filter. */ +static const signed char zywrleConv[4][256]={ +{ /* bi=5, bo=5 r=0.0:PSNR=24.849 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=5 r=2.0:PSNR=74.031 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 64, 64, 64, 64, + 64, 64, 64, 64, 72, 72, 72, 72, + 72, 72, 72, 72, 80, 80, 80, 80, + 80, 80, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 96, 96, + 96, 96, 96, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 0, -120, -120, -120, -120, -120, -120, -120, + -120, -120, -120, -112, -112, -112, -112, -112, + -112, -112, -112, -112, -104, -104, -104, -104, + -104, -104, -104, -104, -104, -104, -96, -96, + -96, -96, -96, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -80, + -80, -80, -80, -80, -80, -72, -72, -72, + -72, -72, -72, -72, -72, -64, -64, -64, + -64, -64, -64, -64, -64, -56, -56, -56, + -56, -56, -56, -56, -56, -56, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=4 r=2.0:PSNR=64.441 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 0, -120, -120, -120, -120, -120, -120, -120, + -120, -120, -120, -120, -120, -112, -112, -112, + -112, -112, -112, -112, -112, -112, -104, -104, + -104, -104, -104, -104, -104, -104, -104, -104, + -104, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, + -80, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, + -64, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=2 r=2.0:PSNR=43.175 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 0, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} +}; +const static signed char* zywrleParam[3][3][3]={ + {{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}}, +}; +# endif +#endif + +static InlineX void Harr(signed char* pX0, signed char* pX1) +{ + /* Piecewise-Linear Harr(PLHarr) */ + int X0 = (int)*pX0, X1 = (int)*pX1; + int orgX0 = X0, orgX1 = X1; + if ((X0 ^ X1) & 0x80) { + /* differ sign */ + X1 += X0; + if (((X1^orgX1)&0x80)==0) { + /* |X1| > |X0| */ + X0 -= X1; /* H = -B */ + } + } else { + /* same sign */ + X0 -= X1; + if (((X0 ^ orgX0) & 0x80) == 0) { + /* |X0| > |X1| */ + X1 += X0; /* L = A */ + } + } + *pX0 = (signed char)X1; + *pX1 = (signed char)X0; +} +/* + 1D-Wavelet transform. + + In coefficients array, the famous 'pyramid' decomposition is well used. + + 1D Model: + |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0 + |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1 + + But this method needs line buffer because H/L is different position from X0/X1. + So, I used 'interleave' decomposition instead of it. + + 1D Model: + |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0 + |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1 + + In this method, H/L and X0/X1 is always same position. + This lead us to more speed and less memory. + Of cause, the result of both method is quite same + because it's only difference that coefficient position. +*/ +static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel) +{ + int s, ofs; + signed char* pX0; + signed char* end; + + pX0 = (signed char*)data; + s = (8<>(l+1))*s; + s -= 2; + ofs = (4<>1; + if (r & 0x02) + pH += (s>>1)*width; + for (y = 0; y < height / s; y++) { + for (x = 0; x < width / s; x++) { + /* + these are same following code. + pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1); + ( round pH[x] with pM[x] bit ) + '&' operator isn't 'round' but is 'floor'. + So, we must offset when pH[x] is negative. + */ + if (((signed char*)pH)[0] & 0x80) + ((signed char*)pH)[0] += ~((signed char*)pM)[0]; + if (((signed char*)pH)[1] & 0x80) + ((signed char*)pH)[1] += ~((signed char*)pM)[1]; + if (((signed char*)pH)[2] & 0x80) + ((signed char*)pH)[2] += ~((signed char*)pM)[2]; + *pH &= *pM; + pH += s; + } + pH += (s-1)*width; + } + } +} +# else +/* + Type B:Non liner quantization filter. + + Coefficients have Gaussian curve and smaller value which is + large part of coefficients isn't more important than larger value. + So, I use filter of Non liner quantize/dequantize table. + In general, Non liner quantize formula is explained as following. + + y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo) + x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi) + ( r:power coefficient bi:effective MSB in input bo:effective MSB in output ) + + r < 1.0 : Smaller value is more important than larger value. + r > 1.0 : Larger value is more important than smaller value. + r = 1.0 : Liner quantization which is same with EZW style. + + r = 0.75 is famous non liner quantization used in MP3 audio codec. + In contrast to audio data, larger value is important in wavelet coefficients. + So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ). + + As compared with EZW style liner quantization, this filter tended to be + more sharp edge and be more compression rate but be more blocking noise and be less quality. + Especially, the surface of graphic objects has distinguishable noise in middle quality mode. + + We need only quantized-dequantized(filtered) value rather than quantized value itself + because all values are packed or palette-lized in later ZRLE section. + This lead us not to need to modify client decoder when we change + the filtering procedure in future. + Client only decodes coefficients given by encoder. +*/ +static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) +{ + int r, s; + int x, y; + int* pH; + const signed char** pM; + + pM = zywrleParam[level-1][l]; + s = 2<>1; + if (r & 0x02) + pH += (s>>1)*width; + for (y = 0; y < height / s; y++) { + for (x = 0; x < width / s; x++) { + ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]]; + ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]]; + ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]]; + pH += s; + } + pH += (s-1)*width; + } + } +} +# endif + +static InlineX void Wavelet(int* pBuf, int width, int height, int level) +{ + int l, s; + int* pTop; + int* pEnd; + + for (l = 0; l < level; l++) { + pTop = pBuf; + pEnd = pBuf+height*width; + s = width<= 0; l--) { + pTop = pBuf; + pEnd = pBuf+width; + s = 1< YUV conversion stuffs. + YUV coversion is explained as following formula in strict meaning: + Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255) + U = -0.169R - 0.331G + 0.500B (-128<=U<=127) + V = 0.500R - 0.419G - 0.081B (-128<=V<=127) + + I use simple conversion RCT(reversible color transform) which is described + in JPEG-2000 specification. + Y = (R + 2G + B)/4 ( 0<=Y<=255) + U = B-G (-256<=U<=255) + V = R-G (-256<=V<=255) +*/ +#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x))) + /* RCT is N-bit RGB to N-bit Y and N+1-bit UV. + For make Same N-bit, UV is lossy. + More exact PLHarr, we reduce to odd range(-127<=x<=127). */ +#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \ + Y = (R+(G<<1)+B)>>2; \ + U = B-G; \ + V = R-G; \ + Y -= 128; \ + U >>= 1; \ + V >>= 1; \ + Y &= ymask; \ + U &= uvmask; \ + V &= uvmask; \ + if (Y == -128) \ + Y += (0xFFFFFFFF-ymask+1); \ + if (U == -128) \ + U += (0xFFFFFFFF-uvmask+1); \ + if (V == -128) \ + V += (0xFFFFFFFF-uvmask+1); \ +} +#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \ + Y += 128; \ + U <<= 1; \ + V <<= 1; \ + G = Y-((U+V)>>2); \ + B = U+G; \ + R = V+G; \ + G = ROUND(G); \ + B = ROUND(B); \ + R = ROUND(R); \ +} + +/* + coefficient packing/unpacking stuffs. + Wavelet transform makes 4 sub coefficient image from 1 original image. + + model with pyramid decomposition: + +------+------+ + | | | + | L | Hx | + | | | + +------+------+ + | | | + | H | Hxy | + | | | + +------+------+ + + So, we must transfer each sub images individually in strict meaning. + But at least ZRLE meaning, following one decompositon image is same as + avobe individual sub image. I use this format. + (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L) + for simplified procedure for any wavelet level.) + + +------+------+ + | L | + +------+------+ + | Hx | + +------+------+ + | Hy | + +------+------+ + | Hxy | + +------+------+ +*/ +#define INC_PTR(data) \ + data++; \ + if( data-pData >= (w+uw) ){ \ + data += scanline-(w+uw); \ + pData = data; \ + } + +#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \ + pH = pBuf; \ + s = 2<>1; \ + if (r & 0x02) \ + pH += (s>>1)*w; \ + pEnd = pH+h*w; \ + while (pH < pEnd) { \ + pLine = pH+w; \ + while (pH < pLine) { \ + TRANS \ + INC_PTR(data) \ + pH += s; \ + } \ + pH += (s-1)*w; \ + } + +#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);) + +#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);) + +#define ZYWRLE_SAVE_UNALIGN(data,TRANS) \ + pTop = pBuf+w*h; \ + pEnd = pBuf + (w+uw)*(h+uh); \ + while (pTop < pEnd) { \ + TRANS \ + INC_PTR(data) \ + pTop++; \ + } + +#define ZYWRLE_LOAD_UNALIGN(data,TRANS) \ + pTop = pBuf+w*h; \ + if (uw) { \ + pData= data + w; \ + pEnd = (int*)(pData+ h*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + uw); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-uw; \ + } \ + } \ + if (uh) { \ + pData= data + h*scanline; \ + pEnd = (int*)(pData+ uh*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + w); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-w; \ + } \ + } \ + if (uw && uh) { \ + pData= data + w+ h*scanline; \ + pEnd = (int*)(pData+ uh*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + uw); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-uw; \ + } \ + } + +static InlineX void zywrleCalcSize(int* pW, int* pH, int level) +{ + *pW &= ~((1<, 1996 +# +# 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; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes. +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $absdir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/droidvncgrab/vnc/libvncserver-kanaka/prepare_x11vnc_dist.sh b/droidvncgrab/vnc/libvncserver-kanaka/prepare_x11vnc_dist.sh new file mode 100755 index 0000000..e28ea6d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/prepare_x11vnc_dist.sh @@ -0,0 +1,136 @@ +#!/bin/bash + +VERSION="0.9.11" + +cd "$(dirname "$0")" + +mv configure.ac configure.ac.LibVNCServer + +cat configure.ac.LibVNCServer | \ +egrep -v '(AC_CONFIG_COMMANDS|chmod).*libvncserver-config' | \ +egrep -v '^[ ]*libvncserver-config$' | \ +sed -e "s/LibVNCServer, [^,)]*\([(,]\)*/x11vnc, $VERSION\1/g" \ + -e "s/\(contrib\|examples\|vncterm\|test\|client_examples\)\/Makefile//g" \ + -e "s/LibVNCServer.spec/x11vnc.spec/g" \ + -e "s/AC_PROG_LIBTOOL/AC_PROG_RANLIB/" \ + -e "s/PKG_CHECK/#PKG_CHECK/" \ + -e 's/if test "x$with_gnutls/with_gnutls=no; if test "x$with_gnutls/' \ +> configure.ac + +mv Makefile.am Makefile.am.LibVNCServer + +echo "EXTRA_DIST=tightvnc-1.3dev5-vncviewer-alpha-cursor.patch README.LibVNCServer" > Makefile.am +echo "" >> Makefile.am +echo "if HAVE_SYSTEM_LIBVNCSERVER" >> Makefile.am +echo "SUBDIRS=x11vnc classes" >> Makefile.am +echo "DIST_SUBDIRS=x11vnc classes" >> Makefile.am +echo "else" >> Makefile.am +echo "SUBDIRS=libvncserver libvncclient x11vnc classes" >> Makefile.am +echo "DIST_SUBDIRS=libvncserver libvncclient x11vnc classes" >> Makefile.am +echo "endif" >> Makefile.am +echo "" >> Makefile.am + +cat Makefile.am.LibVNCServer | \ +sed -e "s/^SUBDIRS.*$/#SUBDIRS=libvncserver libvncclient x11vnc classes/" \ + -e "s/^DIST_SUBDIRS.*$/#DIST_SUBDIRS=libvncserver libvncclient x11vnc classes/" \ + -e "/all: make_config_executable/,\$d" \ + -e "/^.*bin_SCRIPTS.*$/d" \ + -e "s/include_/noinst_/" \ +>> Makefile.am + +mv README README.LibVNCServer +cp x11vnc/README ./README + +cat LibVNCServer.spec.in | \ +sed -e "s/Johannes.Schindelin@gmx.de/runge@karlrunge.com/gi" \ + -e "s/Johannes.Schindelin/Karl Runge/g" \ + -e "s/a library to make writing a vnc server easy/a VNC server for the current X11 session/" \ + -e "/^%description$/,/%description devel$/d" \ + -e 's/^Static libraries.*$/%description\ +x11vnc is to X Window System what WinVNC is to Windows, i.e. a server\ +which serves the current Xwindows desktop via RFB (VNC) protocol\ +to the user.\ +\ +Based on the ideas of x0rfbserver and on LibVNCServer, it has evolved\ +into a versatile and performant while still easy to use program.\ +\ +x11vnc was put together and is (actively ;-) maintained by\ +Karl Runge \ +\ +/i' \ +> x11vnc.spec.in.tmp + +perl -e ' + $s = 0; + while (<>) { + if ($s) { + if (/^\s*$/) { + $s = 0; + } + } else { + if (/^%files\s*$/ || /^%files devel/) { + $s = 1; + } + } + next if $s; + if (/^%files x11vnc/) { + print "\%files\n"; + print "\%doc README x11vnc/ChangeLog\n"; + next; + } + print; + }' < x11vnc.spec.in.tmp > x11vnc.spec.in + +rm -f x11vnc.spec.in.tmp + +mv libvncserver/Makefile.am libvncserver/Makefile.am.LibVNCServer + +cat libvncserver/Makefile.am.LibVNCServer | \ +sed -e "s/\(include\|LIB\|lib\)_/noinst_/g" \ + -e "s/_la_/_a_/" \ + -e "s/\.la/.a/" \ + -e "s/_LTLIBRARIES/_LIBRARIES/" \ +> libvncserver/Makefile.am + +mv libvncclient/Makefile.am libvncclient/Makefile.am.LibVNCServer + +cat libvncclient/Makefile.am.LibVNCServer | \ +sed -e "s/\(include\|LIB\|lib\)_/noinst_/g" \ + -e "s/_la_/_a_/" \ + -e "s/\.la/.a/" \ + -e "s/_LTLIBRARIES/_LIBRARIES/" \ +> libvncclient/Makefile.am + +mv x11vnc/Makefile.am x11vnc/Makefile.am.LibVNCServer + +cat x11vnc/Makefile.am.LibVNCServer | \ +sed -e "s/_la_/_a_/" \ + -e "s/\.la/.a/g" \ + -e "s/_LTLIBRARIES/_LIBRARIES/" \ +> x11vnc/Makefile.am + + +cp classes/Makefile.am classes/Makefile.am.LibVNCServer +echo 'pkgdatadir = $(datadir)/@PACKAGE@/classes' >> classes/Makefile.am +echo 'pkgdata_DATA=VncViewer.jar index.vnc' >> classes/Makefile.am + +cp classes/ssl/Makefile.am classes/ssl/Makefile.am.LibVNCServer +sed -e 's/EXTRA_DIST=/EXTRA_DIST=tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch /' \ + classes/ssl/Makefile.am.LibVNCServer > classes/ssl/Makefile.am +echo 'pkgdatadir = $(datadir)/@PACKAGE@/classes/ssl' >> classes/ssl/Makefile.am +echo 'pkgdata_DATA=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README UltraViewerSSL.jar SignedUltraViewerSSL.jar ultra.vnc ultrasigned.vnc' >> classes/ssl/Makefile.am +echo 'pkgdata_SCRIPTS=ss_vncviewer' >> classes/ssl/Makefile.am + +chmod 755 classes/ssl/ss_vncviewer + +mv acinclude.m4 acinclude.m4.LibVNCServer + +cat acinclude.m4.LibVNCServer | \ +sed -e "s/^\(_PKG.*\)\$PACKAGE\(.*\)$/\1LibVNCServer\2/" \ +> acinclude.m4 + +make x11vnc-${VERSION}.tar.gz +for f in configure.ac Makefile.am x11vnc/Makefile.am libvncserver/Makefile.am libvncclient/Makefile.am classes/Makefile.am classes/ssl/Makefile.am acinclude.m4 README; do + mv -f $f.LibVNCServer $f +done + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/rfb/.cvsignore new file mode 100755 index 0000000..cec07e0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/.cvsignore @@ -0,0 +1,5 @@ +rfbconfig.h +rfbconfig.h.in +stamp-h* +rfbint.h + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/default8x16.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/default8x16.h new file mode 100755 index 0000000..252f411 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/default8x16.h @@ -0,0 +1,261 @@ +static unsigned char default8x16FontData[4096+1]={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00, +0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00, +0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, +0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00, +0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, +0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, +0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, +0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00, +0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00, +0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00, +0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, +0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, +0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, +0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, +0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00, +0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +static int default8x16FontMetaData[256*5+1]={ +0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,}; +static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData }; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/keysym.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/keysym.h new file mode 100755 index 0000000..219f95b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/keysym.h @@ -0,0 +1,1638 @@ +#ifndef XK_0 + +/* $XConsortium: keysym.h,v 1.15 94/04/17 20:10:55 rws Exp $ */ + +/*********************************************************** + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* default keysyms */ +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_GREEK + +/* $TOG: keysymdef.h /main/25 1997/06/21 10:54:51 kaleb $ */ + +/*********************************************************** +Copyright (c) 1987, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#define XK_VoidSymbol 0xFFFFFF /* void symbol */ + +#ifdef XK_MISCELLANY +/* + * TTY Functions, cleverly chosen to map to ascii, for convenience of + * programming, but could have been arbitrary (at the cost of lookup + * tables in client code. + */ + +#define XK_BackSpace 0xFF08 /* back space, back char */ +#define XK_Tab 0xFF09 +#define XK_Linefeed 0xFF0A /* Linefeed, LF */ +#define XK_Clear 0xFF0B +#define XK_Return 0xFF0D /* Return, enter */ +#define XK_Pause 0xFF13 /* Pause, hold */ +#define XK_Scroll_Lock 0xFF14 +#define XK_Sys_Req 0xFF15 +#define XK_Escape 0xFF1B +#define XK_Delete 0xFFFF /* Delete, rubout */ + + + +/* International & multi-key character composition */ + +#define XK_Multi_key 0xFF20 /* Multi-key character compose */ +#define XK_SingleCandidate 0xFF3C +#define XK_MultipleCandidate 0xFF3D +#define XK_PreviousCandidate 0xFF3E + +/* Japanese keyboard support */ + +#define XK_Kanji 0xFF21 /* Kanji, Kanji convert */ +#define XK_Muhenkan 0xFF22 /* Cancel Conversion */ +#define XK_Henkan_Mode 0xFF23 /* Start/Stop Conversion */ +#define XK_Henkan 0xFF23 /* Alias for Henkan_Mode */ +#define XK_Romaji 0xFF24 /* to Romaji */ +#define XK_Hiragana 0xFF25 /* to Hiragana */ +#define XK_Katakana 0xFF26 /* to Katakana */ +#define XK_Hiragana_Katakana 0xFF27 /* Hiragana/Katakana toggle */ +#define XK_Zenkaku 0xFF28 /* to Zenkaku */ +#define XK_Hankaku 0xFF29 /* to Hankaku */ +#define XK_Zenkaku_Hankaku 0xFF2A /* Zenkaku/Hankaku toggle */ +#define XK_Touroku 0xFF2B /* Add to Dictionary */ +#define XK_Massyo 0xFF2C /* Delete from Dictionary */ +#define XK_Kana_Lock 0xFF2D /* Kana Lock */ +#define XK_Kana_Shift 0xFF2E /* Kana Shift */ +#define XK_Eisu_Shift 0xFF2F /* Alphanumeric Shift */ +#define XK_Eisu_toggle 0xFF30 /* Alphanumeric toggle */ +#define XK_Zen_Koho 0xFF3D /* Multiple/All Candidate(s) */ +#define XK_Mae_Koho 0xFF3E /* Previous Candidate */ + +/* 0xFF31 thru 0xFF3F are under XK_KOREAN */ + +/* Cursor control & motion */ + +#define XK_Home 0xFF50 +#define XK_Left 0xFF51 /* Move left, left arrow */ +#define XK_Up 0xFF52 /* Move up, up arrow */ +#define XK_Right 0xFF53 /* Move right, right arrow */ +#define XK_Down 0xFF54 /* Move down, down arrow */ +#define XK_Prior 0xFF55 /* Prior, previous */ +#define XK_Page_Up 0xFF55 +#define XK_Next 0xFF56 /* Next */ +#define XK_Page_Down 0xFF56 +#define XK_End 0xFF57 /* EOL */ +#define XK_Begin 0xFF58 /* BOL */ + + +/* Misc Functions */ + +#define XK_Select 0xFF60 /* Select, mark */ +#define XK_Print 0xFF61 +#define XK_Execute 0xFF62 /* Execute, run, do */ +#define XK_Insert 0xFF63 /* Insert, insert here */ +#define XK_Undo 0xFF65 /* Undo, oops */ +#define XK_Redo 0xFF66 /* redo, again */ +#define XK_Menu 0xFF67 +#define XK_Find 0xFF68 /* Find, search */ +#define XK_Cancel 0xFF69 /* Cancel, stop, abort, exit */ +#define XK_Help 0xFF6A /* Help */ +#define XK_Break 0xFF6B +#define XK_Mode_switch 0xFF7E /* Character set switch */ +#define XK_script_switch 0xFF7E /* Alias for mode_switch */ +#define XK_Num_Lock 0xFF7F + +/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */ + +#define XK_KP_Space 0xFF80 /* space */ +#define XK_KP_Tab 0xFF89 +#define XK_KP_Enter 0xFF8D /* enter */ +#define XK_KP_F1 0xFF91 /* PF1, KP_A, ... */ +#define XK_KP_F2 0xFF92 +#define XK_KP_F3 0xFF93 +#define XK_KP_F4 0xFF94 +#define XK_KP_Home 0xFF95 +#define XK_KP_Left 0xFF96 +#define XK_KP_Up 0xFF97 +#define XK_KP_Right 0xFF98 +#define XK_KP_Down 0xFF99 +#define XK_KP_Prior 0xFF9A +#define XK_KP_Page_Up 0xFF9A +#define XK_KP_Next 0xFF9B +#define XK_KP_Page_Down 0xFF9B +#define XK_KP_End 0xFF9C +#define XK_KP_Begin 0xFF9D +#define XK_KP_Insert 0xFF9E +#define XK_KP_Delete 0xFF9F +#define XK_KP_Equal 0xFFBD /* equals */ +#define XK_KP_Multiply 0xFFAA +#define XK_KP_Add 0xFFAB +#define XK_KP_Separator 0xFFAC /* separator, often comma */ +#define XK_KP_Subtract 0xFFAD +#define XK_KP_Decimal 0xFFAE +#define XK_KP_Divide 0xFFAF + +#define XK_KP_0 0xFFB0 +#define XK_KP_1 0xFFB1 +#define XK_KP_2 0xFFB2 +#define XK_KP_3 0xFFB3 +#define XK_KP_4 0xFFB4 +#define XK_KP_5 0xFFB5 +#define XK_KP_6 0xFFB6 +#define XK_KP_7 0xFFB7 +#define XK_KP_8 0xFFB8 +#define XK_KP_9 0xFFB9 + + + +/* + * Auxilliary Functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufactures have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + +#define XK_F1 0xFFBE +#define XK_F2 0xFFBF +#define XK_F3 0xFFC0 +#define XK_F4 0xFFC1 +#define XK_F5 0xFFC2 +#define XK_F6 0xFFC3 +#define XK_F7 0xFFC4 +#define XK_F8 0xFFC5 +#define XK_F9 0xFFC6 +#define XK_F10 0xFFC7 +#define XK_F11 0xFFC8 +#define XK_L1 0xFFC8 +#define XK_F12 0xFFC9 +#define XK_L2 0xFFC9 +#define XK_F13 0xFFCA +#define XK_L3 0xFFCA +#define XK_F14 0xFFCB +#define XK_L4 0xFFCB +#define XK_F15 0xFFCC +#define XK_L5 0xFFCC +#define XK_F16 0xFFCD +#define XK_L6 0xFFCD +#define XK_F17 0xFFCE +#define XK_L7 0xFFCE +#define XK_F18 0xFFCF +#define XK_L8 0xFFCF +#define XK_F19 0xFFD0 +#define XK_L9 0xFFD0 +#define XK_F20 0xFFD1 +#define XK_L10 0xFFD1 +#define XK_F21 0xFFD2 +#define XK_R1 0xFFD2 +#define XK_F22 0xFFD3 +#define XK_R2 0xFFD3 +#define XK_F23 0xFFD4 +#define XK_R3 0xFFD4 +#define XK_F24 0xFFD5 +#define XK_R4 0xFFD5 +#define XK_F25 0xFFD6 +#define XK_R5 0xFFD6 +#define XK_F26 0xFFD7 +#define XK_R6 0xFFD7 +#define XK_F27 0xFFD8 +#define XK_R7 0xFFD8 +#define XK_F28 0xFFD9 +#define XK_R8 0xFFD9 +#define XK_F29 0xFFDA +#define XK_R9 0xFFDA +#define XK_F30 0xFFDB +#define XK_R10 0xFFDB +#define XK_F31 0xFFDC +#define XK_R11 0xFFDC +#define XK_F32 0xFFDD +#define XK_R12 0xFFDD +#define XK_F33 0xFFDE +#define XK_R13 0xFFDE +#define XK_F34 0xFFDF +#define XK_R14 0xFFDF +#define XK_F35 0xFFE0 +#define XK_R15 0xFFE0 + +/* Modifiers */ + +#define XK_Shift_L 0xFFE1 /* Left shift */ +#define XK_Shift_R 0xFFE2 /* Right shift */ +#define XK_Control_L 0xFFE3 /* Left control */ +#define XK_Control_R 0xFFE4 /* Right control */ +#define XK_Caps_Lock 0xFFE5 /* Caps lock */ +#define XK_Shift_Lock 0xFFE6 /* Shift lock */ + +#define XK_Meta_L 0xFFE7 /* Left meta */ +#define XK_Meta_R 0xFFE8 /* Right meta */ +#define XK_Alt_L 0xFFE9 /* Left alt */ +#define XK_Alt_R 0xFFEA /* Right alt */ +#define XK_Super_L 0xFFEB /* Left super */ +#define XK_Super_R 0xFFEC /* Right super */ +#define XK_Hyper_L 0xFFED /* Left hyper */ +#define XK_Hyper_R 0xFFEE /* Right hyper */ +#endif /* XK_MISCELLANY */ + +/* + * ISO 9995 Function and Modifier Keys + * Byte 3 = 0xFE + */ + +#ifdef XK_XKB_KEYS +#define XK_ISO_Lock 0xFE01 +#define XK_ISO_Level2_Latch 0xFE02 +#define XK_ISO_Level3_Shift 0xFE03 +#define XK_ISO_Level3_Latch 0xFE04 +#define XK_ISO_Level3_Lock 0xFE05 +#define XK_ISO_Group_Shift 0xFF7E /* Alias for mode_switch */ +#define XK_ISO_Group_Latch 0xFE06 +#define XK_ISO_Group_Lock 0xFE07 +#define XK_ISO_Next_Group 0xFE08 +#define XK_ISO_Next_Group_Lock 0xFE09 +#define XK_ISO_Prev_Group 0xFE0A +#define XK_ISO_Prev_Group_Lock 0xFE0B +#define XK_ISO_First_Group 0xFE0C +#define XK_ISO_First_Group_Lock 0xFE0D +#define XK_ISO_Last_Group 0xFE0E +#define XK_ISO_Last_Group_Lock 0xFE0F + +#define XK_ISO_Left_Tab 0xFE20 +#define XK_ISO_Move_Line_Up 0xFE21 +#define XK_ISO_Move_Line_Down 0xFE22 +#define XK_ISO_Partial_Line_Up 0xFE23 +#define XK_ISO_Partial_Line_Down 0xFE24 +#define XK_ISO_Partial_Space_Left 0xFE25 +#define XK_ISO_Partial_Space_Right 0xFE26 +#define XK_ISO_Set_Margin_Left 0xFE27 +#define XK_ISO_Set_Margin_Right 0xFE28 +#define XK_ISO_Release_Margin_Left 0xFE29 +#define XK_ISO_Release_Margin_Right 0xFE2A +#define XK_ISO_Release_Both_Margins 0xFE2B +#define XK_ISO_Fast_Cursor_Left 0xFE2C +#define XK_ISO_Fast_Cursor_Right 0xFE2D +#define XK_ISO_Fast_Cursor_Up 0xFE2E +#define XK_ISO_Fast_Cursor_Down 0xFE2F +#define XK_ISO_Continuous_Underline 0xFE30 +#define XK_ISO_Discontinuous_Underline 0xFE31 +#define XK_ISO_Emphasize 0xFE32 +#define XK_ISO_Center_Object 0xFE33 +#define XK_ISO_Enter 0xFE34 + +#define XK_dead_grave 0xFE50 +#define XK_dead_acute 0xFE51 +#define XK_dead_circumflex 0xFE52 +#define XK_dead_tilde 0xFE53 +#define XK_dead_macron 0xFE54 +#define XK_dead_breve 0xFE55 +#define XK_dead_abovedot 0xFE56 +#define XK_dead_diaeresis 0xFE57 +#define XK_dead_abovering 0xFE58 +#define XK_dead_doubleacute 0xFE59 +#define XK_dead_caron 0xFE5A +#define XK_dead_cedilla 0xFE5B +#define XK_dead_ogonek 0xFE5C +#define XK_dead_iota 0xFE5D +#define XK_dead_voiced_sound 0xFE5E +#define XK_dead_semivoiced_sound 0xFE5F +#define XK_dead_belowdot 0xFE60 + +#define XK_First_Virtual_Screen 0xFED0 +#define XK_Prev_Virtual_Screen 0xFED1 +#define XK_Next_Virtual_Screen 0xFED2 +#define XK_Last_Virtual_Screen 0xFED4 +#define XK_Terminate_Server 0xFED5 + +#define XK_AccessX_Enable 0xFE70 +#define XK_AccessX_Feedback_Enable 0xFE71 +#define XK_RepeatKeys_Enable 0xFE72 +#define XK_SlowKeys_Enable 0xFE73 +#define XK_BounceKeys_Enable 0xFE74 +#define XK_StickyKeys_Enable 0xFE75 +#define XK_MouseKeys_Enable 0xFE76 +#define XK_MouseKeys_Accel_Enable 0xFE77 +#define XK_Overlay1_Enable 0xFE78 +#define XK_Overlay2_Enable 0xFE79 +#define XK_AudibleBell_Enable 0xFE7A + +#define XK_Pointer_Left 0xFEE0 +#define XK_Pointer_Right 0xFEE1 +#define XK_Pointer_Up 0xFEE2 +#define XK_Pointer_Down 0xFEE3 +#define XK_Pointer_UpLeft 0xFEE4 +#define XK_Pointer_UpRight 0xFEE5 +#define XK_Pointer_DownLeft 0xFEE6 +#define XK_Pointer_DownRight 0xFEE7 +#define XK_Pointer_Button_Dflt 0xFEE8 +#define XK_Pointer_Button1 0xFEE9 +#define XK_Pointer_Button2 0xFEEA +#define XK_Pointer_Button3 0xFEEB +#define XK_Pointer_Button4 0xFEEC +#define XK_Pointer_Button5 0xFEED +#define XK_Pointer_DblClick_Dflt 0xFEEE +#define XK_Pointer_DblClick1 0xFEEF +#define XK_Pointer_DblClick2 0xFEF0 +#define XK_Pointer_DblClick3 0xFEF1 +#define XK_Pointer_DblClick4 0xFEF2 +#define XK_Pointer_DblClick5 0xFEF3 +#define XK_Pointer_Drag_Dflt 0xFEF4 +#define XK_Pointer_Drag1 0xFEF5 +#define XK_Pointer_Drag2 0xFEF6 +#define XK_Pointer_Drag3 0xFEF7 +#define XK_Pointer_Drag4 0xFEF8 +#define XK_Pointer_Drag5 0xFEFD + +#define XK_Pointer_EnableKeys 0xFEF9 +#define XK_Pointer_Accelerate 0xFEFA +#define XK_Pointer_DfltBtnNext 0xFEFB +#define XK_Pointer_DfltBtnPrev 0xFEFC + +#endif + +/* + * 3270 Terminal Keys + * Byte 3 = 0xFD + */ + +#ifdef XK_3270 +#define XK_3270_Duplicate 0xFD01 +#define XK_3270_FieldMark 0xFD02 +#define XK_3270_Right2 0xFD03 +#define XK_3270_Left2 0xFD04 +#define XK_3270_BackTab 0xFD05 +#define XK_3270_EraseEOF 0xFD06 +#define XK_3270_EraseInput 0xFD07 +#define XK_3270_Reset 0xFD08 +#define XK_3270_Quit 0xFD09 +#define XK_3270_PA1 0xFD0A +#define XK_3270_PA2 0xFD0B +#define XK_3270_PA3 0xFD0C +#define XK_3270_Test 0xFD0D +#define XK_3270_Attn 0xFD0E +#define XK_3270_CursorBlink 0xFD0F +#define XK_3270_AltCursor 0xFD10 +#define XK_3270_KeyClick 0xFD11 +#define XK_3270_Jump 0xFD12 +#define XK_3270_Ident 0xFD13 +#define XK_3270_Rule 0xFD14 +#define XK_3270_Copy 0xFD15 +#define XK_3270_Play 0xFD16 +#define XK_3270_Setup 0xFD17 +#define XK_3270_Record 0xFD18 +#define XK_3270_ChangeScreen 0xFD19 +#define XK_3270_DeleteWord 0xFD1A +#define XK_3270_ExSelect 0xFD1B +#define XK_3270_CursorSelect 0xFD1C +#define XK_3270_PrintScreen 0xFD1D +#define XK_3270_Enter 0xFD1E +#endif + +/* + * Latin 1 + * Byte 3 = 0 + */ +#ifdef XK_LATIN1 +#define XK_space 0x020 +#define XK_exclam 0x021 +#define XK_quotedbl 0x022 +#define XK_numbersign 0x023 +#define XK_dollar 0x024 +#define XK_percent 0x025 +#define XK_ampersand 0x026 +#define XK_apostrophe 0x027 +#define XK_quoteright 0x027 /* deprecated */ +#define XK_parenleft 0x028 +#define XK_parenright 0x029 +#define XK_asterisk 0x02a +#define XK_plus 0x02b +#define XK_comma 0x02c +#define XK_minus 0x02d +#define XK_period 0x02e +#define XK_slash 0x02f +#define XK_0 0x030 +#define XK_1 0x031 +#define XK_2 0x032 +#define XK_3 0x033 +#define XK_4 0x034 +#define XK_5 0x035 +#define XK_6 0x036 +#define XK_7 0x037 +#define XK_8 0x038 +#define XK_9 0x039 +#define XK_colon 0x03a +#define XK_semicolon 0x03b +#define XK_less 0x03c +#define XK_equal 0x03d +#define XK_greater 0x03e +#define XK_question 0x03f +#define XK_at 0x040 +#define XK_A 0x041 +#define XK_B 0x042 +#define XK_C 0x043 +#define XK_D 0x044 +#define XK_E 0x045 +#define XK_F 0x046 +#define XK_G 0x047 +#define XK_H 0x048 +#define XK_I 0x049 +#define XK_J 0x04a +#define XK_K 0x04b +#define XK_L 0x04c +#define XK_M 0x04d +#define XK_N 0x04e +#define XK_O 0x04f +#define XK_P 0x050 +#define XK_Q 0x051 +#define XK_R 0x052 +#define XK_S 0x053 +#define XK_T 0x054 +#define XK_U 0x055 +#define XK_V 0x056 +#define XK_W 0x057 +#define XK_X 0x058 +#define XK_Y 0x059 +#define XK_Z 0x05a +#define XK_bracketleft 0x05b +#define XK_backslash 0x05c +#define XK_bracketright 0x05d +#define XK_asciicircum 0x05e +#define XK_underscore 0x05f +#define XK_grave 0x060 +#define XK_quoteleft 0x060 /* deprecated */ +#define XK_a 0x061 +#define XK_b 0x062 +#define XK_c 0x063 +#define XK_d 0x064 +#define XK_e 0x065 +#define XK_f 0x066 +#define XK_g 0x067 +#define XK_h 0x068 +#define XK_i 0x069 +#define XK_j 0x06a +#define XK_k 0x06b +#define XK_l 0x06c +#define XK_m 0x06d +#define XK_n 0x06e +#define XK_o 0x06f +#define XK_p 0x070 +#define XK_q 0x071 +#define XK_r 0x072 +#define XK_s 0x073 +#define XK_t 0x074 +#define XK_u 0x075 +#define XK_v 0x076 +#define XK_w 0x077 +#define XK_x 0x078 +#define XK_y 0x079 +#define XK_z 0x07a +#define XK_braceleft 0x07b +#define XK_bar 0x07c +#define XK_braceright 0x07d +#define XK_asciitilde 0x07e + +#define XK_nobreakspace 0x0a0 +#define XK_exclamdown 0x0a1 +#define XK_cent 0x0a2 +#define XK_sterling 0x0a3 +#define XK_currency 0x0a4 +#define XK_yen 0x0a5 +#define XK_brokenbar 0x0a6 +#define XK_section 0x0a7 +#define XK_diaeresis 0x0a8 +#define XK_copyright 0x0a9 +#define XK_ordfeminine 0x0aa +#define XK_guillemotleft 0x0ab /* left angle quotation mark */ +#define XK_notsign 0x0ac +#define XK_hyphen 0x0ad +#define XK_registered 0x0ae +#define XK_macron 0x0af +#define XK_degree 0x0b0 +#define XK_plusminus 0x0b1 +#define XK_twosuperior 0x0b2 +#define XK_threesuperior 0x0b3 +#define XK_acute 0x0b4 +#define XK_mu 0x0b5 +#define XK_paragraph 0x0b6 +#define XK_periodcentered 0x0b7 +#define XK_cedilla 0x0b8 +#define XK_onesuperior 0x0b9 +#define XK_masculine 0x0ba +#define XK_guillemotright 0x0bb /* right angle quotation mark */ +#define XK_onequarter 0x0bc +#define XK_onehalf 0x0bd +#define XK_threequarters 0x0be +#define XK_questiondown 0x0bf +#define XK_Agrave 0x0c0 +#define XK_Aacute 0x0c1 +#define XK_Acircumflex 0x0c2 +#define XK_Atilde 0x0c3 +#define XK_Adiaeresis 0x0c4 +#define XK_Aring 0x0c5 +#define XK_AE 0x0c6 +#define XK_Ccedilla 0x0c7 +#define XK_Egrave 0x0c8 +#define XK_Eacute 0x0c9 +#define XK_Ecircumflex 0x0ca +#define XK_Ediaeresis 0x0cb +#define XK_Igrave 0x0cc +#define XK_Iacute 0x0cd +#define XK_Icircumflex 0x0ce +#define XK_Idiaeresis 0x0cf +#define XK_ETH 0x0d0 +#define XK_Eth 0x0d0 /* deprecated */ +#define XK_Ntilde 0x0d1 +#define XK_Ograve 0x0d2 +#define XK_Oacute 0x0d3 +#define XK_Ocircumflex 0x0d4 +#define XK_Otilde 0x0d5 +#define XK_Odiaeresis 0x0d6 +#define XK_multiply 0x0d7 +#define XK_Ooblique 0x0d8 +#define XK_Ugrave 0x0d9 +#define XK_Uacute 0x0da +#define XK_Ucircumflex 0x0db +#define XK_Udiaeresis 0x0dc +#define XK_Yacute 0x0dd +#define XK_THORN 0x0de +#define XK_Thorn 0x0de /* deprecated */ +#define XK_ssharp 0x0df +#define XK_agrave 0x0e0 +#define XK_aacute 0x0e1 +#define XK_acircumflex 0x0e2 +#define XK_atilde 0x0e3 +#define XK_adiaeresis 0x0e4 +#define XK_aring 0x0e5 +#define XK_ae 0x0e6 +#define XK_ccedilla 0x0e7 +#define XK_egrave 0x0e8 +#define XK_eacute 0x0e9 +#define XK_ecircumflex 0x0ea +#define XK_ediaeresis 0x0eb +#define XK_igrave 0x0ec +#define XK_iacute 0x0ed +#define XK_icircumflex 0x0ee +#define XK_idiaeresis 0x0ef +#define XK_eth 0x0f0 +#define XK_ntilde 0x0f1 +#define XK_ograve 0x0f2 +#define XK_oacute 0x0f3 +#define XK_ocircumflex 0x0f4 +#define XK_otilde 0x0f5 +#define XK_odiaeresis 0x0f6 +#define XK_division 0x0f7 +#define XK_oslash 0x0f8 +#define XK_ugrave 0x0f9 +#define XK_uacute 0x0fa +#define XK_ucircumflex 0x0fb +#define XK_udiaeresis 0x0fc +#define XK_yacute 0x0fd +#define XK_thorn 0x0fe +#define XK_ydiaeresis 0x0ff +#endif /* XK_LATIN1 */ + +/* + * Latin 2 + * Byte 3 = 1 + */ + +#ifdef XK_LATIN2 +#define XK_Aogonek 0x1a1 +#define XK_breve 0x1a2 +#define XK_Lstroke 0x1a3 +#define XK_Lcaron 0x1a5 +#define XK_Sacute 0x1a6 +#define XK_Scaron 0x1a9 +#define XK_Scedilla 0x1aa +#define XK_Tcaron 0x1ab +#define XK_Zacute 0x1ac +#define XK_Zcaron 0x1ae +#define XK_Zabovedot 0x1af +#define XK_aogonek 0x1b1 +#define XK_ogonek 0x1b2 +#define XK_lstroke 0x1b3 +#define XK_lcaron 0x1b5 +#define XK_sacute 0x1b6 +#define XK_caron 0x1b7 +#define XK_scaron 0x1b9 +#define XK_scedilla 0x1ba +#define XK_tcaron 0x1bb +#define XK_zacute 0x1bc +#define XK_doubleacute 0x1bd +#define XK_zcaron 0x1be +#define XK_zabovedot 0x1bf +#define XK_Racute 0x1c0 +#define XK_Abreve 0x1c3 +#define XK_Lacute 0x1c5 +#define XK_Cacute 0x1c6 +#define XK_Ccaron 0x1c8 +#define XK_Eogonek 0x1ca +#define XK_Ecaron 0x1cc +#define XK_Dcaron 0x1cf +#define XK_Dstroke 0x1d0 +#define XK_Nacute 0x1d1 +#define XK_Ncaron 0x1d2 +#define XK_Odoubleacute 0x1d5 +#define XK_Rcaron 0x1d8 +#define XK_Uring 0x1d9 +#define XK_Udoubleacute 0x1db +#define XK_Tcedilla 0x1de +#define XK_racute 0x1e0 +#define XK_abreve 0x1e3 +#define XK_lacute 0x1e5 +#define XK_cacute 0x1e6 +#define XK_ccaron 0x1e8 +#define XK_eogonek 0x1ea +#define XK_ecaron 0x1ec +#define XK_dcaron 0x1ef +#define XK_dstroke 0x1f0 +#define XK_nacute 0x1f1 +#define XK_ncaron 0x1f2 +#define XK_odoubleacute 0x1f5 +#define XK_udoubleacute 0x1fb +#define XK_rcaron 0x1f8 +#define XK_uring 0x1f9 +#define XK_tcedilla 0x1fe +#define XK_abovedot 0x1ff +#endif /* XK_LATIN2 */ + +/* + * Latin 3 + * Byte 3 = 2 + */ + +#ifdef XK_LATIN3 +#define XK_Hstroke 0x2a1 +#define XK_Hcircumflex 0x2a6 +#define XK_Iabovedot 0x2a9 +#define XK_Gbreve 0x2ab +#define XK_Jcircumflex 0x2ac +#define XK_hstroke 0x2b1 +#define XK_hcircumflex 0x2b6 +#define XK_idotless 0x2b9 +#define XK_gbreve 0x2bb +#define XK_jcircumflex 0x2bc +#define XK_Cabovedot 0x2c5 +#define XK_Ccircumflex 0x2c6 +#define XK_Gabovedot 0x2d5 +#define XK_Gcircumflex 0x2d8 +#define XK_Ubreve 0x2dd +#define XK_Scircumflex 0x2de +#define XK_cabovedot 0x2e5 +#define XK_ccircumflex 0x2e6 +#define XK_gabovedot 0x2f5 +#define XK_gcircumflex 0x2f8 +#define XK_ubreve 0x2fd +#define XK_scircumflex 0x2fe +#endif /* XK_LATIN3 */ + + +/* + * Latin 4 + * Byte 3 = 3 + */ + +#ifdef XK_LATIN4 +#define XK_kra 0x3a2 +#define XK_kappa 0x3a2 /* deprecated */ +#define XK_Rcedilla 0x3a3 +#define XK_Itilde 0x3a5 +#define XK_Lcedilla 0x3a6 +#define XK_Emacron 0x3aa +#define XK_Gcedilla 0x3ab +#define XK_Tslash 0x3ac +#define XK_rcedilla 0x3b3 +#define XK_itilde 0x3b5 +#define XK_lcedilla 0x3b6 +#define XK_emacron 0x3ba +#define XK_gcedilla 0x3bb +#define XK_tslash 0x3bc +#define XK_ENG 0x3bd +#define XK_eng 0x3bf +#define XK_Amacron 0x3c0 +#define XK_Iogonek 0x3c7 +#define XK_Eabovedot 0x3cc +#define XK_Imacron 0x3cf +#define XK_Ncedilla 0x3d1 +#define XK_Omacron 0x3d2 +#define XK_Kcedilla 0x3d3 +#define XK_Uogonek 0x3d9 +#define XK_Utilde 0x3dd +#define XK_Umacron 0x3de +#define XK_amacron 0x3e0 +#define XK_iogonek 0x3e7 +#define XK_eabovedot 0x3ec +#define XK_imacron 0x3ef +#define XK_ncedilla 0x3f1 +#define XK_omacron 0x3f2 +#define XK_kcedilla 0x3f3 +#define XK_uogonek 0x3f9 +#define XK_utilde 0x3fd +#define XK_umacron 0x3fe +#endif /* XK_LATIN4 */ + +/* + * Katakana + * Byte 3 = 4 + */ + +#ifdef XK_KATAKANA +#define XK_overline 0x47e +#define XK_kana_fullstop 0x4a1 +#define XK_kana_openingbracket 0x4a2 +#define XK_kana_closingbracket 0x4a3 +#define XK_kana_comma 0x4a4 +#define XK_kana_conjunctive 0x4a5 +#define XK_kana_middledot 0x4a5 /* deprecated */ +#define XK_kana_WO 0x4a6 +#define XK_kana_a 0x4a7 +#define XK_kana_i 0x4a8 +#define XK_kana_u 0x4a9 +#define XK_kana_e 0x4aa +#define XK_kana_o 0x4ab +#define XK_kana_ya 0x4ac +#define XK_kana_yu 0x4ad +#define XK_kana_yo 0x4ae +#define XK_kana_tsu 0x4af +#define XK_kana_tu 0x4af /* deprecated */ +#define XK_prolongedsound 0x4b0 +#define XK_kana_A 0x4b1 +#define XK_kana_I 0x4b2 +#define XK_kana_U 0x4b3 +#define XK_kana_E 0x4b4 +#define XK_kana_O 0x4b5 +#define XK_kana_KA 0x4b6 +#define XK_kana_KI 0x4b7 +#define XK_kana_KU 0x4b8 +#define XK_kana_KE 0x4b9 +#define XK_kana_KO 0x4ba +#define XK_kana_SA 0x4bb +#define XK_kana_SHI 0x4bc +#define XK_kana_SU 0x4bd +#define XK_kana_SE 0x4be +#define XK_kana_SO 0x4bf +#define XK_kana_TA 0x4c0 +#define XK_kana_CHI 0x4c1 +#define XK_kana_TI 0x4c1 /* deprecated */ +#define XK_kana_TSU 0x4c2 +#define XK_kana_TU 0x4c2 /* deprecated */ +#define XK_kana_TE 0x4c3 +#define XK_kana_TO 0x4c4 +#define XK_kana_NA 0x4c5 +#define XK_kana_NI 0x4c6 +#define XK_kana_NU 0x4c7 +#define XK_kana_NE 0x4c8 +#define XK_kana_NO 0x4c9 +#define XK_kana_HA 0x4ca +#define XK_kana_HI 0x4cb +#define XK_kana_FU 0x4cc +#define XK_kana_HU 0x4cc /* deprecated */ +#define XK_kana_HE 0x4cd +#define XK_kana_HO 0x4ce +#define XK_kana_MA 0x4cf +#define XK_kana_MI 0x4d0 +#define XK_kana_MU 0x4d1 +#define XK_kana_ME 0x4d2 +#define XK_kana_MO 0x4d3 +#define XK_kana_YA 0x4d4 +#define XK_kana_YU 0x4d5 +#define XK_kana_YO 0x4d6 +#define XK_kana_RA 0x4d7 +#define XK_kana_RI 0x4d8 +#define XK_kana_RU 0x4d9 +#define XK_kana_RE 0x4da +#define XK_kana_RO 0x4db +#define XK_kana_WA 0x4dc +#define XK_kana_N 0x4dd +#define XK_voicedsound 0x4de +#define XK_semivoicedsound 0x4df +#define XK_kana_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_KATAKANA */ + +/* + * Arabic + * Byte 3 = 5 + */ + +#ifdef XK_ARABIC +#define XK_Arabic_comma 0x5ac +#define XK_Arabic_semicolon 0x5bb +#define XK_Arabic_question_mark 0x5bf +#define XK_Arabic_hamza 0x5c1 +#define XK_Arabic_maddaonalef 0x5c2 +#define XK_Arabic_hamzaonalef 0x5c3 +#define XK_Arabic_hamzaonwaw 0x5c4 +#define XK_Arabic_hamzaunderalef 0x5c5 +#define XK_Arabic_hamzaonyeh 0x5c6 +#define XK_Arabic_alef 0x5c7 +#define XK_Arabic_beh 0x5c8 +#define XK_Arabic_tehmarbuta 0x5c9 +#define XK_Arabic_teh 0x5ca +#define XK_Arabic_theh 0x5cb +#define XK_Arabic_jeem 0x5cc +#define XK_Arabic_hah 0x5cd +#define XK_Arabic_khah 0x5ce +#define XK_Arabic_dal 0x5cf +#define XK_Arabic_thal 0x5d0 +#define XK_Arabic_ra 0x5d1 +#define XK_Arabic_zain 0x5d2 +#define XK_Arabic_seen 0x5d3 +#define XK_Arabic_sheen 0x5d4 +#define XK_Arabic_sad 0x5d5 +#define XK_Arabic_dad 0x5d6 +#define XK_Arabic_tah 0x5d7 +#define XK_Arabic_zah 0x5d8 +#define XK_Arabic_ain 0x5d9 +#define XK_Arabic_ghain 0x5da +#define XK_Arabic_tatweel 0x5e0 +#define XK_Arabic_feh 0x5e1 +#define XK_Arabic_qaf 0x5e2 +#define XK_Arabic_kaf 0x5e3 +#define XK_Arabic_lam 0x5e4 +#define XK_Arabic_meem 0x5e5 +#define XK_Arabic_noon 0x5e6 +#define XK_Arabic_ha 0x5e7 +#define XK_Arabic_heh 0x5e7 /* deprecated */ +#define XK_Arabic_waw 0x5e8 +#define XK_Arabic_alefmaksura 0x5e9 +#define XK_Arabic_yeh 0x5ea +#define XK_Arabic_fathatan 0x5eb +#define XK_Arabic_dammatan 0x5ec +#define XK_Arabic_kasratan 0x5ed +#define XK_Arabic_fatha 0x5ee +#define XK_Arabic_damma 0x5ef +#define XK_Arabic_kasra 0x5f0 +#define XK_Arabic_shadda 0x5f1 +#define XK_Arabic_sukun 0x5f2 +#define XK_Arabic_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_ARABIC */ + +/* + * Cyrillic + * Byte 3 = 6 + */ +#ifdef XK_CYRILLIC +#define XK_Serbian_dje 0x6a1 +#define XK_Macedonia_gje 0x6a2 +#define XK_Cyrillic_io 0x6a3 +#define XK_Ukrainian_ie 0x6a4 +#define XK_Ukranian_je 0x6a4 /* deprecated */ +#define XK_Macedonia_dse 0x6a5 +#define XK_Ukrainian_i 0x6a6 +#define XK_Ukranian_i 0x6a6 /* deprecated */ +#define XK_Ukrainian_yi 0x6a7 +#define XK_Ukranian_yi 0x6a7 /* deprecated */ +#define XK_Cyrillic_je 0x6a8 +#define XK_Serbian_je 0x6a8 /* deprecated */ +#define XK_Cyrillic_lje 0x6a9 +#define XK_Serbian_lje 0x6a9 /* deprecated */ +#define XK_Cyrillic_nje 0x6aa +#define XK_Serbian_nje 0x6aa /* deprecated */ +#define XK_Serbian_tshe 0x6ab +#define XK_Macedonia_kje 0x6ac +#define XK_Byelorussian_shortu 0x6ae +#define XK_Cyrillic_dzhe 0x6af +#define XK_Serbian_dze 0x6af /* deprecated */ +#define XK_numerosign 0x6b0 +#define XK_Serbian_DJE 0x6b1 +#define XK_Macedonia_GJE 0x6b2 +#define XK_Cyrillic_IO 0x6b3 +#define XK_Ukrainian_IE 0x6b4 +#define XK_Ukranian_JE 0x6b4 /* deprecated */ +#define XK_Macedonia_DSE 0x6b5 +#define XK_Ukrainian_I 0x6b6 +#define XK_Ukranian_I 0x6b6 /* deprecated */ +#define XK_Ukrainian_YI 0x6b7 +#define XK_Ukranian_YI 0x6b7 /* deprecated */ +#define XK_Cyrillic_JE 0x6b8 +#define XK_Serbian_JE 0x6b8 /* deprecated */ +#define XK_Cyrillic_LJE 0x6b9 +#define XK_Serbian_LJE 0x6b9 /* deprecated */ +#define XK_Cyrillic_NJE 0x6ba +#define XK_Serbian_NJE 0x6ba /* deprecated */ +#define XK_Serbian_TSHE 0x6bb +#define XK_Macedonia_KJE 0x6bc +#define XK_Byelorussian_SHORTU 0x6be +#define XK_Cyrillic_DZHE 0x6bf +#define XK_Serbian_DZE 0x6bf /* deprecated */ +#define XK_Cyrillic_yu 0x6c0 +#define XK_Cyrillic_a 0x6c1 +#define XK_Cyrillic_be 0x6c2 +#define XK_Cyrillic_tse 0x6c3 +#define XK_Cyrillic_de 0x6c4 +#define XK_Cyrillic_ie 0x6c5 +#define XK_Cyrillic_ef 0x6c6 +#define XK_Cyrillic_ghe 0x6c7 +#define XK_Cyrillic_ha 0x6c8 +#define XK_Cyrillic_i 0x6c9 +#define XK_Cyrillic_shorti 0x6ca +#define XK_Cyrillic_ka 0x6cb +#define XK_Cyrillic_el 0x6cc +#define XK_Cyrillic_em 0x6cd +#define XK_Cyrillic_en 0x6ce +#define XK_Cyrillic_o 0x6cf +#define XK_Cyrillic_pe 0x6d0 +#define XK_Cyrillic_ya 0x6d1 +#define XK_Cyrillic_er 0x6d2 +#define XK_Cyrillic_es 0x6d3 +#define XK_Cyrillic_te 0x6d4 +#define XK_Cyrillic_u 0x6d5 +#define XK_Cyrillic_zhe 0x6d6 +#define XK_Cyrillic_ve 0x6d7 +#define XK_Cyrillic_softsign 0x6d8 +#define XK_Cyrillic_yeru 0x6d9 +#define XK_Cyrillic_ze 0x6da +#define XK_Cyrillic_sha 0x6db +#define XK_Cyrillic_e 0x6dc +#define XK_Cyrillic_shcha 0x6dd +#define XK_Cyrillic_che 0x6de +#define XK_Cyrillic_hardsign 0x6df +#define XK_Cyrillic_YU 0x6e0 +#define XK_Cyrillic_A 0x6e1 +#define XK_Cyrillic_BE 0x6e2 +#define XK_Cyrillic_TSE 0x6e3 +#define XK_Cyrillic_DE 0x6e4 +#define XK_Cyrillic_IE 0x6e5 +#define XK_Cyrillic_EF 0x6e6 +#define XK_Cyrillic_GHE 0x6e7 +#define XK_Cyrillic_HA 0x6e8 +#define XK_Cyrillic_I 0x6e9 +#define XK_Cyrillic_SHORTI 0x6ea +#define XK_Cyrillic_KA 0x6eb +#define XK_Cyrillic_EL 0x6ec +#define XK_Cyrillic_EM 0x6ed +#define XK_Cyrillic_EN 0x6ee +#define XK_Cyrillic_O 0x6ef +#define XK_Cyrillic_PE 0x6f0 +#define XK_Cyrillic_YA 0x6f1 +#define XK_Cyrillic_ER 0x6f2 +#define XK_Cyrillic_ES 0x6f3 +#define XK_Cyrillic_TE 0x6f4 +#define XK_Cyrillic_U 0x6f5 +#define XK_Cyrillic_ZHE 0x6f6 +#define XK_Cyrillic_VE 0x6f7 +#define XK_Cyrillic_SOFTSIGN 0x6f8 +#define XK_Cyrillic_YERU 0x6f9 +#define XK_Cyrillic_ZE 0x6fa +#define XK_Cyrillic_SHA 0x6fb +#define XK_Cyrillic_E 0x6fc +#define XK_Cyrillic_SHCHA 0x6fd +#define XK_Cyrillic_CHE 0x6fe +#define XK_Cyrillic_HARDSIGN 0x6ff +#endif /* XK_CYRILLIC */ + +/* + * Greek + * Byte 3 = 7 + */ + +#ifdef XK_GREEK +#define XK_Greek_ALPHAaccent 0x7a1 +#define XK_Greek_EPSILONaccent 0x7a2 +#define XK_Greek_ETAaccent 0x7a3 +#define XK_Greek_IOTAaccent 0x7a4 +#define XK_Greek_IOTAdieresis 0x7a5 +#define XK_Greek_OMICRONaccent 0x7a7 +#define XK_Greek_UPSILONaccent 0x7a8 +#define XK_Greek_UPSILONdieresis 0x7a9 +#define XK_Greek_OMEGAaccent 0x7ab +#define XK_Greek_accentdieresis 0x7ae +#define XK_Greek_horizbar 0x7af +#define XK_Greek_alphaaccent 0x7b1 +#define XK_Greek_epsilonaccent 0x7b2 +#define XK_Greek_etaaccent 0x7b3 +#define XK_Greek_iotaaccent 0x7b4 +#define XK_Greek_iotadieresis 0x7b5 +#define XK_Greek_iotaaccentdieresis 0x7b6 +#define XK_Greek_omicronaccent 0x7b7 +#define XK_Greek_upsilonaccent 0x7b8 +#define XK_Greek_upsilondieresis 0x7b9 +#define XK_Greek_upsilonaccentdieresis 0x7ba +#define XK_Greek_omegaaccent 0x7bb +#define XK_Greek_ALPHA 0x7c1 +#define XK_Greek_BETA 0x7c2 +#define XK_Greek_GAMMA 0x7c3 +#define XK_Greek_DELTA 0x7c4 +#define XK_Greek_EPSILON 0x7c5 +#define XK_Greek_ZETA 0x7c6 +#define XK_Greek_ETA 0x7c7 +#define XK_Greek_THETA 0x7c8 +#define XK_Greek_IOTA 0x7c9 +#define XK_Greek_KAPPA 0x7ca +#define XK_Greek_LAMDA 0x7cb +#define XK_Greek_LAMBDA 0x7cb +#define XK_Greek_MU 0x7cc +#define XK_Greek_NU 0x7cd +#define XK_Greek_XI 0x7ce +#define XK_Greek_OMICRON 0x7cf +#define XK_Greek_PI 0x7d0 +#define XK_Greek_RHO 0x7d1 +#define XK_Greek_SIGMA 0x7d2 +#define XK_Greek_TAU 0x7d4 +#define XK_Greek_UPSILON 0x7d5 +#define XK_Greek_PHI 0x7d6 +#define XK_Greek_CHI 0x7d7 +#define XK_Greek_PSI 0x7d8 +#define XK_Greek_OMEGA 0x7d9 +#define XK_Greek_alpha 0x7e1 +#define XK_Greek_beta 0x7e2 +#define XK_Greek_gamma 0x7e3 +#define XK_Greek_delta 0x7e4 +#define XK_Greek_epsilon 0x7e5 +#define XK_Greek_zeta 0x7e6 +#define XK_Greek_eta 0x7e7 +#define XK_Greek_theta 0x7e8 +#define XK_Greek_iota 0x7e9 +#define XK_Greek_kappa 0x7ea +#define XK_Greek_lamda 0x7eb +#define XK_Greek_lambda 0x7eb +#define XK_Greek_mu 0x7ec +#define XK_Greek_nu 0x7ed +#define XK_Greek_xi 0x7ee +#define XK_Greek_omicron 0x7ef +#define XK_Greek_pi 0x7f0 +#define XK_Greek_rho 0x7f1 +#define XK_Greek_sigma 0x7f2 +#define XK_Greek_finalsmallsigma 0x7f3 +#define XK_Greek_tau 0x7f4 +#define XK_Greek_upsilon 0x7f5 +#define XK_Greek_phi 0x7f6 +#define XK_Greek_chi 0x7f7 +#define XK_Greek_psi 0x7f8 +#define XK_Greek_omega 0x7f9 +#define XK_Greek_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_GREEK */ + +/* + * Technical + * Byte 3 = 8 + */ + +#ifdef XK_TECHNICAL +#define XK_leftradical 0x8a1 +#define XK_topleftradical 0x8a2 +#define XK_horizconnector 0x8a3 +#define XK_topintegral 0x8a4 +#define XK_botintegral 0x8a5 +#define XK_vertconnector 0x8a6 +#define XK_topleftsqbracket 0x8a7 +#define XK_botleftsqbracket 0x8a8 +#define XK_toprightsqbracket 0x8a9 +#define XK_botrightsqbracket 0x8aa +#define XK_topleftparens 0x8ab +#define XK_botleftparens 0x8ac +#define XK_toprightparens 0x8ad +#define XK_botrightparens 0x8ae +#define XK_leftmiddlecurlybrace 0x8af +#define XK_rightmiddlecurlybrace 0x8b0 +#define XK_topleftsummation 0x8b1 +#define XK_botleftsummation 0x8b2 +#define XK_topvertsummationconnector 0x8b3 +#define XK_botvertsummationconnector 0x8b4 +#define XK_toprightsummation 0x8b5 +#define XK_botrightsummation 0x8b6 +#define XK_rightmiddlesummation 0x8b7 +#define XK_lessthanequal 0x8bc +#define XK_notequal 0x8bd +#define XK_greaterthanequal 0x8be +#define XK_integral 0x8bf +#define XK_therefore 0x8c0 +#define XK_variation 0x8c1 +#define XK_infinity 0x8c2 +#define XK_nabla 0x8c5 +#define XK_approximate 0x8c8 +#define XK_similarequal 0x8c9 +#define XK_ifonlyif 0x8cd +#define XK_implies 0x8ce +#define XK_identical 0x8cf +#define XK_radical 0x8d6 +#define XK_includedin 0x8da +#define XK_includes 0x8db +#define XK_intersection 0x8dc +#define XK_union 0x8dd +#define XK_logicaland 0x8de +#define XK_logicalor 0x8df +#define XK_partialderivative 0x8ef +#define XK_function 0x8f6 +#define XK_leftarrow 0x8fb +#define XK_uparrow 0x8fc +#define XK_rightarrow 0x8fd +#define XK_downarrow 0x8fe +#endif /* XK_TECHNICAL */ + +/* + * Special + * Byte 3 = 9 + */ + +#ifdef XK_SPECIAL +#define XK_blank 0x9df +#define XK_soliddiamond 0x9e0 +#define XK_checkerboard 0x9e1 +#define XK_ht 0x9e2 +#define XK_ff 0x9e3 +#define XK_cr 0x9e4 +#define XK_lf 0x9e5 +#define XK_nl 0x9e8 +#define XK_vt 0x9e9 +#define XK_lowrightcorner 0x9ea +#define XK_uprightcorner 0x9eb +#define XK_upleftcorner 0x9ec +#define XK_lowleftcorner 0x9ed +#define XK_crossinglines 0x9ee +#define XK_horizlinescan1 0x9ef +#define XK_horizlinescan3 0x9f0 +#define XK_horizlinescan5 0x9f1 +#define XK_horizlinescan7 0x9f2 +#define XK_horizlinescan9 0x9f3 +#define XK_leftt 0x9f4 +#define XK_rightt 0x9f5 +#define XK_bott 0x9f6 +#define XK_topt 0x9f7 +#define XK_vertbar 0x9f8 +#endif /* XK_SPECIAL */ + +/* + * Publishing + * Byte 3 = a + */ + +#ifdef XK_PUBLISHING +#define XK_emspace 0xaa1 +#define XK_enspace 0xaa2 +#define XK_em3space 0xaa3 +#define XK_em4space 0xaa4 +#define XK_digitspace 0xaa5 +#define XK_punctspace 0xaa6 +#define XK_thinspace 0xaa7 +#define XK_hairspace 0xaa8 +#define XK_emdash 0xaa9 +#define XK_endash 0xaaa +#define XK_signifblank 0xaac +#define XK_ellipsis 0xaae +#define XK_doubbaselinedot 0xaaf +#define XK_onethird 0xab0 +#define XK_twothirds 0xab1 +#define XK_onefifth 0xab2 +#define XK_twofifths 0xab3 +#define XK_threefifths 0xab4 +#define XK_fourfifths 0xab5 +#define XK_onesixth 0xab6 +#define XK_fivesixths 0xab7 +#define XK_careof 0xab8 +#define XK_figdash 0xabb +#define XK_leftanglebracket 0xabc +#define XK_decimalpoint 0xabd +#define XK_rightanglebracket 0xabe +#define XK_marker 0xabf +#define XK_oneeighth 0xac3 +#define XK_threeeighths 0xac4 +#define XK_fiveeighths 0xac5 +#define XK_seveneighths 0xac6 +#define XK_trademark 0xac9 +#define XK_signaturemark 0xaca +#define XK_trademarkincircle 0xacb +#define XK_leftopentriangle 0xacc +#define XK_rightopentriangle 0xacd +#define XK_emopencircle 0xace +#define XK_emopenrectangle 0xacf +#define XK_leftsinglequotemark 0xad0 +#define XK_rightsinglequotemark 0xad1 +#define XK_leftdoublequotemark 0xad2 +#define XK_rightdoublequotemark 0xad3 +#define XK_prescription 0xad4 +#define XK_minutes 0xad6 +#define XK_seconds 0xad7 +#define XK_latincross 0xad9 +#define XK_hexagram 0xada +#define XK_filledrectbullet 0xadb +#define XK_filledlefttribullet 0xadc +#define XK_filledrighttribullet 0xadd +#define XK_emfilledcircle 0xade +#define XK_emfilledrect 0xadf +#define XK_enopencircbullet 0xae0 +#define XK_enopensquarebullet 0xae1 +#define XK_openrectbullet 0xae2 +#define XK_opentribulletup 0xae3 +#define XK_opentribulletdown 0xae4 +#define XK_openstar 0xae5 +#define XK_enfilledcircbullet 0xae6 +#define XK_enfilledsqbullet 0xae7 +#define XK_filledtribulletup 0xae8 +#define XK_filledtribulletdown 0xae9 +#define XK_leftpointer 0xaea +#define XK_rightpointer 0xaeb +#define XK_club 0xaec +#define XK_diamond 0xaed +#define XK_heart 0xaee +#define XK_maltesecross 0xaf0 +#define XK_dagger 0xaf1 +#define XK_doubledagger 0xaf2 +#define XK_checkmark 0xaf3 +#define XK_ballotcross 0xaf4 +#define XK_musicalsharp 0xaf5 +#define XK_musicalflat 0xaf6 +#define XK_malesymbol 0xaf7 +#define XK_femalesymbol 0xaf8 +#define XK_telephone 0xaf9 +#define XK_telephonerecorder 0xafa +#define XK_phonographcopyright 0xafb +#define XK_caret 0xafc +#define XK_singlelowquotemark 0xafd +#define XK_doublelowquotemark 0xafe +#define XK_cursor 0xaff +#endif /* XK_PUBLISHING */ + +/* + * APL + * Byte 3 = b + */ + +#ifdef XK_APL +#define XK_leftcaret 0xba3 +#define XK_rightcaret 0xba6 +#define XK_downcaret 0xba8 +#define XK_upcaret 0xba9 +#define XK_overbar 0xbc0 +#define XK_downtack 0xbc2 +#define XK_upshoe 0xbc3 +#define XK_downstile 0xbc4 +#define XK_underbar 0xbc6 +#define XK_jot 0xbca +#define XK_quad 0xbcc +#define XK_uptack 0xbce +#define XK_circle 0xbcf +#define XK_upstile 0xbd3 +#define XK_downshoe 0xbd6 +#define XK_rightshoe 0xbd8 +#define XK_leftshoe 0xbda +#define XK_lefttack 0xbdc +#define XK_righttack 0xbfc +#endif /* XK_APL */ + +/* + * Hebrew + * Byte 3 = c + */ + +#ifdef XK_HEBREW +#define XK_hebrew_doublelowline 0xcdf +#define XK_hebrew_aleph 0xce0 +#define XK_hebrew_bet 0xce1 +#define XK_hebrew_beth 0xce1 /* deprecated */ +#define XK_hebrew_gimel 0xce2 +#define XK_hebrew_gimmel 0xce2 /* deprecated */ +#define XK_hebrew_dalet 0xce3 +#define XK_hebrew_daleth 0xce3 /* deprecated */ +#define XK_hebrew_he 0xce4 +#define XK_hebrew_waw 0xce5 +#define XK_hebrew_zain 0xce6 +#define XK_hebrew_zayin 0xce6 /* deprecated */ +#define XK_hebrew_chet 0xce7 +#define XK_hebrew_het 0xce7 /* deprecated */ +#define XK_hebrew_tet 0xce8 +#define XK_hebrew_teth 0xce8 /* deprecated */ +#define XK_hebrew_yod 0xce9 +#define XK_hebrew_finalkaph 0xcea +#define XK_hebrew_kaph 0xceb +#define XK_hebrew_lamed 0xcec +#define XK_hebrew_finalmem 0xced +#define XK_hebrew_mem 0xcee +#define XK_hebrew_finalnun 0xcef +#define XK_hebrew_nun 0xcf0 +#define XK_hebrew_samech 0xcf1 +#define XK_hebrew_samekh 0xcf1 /* deprecated */ +#define XK_hebrew_ayin 0xcf2 +#define XK_hebrew_finalpe 0xcf3 +#define XK_hebrew_pe 0xcf4 +#define XK_hebrew_finalzade 0xcf5 +#define XK_hebrew_finalzadi 0xcf5 /* deprecated */ +#define XK_hebrew_zade 0xcf6 +#define XK_hebrew_zadi 0xcf6 /* deprecated */ +#define XK_hebrew_qoph 0xcf7 +#define XK_hebrew_kuf 0xcf7 /* deprecated */ +#define XK_hebrew_resh 0xcf8 +#define XK_hebrew_shin 0xcf9 +#define XK_hebrew_taw 0xcfa +#define XK_hebrew_taf 0xcfa /* deprecated */ +#define XK_Hebrew_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_HEBREW */ + +/* + * Thai + * Byte 3 = d + */ + +#ifdef XK_THAI +#define XK_Thai_kokai 0xda1 +#define XK_Thai_khokhai 0xda2 +#define XK_Thai_khokhuat 0xda3 +#define XK_Thai_khokhwai 0xda4 +#define XK_Thai_khokhon 0xda5 +#define XK_Thai_khorakhang 0xda6 +#define XK_Thai_ngongu 0xda7 +#define XK_Thai_chochan 0xda8 +#define XK_Thai_choching 0xda9 +#define XK_Thai_chochang 0xdaa +#define XK_Thai_soso 0xdab +#define XK_Thai_chochoe 0xdac +#define XK_Thai_yoying 0xdad +#define XK_Thai_dochada 0xdae +#define XK_Thai_topatak 0xdaf +#define XK_Thai_thothan 0xdb0 +#define XK_Thai_thonangmontho 0xdb1 +#define XK_Thai_thophuthao 0xdb2 +#define XK_Thai_nonen 0xdb3 +#define XK_Thai_dodek 0xdb4 +#define XK_Thai_totao 0xdb5 +#define XK_Thai_thothung 0xdb6 +#define XK_Thai_thothahan 0xdb7 +#define XK_Thai_thothong 0xdb8 +#define XK_Thai_nonu 0xdb9 +#define XK_Thai_bobaimai 0xdba +#define XK_Thai_popla 0xdbb +#define XK_Thai_phophung 0xdbc +#define XK_Thai_fofa 0xdbd +#define XK_Thai_phophan 0xdbe +#define XK_Thai_fofan 0xdbf +#define XK_Thai_phosamphao 0xdc0 +#define XK_Thai_moma 0xdc1 +#define XK_Thai_yoyak 0xdc2 +#define XK_Thai_rorua 0xdc3 +#define XK_Thai_ru 0xdc4 +#define XK_Thai_loling 0xdc5 +#define XK_Thai_lu 0xdc6 +#define XK_Thai_wowaen 0xdc7 +#define XK_Thai_sosala 0xdc8 +#define XK_Thai_sorusi 0xdc9 +#define XK_Thai_sosua 0xdca +#define XK_Thai_hohip 0xdcb +#define XK_Thai_lochula 0xdcc +#define XK_Thai_oang 0xdcd +#define XK_Thai_honokhuk 0xdce +#define XK_Thai_paiyannoi 0xdcf +#define XK_Thai_saraa 0xdd0 +#define XK_Thai_maihanakat 0xdd1 +#define XK_Thai_saraaa 0xdd2 +#define XK_Thai_saraam 0xdd3 +#define XK_Thai_sarai 0xdd4 +#define XK_Thai_saraii 0xdd5 +#define XK_Thai_saraue 0xdd6 +#define XK_Thai_sarauee 0xdd7 +#define XK_Thai_sarau 0xdd8 +#define XK_Thai_sarauu 0xdd9 +#define XK_Thai_phinthu 0xdda +#define XK_Thai_maihanakat_maitho 0xdde +#define XK_Thai_baht 0xddf +#define XK_Thai_sarae 0xde0 +#define XK_Thai_saraae 0xde1 +#define XK_Thai_sarao 0xde2 +#define XK_Thai_saraaimaimuan 0xde3 +#define XK_Thai_saraaimaimalai 0xde4 +#define XK_Thai_lakkhangyao 0xde5 +#define XK_Thai_maiyamok 0xde6 +#define XK_Thai_maitaikhu 0xde7 +#define XK_Thai_maiek 0xde8 +#define XK_Thai_maitho 0xde9 +#define XK_Thai_maitri 0xdea +#define XK_Thai_maichattawa 0xdeb +#define XK_Thai_thanthakhat 0xdec +#define XK_Thai_nikhahit 0xded +#define XK_Thai_leksun 0xdf0 +#define XK_Thai_leknung 0xdf1 +#define XK_Thai_leksong 0xdf2 +#define XK_Thai_leksam 0xdf3 +#define XK_Thai_leksi 0xdf4 +#define XK_Thai_lekha 0xdf5 +#define XK_Thai_lekhok 0xdf6 +#define XK_Thai_lekchet 0xdf7 +#define XK_Thai_lekpaet 0xdf8 +#define XK_Thai_lekkao 0xdf9 +#endif /* XK_THAI */ + +/* + * Korean + * Byte 3 = e + */ + +#ifdef XK_KOREAN + +#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */ +#define XK_Hangul_Start 0xff32 /* Hangul start */ +#define XK_Hangul_End 0xff33 /* Hangul end, English start */ +#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */ +#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ +#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ +#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */ +#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */ +#define XK_Hangul_Banja 0xff39 /* Banja mode */ +#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ +#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ +#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */ +#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ +#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ +#define XK_Hangul_Special 0xff3f /* Special symbols */ +#define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */ + +/* Hangul Consonant Characters */ +#define XK_Hangul_Kiyeog 0xea1 +#define XK_Hangul_SsangKiyeog 0xea2 +#define XK_Hangul_KiyeogSios 0xea3 +#define XK_Hangul_Nieun 0xea4 +#define XK_Hangul_NieunJieuj 0xea5 +#define XK_Hangul_NieunHieuh 0xea6 +#define XK_Hangul_Dikeud 0xea7 +#define XK_Hangul_SsangDikeud 0xea8 +#define XK_Hangul_Rieul 0xea9 +#define XK_Hangul_RieulKiyeog 0xeaa +#define XK_Hangul_RieulMieum 0xeab +#define XK_Hangul_RieulPieub 0xeac +#define XK_Hangul_RieulSios 0xead +#define XK_Hangul_RieulTieut 0xeae +#define XK_Hangul_RieulPhieuf 0xeaf +#define XK_Hangul_RieulHieuh 0xeb0 +#define XK_Hangul_Mieum 0xeb1 +#define XK_Hangul_Pieub 0xeb2 +#define XK_Hangul_SsangPieub 0xeb3 +#define XK_Hangul_PieubSios 0xeb4 +#define XK_Hangul_Sios 0xeb5 +#define XK_Hangul_SsangSios 0xeb6 +#define XK_Hangul_Ieung 0xeb7 +#define XK_Hangul_Jieuj 0xeb8 +#define XK_Hangul_SsangJieuj 0xeb9 +#define XK_Hangul_Cieuc 0xeba +#define XK_Hangul_Khieuq 0xebb +#define XK_Hangul_Tieut 0xebc +#define XK_Hangul_Phieuf 0xebd +#define XK_Hangul_Hieuh 0xebe + +/* Hangul Vowel Characters */ +#define XK_Hangul_A 0xebf +#define XK_Hangul_AE 0xec0 +#define XK_Hangul_YA 0xec1 +#define XK_Hangul_YAE 0xec2 +#define XK_Hangul_EO 0xec3 +#define XK_Hangul_E 0xec4 +#define XK_Hangul_YEO 0xec5 +#define XK_Hangul_YE 0xec6 +#define XK_Hangul_O 0xec7 +#define XK_Hangul_WA 0xec8 +#define XK_Hangul_WAE 0xec9 +#define XK_Hangul_OE 0xeca +#define XK_Hangul_YO 0xecb +#define XK_Hangul_U 0xecc +#define XK_Hangul_WEO 0xecd +#define XK_Hangul_WE 0xece +#define XK_Hangul_WI 0xecf +#define XK_Hangul_YU 0xed0 +#define XK_Hangul_EU 0xed1 +#define XK_Hangul_YI 0xed2 +#define XK_Hangul_I 0xed3 + +/* Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_Kiyeog 0xed4 +#define XK_Hangul_J_SsangKiyeog 0xed5 +#define XK_Hangul_J_KiyeogSios 0xed6 +#define XK_Hangul_J_Nieun 0xed7 +#define XK_Hangul_J_NieunJieuj 0xed8 +#define XK_Hangul_J_NieunHieuh 0xed9 +#define XK_Hangul_J_Dikeud 0xeda +#define XK_Hangul_J_Rieul 0xedb +#define XK_Hangul_J_RieulKiyeog 0xedc +#define XK_Hangul_J_RieulMieum 0xedd +#define XK_Hangul_J_RieulPieub 0xede +#define XK_Hangul_J_RieulSios 0xedf +#define XK_Hangul_J_RieulTieut 0xee0 +#define XK_Hangul_J_RieulPhieuf 0xee1 +#define XK_Hangul_J_RieulHieuh 0xee2 +#define XK_Hangul_J_Mieum 0xee3 +#define XK_Hangul_J_Pieub 0xee4 +#define XK_Hangul_J_PieubSios 0xee5 +#define XK_Hangul_J_Sios 0xee6 +#define XK_Hangul_J_SsangSios 0xee7 +#define XK_Hangul_J_Ieung 0xee8 +#define XK_Hangul_J_Jieuj 0xee9 +#define XK_Hangul_J_Cieuc 0xeea +#define XK_Hangul_J_Khieuq 0xeeb +#define XK_Hangul_J_Tieut 0xeec +#define XK_Hangul_J_Phieuf 0xeed +#define XK_Hangul_J_Hieuh 0xeee + +/* Ancient Hangul Consonant Characters */ +#define XK_Hangul_RieulYeorinHieuh 0xeef +#define XK_Hangul_SunkyeongeumMieum 0xef0 +#define XK_Hangul_SunkyeongeumPieub 0xef1 +#define XK_Hangul_PanSios 0xef2 +#define XK_Hangul_KkogjiDalrinIeung 0xef3 +#define XK_Hangul_SunkyeongeumPhieuf 0xef4 +#define XK_Hangul_YeorinHieuh 0xef5 + +/* Ancient Hangul Vowel Characters */ +#define XK_Hangul_AraeA 0xef6 +#define XK_Hangul_AraeAE 0xef7 + +/* Ancient Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_PanSios 0xef8 +#define XK_Hangul_J_KkogjiDalrinIeung 0xef9 +#define XK_Hangul_J_YeorinHieuh 0xefa + +/* Korean currency symbol */ +#define XK_Korean_Won 0xeff + +#endif /* XK_KOREAN */ + +/* Euro currency symbol */ +#define XK_EuroSign 0x20ac + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfb.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfb.h new file mode 100755 index 0000000..797416a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfb.h @@ -0,0 +1,1044 @@ +#ifndef RFB_H +#define RFB_H + +/* + * rfb.h - header file for RFB DDX implementation. + */ + +/* + * Copyright (C) 2005 Rohit Kumar , + * Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * 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. + */ + +#if(defined __cplusplus) +extern "C" +{ +#endif + +#include +#include +#include +#include + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef ANDROID +#include +#include +#endif + +#ifdef __MINGW32__ +#undef SOCKET +#include +#endif + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#include +#if 0 /* debugging */ +#define LOCK(mutex) (rfbLog("%s:%d LOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_lock(&(mutex))) +#define UNLOCK(mutex) (rfbLog("%s:%d UNLOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_unlock(&(mutex))) +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) (rfbLog("%s:%d INIT_MUTEX(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_init(&(mutex),NULL)) +#define TINI_MUTEX(mutex) (rfbLog("%s:%d TINI_MUTEX(%s)\n",__FILE__,__LINE__,#mutex), pthread_mutex_destroy(&(mutex))) +#define TSIGNAL(cond) (rfbLog("%s:%d TSIGNAL(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_signal(&(cond))) +#define WAIT(cond,mutex) (rfbLog("%s:%d WAIT(%s,%s)\n",__FILE__,__LINE__,#cond,#mutex), pthread_cond_wait(&(cond),&(mutex))) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) (rfbLog("%s:%d INIT_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_init(&(cond),NULL)) +#define TINI_COND(cond) (rfbLog("%s:%d TINI_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_destroy(&(cond))) +#define IF_PTHREADS(x) x +#else +#if !NONETWORK +#define LOCK(mutex) pthread_mutex_lock(&(mutex)); +#define UNLOCK(mutex) pthread_mutex_unlock(&(mutex)); +#endif +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL) +#define TINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex)) +#define TSIGNAL(cond) pthread_cond_signal(&(cond)) +#define WAIT(cond,mutex) pthread_cond_wait(&(cond),&(mutex)) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) pthread_cond_init(&(cond),NULL) +#define TINI_COND(cond) pthread_cond_destroy(&(cond)) +#define IF_PTHREADS(x) x +#endif +#else +#define LOCK(mutex) +#define UNLOCK(mutex) +#define MUTEX(mutex) +#define INIT_MUTEX(mutex) +#define TINI_MUTEX(mutex) +#define TSIGNAL(cond) +#define WAIT(cond,mutex) this_is_unsupported +#define COND(cond) +#define INIT_COND(cond) +#define TINI_COND(cond) +#define IF_PTHREADS(x) +#endif + +/* end of stuff for autoconf */ + +/* if you use pthreads, but don't define LIBVNCSERVER_HAVE_LIBPTHREAD, the structs + get all mixed up. So this gives a linker error reminding you to compile + the library and your application (at least the parts including rfb.h) + with the same support for pthreads. */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithPthreadsAndZRLE +#else +#define rfbInitServer rfbInitServerWithPthreadsButWithoutZRLE +#endif +#else +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithoutPthreadsButWithZRLE +#else +#define rfbInitServer rfbInitServerWithoutPthreadsAndZRLE +#endif +#endif + +struct _rfbClientRec; +struct _rfbScreenInfo; +struct rfbCursor; + +enum rfbNewClientAction { + RFB_CLIENT_ACCEPT, + RFB_CLIENT_ON_HOLD, + RFB_CLIENT_REFUSE +}; + +enum rfbSocketState { + RFB_SOCKET_INIT, + RFB_SOCKET_READY, + RFB_SOCKET_SHUTDOWN +}; + +typedef void (*rfbKbdAddEventProcPtr) (rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl); +typedef void (*rfbKbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl); +typedef void (*rfbPtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl); +typedef void (*rfbSetXCutTextProcPtr) (char* str,int len, struct _rfbClientRec* cl); +typedef struct rfbCursor* (*rfbGetCursorProcPtr) (struct _rfbClientRec* pScreen); +typedef rfbBool (*rfbSetTranslateFunctionProcPtr)(struct _rfbClientRec* cl); +typedef rfbBool (*rfbPasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len); +typedef enum rfbNewClientAction (*rfbNewClientHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbDisplayHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbDisplayFinishedHookPtr)(struct _rfbClientRec* cl, int result); +/* support the capability to view the caps/num/scroll states of the X server */ +typedef int (*rfbGetKeyboardLedStateHookPtr)(struct _rfbScreenInfo* screen); +/* If x==1 and y==1 then set the whole display + * else find the window underneath x and y and set the framebuffer to the dimensions + * of that window + */ +typedef void (*rfbSetSingleWindowProcPtr) (struct _rfbClientRec* cl, int x, int y); +/* Status determines if the X11 server permits input from the local user + * status==0 or 1 + */ +typedef void (*rfbSetServerInputProcPtr) (struct _rfbClientRec* cl, int status); +/* Permit the server to allow or deny filetransfers. This is defaulted to deny + * It is called when a client initiates a connection to determine if it is permitted. + */ +typedef int (*rfbFileTransferPermitted) (struct _rfbClientRec* cl); +/* Handle the textchat messages */ +typedef void (*rfbSetTextChat) (struct _rfbClientRec* cl, int length, char *string); + +typedef struct { + uint32_t count; + rfbBool is16; /* is the data format short? */ + union { + uint8_t* bytes; + uint16_t* shorts; + } data; /* there have to be count*3 entries */ +} rfbColourMap; + +/* + * Security handling (RFB protocol version 3.7) + */ + +typedef struct _rfbSecurity { + uint8_t type; + void (*handler)(struct _rfbClientRec* cl); + struct _rfbSecurity* next; +} rfbSecurityHandler; + +/* + * Protocol extension handling. + */ + +typedef struct _rfbProtocolExtension { + /* returns FALSE if extension should be deactivated for client. + if newClient == NULL, it is always deactivated. */ + rfbBool (*newClient)(struct _rfbClientRec* client, void** data); + /* returns FALSE if extension should be deactivated for client. + if init == NULL, it stays activated. */ + rfbBool (*init)(struct _rfbClientRec* client, void* data); + /* if pseudoEncodings is not NULL, it contains a 0 terminated + list of the pseudo encodings handled by this extension. */ + int *pseudoEncodings; + /* returns TRUE if that pseudo encoding is handled by the extension. + encodingNumber==0 means "reset encodings". */ + rfbBool (*enablePseudoEncoding)(struct _rfbClientRec* client, + void** data, int encodingNumber); + /* returns TRUE if message was handled */ + rfbBool (*handleMessage)(struct _rfbClientRec* client, + void* data, + const rfbClientToServerMsg* message); + void (*close)(struct _rfbClientRec* client, void* data); + void (*usage)(void); + /* processArguments returns the number of handled arguments */ + int (*processArgument)(int argc, char *argv[]); + struct _rfbProtocolExtension* next; +} rfbProtocolExtension; + +typedef struct _rfbExtensionData { + rfbProtocolExtension* extension; + void* data; + struct _rfbExtensionData* next; +} rfbExtensionData; + +/* + * Per-screen (framebuffer) structure. There can be as many as you wish, + * each serving different clients. However, you have to call + * rfbProcessEvents for each of these. + */ + +typedef struct _rfbScreenInfo +{ + /* this structure has children that are scaled versions of this screen */ + struct _rfbScreenInfo *scaledScreenNext; + int scaledScreenRefCount; + + int width; + int paddedWidthInBytes; + int height; + int depth; + int bitsPerPixel; + int sizeInBytes; + + rfbPixel blackPixel; + rfbPixel whitePixel; + + /* some screen specific data can be put into a struct where screenData + * points to. You need this if you have more than one screen at the + * same time while using the same functions. + */ + void* screenData; + + /* additions by libvncserver */ + + rfbPixelFormat serverFormat; + rfbColourMap colourMap; /* set this if rfbServerFormat.trueColour==FALSE */ + const char* desktopName; + char thisHost[255]; + + rfbBool autoPort; + int port; + SOCKET listenSock; + int maxSock; + int maxFd; +#ifdef __MINGW32__ + struct fd_set allFds; +#else + fd_set allFds; +#endif + + enum rfbSocketState socketState; + SOCKET inetdSock; + rfbBool inetdInitDone; + + int udpPort; + SOCKET udpSock; + struct _rfbClientRec* udpClient; + rfbBool udpSockConnected; + struct sockaddr_in udpRemoteAddr; + + int maxClientWait; + + /* http stuff */ + rfbBool httpInitDone; + rfbBool httpEnableProxyConnect; + int httpPort; + char* httpDir; + SOCKET httpListenSock; + SOCKET httpSock; + + rfbPasswordCheckProcPtr passwordCheck; + void* authPasswdData; + /* If rfbAuthPasswdData is given a list, this is the first + view only password. */ + int authPasswdFirstViewOnly; + + /* send only this many rectangles in one update */ + int maxRectsPerUpdate; + /* this is the amount of milliseconds to wait at least before sending + * an update. */ + int deferUpdateTime; +#ifdef TODELETE + char* screen; +#endif + rfbBool alwaysShared; + rfbBool neverShared; + rfbBool dontDisconnect; + struct _rfbClientRec* clientHead; + struct _rfbClientRec* pointerClient; /* "Mutex" for pointer events */ + + + /* cursor */ + int cursorX, cursorY,underCursorBufferLen; + char* underCursorBuffer; + rfbBool dontConvertRichCursorToXCursor; + struct rfbCursor* cursor; + + /* the frameBufferhas to be supplied by the serving process. + * The buffer will not be freed by + */ + char* frameBuffer; + rfbKbdAddEventProcPtr kbdAddEvent; + rfbKbdReleaseAllKeysProcPtr kbdReleaseAllKeys; + rfbPtrAddEventProcPtr ptrAddEvent; + rfbSetXCutTextProcPtr setXCutText; + rfbGetCursorProcPtr getCursorPtr; + rfbSetTranslateFunctionProcPtr setTranslateFunction; + rfbSetSingleWindowProcPtr setSingleWindow; + rfbSetServerInputProcPtr setServerInput; + rfbFileTransferPermitted getFileTransferPermission; + rfbSetTextChat setTextChat; + + /* newClientHook is called just after a new client is created */ + rfbNewClientHookPtr newClientHook; + /* displayHook is called just before a frame buffer update */ + rfbDisplayHookPtr displayHook; + + /* These hooks are called to pass keyboard state back to the client */ + rfbGetKeyboardLedStateHookPtr getKeyboardLedStateHook; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + MUTEX(cursorMutex); + rfbBool backgroundLoop; +#endif + + /* if TRUE, an ignoring signal handler is installed for SIGPIPE */ + rfbBool ignoreSIGPIPE; + + /* if not zero, only a slice of this height is processed every time + * an update should be sent. This should make working on a slow + * link more interactive. */ + int progressiveSliceHeight; + + in_addr_t listenInterface; + int deferPtrUpdateTime; + + /* handle as many input events as possible (default off) */ + rfbBool handleEventsEagerly; + + /* rfbEncodingServerIdentity */ + char *versionString; + + /* What does the server tell the new clients which version it supports */ + int protocolMajorVersion; + int protocolMinorVersion; + + /* command line authorization of file transfers */ + rfbBool permitFileTransfer; + + /* displayFinishedHook is called just after a frame buffer update */ + rfbDisplayFinishedHookPtr displayFinishedHook; +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + char *sslkeyfile; + char *sslcertfile; +#endif +} rfbScreenInfo, *rfbScreenInfoPtr; + + +/* + * rfbTranslateFnType is the type of translation functions. + */ + +typedef void (*rfbTranslateFnType)(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); + + +/* region stuff */ + +struct sraRegion; +typedef struct sraRegion* sraRegionPtr; + +/* + * Per-client structure. + */ + +typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl); + +typedef struct _rfbFileTransferData { + int fd; + int compressionEnabled; + int fileSize; + int numPackets; + int receiving; + int sending; +} rfbFileTransferData; + + +typedef struct _rfbStatList { + uint32_t type; + uint32_t sentCount; + uint32_t bytesSent; + uint32_t bytesSentIfRaw; + uint32_t rcvdCount; + uint32_t bytesRcvd; + uint32_t bytesRcvdIfRaw; + struct _rfbStatList *Next; +} rfbStatList; + +typedef struct _rfbClientRec { + + /* back pointer to the screen */ + rfbScreenInfoPtr screen; + + /* points to a scaled version of the screen buffer in cl->scaledScreenList */ + rfbScreenInfoPtr scaledScreen; + /* how did the client tell us it wanted the screen changed? Ultra style or palm style? */ + rfbBool PalmVNC; + + + /* private data. You should put any application client specific data + * into a struct and let clientData point to it. Don't forget to + * free the struct via clientGoneHook! + * + * This is useful if the IO functions have to behave client specific. + */ + void* clientData; + ClientGoneHookPtr clientGoneHook; + + SOCKET sock; + char *host; + + /* RFB protocol minor version number */ + int protocolMajorVersion; + int protocolMinorVersion; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + pthread_t client_thread; +#endif + /* Possible client states: */ + enum { + RFB_PROTOCOL_VERSION, /* establishing protocol version */ + RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */ + RFB_AUTHENTICATION, /* authenticating */ + RFB_INITIALISATION, /* sending initialisation messages */ + RFB_NORMAL /* normal protocol messages */ + } state; + + rfbBool reverseConnection; + rfbBool onHold; + rfbBool readyForSetColourMapEntries; + rfbBool useCopyRect; + int preferredEncoding; + int correMaxWidth, correMaxHeight; + + rfbBool viewOnly; + + /* The following member is only used during VNC authentication */ + uint8_t authChallenge[CHALLENGESIZE]; + + /* The following members represent the update needed to get the client's + framebuffer from its present state to the current state of our + framebuffer. + + If the client does not accept CopyRect encoding then the update is + simply represented as the region of the screen which has been modified + (modifiedRegion). + + If the client does accept CopyRect encoding, then the update consists of + two parts. First we have a single copy from one region of the screen to + another (the destination of the copy is copyRegion), and second we have + the region of the screen which has been modified in some other way + (modifiedRegion). + + Although the copy is of a single region, this region may have many + rectangles. When sending an update, the copyRegion is always sent + before the modifiedRegion. This is because the modifiedRegion may + overlap parts of the screen which are in the source of the copy. + + In fact during normal processing, the modifiedRegion may even overlap + the destination copyRegion. Just before an update is sent we remove + from the copyRegion anything in the modifiedRegion. */ + + sraRegionPtr copyRegion; /* the destination region of the copy */ + int copyDX, copyDY; /* the translation by which the copy happens */ + + sraRegionPtr modifiedRegion; + + /* As part of the FramebufferUpdateRequest, a client can express interest + in a subrectangle of the whole framebuffer. This is stored in the + requestedRegion member. In the normal case this is the whole + framebuffer if the client is ready, empty if it's not. */ + + sraRegionPtr requestedRegion; + + /* The following member represents the state of the "deferred update" timer + - when the framebuffer is modified and the client is ready, in most + cases it is more efficient to defer sending the update by a few + milliseconds so that several changes to the framebuffer can be combined + into a single update. */ + + struct timeval startDeferring; + struct timeval startPtrDeferring; + int lastPtrX; + int lastPtrY; + int lastPtrButtons; + + /* translateFn points to the translation function which is used to copy + and translate a rectangle from the framebuffer to an output buffer. */ + + rfbTranslateFnType translateFn; + char *translateLookupTable; + rfbPixelFormat format; + + /* + * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the + * framebuffer. So for a max screen width of say 2K with 32-bit pixels this + * means 8K minimum. + */ + +#define UPDATE_BUF_SIZE 30000 + + char updateBuf[UPDATE_BUF_SIZE]; + int ublen; + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + rfbBool webSockets; + rfbBool webSocketsSSL; + rfbBool webSocketsBase64; + + SSL_CTX *ssl_ctx; + SSL *ssl; + + char *keyfile; + char *certfile; + char encodeBuf[UPDATE_BUF_SIZE*2 + 2]; // UTF-8 could double it + framing + char decodeBuf[8192]; // TODO: what makes sense? + int dblen; + char carryBuf[3]; // For base64 carry-over + int carrylen; +#endif + + + /* statistics */ + struct _rfbStatList *statEncList; + struct _rfbStatList *statMsgList; + int rawBytesEquivalent; + int bytesSent; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* zlib encoding -- necessary compression state info per client */ + + struct z_stream_s compStream; + rfbBool compStreamInited; + uint32_t zlibCompressLevel; +#endif +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + uint32_t tightEncoding; /* rfbEncodingTight or rfbEncodingTightPng */ + /* the quality level is also used by ZYWRLE and TightPng */ + int tightQualityLevel; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* tight encoding -- preserve zlib streams' state for each client */ + z_stream zsStruct[4]; + rfbBool zsActive[4]; + int zsLevel[4]; +#endif +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) + int tightCompressLevel; +#endif +#endif + + /* Ultra Encoding support */ + rfbBool compStreamInitedLZO; + char *lzoWrkMem; + + rfbFileTransferData fileTransfer; + + int lastKeyboardLedState; /* keep track of last value so we can send *change* events */ + rfbBool enableSupportedMessages; /* client supports SupportedMessages encoding */ + rfbBool enableSupportedEncodings; /* client supports SupportedEncodings encoding */ + rfbBool enableServerIdentity; /* client supports ServerIdentity encoding */ + rfbBool enableKeyboardLedState; /* client supports KeyboardState encoding */ + rfbBool enableLastRectEncoding; /* client supports LastRect encoding */ + rfbBool enableCursorShapeUpdates; /* client supports cursor shape updates */ + rfbBool enableCursorPosUpdates; /* client supports cursor position updates */ + rfbBool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ + rfbBool cursorWasChanged; /* cursor shape update should be sent */ + rfbBool cursorWasMoved; /* cursor position update should be sent */ + int cursorX,cursorY; /* the coordinates of the cursor, + if enableCursorShapeUpdates = FALSE */ + + rfbBool useNewFBSize; /* client supports NewFBSize encoding */ + rfbBool newFBSizePending; /* framebuffer size was changed */ + + struct _rfbClientRec *prev; + struct _rfbClientRec *next; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + /* whenever a client is referenced, the refCount has to be incremented + and afterwards decremented, so that the client is not cleaned up + while being referenced. + Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl); + */ + int refCount; + MUTEX(refCountMutex); + COND(deleteCond); + + MUTEX(outputMutex); + MUTEX(updateMutex); + COND(updateCond); +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBZ + void* zrleData; + int zywrleLevel; + int zywrleBuf[rfbZRLETileWidth * rfbZRLETileHeight]; +#endif + + /* if progressive updating is on, this variable holds the current + * y coordinate of the progressive slice. */ + int progressiveSliceY; + + rfbExtensionData* extensions; + + /* for threaded zrle */ + char *zrleBeforeBuf; + void *paletteHelper; + + /* for thread safety for rfbSendFBUpdate() */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#define LIBVNCSERVER_SEND_MUTEX + MUTEX(sendMutex); +#endif + +} rfbClientRec, *rfbClientPtr; + +/* + * This macro is used to test whether there is a framebuffer update needing to + * be sent to the client. + */ + +#define FB_UPDATE_PENDING(cl) \ + (((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ + (((cl)->enableCursorShapeUpdates == FALSE && \ + ((cl)->cursorX != (cl)->screen->cursorX || \ + (cl)->cursorY != (cl)->screen->cursorY))) || \ + ((cl)->useNewFBSize && (cl)->newFBSizePending) || \ + ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ + !sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion)) + +/* + * Macros for endian swapping. + */ + +#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) + +#define Swap24(l) ((((l) & 0xff) << 16) | (((l) >> 16) & 0xff) | \ + (((l) & 0x00ff00))) + +#define Swap32(l) (((l) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + ((l) << 24)) + + +extern char rfbEndianTest; + +#define Swap16IfLE(s) (rfbEndianTest ? Swap16(s) : (s)) +#define Swap24IfLE(l) (rfbEndianTest ? Swap24(l) : (l)) +#define Swap32IfLE(l) (rfbEndianTest ? Swap32(l) : (l)) + +/* UltraVNC uses some windows structures unmodified, so the viewer expects LittleEndian Data */ +#define Swap16IfBE(s) (rfbEndianTest ? (s) : Swap16(s)) +#define Swap24IfBE(l) (rfbEndianTest ? (l) : Swap24(l)) +#define Swap32IfBE(l) (rfbEndianTest ? (l) : Swap32(l)) + +/* sockets.c */ + +extern int rfbMaxClientWait; + +extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen); +extern void rfbCloseClient(rfbClientPtr cl); +extern int rfbReadExact(rfbClientPtr cl, char *buf, int len); +extern int rfbReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); +extern int rfbPeekExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); +extern int rfbWriteExact(rfbClientPtr cl, const char *buf, int len); +extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec); +extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port); +extern int rfbConnectToTcpAddr(char* host, int port); +extern int rfbListenOnTCPPort(int port, in_addr_t iface); +extern int rfbListenOnUDPPort(int port, in_addr_t iface); +extern int rfbStringToAddr(char* string,in_addr_t* addr); + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS +/* websockets.c */ + +extern rfbBool webSocketsCheck(rfbClientPtr cl); +extern int webSocketsEncode(rfbClientPtr cl, const char *src, int len); +extern int webSocketsDecode(rfbClientPtr cl, char *dst, int len); +#endif + +/* rfbserver.c */ + +/* Routines to iterate over the client list in a thread-safe way. + Only a single iterator can be in use at a time process-wide. */ +typedef struct rfbClientIterator *rfbClientIteratorPtr; + +extern void rfbClientListInit(rfbScreenInfoPtr rfbScreen); +extern rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbClientIteratorNext(rfbClientIteratorPtr iterator); +extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator); +extern void rfbIncrClientRef(rfbClientPtr cl); +extern void rfbDecrClientRef(rfbClientPtr cl); + +extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,int sock); +extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,int sock); +extern rfbClientPtr rfbNewUDPClient(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port); +extern void rfbClientConnectionGone(rfbClientPtr cl); +extern void rfbProcessClientMessage(rfbClientPtr cl); +extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); +extern void rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,int sock); +extern void rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen); +extern rfbBool rfbSendFramebufferUpdate(rfbClientPtr cl, sraRegionPtr updateRegion); +extern rfbBool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); +extern rfbBool rfbSendUpdateBuf(rfbClientPtr cl); +extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len); +extern rfbBool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy); +extern rfbBool rfbSendLastRectMarker(rfbClientPtr cl); +extern rfbBool rfbSendNewFBSize(rfbClientPtr cl, int w, int h); +extern rfbBool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSendBell(rfbScreenInfoPtr rfbScreen); + +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbSendFileTransferChunk(rfbClientPtr cl); +extern rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer); +extern rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, char *buffer); +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length); + +void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len); + +/* translate.c */ + +extern rfbBool rfbEconomicTranslate; + +extern void rfbTranslateNone(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); +extern rfbBool rfbSetTranslateFunction(rfbClientPtr cl); +extern rfbBool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours); + +/* httpd.c */ + +extern void rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen); + + + +/* auth.c */ + +extern void rfbAuthNewClient(rfbClientPtr cl); +extern void rfbProcessClientSecurityType(rfbClientPtr cl); +extern void rfbAuthProcessClientMessage(rfbClientPtr cl); +extern void rfbRegisterSecurityHandler(rfbSecurityHandler* handler); +extern void rfbUnregisterSecurityHandler(rfbSecurityHandler* handler); + +/* rre.c */ + +extern rfbBool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* corre.c */ + +extern rfbBool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* hextile.c */ + +extern rfbBool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, + int h); + +/* ultra.c */ + +/* Set maximum ultra rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ULTRA_MAX_RECT_SIZE (128*256) +#define ULTRA_MAX_SIZE(min) ((( min * 2 ) > ULTRA_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ULTRA_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingUltra(rfbClientPtr cl, int x,int y,int w,int h); + + +#ifdef LIBVNCSERVER_HAVE_LIBZ +/* zlib.c */ + +/* Minimum zlib rectangle size in bytes. Anything smaller will + * not compress well due to overhead. + */ +#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) + +/* Set maximum zlib rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ZLIB_MAX_RECT_SIZE (128*256) +#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, + int h); + +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) +/* tight.c */ + +#define TIGHT_DEFAULT_COMPRESSION 6 + +extern rfbBool rfbTightDisableGradient; + +extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); + +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) +extern rfbBool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); +#endif +#if defined(LIBVNCSERVER_HAVE_LIBPNG) +extern rfbBool rfbSendRectEncodingTightPng(rfbClientPtr cl, int x,int y,int w,int h); +#endif + +#endif +#endif + + +/* cursor.c */ + +typedef struct rfbCursor { + /* set this to true if LibVNCServer has to free this cursor */ + rfbBool cleanup, cleanupSource, cleanupMask, cleanupRichSource; + unsigned char *source; /* points to bits */ + unsigned char *mask; /* points to bits */ + unsigned short width, height, xhot, yhot; /* metrics */ + unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */ + unsigned short backRed, backGreen, backBlue; /* device-independent colour */ + unsigned char *richSource; /* source bytes for a rich cursor */ + unsigned char *alphaSource; /* source for alpha blending info */ + rfbBool alphaPreMultiplied; /* if richSource already has alpha applied */ +} rfbCursor, *rfbCursorPtr; +extern unsigned char rfbReverseByte[0x100]; + +extern rfbBool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/); +extern rfbBool rfbSendCursorPos(rfbClientPtr cl); +extern void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap); +extern rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString); +extern char* rfbMakeMaskForXCursor(int width,int height,char* cursorString); +extern char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource); +extern void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbFreeCursor(rfbCursorPtr cursor); +extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c); + +/* cursor handling for the pointer */ +extern void rfbDefaultPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl); + +/* zrle.c */ +#ifdef LIBVNCSERVER_HAVE_LIBZ +extern rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w,int h); +#endif + +/* stats.c */ + +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +/* font.c */ + +typedef struct rfbFontData { + unsigned char* data; + /* + metaData is a 256*5 array: + for each character + (offset,width,height,x,y) + */ + int* metaData; +} rfbFontData,* rfbFontDataPtr; + +int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,rfbPixel colour); +void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,rfbPixel colour); +/* if colour==backColour, background is transparent */ +int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +int rfbWidthOfString(rfbFontDataPtr font,const char* string); +int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c); +void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2); +/* this returns the smallest box enclosing any character of font. */ +void rfbWholeFontBBox(rfbFontDataPtr font,int *x1, int *y1, int *x2, int *y2); + +/* dynamically load a linux console font (4096 bytes, 256 glyphs a 8x16 */ +rfbFontDataPtr rfbLoadConsoleFont(char *filename); +/* free a dynamically loaded font */ +void rfbFreeFont(rfbFontDataPtr font); + +/* draw.c */ + +void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); +void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col); +void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); + +/* selbox.c */ + +/* this opens a modal select box. list is an array of strings, the end marked + with a NULL. + It returns the index in the list or -1 if cancelled or something else + wasn't kosher. */ +typedef void (*SelectionChangedHookPtr)(int _index); +extern int rfbSelectBox(rfbScreenInfoPtr rfbScreen, + rfbFontDataPtr font, char** list, + int x1, int y1, int x2, int y2, + rfbPixel foreColour, rfbPixel backColour, + int border,SelectionChangedHookPtr selChangedHook); + +/* cargs.c */ + +extern void rfbUsage(void); +extern void rfbPurgeArguments(int* argc,int* position,int count,char *argv[]); +extern rfbBool rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]); +extern rfbBool rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[]); + +/* main.c */ + +extern void rfbLogEnable(int enabled); +typedef void (*rfbLogProc)(const char *format, ...); +extern rfbLogProc rfbLog, rfbErr; +extern void rfbLogPerror(const char *str); + +void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2); +void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion); +void rfbDoNothingWithClient(rfbClientPtr cl); +enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl); +void rfbRegisterProtocolExtension(rfbProtocolExtension* extension); +void rfbUnregisterProtocolExtension(rfbProtocolExtension* extension); +struct _rfbProtocolExtension* rfbGetExtensionIterator(); +void rfbReleaseExtensionIterator(); +rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension, + void* data); +rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension); +void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension); + +/* to check against plain passwords */ +rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len); + +/* functions to make a vnc server */ +extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, + int width,int height,int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); +extern void rfbInitServer(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownServer(rfbScreenInfoPtr rfbScreen,rfbBool disconnectClients); +extern void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char *framebuffer, + int width,int height, int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); + +extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo); +extern void rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...); + +/* functions to accept/refuse a client that has been put on hold + by a NewClientHookPtr function. Must not be called in other + situations. */ +extern void rfbStartOnHoldClient(rfbClientPtr cl); +extern void rfbRefuseOnHoldClient(rfbClientPtr cl); + +/* call one of these two functions to service the vnc clients. + usec are the microseconds the select on the fds waits. + if you are using the event loop, set this to some value > 0, so the + server doesn't get a high load just by listening. + rfbProcessEvents() returns TRUE if an update was pending. */ + +extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, rfbBool runInBackground); +extern rfbBool rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec); +extern rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo); + +/* TightVNC file transfer extension */ +void rfbRegisterTightVNCFileTransferExtension(); +void rfbUnregisterTightVNCFileTransferExtension(); + +/* Statistics */ +extern char *messageNameServer2Client(uint32_t type, char *buf, int len); +extern char *messageNameClient2Server(uint32_t type, char *buf, int len); +extern char *encodingName(uint32_t enc, char *buf, int len); + +extern rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type); +extern rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type); + +/* Each call to rfbStatRecord* adds one to the rect count for that type */ +extern void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount); /* Specifically for tight encoding */ +extern void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +extern int rfbStatGetSentBytes(rfbClientPtr cl); +extern int rfbStatGetSentBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetRcvdBytes(rfbClientPtr cl); +extern int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type); + +/* Set which version you want to advertise 3.3, 3.6, 3.7 and 3.8 are currently supported*/ +extern void rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_); + +/* send a TextChat message to a client */ +extern rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer); + + + + +#if(defined __cplusplus) +} +#endif + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbclient.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbclient.h new file mode 100755 index 0000000..bc4ec14 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbclient.h @@ -0,0 +1,406 @@ +#ifndef RFBCLIENT_H +#define RFBCLIENT_H + +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. 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. + */ + +/* + * vncviewer.h + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS +#include +#endif + +#define rfbClientSwap16IfLE(s) \ + (*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) + +#define rfbClientSwap32IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) & 0xff000000) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) : (l)) + +#define rfbClientSwap64IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) & 0xff00000000000000ULL) >> 56) | \ + (((l) & 0x00ff000000000000ULL) >> 40) | \ + (((l) & 0x0000ff0000000000ULL) >> 24) | \ + (((l) & 0x000000ff00000000ULL) >> 8) | \ + (((l) & 0x00000000ff000000ULL) << 8) | \ + (((l) & 0x0000000000ff0000ULL) << 24) | \ + (((l) & 0x000000000000ff00ULL) << 40) | \ + (((l) & 0x00000000000000ffULL) << 56)) : (l)) + +#define FLASH_PORT_OFFSET 5400 +#define LISTEN_PORT_OFFSET 5500 +#define TUNNEL_PORT_OFFSET 5500 +#define SERVER_PORT_OFFSET 5900 + +#define DEFAULT_SSH_CMD "/usr/bin/ssh" +#define DEFAULT_TUNNEL_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:localhost:%R %H sleep 20") +#define DEFAULT_VIA_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") + +#if(defined __cplusplus) +extern "C" +{ +#endif + +/* vncrec */ + +typedef struct { + FILE* file; + struct timeval tv; + rfbBool readTimestamp; + rfbBool doNotSleep; +} rfbVNCRec; + +/* client data */ + +typedef struct rfbClientData { + void* tag; + void* data; + struct rfbClientData* next; +} rfbClientData; + +/* app data (belongs into rfbClient?) */ + +typedef struct { + rfbBool shareDesktop; + rfbBool viewOnly; + + const char* encodingsString; + + rfbBool useBGR233; + int nColours; + rfbBool forceOwnCmap; + rfbBool forceTrueColour; + int requestedDepth; + + int compressLevel; + int qualityLevel; + rfbBool enableJPEG; + rfbBool useRemoteCursor; + rfbBool palmVNC; /* use palmvnc specific SetScale (vs ultravnc) */ + int scaleSetting; /* 0 means no scale set, else 1/scaleSetting */ +} AppData; + +/* For GetCredentialProc callback function to return */ +typedef union _rfbCredential +{ + /* X509 (VeNCrypt) */ + struct + { + char *x509CACertFile; + char *x509CACrlFile; + char *x509ClientCertFile; + char *x509ClientKeyFile; + } x509Credential; + /* Plain (VeNCrypt), MSLogon (UltraVNC) */ + struct + { + char *username; + char *password; + } userCredential; +} rfbCredential; + +#define rfbCredentialTypeX509 1 +#define rfbCredentialTypeUser 2 + +struct _rfbClient; + +typedef void (*HandleTextChatProc)(struct _rfbClient* client, int value, char *text); +typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad); +typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y); +typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h); +typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client); +typedef void (*GotFrameBufferUpdateProc)(struct _rfbClient* client, int x, int y, int w, int h); +typedef void (*FinishedFrameBufferUpdateProc)(struct _rfbClient* client); +typedef char* (*GetPasswordProc)(struct _rfbClient* client); +typedef rfbCredential* (*GetCredentialProc)(struct _rfbClient* client, int credentialType); +typedef rfbBool (*MallocFrameBufferProc)(struct _rfbClient* client); +typedef void (*GotXCutTextProc)(struct _rfbClient* client, const char *text, int textlen); +typedef void (*BellProc)(struct _rfbClient* client); + +typedef void (*GotCursorShapeProc)(struct _rfbClient* client, int xhot, int yhot, int width, int height, int bytesPerPixel); +typedef void (*GotCopyRectProc)(struct _rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y); + +typedef struct _rfbClient { + uint8_t* frameBuffer; + int width, height; + + int endianTest; + + AppData appData; + + const char* programName; + char* serverHost; + int serverPort; /* if -1, then use file recorded by vncrec */ + rfbBool listenSpecified; + int listenPort, flashPort; + + struct { + int x, y, w, h; + } updateRect; + + /* Note that the CoRRE encoding uses this buffer and assumes it is big enough + to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes. + Hextile also assumes it is big enough to hold 16 * 16 * 32 bits. + Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */ + +#define RFB_BUFFER_SIZE (640*480) + char buffer[RFB_BUFFER_SIZE]; + + /* rfbproto.c */ + + int sock; + rfbBool canUseCoRRE; + rfbBool canUseHextile; + char *desktopName; + rfbPixelFormat format; + rfbServerInitMsg si; + + /* listen.c */ + int listenSock; + + /* sockets.c */ +#define RFB_BUF_SIZE 8192 + char buf[RFB_BUF_SIZE]; + char *bufoutptr; + int buffered; + + /* The zlib encoding requires expansion/decompression/deflation of the + compressed data in the "buffer" above into another, result buffer. + However, the size of the result buffer can be determined precisely + based on the bitsPerPixel, height and width of the rectangle. We + allocate this buffer one time to be the full size of the buffer. */ + + /* Ultra Encoding uses this buffer too */ + + int ultra_buffer_size; + char *ultra_buffer; + + int raw_buffer_size; + char *raw_buffer; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + z_stream decompStream; + rfbBool decompStreamInited; +#endif + + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* + * Variables for the ``tight'' encoding implementation. + */ + + /* Separate buffer for compressed data. */ +#define ZLIB_BUFFER_SIZE 30000 + char zlib_buffer[ZLIB_BUFFER_SIZE]; + + /* Four independent compression streams for zlib library. */ + z_stream zlibStream[4]; + rfbBool zlibStreamActive[4]; + + /* Filter stuff. Should be initialized by filter initialization code. */ + rfbBool cutZeros; + int rectWidth, rectColors; + char tightPalette[256*4]; + uint8_t tightPrevRow[2048*3*sizeof(uint16_t)]; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* JPEG decoder state. */ + rfbBool jpegError; + + struct jpeg_source_mgr* jpegSrcManager; + void* jpegBufferPtr; + size_t jpegBufferLen; + +#endif +#endif + + + /* cursor.c */ + uint8_t *rcSource, *rcMask; + + /* private data pointer */ + rfbClientData* clientData; + + rfbVNCRec* vncRec; + + /* Keyboard State support (is 'Caps Lock' set on the remote display???) */ + int KeyboardLedStateEnabled; + int CurrentKeyboardLedState; + + int canHandleNewFBSize; + + /* hooks */ + HandleTextChatProc HandleTextChat; + HandleKeyboardLedStateProc HandleKeyboardLedState; + HandleCursorPosProc HandleCursorPos; + SoftCursorLockAreaProc SoftCursorLockArea; + SoftCursorUnlockScreenProc SoftCursorUnlockScreen; + GotFrameBufferUpdateProc GotFrameBufferUpdate; + FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate; + /* the pointer returned by GetPassword will be freed after use! */ + GetPasswordProc GetPassword; + MallocFrameBufferProc MallocFrameBuffer; + GotXCutTextProc GotXCutText; + BellProc Bell; + + GotCursorShapeProc GotCursorShape; + GotCopyRectProc GotCopyRect; + + /* Which messages are supported by the server + * This is a *guess* for most servers. + * (If we can even detect the type of server) + * + * If the server supports the "rfbEncodingSupportedMessages" + * then this will be updated when the encoding is received to + * accurately reflect the servers capabilities. + */ + rfbSupportedMessages supportedMessages; + + /* negotiated protocol version */ + int major, minor; + + /* The selected security types */ + uint32_t authScheme, subAuthScheme; + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + /* The TLS session for Anonymous TLS and VeNCrypt */ + gnutls_session_t tlsSession; +#endif + + /* To support security types that requires user input (except VNC password + * authentication), for example VeNCrypt and MSLogon, this callback function + * must be set before the authentication. Otherwise, it implicates that the + * caller application does not support it and related security types should + * be bypassed. + */ + GetCredentialProc GetCredential; + + /* The 0-terminated security types supported by the client. + * Set by function SetClientAuthSchemes() */ + uint32_t *clientAuthSchemes; + + /* When the server is a repeater, this specifies the final destination */ + char *destHost; + int destPort; +} rfbClient; + +/* cursor.c */ + +extern rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc); + +/* listen.c */ + +extern void listenForIncomingConnections(rfbClient* viewer); +extern int listenForIncomingConnectionsNoFork(rfbClient* viewer, int usec_timeout); + +/* rfbproto.c */ + +extern rfbBool rfbEnableClientLogging; +typedef void (*rfbClientLogProc)(const char *format, ...); +extern rfbClientLogProc rfbClientLog,rfbClientErr; +extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port); +extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort); +extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size); +extern rfbBool InitialiseRFBConnection(rfbClient* client); +extern rfbBool SetFormatAndEncodings(rfbClient* client); +extern rfbBool SendIncrementalFramebufferUpdateRequest(rfbClient* client); +extern rfbBool SendFramebufferUpdateRequest(rfbClient* client, + int x, int y, int w, int h, + rfbBool incremental); +extern rfbBool SendScaleSetting(rfbClient* client,int scaleSetting); +extern rfbBool SendPointerEvent(rfbClient* client,int x, int y, int buttonMask); +extern rfbBool SendKeyEvent(rfbClient* client,uint32_t key, rfbBool down); +extern rfbBool SendClientCutText(rfbClient* client,char *str, int len); +extern rfbBool HandleRFBServerMessage(rfbClient* client); + +extern rfbBool TextChatSend(rfbClient* client, char *text); +extern rfbBool TextChatOpen(rfbClient* client); +extern rfbBool TextChatClose(rfbClient* client); +extern rfbBool TextChatFinish(rfbClient* client); +extern rfbBool PermitServerInput(rfbClient* client, int enabled); + +extern void PrintPixelFormat(rfbPixelFormat *format); + +extern rfbBool SupportsClient2Server(rfbClient* client, int messageType); +extern rfbBool SupportsServer2Client(rfbClient* client, int messageType); + +/* client data */ + +void rfbClientSetClientData(rfbClient* client, void* tag, void* data); +void* rfbClientGetClientData(rfbClient* client, void* tag); + +/* protocol extensions */ + +typedef struct _rfbClientProtocolExtension { + int* encodings; + /* returns TRUE if the encoding was handled */ + rfbBool (*handleEncoding)(rfbClient* cl, + rfbFramebufferUpdateRectHeader* rect); + /* returns TRUE if it handled the message */ + rfbBool (*handleMessage)(rfbClient* cl, + rfbServerToClientMsg* message); + struct _rfbClientProtocolExtension* next; +} rfbClientProtocolExtension; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e); + +/* sockets.c */ + +extern rfbBool errorMessageOnReadFailure; + +extern rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n); +extern rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n); +extern int FindFreeTcpPort(void); +extern int ListenAtTcpPort(int port); +extern int ConnectClientToTcpAddr(unsigned int host, int port); +extern int ConnectClientToUnixSock(const char *sockFile); +extern int AcceptTcpConnection(int listenSock); +extern rfbBool SetNonBlocking(int sock); + +extern rfbBool StringToIPAddr(const char *str, unsigned int *addr); +extern rfbBool SameMachine(int sock); +extern int WaitForMessage(rfbClient* client,unsigned int usecs); + +/* vncviewer.c */ +rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,int bytesPerPixel); +rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv); +/* rfbClientCleanup() does not touch client->frameBuffer */ +void rfbClientCleanup(rfbClient* client); + +#if(defined __cplusplus) +} +#endif + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbconfig.h.cmake b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbconfig.h.cmake new file mode 100755 index 0000000..f9f9ba3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbconfig.h.cmake @@ -0,0 +1,92 @@ +#ifndef _RFB_RFBCONFIG_H +#cmakedefine _RFB_RFBCONFIG_H 1 + +/* rfb/rfbconfig.h. Generated automatically by cmake. */ + +/* Enable 24 bit per pixel in native framebuffer */ +#cmakedefine LIBVNCSERVER_ALLOW24BPP 1 + +/* work around when write() returns ENOENT but does not mean it */ +#cmakedefine LIBVNCSERVER_ENOENT_WORKAROUND 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1 + +/* Need a typedef for in_addr_t */ +#cmakedefine LIBVNCSERVER_NEED_INADDR_T 1 + +/* Define to the full name and version of this package. */ +#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @PACKAGE_VERSION@" + +/* Define to the version of this package. */ +#define LIBVNCSERVER_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Define to 1 if GnuTLS is present */ +#cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1 + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#cmakedefine LIBVNCSERVER_WORDS_BIGENDIAN 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +//#cmakedefine const @CMAKE_CONST@ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +//#ifndef __cplusplus +//#cmakedefine inline @CMAKE_INLINE@ +//#endif + +/* Define to `int' if does not define. */ +#cmakedefine HAVE_LIBVNCSERVER_PID_T 1 +#ifndef HAVE_LIBVNCSERVER_PID_T +typedef int pid_t; +#endif + +/* The type for size_t */ +#cmakedefine HAVE_LIBVNCSERVER_SIZE_T 1 +#ifndef HAVE_LIBVNCSERVER_SIZE_T +typedef int size_t; +#endif + +/* The type for socklen */ +#cmakedefine HAVE_LIBVNCSERVER_SOCKLEN_T 1 +#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T +typedef int socklen_t; +#endif + +/* once: _RFB_RFBCONFIG_H */ +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbint.h.cmake b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbint.h.cmake new file mode 100755 index 0000000..17de6cd --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbint.h.cmake @@ -0,0 +1,4 @@ +#ifndef _RFB_RFBINT_H +#define _RFB_RFBINT_H 1 +/* empty ... */ +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbproto.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbproto.h new file mode 100755 index 0000000..944c1d2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbproto.h @@ -0,0 +1,1383 @@ +#ifndef RFBPROTO_H +#define RFBPROTO_H + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. 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. + */ + +/* + * rfbproto.h - header file for the RFB protocol version 3.3 + * + * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed + * integer (for n = 8, 16 and 32). + * + * All multiple byte integers are in big endian (network) order (most + * significant byte first). Unless noted otherwise there is no special + * alignment of protocol structures. + * + * + * Once the initial handshaking is done, all messages start with a type byte, + * (usually) followed by message-specific data. The order of definitions in + * this file is as follows: + * + * (1) Structures used in several types of message. + * (2) Structures used in the initial handshaking. + * (3) Message types. + * (4) Encoding types. + * (5) For each message type, the form of the data following the type byte. + * Sometimes this is defined by a single structure but the more complex + * messages have to be explained by comments. + */ + + +#if defined(WIN32) && !defined(__MINGW32__) +#define LIBVNCSERVER_WORDS_BIGENDIAN +#define rfbBool int +#include +#include +#undef SOCKET +#define SOCKET int +#else +#include + +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#include +#ifdef __CHECKER__ +#undef Z_NULL +#define Z_NULL NULL +#endif +#endif + + +#if !defined(WIN32) || defined(__MINGW32__) +#define max(a,b) (((a)>(b))?(a):(b)) +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#endif +#define SOCKET int +typedef int8_t rfbBool; +#undef FALSE +#define FALSE 0 +#undef TRUE +#define TRUE -1 +#endif + +typedef uint32_t rfbKeySym; +typedef uint32_t rfbPixel; + +#ifdef LIBVNCSERVER_NEED_INADDR_T +typedef uint32_t in_addr_t; +#endif +/* +#ifndef INADDR_NONE +#define INADDR_NONE ((in_addr_t) 0xffffffff) +#endif*/ + +#define MAX_ENCODINGS 20 + +/***************************************************************************** + * + * Structures used in several messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Structure used to specify a rectangle. This structure is a multiple of 4 + * bytes so that it can be interspersed with 32-bit pixel data without + * affecting alignment. + */ + +typedef struct { + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbRectangle; + +#define sz_rfbRectangle 8 + + +/*----------------------------------------------------------------------------- + * Structure used to specify pixel format. + */ + +typedef struct { + + uint8_t bitsPerPixel; /* 8,16,32 only */ + + uint8_t depth; /* 8 to 32 */ + + uint8_t bigEndian; /* True if multi-byte pixels are interpreted + as big endian, or if single-bit-per-pixel + has most significant bit of the byte + corresponding to first (leftmost) pixel. Of + course this is meaningless for 8 bits/pix */ + + uint8_t trueColour; /* If false then we need a "colour map" to + convert pixels to RGB. If true, xxxMax and + xxxShift specify bits used for red, green + and blue */ + + /* the following fields are only meaningful if trueColour is true */ + + uint16_t redMax; /* maximum red value (= 2^n - 1 where n is the + number of bits used for red). Note this + value is always in big endian order. */ + + uint16_t greenMax; /* similar for green */ + + uint16_t blueMax; /* and blue */ + + uint8_t redShift; /* number of shifts needed to get the red + value in a pixel to the least significant + bit. To find the red value from a given + pixel, do the following: + 1) Swap pixel value according to bigEndian + (e.g. if bigEndian is false and host byte + order is big endian, then swap). + 2) Shift right by redShift. + 3) AND with redMax (in host byte order). + 4) You now have the red value between 0 and + redMax. */ + + uint8_t greenShift; /* similar for green */ + + uint8_t blueShift; /* and blue */ + + uint8_t pad1; + uint16_t pad2; + +} rfbPixelFormat; + +#define sz_rfbPixelFormat 16 + +/* UltraVNC: Color settings values */ +#define rfbPFFullColors 0 +#define rfbPF256Colors 1 +#define rfbPF64Colors 2 +#define rfbPF8Colors 3 +#define rfbPF8GreyColors 4 +#define rfbPF4GreyColors 5 +#define rfbPF2GreyColors 6 + + +/***************************************************************************** + * + * Initial handshaking messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Protocol Version + * + * The server always sends 12 bytes to start which identifies the latest RFB + * protocol version number which it supports. These bytes are interpreted + * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where + * xxx and yyy are the major and minor version numbers (for version 3.3 + * this is "RFB 003.003\n"). + * + * The client then replies with a similar 12-byte message giving the version + * number of the protocol which should actually be used (which may be different + * to that quoted by the server). + * + * It is intended that both clients and servers may provide some level of + * backwards compatibility by this mechanism. Servers in particular should + * attempt to provide backwards compatibility, and even forwards compatibility + * to some extent. For example if a client demands version 3.1 of the + * protocol, a 3.0 server can probably assume that by ignoring requests for + * encoding types it doesn't understand, everything will still work OK. This + * will probably not be the case for changes in the major version number. + * + * The format string below can be used in sprintf or sscanf to generate or + * decode the version string respectively. + */ + +#define rfbProtocolVersionFormat "RFB %03d.%03d\n" +#define rfbProtocolMajorVersion 3 +#define rfbProtocolMinorVersion 8 +/* UltraVNC Viewer examines rfbProtocolMinorVersion number (4, and 6) + * to identify if the server supports File Transfer + */ + +typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ + +#define sz_rfbProtocolVersionMsg 12 + +/* + * Negotiation of the security type (protocol version 3.7) + * + * Once the protocol version has been decided, the server either sends a list + * of supported security types, or informs the client about an error (when the + * number of security types is 0). Security type rfbSecTypeTight is used to + * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth + * stands for classic VNC authentication. + * + * The client selects a particular security type from the list provided by the + * server. + */ + +#define rfbSecTypeInvalid 0 +#define rfbSecTypeNone 1 +#define rfbSecTypeVncAuth 2 + + +/*----------------------------------------------------------------------------- + * Authentication + * + * Once the protocol version has been decided, the server then sends a 32-bit + * word indicating whether any authentication is needed on the connection. + * The value of this word determines the authentication scheme in use. For + * version 3.0 of the protocol this may have one of the following values: + */ + +#define rfbConnFailed 0 +#define rfbNoAuth 1 +#define rfbVncAuth 2 + +#define rfbRA2 5 +#define rfbRA2ne 6 +#define rfbSSPI 7 +#define rfbSSPIne 8 +#define rfbTight 16 +#define rfbUltra 17 +#define rfbTLS 18 +#define rfbVeNCrypt 19 +#define rfbMSLogon 0xfffffffa + +#define rfbVeNCryptPlain 256 +#define rfbVeNCryptTLSNone 257 +#define rfbVeNCryptTLSVNC 258 +#define rfbVeNCryptTLSPlain 259 +#define rfbVeNCryptX509None 260 +#define rfbVeNCryptX509VNC 261 +#define rfbVeNCryptX509Plain 262 +#define rfbVeNCryptX509SASL 263 +#define rfbVeNCryptTLSSASL 264 + +/* + * rfbConnFailed: For some reason the connection failed (e.g. the server + * cannot support the desired protocol version). This is + * followed by a string describing the reason (where a + * string is specified as a 32-bit length followed by that + * many ASCII characters). + * + * rfbNoAuth: No authentication is needed. + * + * rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte + * challenge follows, which the client encrypts as + * appropriate using the password and sends the resulting + * 16-byte response. If the response is correct, the + * server sends the 32-bit word rfbVncAuthOK. If a simple + * failure happens, the server sends rfbVncAuthFailed and + * closes the connection. If the server decides that too + * many failures have occurred, it sends rfbVncAuthTooMany + * and closes the connection. In the latter case, the + * server should not allow an immediate reconnection by + * the client. + */ + +#define rfbVncAuthOK 0 +#define rfbVncAuthFailed 1 +#define rfbVncAuthTooMany 2 + + +/*----------------------------------------------------------------------------- + * Client Initialisation Message + * + * Once the client and server are sure that they're happy to talk to one + * another, the client sends an initialisation message. At present this + * message only consists of a boolean indicating whether the server should try + * to share the desktop by leaving other clients connected, or give exclusive + * access to this client by disconnecting all other clients. + */ + +typedef struct { + uint8_t shared; +} rfbClientInitMsg; + +#define sz_rfbClientInitMsg 1 + + +/*----------------------------------------------------------------------------- + * Server Initialisation Message + * + * After the client initialisation message, the server sends one of its own. + * This tells the client the width and height of the server's framebuffer, + * its pixel format and the name associated with the desktop. + */ + +typedef struct { + uint16_t framebufferWidth; + uint16_t framebufferHeight; + rfbPixelFormat format; /* the server's preferred pixel format */ + uint32_t nameLength; + /* followed by char name[nameLength] */ +} rfbServerInitMsg; + +#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) + + +/* + * Following the server initialisation message it's up to the client to send + * whichever protocol messages it wants. Typically it will send a + * SetPixelFormat message and a SetEncodings message, followed by a + * FramebufferUpdateRequest. From then on the server will send + * FramebufferUpdate messages in response to the client's + * FramebufferUpdateRequest messages. The client should send + * FramebufferUpdateRequest messages with incremental set to true when it has + * finished processing one FramebufferUpdate and is ready to process another. + * With a fast client, the rate at which FramebufferUpdateRequests are sent + * should be regulated to avoid hogging the network. + */ + + + +/***************************************************************************** + * + * Message types + * + *****************************************************************************/ + +/* server -> client */ + +#define rfbFramebufferUpdate 0 +#define rfbSetColourMapEntries 1 +#define rfbBell 2 +#define rfbServerCutText 3 +/* Modif sf@2002 */ +#define rfbResizeFrameBuffer 4 +#define rfbKeyFrameUpdate 5 +#define rfbPalmVNCReSizeFrameBuffer 0xF + +/* client -> server */ + +#define rfbSetPixelFormat 0 +#define rfbFixColourMapEntries 1 /* not currently supported */ +#define rfbSetEncodings 2 +#define rfbFramebufferUpdateRequest 3 +#define rfbKeyEvent 4 +#define rfbPointerEvent 5 +#define rfbClientCutText 6 +/* Modif sf@2002 - actually bidirectionnal */ +#define rfbFileTransfer 7 +/* Modif sf@2002 */ +#define rfbSetScale 8 +/* Modif rdv@2002 */ +#define rfbSetServerInput 9 +/* Modif rdv@2002 */ +#define rfbSetSW 10 +/* Modif sf@2002 - TextChat - Bidirectionnal */ +#define rfbTextChat 11 +/* Modif cs@2005 */ +#define rfbKeyFrameRequest 12 +/* PalmVNC 1.4 & 2.0 SetScale Factor message */ +#define rfbPalmVNCSetScaleFactor 0xF + + + + +/***************************************************************************** + * + * Encoding types + * + *****************************************************************************/ + +#define rfbEncodingRaw 0 +#define rfbEncodingCopyRect 1 +#define rfbEncodingRRE 2 +#define rfbEncodingCoRRE 4 +#define rfbEncodingHextile 5 +#define rfbEncodingZlib 6 +#define rfbEncodingTight 7 +#define rfbEncodingTightPng 0xFFFFFEFC /* -260 */ +#define rfbEncodingZlibHex 8 +#define rfbEncodingUltra 9 +#define rfbEncodingZRLE 16 +#define rfbEncodingZYWRLE 17 + +/* Cache & XOR-Zlib - rdv@2002 */ +#define rfbEncodingCache 0xFFFF0000 +#define rfbEncodingCacheEnable 0xFFFF0001 +#define rfbEncodingXOR_Zlib 0xFFFF0002 +#define rfbEncodingXORMonoColor_Zlib 0xFFFF0003 +#define rfbEncodingXORMultiColor_Zlib 0xFFFF0004 +#define rfbEncodingSolidColor 0xFFFF0005 +#define rfbEncodingXOREnable 0xFFFF0006 +#define rfbEncodingCacheZip 0xFFFF0007 +#define rfbEncodingSolMonoZip 0xFFFF0008 +#define rfbEncodingUltraZip 0xFFFF0009 + +/* + * Special encoding numbers: + * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; + * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; + * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; + * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; + * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; + * 0xFFFFFFF0 .. 0xFFFFFFFF -- cross-encoding compression levels. + */ + +#define rfbEncodingCompressLevel0 0xFFFFFF00 +#define rfbEncodingCompressLevel1 0xFFFFFF01 +#define rfbEncodingCompressLevel2 0xFFFFFF02 +#define rfbEncodingCompressLevel3 0xFFFFFF03 +#define rfbEncodingCompressLevel4 0xFFFFFF04 +#define rfbEncodingCompressLevel5 0xFFFFFF05 +#define rfbEncodingCompressLevel6 0xFFFFFF06 +#define rfbEncodingCompressLevel7 0xFFFFFF07 +#define rfbEncodingCompressLevel8 0xFFFFFF08 +#define rfbEncodingCompressLevel9 0xFFFFFF09 + +#define rfbEncodingXCursor 0xFFFFFF10 +#define rfbEncodingRichCursor 0xFFFFFF11 +#define rfbEncodingPointerPos 0xFFFFFF18 + +#define rfbEncodingLastRect 0xFFFFFF20 +#define rfbEncodingNewFBSize 0xFFFFFF21 + +#define rfbEncodingQualityLevel0 0xFFFFFFE0 +#define rfbEncodingQualityLevel1 0xFFFFFFE1 +#define rfbEncodingQualityLevel2 0xFFFFFFE2 +#define rfbEncodingQualityLevel3 0xFFFFFFE3 +#define rfbEncodingQualityLevel4 0xFFFFFFE4 +#define rfbEncodingQualityLevel5 0xFFFFFFE5 +#define rfbEncodingQualityLevel6 0xFFFFFFE6 +#define rfbEncodingQualityLevel7 0xFFFFFFE7 +#define rfbEncodingQualityLevel8 0xFFFFFFE8 +#define rfbEncodingQualityLevel9 0xFFFFFFE9 + + +/* LibVNCServer additions. We claim 0xFFFE0000 - 0xFFFE00FF */ +#define rfbEncodingKeyboardLedState 0xFFFE0000 +#define rfbEncodingSupportedMessages 0xFFFE0001 +#define rfbEncodingSupportedEncodings 0xFFFE0002 +#define rfbEncodingServerIdentity 0xFFFE0003 + + +/***************************************************************************** + * + * Server -> client message definitions + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. + * + * This message consists of a header giving the number of rectangles of pixel + * data followed by the rectangles themselves. The header is padded so that + * together with the type byte it is an exact multiple of 4 bytes (to help + * with alignment of 32-bit pixels): + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdate */ + uint8_t pad; + uint16_t nRects; + /* followed by nRects rectangles */ +} rfbFramebufferUpdateMsg; + +#define sz_rfbFramebufferUpdateMsg 4 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * KeyFrameUpdate - Acknowledgment of a key frame request, it tells the client + * that the next update received will be a key frame. + */ + +typedef struct { + uint8_t type; +} rfbKeyFrameUpdateMsg; + +#define sz_rfbKeyFrameUpdateMsg 1 + + +/* + * Each rectangle of pixel data consists of a header describing the position + * and size of the rectangle and a type word describing the encoding of the + * pixel data, followed finally by the pixel data. Note that if the client has + * not sent a SetEncodings message then it will only receive raw pixel data. + * Also note again that this structure is a multiple of 4 bytes. + */ + +typedef struct { + rfbRectangle r; + uint32_t encoding; /* one of the encoding types rfbEncoding... */ +} rfbFramebufferUpdateRectHeader; + +#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Messages Encoding. This encoding does not contain any pixel data. + * Instead, it contains 2 sets of bitflags. These bitflags indicate what messages + * are supported by the server. + * rect->w contains byte count + */ + +typedef struct { + uint8_t client2server[32]; /* maximum of 256 message types (256/8)=32 */ + uint8_t server2client[32]; /* maximum of 256 message types (256/8)=32 */ +} rfbSupportedMessages; + +#define sz_rfbSupportedMessages 64 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Encodings Encoding. This encoding does not contain any pixel data. + * Instead, it contains a list of (uint32_t) Encodings supported by this server. + * rect->w contains byte count + * rect->h contains encoding count + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Server Identity Encoding. This encoding does not contain any pixel data. + * Instead, it contains a text string containing information about the server. + * ie: "x11vnc: 0.8.1 lastmod: 2006-04-25 (libvncserver 0.9pre)\0" + * rect->w contains byte count + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Raw Encoding. Pixels are sent in top-to-bottom scanline order, + * left-to-right within a scanline with no padding in between. + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * KeyboardLedState Encoding. The X coordinate contains the Locked Modifiers + * so that a remote troubleshooter can identify that the users 'Caps Lock' + * is set... (It helps a *lot* when the users are untrained) + */ +#define rfbKeyboardMaskShift 1 +#define rfbKeyboardMaskCapsLock 2 +#define rfbKeyboardMaskControl 4 +#define rfbKeyboardMaskAlt 8 +#define rfbKeyboardMaskMeta 16 +#define rfbKeyboardMaskSuper 32 +#define rfbKeyboardMaskHyper 64 +#define rfbKeyboardMaskNumLock 128 +#define rfbKeyboardMaskScrollLock 256 +#define rfbKeyboardMaskAltGraph 512 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CopyRect Encoding. The pixels are specified simply by the x and y position + * of the source rectangle. + */ + +typedef struct { + uint16_t srcX; + uint16_t srcY; +} rfbCopyRect; + +#define sz_rfbCopyRect 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure + * giving the number of subrectangles following. Finally the data follows in + * the form [...] where each is + * []. + */ + +typedef struct { + uint32_t nSubrects; +} rfbRREHeader; + +#define sz_rfbRREHeader 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving + * the number of subrectangles following. Finally the data follows in the form + * [...] where each is + * []. This means that + * the whole rectangle must be at most 255x255 pixels. + */ + +typedef struct { + uint8_t x; + uint8_t y; + uint8_t w; + uint8_t h; +} rfbCoRRERectangle; + +#define sz_rfbCoRRERectangle 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, + * starting at the top left going in left-to-right, top-to-bottom order. If + * the width of the rectangle is not an exact multiple of 16 then the width of + * the last tile in each row will be correspondingly smaller. Similarly if the + * height is not an exact multiple of 16 then the height of each tile in the + * final row will also be smaller. Each tile begins with a "subencoding" type + * byte, which is a mask made up of a number of bits. If the Raw bit is set + * then the other bits are irrelevant; w*h pixel values follow (where w and h + * are the width and height of the tile). Otherwise the tile is encoded in a + * similar way to RRE, except that the position and size of each subrectangle + * can be specified in just two bytes. The other bits in the mask are as + * follows: + * + * BackgroundSpecified - if set, a pixel value follows which specifies + * the background colour for this tile. The first non-raw tile in a + * rectangle must have this bit set. If this bit isn't set then the + * background is the same as the last tile. + * + * ForegroundSpecified - if set, a pixel value follows which specifies + * the foreground colour to be used for all subrectangles in this tile. + * If this bit is set then the SubrectsColoured bit must be zero. + * + * AnySubrects - if set, a single byte follows giving the number of + * subrectangles following. If not set, there are no subrectangles (i.e. + * the whole tile is just solid background colour). + * + * SubrectsColoured - if set then each subrectangle is preceded by a pixel + * value giving the colour of that subrectangle. If not set, all + * subrectangles are the same colour, the foreground colour; if the + * ForegroundSpecified bit wasn't set then the foreground is the same as + * the last tile. + * + * The position and size of each subrectangle is specified in two bytes. The + * Pack macros below can be used to generate the two bytes from x, y, w, h, + * and the Extract macros can be used to extract the x, y, w, h values from + * the two bytes. + */ + +#define rfbHextileRaw (1 << 0) +#define rfbHextileBackgroundSpecified (1 << 1) +#define rfbHextileForegroundSpecified (1 << 2) +#define rfbHextileAnySubrects (1 << 3) +#define rfbHextileSubrectsColoured (1 << 4) + +#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) +#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) +#define rfbHextileExtractX(byte) ((byte) >> 4) +#define rfbHextileExtractY(byte) ((byte) & 0xf) +#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) +#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * zlib - zlib compressed Encoding. We have an rfbZlibHeader structure + * giving the number of bytes following. Finally the data follows is + * zlib compressed version of the raw pixel data as negotiated. + * (NOTE: also used by Ultra Encoding) + */ + +typedef struct { + uint32_t nBytes; +} rfbZlibHeader; + +#define sz_rfbZlibHeader 4 + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Tight and TightPng Encoding. + * + *-- TightPng is like Tight but basic compression is not used, instead PNG + * data is sent. + * + *-- The first byte of each Tight-encoded rectangle is a "compression control + * byte". Its format is as follows (bit 0 is the least significant one): + * + * bit 0: if 1, then compression stream 0 should be reset; + * bit 1: if 1, then compression stream 1 should be reset; + * bit 2: if 1, then compression stream 2 should be reset; + * bit 3: if 1, then compression stream 3 should be reset; + * bits 7-4: if 1000 (0x08), then the compression type is "fill", + * if 1001 (0x09), then the compression type is "jpeg", + * if 1001 (0x0A), then the compression type is "png", + * if 0xxx, then the compression type is "basic", + * values greater than 1010 are not valid. + * + * If the compression type is "basic", then bits 6..4 of the + * compression control byte (those xxx in 0xxx) specify the following: + * + * bits 5-4: decimal representation is the index of a particular zlib + * stream which should be used for decompressing the data; + * bit 6: if 1, then a "filter id" byte is following this byte. + * + *-- The data that follows after the compression control byte described + * above depends on the compression type ("fill", "jpeg", "png" or "basic"). + * + *-- If the compression type is "fill", then the only pixel value follows, in + * client pixel format (see NOTE 1). This value applies to all pixels of the + * rectangle. + * + *-- If the compression type is "jpeg" or "png", the following data stream + * looks like this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: JPEG or PNG image. + * + * Data size is compactly represented in one, two or three bytes, according + * to the following scheme: + * + * 0xxxxxxx (for values 0..127) + * 1xxxxxxx 0yyyyyyy (for values 128..16383) + * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) + * + * Here each character denotes one bit, xxxxxxx are the least significant 7 + * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the + * most significant 8 bits (bits 14-21). For example, decimal value 10000 + * should be represented as two bytes: binary 10010000 01001110, or + * hexadecimal 90 4E. + * + *-- If the compression type is "basic" and bit 6 of the compression control + * byte was set to 1, then the next (second) byte specifies "filter id" which + * tells the decoder what filter type was used by the encoder to pre-process + * pixel data before the compression. The "filter id" byte can be one of the + * following: + * + * 0: no filter ("copy" filter); + * 1: "palette" filter; + * 2: "gradient" filter. + * + *-- If bit 6 of the compression control byte is set to 0 (no "filter id" + * byte), or if the filter id is 0, then raw pixel values in the client + * format (see NOTE 1) will be compressed. See below details on the + * compression. + * + *-- The "gradient" filter pre-processes pixel data with a simple algorithm + * which converts each color component to a difference between a "predicted" + * intensity and the actual intensity. Such a technique does not affect + * uncompressed data size, but helps to compress photo-like images better. + * Pseudo-code for converting intensities to differences is the following: + * + * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; + * if (P[i,j] < 0) then P[i,j] := 0; + * if (P[i,j] > MAX) then P[i,j] := MAX; + * D[i,j] := V[i,j] - P[i,j]; + * + * Here V[i,j] is the intensity of a color component for a pixel at + * coordinates (i,j). MAX is the maximum value of intensity for a color + * component. + * + *-- The "palette" filter converts true-color pixel data to indexed colors + * and a palette which can consist of 2..256 colors. If the number of colors + * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to + * encode one pixel. 1-bit encoding is performed such way that the most + * significant bits correspond to the leftmost pixels, and each raw of pixels + * is aligned to the byte boundary. When "palette" filter is used, the + * palette is sent before the pixel data. The palette begins with an unsigned + * byte which value is the number of colors in the palette minus 1 (i.e. 1 + * means 2 colors, 255 means 256 colors in the palette). Then follows the + * palette itself which consist of pixel values in client pixel format (see + * NOTE 1). + * + *-- The pixel data is compressed using the zlib library. But if the data + * size after applying the filter but before the compression is less then 12, + * then the data is sent as is, uncompressed. Four separate zlib streams + * (0..3) can be used and the decoder should read the actual stream id from + * the compression control byte (see NOTE 2). + * + * If the compression is not used, then the pixel data is sent as is, + * otherwise the data stream looks like this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: zlib-compressed data. + * + * Data size is compactly represented in one, two or three bytes, just like + * in the "jpeg" compression method (see above). + * + *-- NOTE 1. If the color depth is 24, and all three color components are + * 8-bit wide, then one pixel in Tight encoding is always represented by + * three bytes, where the first byte is red component, the second byte is + * green component, and the third byte is blue component of the pixel color + * value. This applies to colors in palettes as well. + * + *-- NOTE 2. The decoder must reset compression streams' states before + * decoding the rectangle, if some of bits 0,1,2,3 in the compression control + * byte are set to 1. Note that the decoder must reset zlib streams even if + * the compression type is "fill", "jpeg" or "png". + * + *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only + * when bits-per-pixel value is either 16 or 32, not 8. + * + *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 + * pixels. If a rectangle is wider, it must be split into several rectangles + * and each one should be encoded separately. + * + */ + +#define rfbTightExplicitFilter 0x04 +#define rfbTightFill 0x08 +#define rfbTightJpeg 0x09 +#define rfbTightPng 0x0A +#define rfbTightMaxSubencoding 0x0A + +/* Filters to improve compression efficiency */ +#define rfbTightFilterCopy 0x00 +#define rfbTightFilterPalette 0x01 +#define rfbTightFilterGradient 0x02 + +#endif + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * XCursor encoding. This is a special encoding used to transmit X-style + * cursor shapes from server to clients. Note that for this encoding, + * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot + * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB + * samples are sent after header in the rfbXCursorColors structure. They + * denote foreground and background colors of the cursor. If a client + * supports only black-and-white cursors, it should ignore these colors and + * assume that foreground is black and background is white. Next, two bitmaps + * (1 bits per pixel) follow: first one with actual data (value 0 denotes + * background color, value 1 denotes foreground color), second one with + * transparency data (bits with zero value mean that these pixels are + * transparent). Both bitmaps represent cursor data in a byte stream, from + * left to right, from top to bottom, and each row is byte-aligned. Most + * significant bits correspond to leftmost pixels. The number of bytes in + * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor + * should be hidden (or default local cursor should be set by the client). + */ + +typedef struct { + uint8_t foreRed; + uint8_t foreGreen; + uint8_t foreBlue; + uint8_t backRed; + uint8_t backGreen; + uint8_t backBlue; +} rfbXCursorColors; + +#define sz_rfbXCursorColors 6 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RichCursor encoding. This is a special encoding used to transmit cursor + * shapes from server to clients. It is similar to the XCursor encoding but + * uses client pixel format instead of two RGB colors to represent cursor + * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader + * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). + * After header, two pixmaps follow: first one with cursor image in current + * client pixel format (like in raw encoding), second with transparency data + * (1 bit per pixel, exactly the same format as used for transparency bitmap + * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or + * default local cursor should be set by the client). + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZRLE - encoding combining Zlib compression, tiling, palettisation and + * run-length encoding. + */ + +typedef struct { + uint32_t length; +} rfbZRLEHeader; + +#define sz_rfbZRLEHeader 4 + +#define rfbZRLETileWidth 64 +#define rfbZRLETileHeight 64 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the + * hextile encoding with zlib compression on the tiles that can not be + * efficiently encoded with one of the other hextile subencodings. The + * new zlib subencoding uses two bytes to specify the length of the + * compressed tile and then the compressed data follows. As with the + * raw sub-encoding, the zlib subencoding invalidates the other + * values, if they are also set. + */ + +#define rfbHextileZlibRaw (1 << 5) +#define rfbHextileZlibHex (1 << 6) +#define rfbHextileZlibMono (1 << 7) + + +/*----------------------------------------------------------------------------- + * SetColourMapEntries - these messages are only sent if the pixel + * format uses a "colour map" (i.e. trueColour false) and the client has not + * fixed the entire colour map using FixColourMapEntries. In addition they + * will only start being sent after the client has sent its first + * FramebufferUpdateRequest. So if the client always tells the server to use + * trueColour then it never needs to process this type of message. + */ + +typedef struct { + uint8_t type; /* always rfbSetColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbSetColourMapEntriesMsg; + +#define sz_rfbSetColourMapEntriesMsg 6 + + + +/*----------------------------------------------------------------------------- + * Bell - ring a bell on the client if it has one. + */ + +typedef struct { + uint8_t type; /* always rfbBell */ +} rfbBellMsg; + +#define sz_rfbBellMsg 1 + + + +/*----------------------------------------------------------------------------- + * ServerCutText - the server has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbServerCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbServerCutTextMsg; + +#define sz_rfbServerCutTextMsg 8 + + +/*----------------------------------------------------------------------------- + * // Modif sf@2002 + * FileTransferMsg - The client sends FileTransfer message. + * Bidirectional message - Files can be sent from client to server & vice versa + */ + +typedef struct _rfbFileTransferMsg { + uint8_t type; /* always rfbFileTransfer */ + uint8_t contentType; /* See defines below */ + uint8_t contentParam;/* Other possible content classification (Dir or File name, etc..) */ + uint8_t pad; /* It appears that UltraVNC *forgot* to Swap16IfLE(contentParam) */ + uint32_t size; /* FileSize or packet index or error or other */ +/* uint32_t sizeH; Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions) */ + uint32_t length; + /* followed by data char text[length] */ +} rfbFileTransferMsg; + +#define sz_rfbFileTransferMsg 12 + +#define rfbFileTransferVersion 2 /* v1 is the old FT version ( <= 1.0.0 RC18 versions) */ + +/* FileTransfer Content types and Params defines */ +#define rfbDirContentRequest 1 /* Client asks for the content of a given Server directory */ +#define rfbDirPacket 2 /* Full directory name or full file name. */ + /* Null content means end of Directory */ +#define rfbFileTransferRequest 3 /* Client asks the server for the transfer of a given file */ +#define rfbFileHeader 4 /* First packet of a file transfer, containing file's features */ +#define rfbFilePacket 5 /* One chunk of the file */ +#define rfbEndOfFile 6 /* End of file transfer (the file has been received or error) */ +#define rfbAbortFileTransfer 7 /* The file transfer must be aborted, whatever the state */ +#define rfbFileTransferOffer 8 /* The client offers to send a file to the server */ +#define rfbFileAcceptHeader 9 /* The server accepts or rejects the file */ +#define rfbCommand 10 /* The Client sends a simple command (File Delete, Dir create etc...) */ +#define rfbCommandReturn 11 /* The Client receives the server's answer about a simple command */ +#define rfbFileChecksums 12 /* The zipped checksums of the destination file (Delta Transfer) */ +#define rfbFileTransferAccess 14 /* Request FileTransfer authorization */ + + /* rfbDirContentRequest client Request - content params */ +#define rfbRDirContent 1 /* Request a Server Directory contents */ +#define rfbRDrivesList 2 /* Request the server's drives list */ +#define rfbRDirRecursiveList 3 /* Request a server directory content recursive sorted list */ +#define rfbRDirRecursiveSize 4 /* Request a server directory content recursive size */ + + /* rfbDirPacket & rfbCommandReturn server Answer - content params */ +#define rfbADirectory 1 /* Reception of a directory name */ +#define rfbAFile 2 /* Reception of a file name */ +#define rfbADrivesList 3 /* Reception of a list of drives */ +#define rfbADirCreate 4 /* Response to a create dir command */ +#define rfbADirDelete 5 /* Response to a delete dir command */ +#define rfbAFileCreate 6 /* Response to a create file command */ +#define rfbAFileDelete 7 /* Response to a delete file command */ +#define rfbAFileRename 8 /* Response to a rename file command */ +#define rfbADirRename 9 /* Response to a rename dir command */ +#define rfbADirRecursiveListItem 10 +#define rfbADirRecursiveSize 11 + + /* rfbCommand Command - content params */ +#define rfbCDirCreate 1 /* Request the server to create the given directory */ +#define rfbCDirDelete 2 /* Request the server to delete the given directory */ +#define rfbCFileCreate 3 /* Request the server to create the given file */ +#define rfbCFileDelete 4 /* Request the server to delete the given file */ +#define rfbCFileRename 5 /* Request the server to rename the given file */ +#define rfbCDirRename 6 /* Request the server to rename the given directory */ + + /* Errors - content params or "size" field */ +#define rfbRErrorUnknownCmd 1 /* Unknown FileTransfer command. */ +#define rfbRErrorCmd 0xFFFFFFFF/* Error when a command fails on remote side (ret in "size" field) */ + +#define sz_rfbBlockSize 8192 /* Size of a File Transfer packet (before compression) */ +#define rfbZipDirectoryPrefix "!UVNCDIR-\0" /* Transfered directory are zipped in a file with this prefix. Must end with "-" */ +#define sz_rfbZipDirectoryPrefix 9 +#define rfbDirPrefix "[ " +#define rfbDirSuffix " ]" + + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * TextChatMsg - Utilized to order the TextChat mode on server or client + * Bidirectional message + */ + +typedef struct _rfbTextChatMsg { + uint8_t type; /* always rfbTextChat */ + uint8_t pad1; /* Could be used later as an additionnal param */ + uint16_t pad2; /* Could be used later as text offset, for instance */ + uint32_t length; /* Specific values for Open, close, finished (-1, -2, -3) */ + /* followed by char text[length] */ +} rfbTextChatMsg; + +#define sz_rfbTextChatMsg 8 + +#define rfbTextMaxSize 4096 +#define rfbTextChatOpen 0xFFFFFFFF +#define rfbTextChatClose 0xFFFFFFFE +#define rfbTextChatFinished 0xFFFFFFFD + + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * ResizeFrameBuffer - The Client must change the size of its framebuffer + */ + +typedef struct _rfbResizeFrameBufferMsg { + uint8_t type; /* always rfbResizeFrameBuffer */ + uint8_t pad1; + uint16_t framebufferWidth; /* FrameBuffer width */ + uint16_t framebufferHeigth; /* FrameBuffer height */ +} rfbResizeFrameBufferMsg; + +#define sz_rfbResizeFrameBufferMsg 6 + + +/*----------------------------------------------------------------------------- + * Copyright (C) 2001 Harakan Software + * PalmVNC 1.4 & 2.? ResizeFrameBuffer message + * ReSizeFrameBuffer - tell the RFB client to alter its framebuffer, either + * due to a resize of the server desktop or a client-requested scaling factor. + * The pixel format remains unchanged. + */ + +typedef struct { + uint8_t type; /* always rfbReSizeFrameBuffer */ + uint8_t pad1; + uint16_t desktop_w; /* Desktop width */ + uint16_t desktop_h; /* Desktop height */ + uint16_t buffer_w; /* FrameBuffer width */ + uint16_t buffer_h; /* Framebuffer height */ + uint16_t pad2; + +} rfbPalmVNCReSizeFrameBufferMsg; + +#define sz_rfbPalmVNCReSizeFrameBufferMsg (12) + + + + +/*----------------------------------------------------------------------------- + * Union of all server->client messages. + */ + +typedef union { + uint8_t type; + rfbFramebufferUpdateMsg fu; + rfbSetColourMapEntriesMsg scme; + rfbBellMsg b; + rfbServerCutTextMsg sct; + rfbResizeFrameBufferMsg rsfb; + rfbPalmVNCReSizeFrameBufferMsg prsfb; + rfbFileTransferMsg ft; + rfbTextChatMsg tc; +} rfbServerToClientMsg; + + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RDV Cache Encoding. + * special is not used at this point, can be used to reset cache or other specials + * just put it to make sure we don't have to change the encoding again. + */ + +typedef struct { + uint16_t special; +} rfbCacheRect; + +#define sz_rfbCacheRect 2 + + + + +/***************************************************************************** + * + * Message definitions (client -> server) + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * SetPixelFormat - tell the RFB server the format in which the client wants + * pixels sent. + */ + +typedef struct { + uint8_t type; /* always rfbSetPixelFormat */ + uint8_t pad1; + uint16_t pad2; + rfbPixelFormat format; +} rfbSetPixelFormatMsg; + +#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) + + +/*----------------------------------------------------------------------------- + * FixColourMapEntries - when the pixel format uses a "colour map", fix + * read-only colour map entries. + * + * ***************** NOT CURRENTLY SUPPORTED ***************** + */ + +typedef struct { + uint8_t type; /* always rfbFixColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbFixColourMapEntriesMsg; + +#define sz_rfbFixColourMapEntriesMsg 6 + + +/*----------------------------------------------------------------------------- + * SetEncodings - tell the RFB server which encoding types we accept. Put them + * in order of preference, if we have any. We may always receive raw + * encoding, even if we don't specify it here. + */ + +typedef struct { + uint8_t type; /* always rfbSetEncodings */ + uint8_t pad; + uint16_t nEncodings; + /* followed by nEncodings * uint32_t encoding types */ +} rfbSetEncodingsMsg; + +#define sz_rfbSetEncodingsMsg 4 + + +/*----------------------------------------------------------------------------- + * FramebufferUpdateRequest - request for a framebuffer update. If incremental + * is true then the client just wants the changes since the last update. If + * false then it wants the whole of the specified rectangle. + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdateRequest */ + uint8_t incremental; + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbFramebufferUpdateRequestMsg; + +#define sz_rfbFramebufferUpdateRequestMsg 10 + + +/*----------------------------------------------------------------------------- + * KeyEvent - key press or release + * + * Keys are specified using the "keysym" values defined by the X Window System. + * For most ordinary keys, the keysym is the same as the corresponding ASCII + * value. Other common keys are: + * + * BackSpace 0xff08 + * Tab 0xff09 + * Return or Enter 0xff0d + * Escape 0xff1b + * Insert 0xff63 + * Delete 0xffff + * Home 0xff50 + * End 0xff57 + * Page Up 0xff55 + * Page Down 0xff56 + * Left 0xff51 + * Up 0xff52 + * Right 0xff53 + * Down 0xff54 + * F1 0xffbe + * F2 0xffbf + * ... ... + * F12 0xffc9 + * Shift 0xffe1 + * Control 0xffe3 + * Meta 0xffe7 + * Alt 0xffe9 + */ + +typedef struct { + uint8_t type; /* always rfbKeyEvent */ + uint8_t down; /* true if down (press), false if up */ + uint16_t pad; + uint32_t key; /* key is specified as an X keysym */ +} rfbKeyEventMsg; + +#define sz_rfbKeyEventMsg 8 + + +/*----------------------------------------------------------------------------- + * PointerEvent - mouse/pen move and/or button press. + */ + +typedef struct { + uint8_t type; /* always rfbPointerEvent */ + uint8_t buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ + uint16_t x; + uint16_t y; +} rfbPointerEventMsg; + +#define rfbButton1Mask 1 +#define rfbButton2Mask 2 +#define rfbButton3Mask 4 +#define rfbButton4Mask 8 +#define rfbButton5Mask 16 +/* RealVNC 335 method */ +#define rfbWheelUpMask rfbButton4Mask +#define rfbWheelDownMask rfbButton5Mask + +#define sz_rfbPointerEventMsg 6 + + + +/*----------------------------------------------------------------------------- + * ClientCutText - the client has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbClientCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbClientCutTextMsg; + +#define sz_rfbClientCutTextMsg 8 + + + +/*----------------------------------------------------------------------------- + * sf@2002 - Set Server Scale + * SetServerScale - Server must change the scale of the client buffer. + */ + +typedef struct _rfbSetScaleMsg { + uint8_t type; /* always rfbSetScale */ + uint8_t scale; /* Scale value 1server messages. + */ + +typedef union { + uint8_t type; + rfbSetPixelFormatMsg spf; + rfbFixColourMapEntriesMsg fcme; + rfbSetEncodingsMsg se; + rfbFramebufferUpdateRequestMsg fur; + rfbKeyEventMsg ke; + rfbPointerEventMsg pe; + rfbClientCutTextMsg cct; + rfbSetScaleMsg ssc; + rfbPalmVNCSetScaleFactorMsg pssf; + rfbSetServerInputMsg sim; + rfbFileTransferMsg ft; + rfbSetSWMsg sw; + rfbTextChatMsg tc; +} rfbClientToServerMsg; + +/* + * vncauth.h - describes the functions provided by the vncauth library. + */ + +#define MAXPWLEN 8 +#define CHALLENGESIZE 16 + +extern int rfbEncryptAndStorePasswd(char *passwd, char *fname); +extern char *rfbDecryptPasswdFromFile(char *fname); +extern void rfbRandomBytes(unsigned char *bytes); +extern void rfbEncryptBytes(unsigned char *bytes, char *passwd); + + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbregion.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbregion.h new file mode 100755 index 0000000..53da667 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbregion.h @@ -0,0 +1,65 @@ +#ifndef SRAREGION_H +#define SRAREGION_H + +/* -=- SRA - Simple Region Algorithm + * A simple rectangular region implementation. + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + */ + +/* -=- sraRect */ + +typedef struct _rect { + int x1; + int y1; + int x2; + int y2; +} sraRect; + +typedef struct sraRegion sraRegion; + +/* -=- Region manipulation functions */ + +extern sraRegion *sraRgnCreate(); +extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2); +extern sraRegion *sraRgnCreateRgn(const sraRegion *src); + +extern void sraRgnDestroy(sraRegion *rgn); +extern void sraRgnMakeEmpty(sraRegion *rgn); +extern rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src); +extern void sraRgnOr(sraRegion *dst, const sraRegion *src); +extern rfbBool sraRgnSubtract(sraRegion *dst, const sraRegion *src); + +extern void sraRgnOffset(sraRegion *dst, int dx, int dy); + +extern rfbBool sraRgnPopRect(sraRegion *region, sraRect *rect, + unsigned long flags); + +extern unsigned long sraRgnCountRects(const sraRegion *rgn); +extern rfbBool sraRgnEmpty(const sraRegion *rgn); + +extern sraRegion *sraRgnBBox(const sraRegion *src); + +/* -=- rectangle iterator */ + +typedef struct sraRectangleIterator { + rfbBool reverseX,reverseY; + int ptrSize,ptrPos; + struct sraSpan** sPtrs; +} sraRectangleIterator; + +extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s); +extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY); +extern rfbBool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r); +extern void sraRgnReleaseIterator(sraRectangleIterator *i); + +void sraRgnPrint(const sraRegion *s); + +/* -=- Rectangle clipper (for speed) */ + +extern rfbBool sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch); + +extern rfbBool sraClipRect2(int *x, int *y, int *x2, int *y2, + int cx, int cy, int cx2, int cy2); + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/success.html b/droidvncgrab/vnc/libvncserver-kanaka/success.html new file mode 100755 index 0000000..45caf18 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/success.html @@ -0,0 +1,45 @@ + + +Success stories + + +
    +
  • +Karl Runge took my first version of +x11vnc, which was just a proof-of-concept that the library actually is +usable, and turned it into a +fully fledged application. +
  • +Tim Jansen created KRFB, which is +x11vnc integrated into KDE. +
  • +Jeff Mock of the world's largest radio telescope +in Arecibo sent me a nice +screenshot, +describing his use of LibVNCServer: + +

    + +I've been using it for about 4 months +on a project to build a new spectrometer for the radio telescope at +Arecibo. Arecibo is the largest radio telescope in the world (305m!) in +Puerto Rico. It has 10-times the collecting area of the second largest +telescope in Effelsburg (maybe near you?). + +

    + +The project is an embedded linux box that boots from a compact flash +card. The root filesystem is only about 5MB. X wasn't reasonable +for such a small embedded system, but libvncserver was perfect. On +the console we run graphical diagnostics that write directly to the +frame buffer. It was a simple matter to hook this direct-framebuffer +application to libvncserver. This way we can easily view the +diagnostics for the spectrometer from the control room (or anyplace +else for that matter). + +

  • +michu let me know that +LCD4Linux has a VNC backend using LibVNCServer. + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/test/.cvsignore new file mode 100755 index 0000000..0c7b7d7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/.cvsignore @@ -0,0 +1,9 @@ +.deps +Makefile +Makefile.in +encodingstest +blooptest +cargstest +copyrecttest +cursortest + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/test/Makefile.am new file mode 100755 index 0000000..30498c2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = -I$(top_srcdir) +LDADD = ../libvncserver/libvncserver.la ../libvncclient/libvncclient.la @WSOCKLIB@ + +if HAVE_LIBPTHREAD +BACKGROUND_TEST=blooptest +ENCODINGS_TEST=encodingstest +endif + +copyrecttest_LDADD=$(LDADD) -lm + +check_PROGRAMS=$(ENCODINGS_TEST) cargstest copyrecttest $(BACKGROUND_TEST) \ + cursortest + +test: encodingstest$(EXEEXT) cargstest$(EXEEXT) copyrecttest$(EXEEXT) + ./encodingstest && ./cargstest + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/blooptest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/blooptest.c new file mode 100755 index 0000000..a2661e8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/blooptest.c @@ -0,0 +1,2 @@ +#define BACKGROUND_LOOP_TEST +#include "../examples/example.c" diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/cargstest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/cargstest.c new file mode 100755 index 0000000..263982d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/cargstest.c @@ -0,0 +1,29 @@ +#include + +int main(int argc,char** argv) +{ + int fake_argc=6; + char* fake_argv[6]={ + "dummy_program","-alwaysshared","-httpport","3002","-nothing","-dontdisconnect" + }; + rfbScreenInfoPtr screen; + rfbBool ret=0; + + screen = rfbGetScreen(&fake_argc,fake_argv,1024,768,8,3,1); +#define CHECK(a,b) if(screen->a!=b) { fprintf(stderr,#a " is %d (should be " #b ")\n",screen->a); ret=1; } + CHECK(width,1024); + CHECK(height,768); + CHECK(alwaysShared,TRUE); + CHECK(httpPort,3002); + CHECK(dontDisconnect,TRUE); + if(fake_argc!=2) { + fprintf(stderr,"fake_argc is %d (should be 2)\n",fake_argc); + ret=1; + } + if(strcmp(fake_argv[1],"-nothing")) { + fprintf(stderr,"fake_argv[1] is %s (should be -nothing)\n",fake_argv[1]); + ret=1; + } + return ret; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/copyrecttest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/copyrecttest.c new file mode 100755 index 0000000..5521595 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/copyrecttest.c @@ -0,0 +1,53 @@ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include + +static void initBackground(rfbScreenInfoPtr server) +{ + unsigned int i,j; + + for(i=0;iwidth;i++) + for(j=0;jheight;j++) { + server->frameBuffer[(j*server->width+i)*4+0]=i&0xff; + server->frameBuffer[(j*server->width+i)*4+1]=j&0xff; + server->frameBuffer[(j*server->width+i)*4+2]=(i*j)&0xff; + } +} + +int main(int argc,char** argv) +{ + int width=400,height=300,w=20,x,y; + double r,phi=0; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,width,height,8,3,4); + server->frameBuffer=(char*)malloc(width*height*4); + initBackground(server); + server->deferUpdateTime=0; + rfbInitServer(server); + + r=0; + while(1) { + if(r<=0) { + initBackground(server); + rfbMarkRectAsModified(server,0,0,width,height); + r=0.43; + phi=0; + } else { + r-=0.0001; + phi+=0.02; + if(phi>2*M_PI) + phi-=2*M_PI; + } + x=width*(0.5+cos(phi)*r); + y=height*(0.5+sin(phi)*r); + if(x>=0 && y>=0 && x+w<=width && y+w<=height) { + unsigned int dx=width*0.5*(1-cos(phi)*r)-x, + dy=height*0.5*(1-sin(phi)*r)-y; + rfbDoCopyRect(server,x,y,x+w,y+w,-dx,-dy); + } + rfbProcessEvents(server,50000); + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/cursortest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/cursortest.c new file mode 100755 index 0000000..7a4efd3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/cursortest.c @@ -0,0 +1,351 @@ +/* + * + * This is an example of how to use libvncserver. + * + * libvncserver example + * Copyright (C) 2005 Johannes E. Schindelin , + * Karl Runge + * + * 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 + +static const int bpp=4; +static int maxx=800, maxy=600; + +/* This initializes a nice (?) background */ + +static void initBuffer(unsigned char* buffer) +{ + int i,j; + for(j=0;jxhot=width/2;c->yhot=height/2; + + rfbSetCursor(rfbScreen, c); +} + +static void SetXCursor2(rfbScreenInfoPtr rfbScreen) +{ + int width=13,height=22; + char cursor[]= + " xx " + " x x " + " x x " + " x x " + " x x " + " x x " + " x x " + " x x " + " x xx x " + " x x x xxx " + " x xx x x " + " xx x x " + " xx x x " + " x x x " + " x x x " + " x x " + " x x " + " x x " + " xx " + " " + " ", + mask[]= + "xxx " + "xxxx " + "xxxxx " + "xxxxxx " + "xxxxxxx " + "xxxxxxxx " + "xxxxxxxxx " + "xxxxxxxxxx " + "xxxxxxxxxxx " + "xxxxxxxxxxxx " + "xxxxxxxxxxxxx" + "xxxxxxxxxxxxx" + "xxxxxxxxxx x" + "xxxxxxxxxx " + "xxx xxxxxx " + "xxx xxxxxx " + "xx xxxxxx " + " xxxxx " + " xxxxxx" + " xxxxx" + " xxx " + " "; + rfbCursorPtr c; + + c=rfbMakeXCursor(width,height,cursor,mask); + c->xhot=0;c->yhot=0; + + rfbSetCursor(rfbScreen, c); +} + +/* Example for a rich cursor (full-colour) */ + +static void SetRichCursor(rfbScreenInfoPtr rfbScreen) +{ + int i,j,w=32,h=32; + /* runge */ + /* rfbCursorPtr c = rfbScreen->cursor; */ + rfbCursorPtr c; + char bitmap[]= + " " + " xxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxx xxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxx xxxxxxxxx xxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxx xxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxx xxxxxxxxxxxxxx " + " xxxxxxxxxx xxxxxxxxxxxx " + " xxxxxxxxx xxxxxxxxx " + " xxxxxxxxxx xxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxx " + " xxxx xxxxxxxxxxxxx " + " xx x xxxxxxxxxxx " + " xxx xxxxxxxxxxx " + " xxxx xxxxxxxxxxx " + " xxxxxx xxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxx " + " "; + + c=rfbMakeXCursor(w,h,bitmap,bitmap); + c->xhot = 16; c->yhot = 24; + + c->richSource = (char*)malloc(w*h*bpp); + for(j=0;jrichSource[j*w*bpp+i*bpp+0]=i*0xff/w; + c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h); + c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h; + c->richSource[j*w*bpp+i*bpp+3]=0; + } + } + rfbSetCursor(rfbScreen, c); +} + +/* runge */ +static void SetRichCursor2(rfbScreenInfoPtr rfbScreen) +{ + int i,j,w=17,h=16; + /* rfbCursorPtr c = rfbScreen->cursor; */ + rfbCursorPtr c; + char bitmap[]= + " " + "xxxx " + "xxxxxxxx " + "xxxxxxxxxxxx x" + "xxx xxxxxxxx x" + "xxxxxxxxxxxxxx x" + "xxxxxxxxxxxxxxx x" + "xxxxx xxxxxxx x" + "xxxx xxxxxx x" + "xxxxx xxxxxxx x" + "xxxxxxxxxxxxxxx x" + "xxxxxxxxxxxxxxx x" + "xxxxxxxxxxxxxx x" + "xxxxxxxxxxxxx x" + "xxxxxxxxxxxxx x" + "xxxxxxxxxxxxx x"; + /* c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap); */ + c=rfbMakeXCursor(w,h,bitmap,bitmap); + c->xhot = 5; c->yhot = 7; + + c->richSource = (char*)malloc(w*h*bpp); + for(j=0;jrichSource[j*w*bpp+i*bpp+0]=0xff; + c->richSource[j*w*bpp+i*bpp+1]=0x00; + c->richSource[j*w*bpp+i*bpp+2]=0x7f; + c->richSource[j*w*bpp+i*bpp+3]=0; + } + } + rfbSetCursor(rfbScreen, c); +} + +/* alpha channel */ + +static void SetAlphaCursor(rfbScreenInfoPtr screen,int mode) +{ + int i,j; + rfbCursorPtr c = screen->cursor; + int maskStride=(c->width+7)/8; + + if(!c) + return; + + if(c->alphaSource) { + free(c->alphaSource); + c->alphaSource=NULL; + } + + if(mode==0) + return; + + c->alphaSource = (unsigned char*)malloc(c->width*c->height); + + for(j=0;jheight;j++) + for(i=0;iwidth;i++) { + unsigned char value=0x100*i/c->width; + rfbBool masked=(c->mask[(i/8)+maskStride*j]<<(i&7))&0x80; + c->alphaSource[i+c->width*j]=(masked?(mode==1?value:0xff-value):0); + } + if(c->cleanupMask) + free(c->mask); + c->mask=rfbMakeMaskFromAlphaSource(c->width,c->height,c->alphaSource); + c->cleanupMask=TRUE; +} + +/* Here the pointer events are handled */ + +static void doptr(int buttonMask,int x,int y,rfbClientPtr cl) +{ + static int oldButtonMask=0; + static int counter=0; + + if((oldButtonMask&1)==0 && (buttonMask&1)==1) { + switch(++counter) { + case 7: + SetRichCursor(cl->screen); + SetAlphaCursor(cl->screen,2); + break; + case 6: + SetRichCursor(cl->screen); + SetAlphaCursor(cl->screen,1); + break; + case 5: + SetRichCursor2(cl->screen); + SetAlphaCursor(cl->screen,0); + break; + case 4: + SetXCursor(cl->screen); + break; + case 3: + SetRichCursor2(cl->screen); + SetAlphaCursor(cl->screen,2); + break; + case 2: + SetXCursor(cl->screen); + SetAlphaCursor(cl->screen,2); + break; + case 1: + SetXCursor2(cl->screen); + SetAlphaCursor(cl->screen,0); + break; + default: + SetRichCursor(cl->screen); + counter=0; + } + } + if(buttonMask&2) { + rfbScreenCleanup(cl->screen); + exit(0); + } + + if(buttonMask&4) + rfbCloseClient(cl); + + + oldButtonMask=buttonMask; + + rfbDefaultPtrAddEvent(buttonMask,x,y,cl); +} + +/* Initialization */ + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr rfbScreen = + rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp); + rfbScreen->desktopName = "Cursor Test"; + rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp); + rfbScreen->ptrAddEvent = doptr; + + initBuffer((unsigned char*)rfbScreen->frameBuffer); + + + SetRichCursor(rfbScreen); + + /* initialize the server */ + rfbInitServer(rfbScreen); + + rfbLog("Change cursor shape with left mouse button,\n\t" + "quit with right one (middle button quits server).\n"); + + /* this is the blocking event loop, i.e. it never returns */ + /* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */ + rfbRunEventLoop(rfbScreen,40000,FALSE); + + free(rfbScreen->frameBuffer); + rfbScreenCleanup(rfbScreen); + + return(0); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/encodingstest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/encodingstest.c new file mode 100755 index 0000000..bef30a8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/encodingstest.c @@ -0,0 +1,353 @@ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include + +#ifndef LIBVNCSERVER_HAVE_LIBPTHREAD +#error This test need pthread support (otherwise the client blocks the client) +#endif + +#define ALL_AT_ONCE +/*#define VERY_VERBOSE*/ + +static MUTEX(frameBufferMutex); + +typedef struct { int id; char* str; } encoding_t; +static encoding_t testEncodings[]={ + { rfbEncodingRaw, "raw" }, + { rfbEncodingRRE, "rre" }, + /* TODO: fix corre */ + /* { rfbEncodingCoRRE, "corre" }, */ + { rfbEncodingHextile, "hextile" }, +#ifdef LIBVNCSERVER_HAVE_LIBZ + { rfbEncodingZlib, "zlib" }, + { rfbEncodingZlibHex, "zlibhex" }, + { rfbEncodingZRLE, "zrle" }, +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + { rfbEncodingTight, "tight" }, +#endif +#endif + { 0, NULL } +}; + +#define NUMBER_OF_ENCODINGS_TO_TEST (sizeof(testEncodings)/sizeof(encoding_t)-1) +/*#define NUMBER_OF_ENCODINGS_TO_TEST 1*/ + +/* Here come the variables/functions to handle the test output */ + +static const int width=400,height=300; +static struct { int x1,y1,x2,y2; } lastUpdateRect; +static unsigned int statistics[2][NUMBER_OF_ENCODINGS_TO_TEST]; +static unsigned int totalFailed,totalCount; +static unsigned int countGotUpdate; +static MUTEX(statisticsMutex); + +static void initStatistics(void) { + memset(statistics[0],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); + memset(statistics[1],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); + totalFailed=totalCount=0; + lastUpdateRect.x1=0; + lastUpdateRect.y1=0; + lastUpdateRect.x2=width; + lastUpdateRect.y2=height; + INIT_MUTEX(statisticsMutex); +} + +static void updateServerStatistics(int x1,int y1,int x2,int y2) { + LOCK(statisticsMutex); + countGotUpdate=0; + lastUpdateRect.x1=x1; + lastUpdateRect.y1=y1; + lastUpdateRect.x2=x2; + lastUpdateRect.y2=y2; + UNLOCK(statisticsMutex); +} + +static void updateStatistics(int encodingIndex,rfbBool failed) { + LOCK(statisticsMutex); + if(failed) { + statistics[1][encodingIndex]++; + totalFailed++; + } + statistics[0][encodingIndex]++; + totalCount++; + countGotUpdate++; + UNLOCK(statisticsMutex); +} + +/* Here begin the functions for the client. They will be called in a + * pthread. */ + +/* maxDelta=0 means they are expected to match exactly; + * maxDelta>0 means that the average difference must be lower than maxDelta */ +static rfbBool doFramebuffersMatch(rfbScreenInfo* server,rfbClient* client, + int maxDelta) +{ + int i,j,k; + unsigned int total=0,diff=0; + if(server->width!=client->width || server->height!=client->height) + return FALSE; + LOCK(frameBufferMutex); + /* TODO: write unit test for colour transformation, use here, too */ + for(i=0;iwidth;i++) + for(j=0;jheight;j++) + for(k=0;k<3/*server->serverFormat.bitsPerPixel/8*/;k++) { + unsigned char s=server->frameBuffer[k+i*4+j*server->paddedWidthInBytes]; + unsigned char cl=client->frameBuffer[k+i*4+j*client->width*4]; + + if(maxDelta==0 && s!=cl) { + UNLOCK(frameBufferMutex); + return FALSE; + } else { + total++; + diff+=(s>cl?s-cl:cl-s); + } + } + UNLOCK(frameBufferMutex); + if(maxDelta>0 && diff/total>=maxDelta) + return FALSE; + return TRUE; +} + +static rfbBool resize(rfbClient* cl) { + if(cl->frameBuffer) + free(cl->frameBuffer); + cl->frameBuffer=(char*)malloc(cl->width*cl->height*cl->format.bitsPerPixel/8); + if(!cl->frameBuffer) + return FALSE; + SendFramebufferUpdateRequest(cl,0,0,cl->width,cl->height,FALSE); + return TRUE; +} + +typedef struct clientData { + int encodingIndex; + rfbScreenInfo* server; + char* display; +} clientData; + +static void update(rfbClient* client,int x,int y,int w,int h) { + clientData* cd=(clientData*)client->clientData; + int maxDelta=0; + +#ifndef VERY_VERBOSE + static const char* progress="|/-\\"; + static int counter=0; + + if(++counter>sizeof(progress)) counter=0; + fprintf(stderr,"%c\r",progress[counter]); +#else + rfbClientLog("Got update (encoding=%s): (%d,%d)-(%d,%d)\n", + testEncodings[cd->encodingIndex].str, + x,y,x+w,y+h); +#endif + + /* only check if this was the last update */ + if(x+w!=lastUpdateRect.x2 || y+h!=lastUpdateRect.y2) { +#ifdef VERY_VERBOSE + rfbClientLog("Waiting (%d!=%d or %d!=%d)\n", + x+w,lastUpdateRect.x2,y+h,lastUpdateRect.y2); +#endif + return; + } + +#ifdef LIBVNCSERVER_HAVE_LIBZ + if(testEncodings[cd->encodingIndex].id==rfbEncodingTight) + maxDelta=5; +#endif + + updateStatistics(cd->encodingIndex, + !doFramebuffersMatch(cd->server,client,maxDelta)); +} + +static void* clientLoop(void* data) { + rfbClient* client=(rfbClient*)data; + clientData* cd=(clientData*)client->clientData; + + client->appData.encodingsString=strdup(testEncodings[cd->encodingIndex].str); + + sleep(1); + rfbClientLog("Starting client (encoding %s, display %s)\n", + testEncodings[cd->encodingIndex].str, + cd->display); + if(!rfbInitClient(client,NULL,NULL)) { + rfbClientErr("Had problems starting client (encoding %s)\n", + testEncodings[cd->encodingIndex].str); + updateStatistics(cd->encodingIndex,TRUE); + return NULL; + } + while(1) { + if(WaitForMessage(client,50)>=0) + if(!HandleRFBServerMessage(client)) + break; + } + free(((clientData*)client->clientData)->display); + free(client->clientData); + if(client->frameBuffer) + free(client->frameBuffer); + rfbClientCleanup(client); + return NULL; +} + +static pthread_t all_threads[NUMBER_OF_ENCODINGS_TO_TEST]; +static int thread_counter; + +static void startClient(int encodingIndex,rfbScreenInfo* server) { + rfbClient* client=rfbGetClient(8,3,4); + clientData* cd; + + client->clientData=malloc(sizeof(clientData)); + client->MallocFrameBuffer=resize; + client->GotFrameBufferUpdate=update; + + cd=(clientData*)client->clientData; + cd->encodingIndex=encodingIndex; + cd->server=server; + cd->display=(char*)malloc(6); + sprintf(cd->display,":%d",server->port-5900); + + lastUpdateRect.x1=lastUpdateRect.y1=0; + lastUpdateRect.x2=server->width; + lastUpdateRect.y2=server->height; + + pthread_create(&all_threads[thread_counter++],NULL,clientLoop,(void*)client); +} + +/* Here begin the server functions */ + +static void idle(rfbScreenInfo* server) +{ + int c; + rfbBool goForward; + + LOCK(statisticsMutex); +#ifdef ALL_AT_ONCE + goForward=(countGotUpdate==NUMBER_OF_ENCODINGS_TO_TEST); +#else + goForward=(countGotUpdate==1); +#endif + /* if(lastUpdateRect.x2==354) + rfbLog("server checked: countGotUpdate=%d\n",countGotUpdate); */ + UNLOCK(statisticsMutex); + if(!goForward) + return; + countGotUpdate=0; + + LOCK(frameBufferMutex); + { + int i,j; + int x1=(rand()%(server->width-1)),x2=(rand()%(server->width-1)), + y1=(rand()%(server->height-1)),y2=(rand()%(server->height-1)); + if(x1>x2) { i=x1; x1=x2; x2=i; } + if(y1>y2) { i=y1; y1=y2; y2=i; } + x2++; y2++; + for(c=0;c<3;c++) { + for(i=x1;iframeBuffer[i*4+c+j*server->paddedWidthInBytes]=255*(i-x1+j-y1)/(x2-x1+y2-y1); + } + rfbMarkRectAsModified(server,x1,y1,x2,y2); + + lastUpdateRect.x1=x1; + lastUpdateRect.y1=y1; + lastUpdateRect.x2=x2; + lastUpdateRect.y2=y2; +#ifdef VERY_VERBOSE + rfbLog("Sent update (%d,%d)-(%d,%d)\n",x1,y1,x2,y2); +#endif + } + UNLOCK(frameBufferMutex); +} + +/* log function (to show what messages are from the client) */ + +static void +rfbTestLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X (client) ", localtime(&log_clock)); + fprintf(stderr,buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); +} + +/* the main function */ + +int main(int argc,char** argv) +{ + int i,j; + time_t t; + rfbScreenInfoPtr server; + + rfbClientLog=rfbTestLog; + rfbClientErr=rfbTestLog; + + /* Initialize server */ + server=rfbGetScreen(&argc,argv,width,height,8,3,4); + + server->frameBuffer=malloc(400*300*4); + server->cursor=NULL; + for(j=0;j<400*300*4;j++) + server->frameBuffer[j]=j; + rfbInitServer(server); + rfbProcessEvents(server,0); + + initStatistics(); + +#ifndef ALL_AT_ONCE + for(i=0;iframeBuffer); + + rfbLog("Statistics:\n"); + for(i=0;i */ ++ static int alphablend = -1; ++ ++ if (alphablend < 0) { ++ /* you have to set NO_ALPHABLEND=1 in your environment to disable */ ++ if (getenv("NO_ALPHABLEND")) { ++ alphablend = 0; ++ } else { ++ alphablend = 1; ++ } ++ } ++ ++ bytesPerPixel = myFormat.bitsPerPixel / 8; ++ ++ if (alphablend && bytesPerPixel == 4) { ++ unsigned long pixel, put, *upos, *upix; ++ int got_alpha = 0, rsX, rsY, rsW, rsH; ++ static XImage *image = NULL; ++ static int iwidth = 128; ++ ++ if (! image) { ++ /* watch out for tiny fb (rare) */ ++ if (iwidth > si.framebufferWidth) { ++ iwidth = si.framebufferWidth; ++ } ++ if (iwidth > si.framebufferHeight) { ++ iwidth = si.framebufferHeight; ++ } ++ ++ /* initialize an XImage with a chunk of desktopWin */ ++ image = XGetImage(dpy, desktopWin, 0, 0, iwidth, iwidth, ++ AllPlanes, ZPixmap); ++ } ++ ++ /* first check if there is any non-zero alpha channel data at all: */ ++ for (y = 0; y < rcHeight; y++) { ++ for (x = 0; x < rcWidth; x++) { ++ int alpha; ++ ++ offset = y * rcWidth + x; ++ pos = (char *)&rcSource[offset * bytesPerPixel]; ++ ++ upos = (unsigned long *) pos; ++ alpha = (*upos & 0xff000000) >> 24; ++ if (alpha) { ++ got_alpha = 1; ++ break; ++ } ++ } ++ if (got_alpha) { ++ break; ++ } ++ } ++ ++ if (!got_alpha) { ++ /* no alpha channel data, fallback to the old way */ ++ goto oldway; ++ } ++ ++ /* load the saved fb patch in to image (faster way?) */ ++ XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight, ++ AllPlanes, ZPixmap, image, 0, 0); ++ upix = (unsigned long *)image->data; ++ ++ /* if the richcursor is clipped, the fb patch will be smaller */ ++ rsW = rcWidth; ++ rsX = 0; /* used to denote a shift from the left side */ ++ x = rcCursorX - rcHotX; ++ if (x < 0) { ++ rsW += x; ++ rsX = -x; ++ } else if (x + rsW > si.framebufferWidth) { ++ rsW = si.framebufferWidth - x; ++ } ++ rsH = rcHeight; ++ rsY = 0; /* used to denote a shift from the top side */ ++ y = rcCursorY - rcHotY; ++ if (y < 0) { ++ rsH += y; ++ rsY = -y; ++ } else if (y + rsH > si.framebufferHeight) { ++ rsH = si.framebufferHeight - y; ++ } ++ ++ /* ++ * now loop over the cursor data, blend in the fb values, ++ * and then overwrite the fb (CopyDataToScreen()) ++ */ ++ for (y = 0; y < rcHeight; y++) { ++ y0 = rcCursorY - rcHotY + y; ++ if (y0 < 0 || y0 >= si.framebufferHeight) { ++ continue; /* clipped */ ++ } ++ for (x = 0; x < rcWidth; x++) { ++ int alpha, color_curs, color_fb, i; ++ ++ x0 = rcCursorX - rcHotX + x; ++ if (x0 < 0 || x0 >= si.framebufferWidth) { ++ continue; /* clipped */ ++ } ++ ++ offset = y * rcWidth + x; ++ pos = (char *)&rcSource[offset * bytesPerPixel]; ++ ++ /* extract secret alpha byte from rich cursor: */ ++ upos = (unsigned long *) pos; ++ alpha = (*upos & 0xff000000) >> 24; /* XXX MSB? */ ++ ++ /* extract the pixel from the fb: */ ++ pixel = *(upix + (y-rsY)*iwidth + (x-rsX)); ++ ++ put = 0; ++ /* for simplicity, blend all 4 bytes */ ++ for (i = 0; i < 4; i++) { ++ int sh = i*8; ++ color_curs = ((0xff << sh) & *upos) >> sh; ++ color_fb = ((0xff << sh) & pixel) >> sh; ++ ++ /* XXX assumes pre-multipled color_curs */ ++ color_fb = color_curs ++ + ((0xff - alpha) * color_fb)/0xff; ++ put |= color_fb << sh; ++ } ++ /* place in the fb: */ ++ CopyDataToScreen((char *)&put, x0, y0, 1, 1); ++ } ++ } ++ return; ++ } ++oldway: ++#endif ++ + bytesPerPixel = myFormat.bitsPerPixel / 8; + + /* FIXME: Speed optimization is possible. */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/.cvsignore new file mode 100755 index 0000000..88897f0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/.cvsignore @@ -0,0 +1,7 @@ +LinuxVNC +VNCommand +example +.deps +Makefile +Makefile.in + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/ChangeLog new file mode 100755 index 0000000..53a9c37 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/ChangeLog @@ -0,0 +1,15 @@ +included in LibVNCServer package, autoconf'ed it +SetXCutText implemented +fix for cargs +attributes work. +cursor in LinuxVNC is shown. +paste works +selection works (no cursor trails) +LinuxVNC gets it's dimensions via ioctl TIOCGWINSZ +First working key injection in LinuxVNC! +Added Mouse marking +added screenBuffer (so you have ASCII screen also) +fixed CopyRect for scrolling (need to propagate to libvncserver) +made VNCommand work (no prompt for bash, but else seems ok) +added flag for VNCommand to send input only after a newline + (good for interactive bash) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/LinuxVNC.c b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/LinuxVNC.c new file mode 100755 index 0000000..9b58954 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/LinuxVNC.c @@ -0,0 +1,191 @@ +#include +#include "VNConsole.h" +#include "vga.h" +#include +#include + +static int tty=2; +static int tty_inject_device; + +void do_key(rfbBool down,rfbKeySym keySym,rfbClientPtr cl) +{ + static char isControl=0; + + if(down) { + /* if(keySym==XK_Escape) + rfbCloseClient(cl); + else */ if(keySym==XK_Control_L || keySym==XK_Control_R) + isControl++; + else if(tty_inject_device>=0) { + if(keySym==XK_Escape) + keySym=27; + if(isControl) { + if(keySym>='a' && keySym<='z') + keySym-='a'-1; + else if(keySym>='A' && keySym<='Z') + keySym-='A'-1; + else + keySym=0xffff; + } + + if(keySym==XK_Tab) + keySym='\t'; + else if(keySym==XK_Return) + keySym='\r'; + else if(keySym==XK_BackSpace) + keySym=8; + else if(keySym==XK_Home || keySym==XK_KP_Home) + keySym=1; + else if(keySym==XK_End || keySym==XK_KP_End) + keySym=5; + else if(keySym==XK_Up || keySym==XK_KP_Up) + keySym=16; + else if(keySym==XK_Down || keySym==XK_KP_Down) + keySym=14; + else if(keySym==XK_Right || keySym==XK_KP_Right) + keySym=6; + else if(keySym==XK_Left || keySym==XK_KP_Left) + keySym=2; + + if(keySym<0x100) { + int ret; + ret=ioctl(tty_inject_device,TIOCSTI,&keySym); + if(ret<0) { + static char device[64]; + close(tty_inject_device); + sprintf(device,"/dev/tty%d",tty); + tty_inject_device=open(device,O_WRONLY); + ret=ioctl(tty_inject_device,TIOCSTI,&keySym); + if(ret<0) + rfbErr("Couldn't reopen device %s!\n",device); + } + } + } + } else if(keySym==XK_Control_L || keySym==XK_Control_R) + if(isControl>0) + isControl--; +} + +/* these colours are from linux kernel drivers/char/console.c */ +unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, + 8,12,10,14, 9,13,11,15 }; +/* the default colour table, for VGA+ colour systems */ +int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa, + 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff}; +int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa, + 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff}; +int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, + 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff}; + +int main(int argc,char **argv) +{ + int width=80,height=25; + char *buffer; + vncConsolePtr console; + char tty_device[64],title[128]; + int i; + FILE* tty_file; + struct winsize dimensions; + + if(argc>1) { + if((tty=atoi(argv[1]))<1) { + rfbErr("Usage: %s [tty_number [vnc args]]\n",argv[0]); + exit(1); + } else { + argv++; + argc--; + } + } + + /* getopt goes here! */ + + sprintf(tty_device,"/dev/tty%d",tty); + if((tty_inject_device=open(tty_device,O_WRONLY))<0) { + rfbErr("Couldn't open tty device %s!\n",tty_device); + exit(1); + } + rfbLog("Using device %s.\n",tty_device); + + if(ioctl(tty_inject_device,TIOCGWINSZ,&dimensions)>=0) { + width=dimensions.ws_col; + height=dimensions.ws_row; + } + + sprintf(title,"LinuxVNC: /dev/tty%d",tty); + + /* console init */ + if(!(console=vcGetConsole(&argc,argv,width,height,&vgaFont,TRUE))) + exit(1); + + for(i=0;i<16;i++) { + console->screen->colourMap.data.bytes[i*3+0]=default_red[color_table[i]]; + console->screen->colourMap.data.bytes[i*3+1]=default_grn[color_table[i]]; + console->screen->colourMap.data.bytes[i*3+2]=default_blu[color_table[i]]; + } + console->screen->desktopName=title; + console->screen->kbdAddEvent=do_key; + console->selectTimeOut=100000; + console->wrapBottomToTop=TRUE; +#ifdef USE_OLD_VCS + buffer=malloc(width*height); + console->cursorActive=FALSE; +#else + buffer=malloc(width*height*2+4); + console->cursorActive=TRUE; +#endif + /* memcpy(buffer,console->screenBuffer,width*height); */ + +#ifdef USE_OLD_VCS + sprintf(tty_device,"/dev/vcs%d",tty); +#else + sprintf(tty_device,"/dev/vcsa%d",tty); +#endif + + while(rfbIsActive(console->screen)) { + if(!console->currentlyMarking) { + tty_file=fopen(tty_device,"rb"); + if(!tty_file) { + rfbErr("cannot open device \"%s\"\n", + tty_device); + exit(1); + } +#ifdef USE_OLD_VCS + fread(buffer,width,height,tty_file); +#else + fread(buffer,width*height*2+4,1,tty_file); + vcHideCursor(console); +#endif + fclose(tty_file); + + for(i=0;iwidth*console->height;i++) { + if +#ifdef USE_OLD_VCS + (buffer[i]!=console->screenBuffer[i]) +#else + (buffer[4+2*i]!=console->screenBuffer[i] || + buffer[5+2*i]!=console->attributeBuffer[i]) +#endif + { + console->x=(i%console->width); + console->y=(i/console->width); + /* + rfbLog("changes: %d,%d (%d!=%d || %d!=%d)\n", + console->x,console->y, + buffer[4+2*i],console->screenBuffer[i], + buffer[5+2*i],console->attributeBuffer[i]); + */ + +#ifdef USE_OLD_VCS + vcPutChar(console,buffer[i]); +#else + vcPutCharColour(console,buffer[4+i*2],buffer[5+i*2]&0x7,buffer[5+i*2]>>4); +#endif + } + } + console->x=buffer[2]; + console->y=buffer[3]; + } + vcProcessEvents(console); + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/Makefile.am new file mode 100755 index 0000000..3ad36a3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/Makefile.am @@ -0,0 +1,25 @@ +INCLUDES = -I$(top_srcdir) + +CONSOLE_SRCS=VNConsole.c + +noinst_HEADERS=VNConsole.h vga.h + +LDADD=../libvncserver/libvncserver.la @WSOCKLIB@ + +if LINUX +if ! MINGW +bin_PROGRAMS=LinuxVNC +LinuxVNC_SOURCES=LinuxVNC.c $(CONSOLE_SRCS) +endif +endif + +if ! MINGW +VNCOMMAND=VNCommand +endif + +noinst_PROGRAMS=example $(VNCOMMAND) +example_SOURCES=example.c $(CONSOLE_SRCS) +VNCommand_SOURCES=VNCommand.c $(CONSOLE_SRCS) + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/README b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/README new file mode 100755 index 0000000..b01e88a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/README @@ -0,0 +1,25 @@ + +In this stage (beta), there are two programs functional: + +LinuxVNC + monitor a virtual console (text mode) of Linux. You need + root privileges, or at least be in the "tty" group, because + it reads /dev/vcsN and writes /dev/ttyN. + It follows the same idea as WinVNC, x11vnc or OSXvnc, i.e. it + takes an existing desktop and exports it via RFB (VNC), just that + LinuxVNC exports text. + +VNCommand + executes redirecting stdin from a vncviewer and stdout & + stderr to the vnc clients. This might be renamed to vncTerm if + there are some term capabilities added (up to now, bash doesn't look + nice). Colours and other ANSI sequences need to be added. + +My original plan was to create a program named vncTerm. It was meant to +overcome incompatibilities between different TERMs, but I found "screen" to +be just such a program. Maybe once some time in the future I'll make a +patch for screen to use VNConsole to export it's contents via RFB... + +These two programs are a simple application of LibVNCServer with a small +console layer in between (VNConsole). You can use them under the terms +(not vncTerms ;-) of the GPL. They where written by Johannes E. Schindelin. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/TODO b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/TODO new file mode 100755 index 0000000..5c6f189 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/TODO @@ -0,0 +1,21 @@ +VNConsole: +LinuxVNC: +VNCommand: + make Control or Alt sequences work. + Find out how to satisfy isatty(). => /dev/ptyN + Fix check if child is alive. + Add command line option for real interactive mode. + +done: + +.treat colours correctly (use /dev/vcsaN's attributes). +.introduce per cell colours (for attributes) +.fix cursor fuckup when selecting. +.default to paste for right mouse button. +.have an idea how to insert keys +.convert VNCommand to an interactive shell (vncTerm) +.bidirectional pipes (spawn a shell ...) +.mark with mouse (copy text) +.when scrolling, cursor must be hidden! + + modifiedRegion which are copied with CopyRect have to be modified also. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNCommand.c b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNCommand.c new file mode 100755 index 0000000..ecf2543 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNCommand.c @@ -0,0 +1,127 @@ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#include "VNConsole.h" +#include "vga.h" +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_WAIT_H +#include +#endif +#include + + +int main(int argc, char **argv) +{ + rfbBool interactive=FALSE,sendOnlyWholeLines=TRUE; + int serverArgc,programArg0; + for(serverArgc=1;serverArgcdoEcho = FALSE; + + if(max_fdinputCount) { + if(sendOnlyWholeLines) { + for(i=0;iinputCount;i++) + if(console->inputBuffer[i]=='\n') { + i++; + fwrite(console->inputBuffer,i,1,input_pipe); + fflush(input_pipe); + /* fwrite(console->inputBuffer,i,1,stderr); */ + if(console->inputCount>i) + memmove(console->inputBuffer,console->inputBuffer+i,console->inputCount-i); + console->inputCount-=i; + i=0; + } + } else { + fwrite(console->inputBuffer,console->inputCount,1,input_pipe); + fflush(input_pipe); + /* fwrite(console->inputBuffer,console->inputCount,1,stderr); */ + console->inputCount=0; + } + } + /* process output */ + fs1=fs; tv1=tv; + num_fds=select(max_fd+1,&fs1,NULL,NULL,&tv1); + if(num_fds>0) { + /* + if(FD_ISSET(0,&fs1)) { + ch=getchar(); + fputc(ch,f); + } + */ + if(FD_ISSET(out[0],&fs1)) { + c=read(out[0],buffer,1024); + for(i=0;i +#include +#include "VNConsole.h" + +#define DEBUG(x) + +unsigned char colourMap16[16*3]={ + /* 0 black #000000 */ 0x00,0x00,0x00, + /* 1 maroon #800000 */ 0x80,0x00,0x00, + /* 2 green #008000 */ 0x00,0x80,0x00, + /* 3 khaki #808000 */ 0x80,0x80,0x00, + /* 4 navy #000080 */ 0x00,0x00,0x80, + /* 5 purple #800080 */ 0x80,0x00,0x80, + /* 6 aqua-green #008080 */ 0x00,0x80,0x80, + /* 7 light grey #c0c0c0 */ 0xc0,0xc0,0xc0, + /* 8 dark grey #808080 */ 0x80,0x80,0x80, + /* 9 red #ff0000 */ 0xff,0x00,0x00, + /* a light green #00ff00 */ 0x00,0xff,0x00, + /* b yellow #ffff00 */ 0xff,0xff,0x00, + /* c blue #0000ff */ 0x00,0x00,0xff, + /* d pink #ff00ff */ 0xff,0x00,0xff, + /* e light blue #00ffff */ 0x00,0xff,0xff, + /* f white #ffffff */ 0xff,0xff,0xff +}; + +void MakeColourMap16(vncConsolePtr c) +{ + rfbColourMap* colourMap=&(c->screen->colourMap); + if(colourMap->count) + free(colourMap->data.bytes); + colourMap->data.bytes=malloc(16*3); + memcpy(colourMap->data.bytes,colourMap16,16*3); + colourMap->count=16; + colourMap->is16=FALSE; + c->screen->serverFormat.trueColour=FALSE; +} + +void vcDrawOrHideCursor(vncConsolePtr c) +{ + int i,j,w=c->screen->paddedWidthInBytes; + char *b=c->screen->frameBuffer+c->y*c->cHeight*w+c->x*c->cWidth; + for(j=c->cy1;jcy2;j++) + for(i=c->cx1;icx2;i++) + b[j*w+i]^=0x0f; + rfbMarkRectAsModified(c->screen, + c->x*c->cWidth+c->cx1,c->y*c->cHeight+c->cy1, + c->x*c->cWidth+c->cx2,c->y*c->cHeight+c->cy2); + c->cursorIsDrawn=c->cursorIsDrawn?FALSE:TRUE; +} + +void vcDrawCursor(vncConsolePtr c) +{ + if(c->cursorActive && c->yheight && c->xwidth) { + /* rfbLog("DrawCursor: %d,%d\n",c->x,c->y); */ + vcDrawOrHideCursor(c); + } +} + +void vcHideCursor(vncConsolePtr c) +{ + if(c->currentlyMarking) + vcUnmark(c); + vcDrawOrHideCursor(c); +} + +void vcMakeSureCursorIsDrawn(rfbClientPtr cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + if(!c->dontDrawCursor) + vcDrawCursor(c); +} + +vncConsolePtr vcGetConsole(int *argc,char **argv, + int width,int height,rfbFontDataPtr font +#ifdef USE_ATTRIBUTE_BUFFER + ,rfbBool withAttributes +#endif + ) +{ + vncConsolePtr c=(vncConsolePtr)malloc(sizeof(vncConsole)); + + c->font=font; + c->width=width; + c->height=height; + c->screenBuffer=(char*)malloc(width*height); + memset(c->screenBuffer,' ',width*height); +#ifdef USE_ATTRIBUTE_BUFFER + if(withAttributes) { + c->attributeBuffer=(char*)malloc(width*height); + memset(c->attributeBuffer,0x07,width*height); + } else + c->attributeBuffer=NULL; +#endif + c->x=0; + c->y=0; + c->wrapBottomToTop=FALSE; + c->cursorActive=TRUE; + c->cursorIsDrawn=FALSE; + c->dontDrawCursor=FALSE; + c->inputBuffer=(char*)malloc(1024); + c->inputSize=1024; + c->inputCount=0; + c->selection=0; + c->selectTimeOut=40000; /* 40 ms */ + c->doEcho=TRUE; + + c->wasRightButtonDown=FALSE; + c->currentlyMarking=FALSE; + + rfbWholeFontBBox(font,&c->xhot,&c->cHeight,&c->cWidth,&c->yhot); + c->cWidth-=c->xhot; + c->cHeight=-c->cHeight-c->yhot; + + /* text cursor */ + c->cx1=c->cWidth/8; + c->cx2=c->cWidth*7/8; + c->cy2=c->cHeight-1-c->yhot+c->cHeight/16; + if(c->cy2>=c->cHeight) + c->cy2=c->cHeight-1; + c->cy1=c->cy2-c->cHeight/8; + if(c->cy1<0) + c->cy2=0; + + if(!(c->screen = rfbGetScreen(argc,argv,c->cWidth*c->width,c->cHeight*c->height,8,1,1))) + return NULL; + c->screen->screenData=(void*)c; + c->screen->displayHook=vcMakeSureCursorIsDrawn; + c->screen->frameBuffer= + (char*)malloc(c->screen->width*c->screen->height); + memset(c->screen->frameBuffer,c->backColour, + c->screen->width*c->screen->height); + c->screen->kbdAddEvent=vcKbdAddEventProc; + c->screen->ptrAddEvent=vcPtrAddEventProc; + c->screen->setXCutText=vcSetXCutTextProc; + + MakeColourMap16(c); + c->foreColour=0x7; + c->backColour=0; + + rfbInitServer(c->screen); + + return(c); +} + +#include + +/* before using this function, hide the cursor */ +void vcScroll(vncConsolePtr c,int lineCount) +{ + int y1,y2; + rfbScreenInfoPtr s=c->screen; + + if(lineCount==0) + return; + + /* rfbLog("begin scroll\n"); */ + vcHideCursor(c); + c->dontDrawCursor=TRUE; + + if(lineCount>=c->height || lineCount<=-c->height) { + y1=0; y2=s->height; + } else if(lineCount>0) { + y1=s->height-lineCount*c->cHeight; y2=s->height; + rfbDoCopyRect(s,0,0,s->width,y1,0,-lineCount*c->cHeight); + memmove(c->screenBuffer, + c->screenBuffer+(c->height-lineCount)*c->width, + (c->height-lineCount)*c->width); +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + memmove(c->attributeBuffer, + c->attributeBuffer+(c->height-lineCount)*c->width, + (c->height-lineCount)*c->width); +#endif + } else { + y1=0; y2=-lineCount*c->cHeight; + rfbDoCopyRect(s,0,y2,s->width,s->height,0,-lineCount*c->cHeight); + memmove(c->screenBuffer-lineCount*c->width, + c->screenBuffer, + (c->height+lineCount)*c->width); +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + memmove(c->attributeBuffer-lineCount*c->width, + c->attributeBuffer, + (c->height+lineCount)*c->width); +#endif + } + + c->dontDrawCursor=FALSE; + memset(s->frameBuffer+y1*s->width,c->backColour,(y2-y1)*s->width); + rfbMarkRectAsModified(s,0,y1-c->cHeight,s->width,y2); + memset(c->screenBuffer+y1/c->cHeight*c->width,' ', + (y2-y1)/c->cHeight*c->width); +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + memset(c->attributeBuffer+y1/c->cHeight*c->width,0x07, + (y2-y1)/c->cHeight*c->width); +#endif + /* rfbLog("end scroll\n"); */ +} + +void vcCheckCoordinates(vncConsolePtr c) +{ + if(c->x>=c->width) { + c->x=0; + c->y++; + } + if(c->y>=c->height) { + if(c->wrapBottomToTop) + c->y=0; + else { + vcScroll(c,c->y+1-c->height); + c->y=c->height-1; + } + } +} + +void vcPutChar(vncConsolePtr c,unsigned char ch) +{ +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) { + unsigned char colour=c->attributeBuffer[c->x+c->y*c->width]; + vcPutCharColour(c,ch,colour&0x7,colour>>4); + } else +#endif + vcPutCharColour(c,ch,c->foreColour,c->backColour); +} + +void vcPutCharColour(vncConsolePtr c,unsigned char ch,unsigned char foreColour,unsigned char backColour) +{ + rfbScreenInfoPtr s=c->screen; + int j,x,y; + + vcHideCursor(c); + if(ch<' ') { + switch(ch) { + case 7: + case 13: + break; + case 8: /* BackSpace */ + if(c->x>0) { + c->x--; + vcPutChar(c,' '); + c->x--; + } + break; + case 10: /* return */ + c->x=0; + c->y++; + vcCheckCoordinates(c); + break; + case 9: /* tabulator */ + do { + vcPutChar(c,' '); + } while(c->x%8); + break; + default: + rfbLog("putchar of unknown character: %c(%d).\n",ch,ch); + vcPutChar(c,' '); + } + } else { +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + c->attributeBuffer[c->x+c->y*c->width]=foreColour|(backColour<<4); +#endif + x=c->x*c->cWidth; + y=c->y*c->cHeight; + for(j=y+c->cHeight-1;j>=y;j--) + memset(s->frameBuffer+j*s->width+x,backColour,c->cWidth); + rfbDrawChar(s,c->font, + x-c->xhot+(c->cWidth-rfbWidthOfChar(c->font,ch))/2, + y+c->cHeight-c->yhot-1, + ch,foreColour); + c->screenBuffer[c->y*c->width+c->x]=ch; + c->x++; + rfbMarkRectAsModified(s,x,y-c->cHeight+1,x+c->cWidth,y+c->cHeight+1); + vcCheckCoordinates(c); + } +} + +void vcPrint(vncConsolePtr c,unsigned char* str) +{ + while(*str) { + vcPutChar(c,*str); + str++; + } +} + +void vcPrintColour(vncConsolePtr c,unsigned char* str,unsigned char foreColour,unsigned char backColour) +{ + while(*str) { + vcPutCharColour(c,*str,foreColour,backColour); + str++; + } +} + +void vcPrintF(vncConsolePtr c,char* format,...) +{ + va_list args; + char buf[4096]; + va_start(args, format); + vsprintf(buf, format, args); + vcPrint(c,(unsigned char*)buf); + va_end(args); +} + +void vcPrintFColour(vncConsolePtr c,unsigned char foreColour,unsigned char backColour,char* format,...) +{ + va_list args; + char buf[4096]; + va_start(args, format); + vsprintf(buf, format, args); + vcPrintColour(c,(unsigned char*)buf,foreColour,backColour); + va_end(args); +} + +char vcGetCh(vncConsolePtr c) +{ + if(c->inputCount>0) { + char ch; + ch=c->inputBuffer[0]; + c->inputCount--; + if(c->inputCount>0) + memmove(c->inputBuffer,c->inputBuffer+1,c->inputCount); + return(ch); + } else + return(0); +} + +char vcGetChar(vncConsolePtr c) +{ + while(rfbIsActive(c->screen) && c->inputCount==0) + vcProcessEvents(c); + return(vcGetCh(c)); +} + +char *vcGetString(vncConsolePtr c,char *buffer,int bufferSize) +{ + char *bufferBackup=c->inputBuffer; + int i,count=bufferSize-1; + + if(count>c->inputCount) + count=c->inputCount; + for(i=1;iinputCount-=i; + memmove(bufferBackup,bufferBackup+i+2,c->inputCount); + return(buffer); + } + memcpy(buffer,bufferBackup,c->inputCount); + count=c->inputSize; + c->inputSize=bufferSize; + c->inputBuffer=buffer; + while(rfbIsActive(c->screen) + && c->inputCountinputCount-1]!='\n') + vcProcessEvents(c); + buffer[c->inputCount]=0; + c->inputBuffer=bufferBackup; + c->inputSize=count; + c->inputCount=0; + return(buffer); +} + +void vcKbdAddEventProc(rfbBool down,rfbKeySym keySym,rfbClientPtr cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + if(down) { + if(c->inputCountinputSize) { + if(keySym<0 || keySym>0xff) { + if(keySym==XK_Return) keySym='\n'; + else if(keySym==XK_BackSpace) keySym=8; + else if(keySym==XK_Tab) keySym=9; + else keySym=0; + } + if(keySym>0) { + if(keySym==8) { + if(c->inputCount>0) + c->inputCount--; + } else + c->inputBuffer[c->inputCount++]=(char)keySym; + if(c->doEcho) + vcPutChar(c,(unsigned char)keySym); + } + } + } +} + +void vcPtrAddEventProc(int buttonMask,int x,int y,rfbClientPtr cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + + if(c->wasRightButtonDown) { + if((buttonMask&4)==0) { + if(c->selection) { + char* s; + for(s=c->selection;*s;s++) { + c->screen->kbdAddEvent(1,*s,cl); + c->screen->kbdAddEvent(0,*s,cl); + } + } + c->wasRightButtonDown=0; + } + } else if(buttonMask&4) + c->wasRightButtonDown=1; + + if(buttonMask&1) { + int cx=x/c->cWidth,cy=y/c->cHeight,pos; + if(cx<0) cx=0; else if(cx>=c->width) cx=c->width-1; + if(cy<0) cy=0; else if(cy>=c->height) cy=c->height-1; + pos=cy*c->width+cx; + + /* mark */ + if(!c->currentlyMarking) { + c->currentlyMarking=TRUE; + c->markStart=pos; + c->markEnd=pos; + vcToggleMarkCell(c,pos); + } else { + DEBUG(rfbLog("markStart: %d, markEnd: %d, pos: %d\n", + c->markStart,c->markEnd,pos)); + if(c->markEnd!=pos) { + if(c->markEndmarkEnd; cy=pos; + } else { + cx=pos; cy=c->markEnd; + } + if(cxmarkStart) { + if(cymarkStart) + cy--; + } else + cx++; + while(cx<=cy) { + vcToggleMarkCell(c,cx); + cx++; + } + c->markEnd=pos; + } + } + } else if(c->currentlyMarking) { + int i,j; + if(c->markStartmarkEnd) { + i=c->markStart; j=c->markEnd+1; + } else { + i=c->markEnd; j=c->markStart; + } + if(c->selection) free(c->selection); + c->selection=(char*)malloc(j-i+1); + memcpy(c->selection,c->screenBuffer+i,j-i); + c->selection[j-i]=0; + vcUnmark(c); + rfbGotXCutText(c->screen,c->selection,j-i); + } + rfbDefaultPtrAddEvent(buttonMask,x,y,cl); +} + +void vcSetXCutTextProc(char* str,int len, struct _rfbClientRec* cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + + if(c->selection) free(c->selection); + c->selection=(char*)malloc(len+1); + memcpy(c->selection,str,len); + c->selection[len]=0; +} + +void vcToggleMarkCell(vncConsolePtr c,int pos) +{ + int x=(pos%c->width)*c->cWidth, + y=(pos/c->width)*c->cHeight; + int i,j; + rfbScreenInfoPtr s=c->screen; + char *b=s->frameBuffer+y*s->width+x; + for(j=0;jcHeight;j++) + for(i=0;icWidth;i++) + b[j*s->width+i]^=0x0f; + rfbMarkRectAsModified(c->screen,x,y,x+c->cWidth,y+c->cHeight); +} + +void vcUnmark(vncConsolePtr c) +{ + int i,j; + c->currentlyMarking=FALSE; + if(c->markStartmarkEnd) { + i=c->markStart; j=c->markEnd+1; + } else { + i=c->markEnd; j=c->markStart; + } + for(;iscreen,c->selectTimeOut); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.h b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.h new file mode 100755 index 0000000..ae6822d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.h @@ -0,0 +1,95 @@ +#include + +/* this is now the default */ +#define USE_ATTRIBUTE_BUFFER + +typedef struct vncConsole { + /* width and height in cells (=characters) */ + int width, height; + + /* current position */ + int x,y; + + /* characters */ + char *screenBuffer; + +#ifdef USE_ATTRIBUTE_BUFFER + /* attributes: colours. If NULL, default to gray on black, else + for each cell an unsigned char holds foreColour|(backColour<<4) */ + char *attributeBuffer; +#endif + + /* if this is set, the screen doesn't scroll. */ + rfbBool wrapBottomToTop; + + /* height and width of one character */ + int cWidth, cHeight; + /* offset of characters */ + int xhot,yhot; + + /* colour */ + unsigned char foreColour,backColour; + int8_t cx1,cy1,cx2,cy2; + + /* input buffer */ + char *inputBuffer; + int inputCount; + int inputSize; + long selectTimeOut; + rfbBool doEcho; /* if reading input, do output directly? */ + + /* selection */ + char *selection; + + /* mouse */ + rfbBool wasRightButtonDown; + rfbBool currentlyMarking; + int markStart,markEnd; + + /* should text cursor be drawn? (an underscore at current position) */ + rfbBool cursorActive; + rfbBool cursorIsDrawn; + rfbBool dontDrawCursor; /* for example, while scrolling */ + + rfbFontDataPtr font; + rfbScreenInfoPtr screen; +} vncConsole, *vncConsolePtr; + +#ifdef USE_ATTRIBUTE_BUFFER +vncConsolePtr vcGetConsole(int *argc,char **argv, + int width,int height,rfbFontDataPtr font, + rfbBool withAttributes); +#else +vncConsolePtr vcGetConsole(int argc,char **argv, + int width,int height,rfbFontDataPtr font); +#endif +void vcDrawCursor(vncConsolePtr c); +void vcHideCursor(vncConsolePtr c); +void vcCheckCoordinates(vncConsolePtr c); + +void vcPutChar(vncConsolePtr c,unsigned char ch); +void vcPrint(vncConsolePtr c,unsigned char* str); +void vcPrintF(vncConsolePtr c,char* format,...); + +void vcPutCharColour(vncConsolePtr c,unsigned char ch, + unsigned char foreColour,unsigned char backColour); +void vcPrintColour(vncConsolePtr c,unsigned char* str, + unsigned char foreColour,unsigned char backColour); +void vcPrintFColour(vncConsolePtr c,unsigned char foreColour, + unsigned char backColour,char* format,...); + +char vcGetCh(vncConsolePtr c); +char vcGetChar(vncConsolePtr c); /* blocking */ +char *vcGetString(vncConsolePtr c,char *buffer,int maxLen); + +void vcKbdAddEventProc(rfbBool down,rfbKeySym keySym,rfbClientPtr cl); +void vcPtrAddEventProc(int buttonMask,int x,int y,rfbClientPtr cl); +void vcSetXCutTextProc(char* str,int len, struct _rfbClientRec* cl); + +void vcToggleMarkCell(vncConsolePtr c,int pos); +void vcUnmark(vncConsolePtr c); + +void vcProcessEvents(vncConsolePtr c); + +/* before using this function, hide the cursor */ +void vcScroll(vncConsolePtr c,int lineCount); diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/example.c b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/example.c new file mode 100755 index 0000000..54de666 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/example.c @@ -0,0 +1,31 @@ +#include "VNConsole.h" +#include "vga.h" + +int main(int argc,char **argv) +{ + vncConsolePtr c=vcGetConsole(&argc,argv,80,25,&vgaFont,FALSE); + char buffer[1024]; + int i,j,l; + for(j=32;j<256;j+=16) { + vcPrintF(c,"%02x: ",j); + for(i=j;i ",i); + vcGetString(c,buffer,1024); + l=strlen(buffer)-1; + while(l>=0 && buffer[l]=='\n') + buffer[l]=0; + if(!strcmp(buffer,"quit")) + return(0); + if(!strcmp(buffer,"s")) + vcScroll(c,2); + if(!strcmp(buffer,"S")) + vcScroll(c,-2); + i++; + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/vga.h b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/vga.h new file mode 100755 index 0000000..21e03eb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/vga.h @@ -0,0 +1,261 @@ +unsigned char vgaFontData[2399]={ +0x7c,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c, /* 0 */ +0x7e,0x81,0xa5,0x81,0x81,0xa5,0x99,0x81,0x81,0x7e, /* 1 */ +0x7e,0xff,0xdb,0xff,0xff,0xdb,0xe7,0xff,0xff,0x7e, /* 2 */ +0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10, /* 3 */ +0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10, /* 4 */ +0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c, /* 5 */ +0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c, /* 6 */ +0x60,0xf0,0xf0,0x60, /* 7 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, /* 8 */ +0x78,0xcc,0x84,0x84,0xcc,0x78, /* 9 */ +0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, /* 10 */ +0x1e,0x06,0x0e,0x1a,0x78,0xcc,0xcc,0xcc,0xcc,0x78, /* 11 */ +0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0xfc,0x30,0x30, /* 12 */ +0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0, /* 13 */ +0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0, /* 14 */ +0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18, /* 15 */ +0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80, /* 16 */ +0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02, /* 17 */ +0x30,0x78,0xfc,0x30,0x30,0x30,0xfc,0x78,0x30, /* 18 */ +0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0xcc,0xcc, /* 19 */ +0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b, /* 20 */ +0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c, /* 21 */ +0xfe,0xfe,0xfe,0xfe, /* 22 */ +0x30,0x78,0xfc,0x30,0x30,0x30,0xfc,0x78,0x30,0xfc, /* 23 */ +0x30,0x78,0xfc,0x30,0x30,0x30,0x30,0x30,0x30,0x30, /* 24 */ +0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xfc,0x78,0x30, /* 25 */ +0x18,0x0c,0xfe,0x0c,0x18, /* 26 */ +0x30,0x60,0xfe,0x60,0x30, /* 27 */ +0xc0,0xc0,0xc0,0xfe, /* 28 */ +0x28,0x6c,0xfe,0x6c,0x28, /* 29 */ +0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe, /* 30 */ +0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10, /* 31 */ + /* 32 */ +0x60,0xf0,0xf0,0xf0,0x60,0x60,0x60,0x00,0x60,0x60, /* 33 */ +0xcc,0xcc,0xcc,0x48, /* 34 */ +0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c, /* 35 */ +0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18, /* 36 */ +0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86, /* 37 */ +0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76, /* 38 */ +0x60,0x60,0x60,0xc0, /* 39 */ +0x30,0x60,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x60,0x30, /* 40 */ +0xc0,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0xc0, /* 41 */ +0x66,0x3c,0xff,0x3c,0x66, /* 42 */ +0x30,0x30,0xfc,0x30,0x30, /* 43 */ +0x60,0x60,0x60,0xc0, /* 44 */ +0xfe, /* 45 */ +0xc0,0xc0, /* 46 */ +0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80, /* 47 */ +0x38,0x6c,0xc6,0xc6,0xd6,0xd6,0xc6,0xc6,0x6c,0x38, /* 48 */ +0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0xfc, /* 49 */ +0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe, /* 50 */ +0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c, /* 51 */ +0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e, /* 52 */ +0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c, /* 53 */ +0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c, /* 54 */ +0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30, /* 55 */ +0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c, /* 56 */ +0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78, /* 57 */ +0xc0,0xc0,0x00,0x00,0x00,0xc0,0xc0, /* 58 */ +0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xc0, /* 59 */ +0x0c,0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x0c, /* 60 */ +0xfc,0x00,0x00,0xfc, /* 61 */ +0xc0,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0xc0, /* 62 */ +0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18, /* 63 */ +0x7c,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c, /* 64 */ +0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6, /* 65 */ +0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc, /* 66 */ +0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c, /* 67 */ +0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8, /* 68 */ +0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe, /* 69 */ +0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0, /* 70 */ +0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a, /* 71 */ +0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6, /* 72 */ +0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xf0, /* 73 */ +0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78, /* 74 */ +0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6, /* 75 */ +0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe, /* 76 */ +0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0xc6,0xc6,0xc6, /* 77 */ +0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6, /* 78 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 79 */ +0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0, /* 80 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e, /* 81 */ +0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6, /* 82 */ +0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c, /* 83 */ +0xfc,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x78, /* 84 */ +0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 85 */ +0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x10, /* 86 */ +0xc6,0xc6,0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0xee,0x6c, /* 87 */ +0xc6,0xc6,0x6c,0x7c,0x38,0x38,0x7c,0x6c,0xc6,0xc6, /* 88 */ +0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x30,0x78, /* 89 */ +0xfe,0xc6,0x86,0x0c,0x18,0x30,0x60,0xc2,0xc6,0xfe, /* 90 */ +0xf0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf0, /* 91 */ +0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02, /* 92 */ +0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xf0, /* 93 */ +0x10,0x38,0x6c,0xc6, /* 94 */ +0xff, /* 95 */ +0xc0,0xc0,0x60, /* 96 */ +0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 97 */ +0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c, /* 98 */ +0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c, /* 99 */ +0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76, /* 100 */ +0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 101 */ +0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0, /* 102 */ +0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78, /* 103 */ +0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6, /* 104 */ +0x60,0x60,0x00,0xe0,0x60,0x60,0x60,0x60,0x60,0xf0, /* 105 */ +0x0c,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0x78, /* 106 */ +0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6, /* 107 */ +0xe0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xf0, /* 108 */ +0xec,0xfe,0xd6,0xd6,0xd6,0xd6,0xc6, /* 109 */ +0xdc,0x66,0x66,0x66,0x66,0x66,0x66, /* 110 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 111 */ +0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0, /* 112 */ +0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e, /* 113 */ +0xdc,0x76,0x66,0x60,0x60,0x60,0xf0, /* 114 */ +0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c, /* 115 */ +0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c, /* 116 */ +0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 117 */ +0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30, /* 118 */ +0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0x6c, /* 119 */ +0xc6,0x6c,0x38,0x38,0x38,0x6c,0xc6, /* 120 */ +0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8, /* 121 */ +0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe, /* 122 */ +0x1c,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x30,0x1c, /* 123 */ +0xc0,0xc0,0xc0,0xc0,0x00,0xc0,0xc0,0xc0,0xc0,0xc0, /* 124 */ +0xe0,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0x30,0xe0, /* 125 */ +0x76,0xdc, /* 126 */ +0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe, /* 127 */ +0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c, /* 128 */ +0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 129 */ +0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 130 */ +0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 131 */ +0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 132 */ +0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 133 */ +0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 134 */ +0x78,0xcc,0xc0,0xc0,0xcc,0x78,0x18,0x0c,0x78, /* 135 */ +0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 136 */ +0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 137 */ +0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 138 */ +0xcc,0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78, /* 139 */ +0x30,0x78,0xcc,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78, /* 140 */ +0xc0,0x60,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78, /* 141 */ +0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6, /* 142 */ +0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6, /* 143 */ +0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe, /* 144 */ +0xcc,0x76,0x36,0x7e,0xd8,0xd8,0x6e, /* 145 */ +0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce, /* 146 */ +0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 147 */ +0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 148 */ +0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 149 */ +0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 150 */ +0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 151 */ +0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78, /* 152 */ +0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 153 */ +0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 154 */ +0x30,0x30,0x78,0xcc,0xc0,0xc0,0xc0,0xcc,0x78,0x30,0x30, /* 155 */ +0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc, /* 156 */ +0xcc,0xcc,0x78,0x30,0xfc,0x30,0xfc,0x30,0x30,0x30, /* 157 */ +0xf8,0xcc,0xcc,0xf8,0xc4,0xcc,0xde,0xcc,0xcc,0xcc,0xc6, /* 158 */ +0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70, /* 159 */ +0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 160 */ +0x30,0x60,0xc0,0x00,0xe0,0x60,0x60,0x60,0x60,0x60,0xf0, /* 161 */ +0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 162 */ +0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 163 */ +0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66, /* 164 */ +0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6, /* 165 */ +0x78,0xd8,0xd8,0x7c,0x00,0xfc, /* 166 */ +0x70,0xd8,0xd8,0x70,0x00,0xf8, /* 167 */ +0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c, /* 168 */ +0xfe,0xc0,0xc0,0xc0,0xc0, /* 169 */ +0xfe,0x06,0x06,0x06,0x06, /* 170 */ +0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xdc,0x86,0x0c,0x18,0x3e, /* 171 */ +0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x9e,0x3e,0x06,0x06, /* 172 */ +0x60,0x60,0x00,0x60,0x60,0x60,0xf0,0xf0,0xf0,0x60, /* 173 */ +0x36,0x6c,0xd8,0x6c,0x36, /* 174 */ +0xd8,0x6c,0x36,0x6c,0xd8, /* 175 */ +0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88, /* 176 */ +0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, /* 177 */ +0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, /* 178 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 179 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 180 */ +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 181 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 182 */ +0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 183 */ +0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 184 */ +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 185 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 186 */ +0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 187 */ +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe, /* 188 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe, /* 189 */ +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8, /* 190 */ +0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 191 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf8, /* 192 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff, /* 193 */ +0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 194 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 195 */ +0xff, /* 196 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 197 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xc0,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 198 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xdc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 199 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xdc,0xc0,0xfc, /* 200 */ +0xfc,0xc0,0xdc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 201 */ +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff, /* 202 */ +0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 203 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xdc,0xc0,0xdc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 204 */ +0xff,0x00,0xff, /* 205 */ +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 206 */ +0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff, /* 207 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff, /* 208 */ +0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 209 */ +0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 210 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xfc, /* 211 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xc0,0xf8, /* 212 */ +0xf8,0xc0,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 213 */ +0xfc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 214 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 215 */ +0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 216 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8, /* 217 */ +0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 218 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 219 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 220 */ +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, /* 221 */ +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, /* 222 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 223 */ +0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76, /* 224 */ +0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc, /* 225 */ +0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 226 */ +0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c, /* 227 */ +0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe, /* 228 */ +0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70, /* 229 */ +0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0, /* 230 */ +0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18, /* 231 */ +0xfc,0x30,0x78,0xcc,0xcc,0xcc,0x78,0x30,0xfc, /* 232 */ +0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38, /* 233 */ +0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee, /* 234 */ +0x3c,0x60,0x30,0x18,0x7c,0xcc,0xcc,0xcc,0xcc,0x78, /* 235 */ +0x7e,0xdb,0xdb,0xdb,0x7e, /* 236 */ +0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0, /* 237 */ +0x38,0x60,0xc0,0xc0,0xf8,0xc0,0xc0,0xc0,0x60,0x38, /* 238 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6, /* 239 */ +0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe, /* 240 */ +0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff, /* 241 */ +0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00,0xfc, /* 242 */ +0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x00,0xfc, /* 243 */ +0x70,0xd8,0xd8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 244 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70, /* 245 */ +0x30,0x30,0x00,0xfc,0x00,0x30,0x30, /* 246 */ +0x76,0xdc,0x00,0x76,0xdc, /* 247 */ +0x70,0xd8,0xd8,0x70, /* 248 */ +0xc0,0xc0, /* 249 */ +0xc0, /* 250 */ +0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c, /* 251 */ +0xd8,0x6c,0x6c,0x6c,0x6c,0x6c, /* 252 */ +0x70,0xd8,0x30,0x60,0xc8,0xf8, /* 253 */ +0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, /* 254 */ + /* 255 */ +}; +int vgaFontMetaData[256*5]={ +0,8,9,0,0,9,8,10,0,0,19,8,10,0,0,29,8,8,0,0,37,8,7,0,1,44,8,9,0,0,53,8,9,0,0,62,8,4,2,2,66,8,16,0,-4,82,8,6,1,1,88,8,16,0,-4,104,8,10,0,0,114,8,10,1,0,124,8,10,0,0,134,8,11,0,-1,145,8,9,0,0,154,8,11,0,0,165,8,11,0,0,176,8,9,1,1,185,8,10,1,0,195,8,10,0,0,205,8,12,0,-1,217,8,4,0,0,221,8,10,1,0,231,8,10,1,0,241,8,10,1,0,251,8,5,0,2,256,8,5,0,2,261,8,4,0,2,265,8,5,0,2,270,8,7,0,1,277,8,7,0,1,284,8,0,0,0,284,8,10,2,0,294,8,4,1,7,298,8,9,0,0,307,8,14,0,-2,321,8,8,0,0,329,8,10,0,0,339,8,4,1,7,343,8,10,2,0,353,8,10,2,0,363,8,5,0,2,368,8,5,1,2,373,8,4,2,-1,377,8,1,0,4,378,8,2,3,0,380,8,8,0,0,388,8,10,0,0,398,8,10,1,0,408,8,10,0,0,418,8,10,0,0,428,8,10,0,0,438,8,10,0,0,448,8,10,0,0,458,8,10,0,0,468,8,10,0,0,478,8,10,0,0,488,8,7,3,1,495,8,8,2,0,503,8,9,1,0,512,8,4,1,3,516,8,9,1,0,525,8,10,0,0,535,8,9,0,0,544,8,10,0,0,554,8,10,0,0,564,8,10,0,0,574,8,10,0,0,584,8,10,0,0,594,8,10,0,0,604,8,10,0,0,614,8,10,0,0,624,8,10,2,0,634,8,10,0,0,644,8,10,0,0,654,8,10,0,0,664,8,10,0,0,674,8,10,0,0,684,8,10,0,0,694,8,10,0,0,704,8,12,0,-2,716,8,10,0,0,726,8,10,0,0,736,8,10,1,0,746,8,10,0,0,756,8,10,0,0,766,8,10,0,0,776,8,10,0,0,786,8,10,1,0,796,8,10,0,0,806,8,10,2,0,816,8,9,0,0,825,8,10,2,0,835,8,4,0,8,839,8,1,0,-2,840,8,3,2,9,843,8,7,0,0,850,8,10,0,0,860,8,7,0,0,867,8,10,0,0,877,8,7,0,0,884,8,10,0,0,894,8,10,0,-3,904,8,10,0,0,914,8,10,2,0,924,8,13,1,-3,937,8,10,0,0,947,8,10,2,0,957,8,7,0,0,964,8,7,0,0,971,8,7,0,0,978,8,10,0,-3,988,8,10,0,-3,998,8,7,0,0,1005,8,7,0,0,1012,8,10,0,0,1022,8,7,0,0,1029,8,7,1,0,1036,8,7,0,0,1043,8,7,0,0,1050,8,10,0,-3,1060,8,7,0,0,1067,8,10,1,0,1077,8,10,3,0,1087,8,10,1,0,1097,8,2,0,8,1099,8,7,0,1,1106,8,12,0,-2,1118,8,10,0,0,1128,8,11,0,0,1139,8,11,0,0,1150,8,10,0,0,1160,8,11,0,0,1171,8,11,0,0,1182,8,9,1,-1,1191,8,11,0,0,1202,8,10,0,0,1212,8,11,0,0,1223,8,10,1,0,1233,8,11,1,0,1244,8,11,1,0,1255,8,11,0,0,1266,8,12,0,0,1278,8,12,0,0,1290,8,7,0,0,1297,8,10,0,0,1307,8,11,0,0,1318,8,10,0,0,1328,8,11,0,0,1339,8,11,0,0,1350,8,11,0,0,1361,8,13,0,-3,1374,8,11,0,0,1385,8,11,0,0,1396,8,11,1,0,1407,8,11,0,0,1418,8,10,1,0,1428,8,11,0,0,1439,8,13,0,-2,1452,8,11,0,0,1463,8,11,2,0,1474,8,11,0,0,1485,8,11,0,0,1496,8,10,0,0,1506,8,12,0,0,1518,8,6,1,5,1524,8,6,1,5,1530,8,10,0,0,1540,8,5,0,1,1545,8,5,0,1,1550,8,13,0,-2,1563,8,13,0,-2,1576,8,10,2,0,1586,8,5,0,2,1591,8,5,0,2,1596,8,16,1,-4,1612,8,16,0,-4,1628,8,16,0,-4,1644,8,16,3,-4,1660,8,16,0,-4,1676,8,16,0,-4,1692,8,16,0,-4,1708,8,9,0,-4,1717,8,11,0,-4,1728,8,16,0,-4,1744,8,16,2,-4,1760,8,11,0,-4,1771,8,8,0,4,1779,8,8,0,4,1787,8,8,0,4,1795,8,9,0,-4,1804,8,8,3,4,1812,8,8,0,4,1820,8,9,0,-4,1829,8,16,3,-4,1845,8,1,0,4,1846,8,16,0,-4,1862,8,16,3,-4,1878,8,16,2,-4,1894,8,8,2,4,1902,8,11,2,-4,1913,8,8,0,4,1921,8,11,0,-4,1932,8,16,2,-4,1948,8,3,0,4,1951,8,16,0,-4,1967,8,8,0,4,1975,8,8,0,4,1983,8,11,0,-4,1994,8,9,0,-4,2003,8,8,2,4,2011,8,8,3,4,2019,8,11,3,-4,2030,8,9,2,-4,2039,8,16,0,-4,2055,8,16,0,-4,2071,8,8,0,4,2079,8,9,3,-4,2088,8,16,0,-4,2104,8,9,0,-4,2113,8,16,0,-4,2129,8,16,4,-4,2145,8,7,0,5,2152,8,7,0,0,2159,8,10,0,0,2169,8,10,0,0,2179,8,8,0,0,2187,8,9,0,0,2196,8,7,0,0,2203,8,9,0,-1,2212,8,8,0,0,2220,8,9,1,0,2229,8,9,0,0,2238,8,10,0,0,2248,8,10,1,0,2258,8,5,0,2,2263,8,9,0,0,2272,8,10,1,0,2282,8,9,0,0,2291,8,7,0,1,2298,8,8,0,0,2306,8,9,1,0,2315,8,9,1,0,2324,8,14,3,-4,2338,8,12,0,0,2350,8,7,1,1,2357,8,5,0,2,2362,8,4,1,7,2366,8,2,3,3,2368,8,1,3,3,2369,8,11,0,0,2380,8,6,0,5,2386,8,6,0,5,2392,8,7,1,1,2399,8,0,0,0,}; +rfbFontData vgaFont={vgaFontData, vgaFontMetaData}; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/.cvsignore new file mode 100755 index 0000000..27e9b7a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/.cvsignore @@ -0,0 +1,5 @@ +.deps +Makefile +Makefile.in +x11vnc + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.c new file mode 100755 index 0000000..4c55e02 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.c @@ -0,0 +1,2155 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- 8to24.c -- */ +#include "x11vnc.h" +#include "cleanup.h" +#include "scan.h" +#include "util.h" +#include "win_utils.h" +#include "xwrappers.h" + +int multivis_count = 0; +int multivis_24count = 0; + +void check_for_multivis(void); +void bpp8to24(int, int, int, int); +void mark_8bpp(int); + +#if SKIP_8TO24 +void check_for_multivis(void) {} +void bpp8to24(int x, int y, int z, int t) {} +void mark_8bpp(int x) {} +#else +/* lots... */ + +static void set_root_cmap(void); +static int check_pointer_in_depth24(void); +static void parse_cmap8to24(void); +static void set_poll_fb(void); +static int check_depth(Window win, Window top, int doall); +static int check_depth_win(Window win, Window top, XWindowAttributes *attr); +static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w); +static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod); +static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod); +static int poll_8bpp(sraRegionPtr, int); +static void poll_8bpp_complement(sraRegionPtr); +static void mark_rgn_rects(sraRegionPtr mod); +static int get_8bpp_regions(int validate); +static int get_cmap(int j, Colormap cmap); +static void do_8bpp_region(int n, sraRegionPtr mark); +static XImage *cmap_xi(XImage *xi, Window win, int win_depth); +static void transform_rect(sraRect rect, Window win, int win_depth, int cm); + +/* struct for keeping info about the 8bpp windows: */ +typedef struct window8 { + Window win; + Window top; + int depth; + int x, y; + int w, h; + int map_state; + Colormap cmap; + Bool map_installed; + int fetched; + double last_fetched; + sraRegionPtr clip_region; +} window8bpp_t; + +enum mark_8bpp_modes { + MARK_8BPP_ALL = 0, + MARK_8BPP_POINTER, + MARK_8BPP_TOP +}; + + +#define NCOLOR 256 + +static Colormap root_cmap = 0; +static unsigned int *root_rgb = NULL; + +static void set_root_cmap(void) { +#if NO_X11 + RAWFB_RET_VOID + return; +#else + static time_t last_set = 0; + time_t now = time(NULL); + XWindowAttributes attr; + static XColor *color = NULL; + int redo = 0; + int ncolor = 0; + + RAWFB_RET_VOID + + if (depth > 16) { + ncolor = NCOLOR; + } else if (depth > 8) { + ncolor = 1 << depth; + } else { + ncolor = NCOLOR; + } + + if (!root_rgb) { + root_rgb = (unsigned int *) malloc(ncolor * sizeof(unsigned int)); + } + if (!color) { + color = (XColor *) malloc(ncolor * sizeof(XColor)); + } + + if (now > last_set + 10) { + redo = 1; + } + if (! root_cmap || redo) { + X_LOCK; + if (! valid_window(window, &attr, 1)) { + X_UNLOCK; + return; + } + if (attr.colormap) { + int i, ncells = ncolor; + + if (depth < 8) { + ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); + } + for (i=0; i < ncells; i++) { + color[i].pixel = i; + color[i].pad = 0; + } + last_set = now; + root_cmap = attr.colormap; + XQueryColors(dpy, root_cmap, color, ncells); + for (i=0; i < ncells; i++) { + unsigned int red, green, blue; + /* strip out highest 8 bits of values: */ + red = (color[i].red & 0xff00) >> 8; + green = (color[i].green & 0xff00) >> 8; + blue = (color[i].blue & 0xff00) >> 8; + + /* + * the maxes should be at 255 already, + * but just in case... + */ + red = (main_red_max * red )/255; + green = (main_green_max * green)/255; + blue = (main_blue_max * blue )/255; + + /* shift them over and or together for value */ + red = red << main_red_shift; + green = green << main_green_shift; + blue = blue << main_blue_shift; + + /* store it in the array to be used later */ + root_rgb[i] = red | green | blue; + } + } + X_UNLOCK; + } +#endif /* NO_X11 */ +} + +/* fixed size array. Will primarily hold visible 8bpp windows */ +#define MAX_8BPP_WINDOWS 64 +static window8bpp_t windows_8bpp[MAX_8BPP_WINDOWS]; + +static int db24 = 0; +static int xgetimage_8to24 = 1; +static double poll_8to24_delay = POLL_8TO24_DELAY; +static double cache_win = 0.0; +static int level2_8to24 = 0; + +static int check_pointer_in_depth24(void) { + int tries = 0, in_24 = 0; + XWindowAttributes attr; + Window c, w; + double now = dnow(); + + c = window; + + RAWFB_RET(0) + + if (now > last_keyboard_time + 1.0 && now > last_pointer_time + 1.0) { + return 0; + } + + X_LOCK; + while (c && tries++ < 3) { + c = query_pointer(c); + if (valid_window(c, &attr, 1)) { + if (attr.depth == 24) { + in_24 = 1; + break; + } + } + } + X_UNLOCK; + if (in_24) { + int x1, y1, x2, y2; + X_LOCK; + xtranslate(c, window, 0, 0, &x1, &y1, &w, 1); + X_UNLOCK; + x2 = x1 + attr.width; + y2 = y1 + attr.height; + x1 = nfix(x1, dpy_x); + y1 = nfix(y1, dpy_y); + x2 = nfix(x2, dpy_x+1); + y2 = nfix(y2, dpy_y+1); + mark_rect_as_modified(x1, y1, x2, y2, 0); + +if (db24 > 1) fprintf(stderr, "check_pointer_in_depth24 %d %d %d %d\n", x1, y1, x2, y2); + + return 1; + } + return 0; +} + +static void parse_cmap8to24(void) { + if (cmap8to24_str) { + char *p, *str = strdup(cmap8to24_str); + p = strtok(str, ","); + /* defaults: */ + db24 = 0; + xgetimage_8to24 = 1; + poll_8to24_delay = POLL_8TO24_DELAY; + level2_8to24 = 0; + cache_win = 0.0; + while (p) { + if (strstr(p, "dbg=") == p) { + db24 = atoi(p + strlen("dbg=")); + } else if (strstr(p, "poll=") == p) { + poll_8to24_delay = atof(p + strlen("poll=")); + } else if (strstr(p, "cachewin=") == p) { + cache_win = atof(p + strlen("cachewin=")); + } else if (!strcmp(p, "nogetimage")) { + xgetimage_8to24 = 0; + } else if (!strcmp(p, "level2")) { + level2_8to24 = 1; + } + p = strtok(NULL, ","); + } + free(str); + } else { + if (getenv("DEBUG_8TO24") != NULL) { + db24 = atoi(getenv("DEBUG_8TO24")); + } + if (getenv("NOXGETIMAGE_8TO24") != NULL) { + xgetimage_8to24 = 0; + } + } +} + +static char *poll8_fb = NULL, *poll24_fb = NULL; +static int poll8_fb_w = 0, poll8_fb_h = 0; +static int poll24_fb_w = 0, poll24_fb_h = 0; + +static void pfb(int fac, char **fb, int *w, int *h) { + if (! *fb || *w != dpy_x || *h != dpy_y) { + if (*fb) { + free(*fb); + } + *fb = (char *) calloc(fac * dpy_x * dpy_y, 1); + *w = dpy_x; + *h = dpy_y; + } +} + +static void set_poll_fb(void) { + /* create polling framebuffers or recreate if too small. */ + + if (! xgetimage_8to24) { + return; /* this saves a bit of RAM */ + } + pfb(4, &poll24_fb, &poll24_fb_w, &poll24_fb_h); + if (depth > 8 && depth <= 16) { + pfb(2, &poll8_fb, &poll8_fb_w, &poll8_fb_h); /* 2X for rare 16bpp colormap case */ + } else { + pfb(1, &poll8_fb, &poll8_fb_w, &poll8_fb_h); + } +} + +int MV_glob = 0; +int MV_count; +int MV_hit; +double MV_start; + +void check_for_multivis(void) { +#if NO_X11 + RAWFB_RET_VOID + return; +#else + XWindowAttributes attr; + int doall = 0; + int k, i, cnt, diff; + static int first = 1; + static Window *stack_old = NULL; + static int stack_old_len = 0; + static double last_parse = 0.0; + static double last_update = 0.0; + static double last_clear = 0.0; + static double last_poll = 0.0; + static double last_fixup = 0.0; + static double last_call = 0.0; + static double last_query = 0.0; + double now = dnow(); + double delay; + + RAWFB_RET_VOID + + if (now > last_parse + 1.0) { + last_parse = now; + parse_cmap8to24(); + } +if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); + last_call = now; + + if (first) { + int i; + /* initialize 8bpp window table: */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + windows_8bpp[i].win = None; + windows_8bpp[i].top = None; + windows_8bpp[i].map_state = IsUnmapped; + windows_8bpp[i].cmap = (Colormap) 0; + windows_8bpp[i].fetched = 0; + windows_8bpp[i].last_fetched = -1.0; + windows_8bpp[i].clip_region = NULL; + } + set_poll_fb(); + + first = 0; + doall = 1; /* fetch everything first time */ + } + + if (wireframe_in_progress) { + return; + } + + set_root_cmap(); + + /* + * allocate an "old stack" list of all toplevels. we compare + * this to the current stack to guess stacking order changes. + */ + if (!stack_old || stack_old_len < stack_list_len) { + int n = stack_list_len; + if (n < 256) { + n = 256; + } + if (stack_old) { + free(stack_old); + } + stack_old = (Window *) calloc(n*sizeof(Window), 1); + stack_old_len = n; + } + + /* fill the old stack with visible windows: */ + cnt = 0; + for (k=0; k < stack_list_num; k++) { + if (stack_list[k].valid && + stack_list[k].map_state == IsViewable) { + stack_old[cnt++] = stack_list[k].win; + } + } + + /* snapshot + update the current stacking order: */ + /* TUNABLE */ + if (poll_8to24_delay >= POLL_8TO24_DELAY) { + delay = 3.0 * poll_8to24_delay; + } else { + delay = 3.0 * POLL_8TO24_DELAY; /* 0.15 */ + } + if (doall || now > last_update + delay) { + snapshot_stack_list(0, 0.0); + update_stack_list(); + last_update = now; + } + + /* look for differences in the visible toplevels: */ + diff = 0; + cnt = 0; + for (k=0; k < stack_list_num; k++) { + if (stack_list[k].valid && stack_list[k].map_state == + IsViewable) { + if (stack_old[cnt] != stack_list[k].win) { + diff = 1; + break; + } + cnt++; + } + } + + multivis_count = 0; + multivis_24count = 0; + + /* + * every 10 seconds we try to clean out and also refresh the window + * info in the the 8bpp window table: + */ + if (now > last_clear + 10) { + last_clear = now; + X_LOCK; + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + Window w = windows_8bpp[i].win; + if (! valid_window(w, &attr, 1)) { + /* catch windows that went away: */ + windows_8bpp[i].win = None; + windows_8bpp[i].top = None; + windows_8bpp[i].map_state = IsUnmapped; + windows_8bpp[i].cmap = (Colormap) 0; + windows_8bpp[i].fetched = 0; + windows_8bpp[i].last_fetched = -1.0; + } + } + X_UNLOCK; + } + + MV_count = 0; + MV_hit = 0; + MV_start = dnow(); + + set_root_cmap(); + + /* loop over all toplevels, both 8 and 24 depths: */ + + X_LOCK; /* a giant lock around the whole activity */ + + for (k=0; k < stack_list_num; k++) { + Window r, parent; + Window *list0; + Status rc; + unsigned int nc0; + int i1; + XErrorHandler old_handler; + double delay; + + Window win = stack_list[k].win; + + /* TUNABLE */ + if (poll_8to24_delay >= POLL_8TO24_DELAY) { + delay = 1.5 * poll_8to24_delay; + } else { + delay = 1.5 * POLL_8TO24_DELAY; /* 0.075 */ + } + + if (now < last_query + delay) { + break; + } + + if (win == None) { + continue; + } + + if (stack_list[k].map_state != IsViewable) { + int i; + /* + * if the toplevel became unmapped, mark it + * for the children as well... + */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + if (windows_8bpp[i].top == win) { + windows_8bpp[i].map_state = + stack_list[k].map_state; + } + } + } + + if (check_depth(win, win, doall)) { + /* + * returns 1 if no need to recurse down e.g. It + * is 8bpp and we assume all lower ones are too. + */ + continue; + } + + /* we recurse up to two levels down from stack_list windows */ + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + rc = XQueryTree_wr(dpy, win, &r, &parent, &list0, &nc0); + XSetErrorHandler(old_handler); + + if (! rc || trapped_xerror) { + trapped_xerror = 0; + continue; + } + trapped_xerror = 0; + + /* loop over grandchildren of rootwin: */ + for (i1=0; i1 < (int) nc0; i1++) { + Window win1 = list0[i1]; + Window *list1; + unsigned int nc1; + int i2; + + if (check_depth(win1, win, doall)) { + continue; + } + + if (level2_8to24) { + continue; + } + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + rc = XQueryTree_wr(dpy, win1, &r, &parent, &list1, &nc1); + XSetErrorHandler(old_handler); + + if (! rc || trapped_xerror) { + trapped_xerror = 0; + continue; + } + trapped_xerror = 0; + + /* loop over great-grandchildren of rootwin: */ + for (i2=0; i2< (int) nc1; i2++) { + Window win2 = list1[i2]; + + if (check_depth(win2, win, doall)) { + continue; + } + /* more? Which wm does this? */ + } + if (nc1) { + XFree_wr(list1); + } + } + if (nc0) { + XFree_wr(list0); + } + } + X_UNLOCK; + + last_query = dnow(); + +MV_glob += MV_count; +if (0) fprintf(stderr, "MV_count: %d hit: %d %.4f %10.2f\n", MV_count, MV_hit, last_query - MV_start, MV_glob / (last_query - x11vnc_start)); + + if (screen_fixup_8 > 0.0 && now > last_fixup + screen_fixup_8) { + last_fixup = now; + mark_8bpp(MARK_8BPP_ALL); + last_poll = now; + + } else if (poll_8to24_delay > 0.0) { + int area = -1; + int validate = 0; + + if (diff && multivis_count) { + validate = 1; + } + if (now > last_poll + poll_8to24_delay) { + sraRegionPtr mod; + + last_poll = now; + mod = sraRgnCreate(); + area = poll_8bpp(mod, validate); + if (depth == 24) { + poll_8bpp_complement(mod); + } + mark_rgn_rects(mod); + sraRgnDestroy(mod); + } + if (0 && area < dpy_x * dpy_y / 2 && diff && multivis_count) { + mark_8bpp(MARK_8BPP_POINTER); + last_poll = now; + } + + } else if (diff && multivis_count) { + mark_8bpp(MARK_8BPP_ALL); + last_poll = now; + + } else if (depth <= 16 && multivis_24count) { + static double last_check = 0.0; + if (now > last_check + 0.4) { + last_check = now; + if (check_pointer_in_depth24()) { + last_poll = now; + } + } + } +if (0) fprintf(stderr, "done: %.4f\n", dnow() - last_query); +#endif /* NO_X11 */ +} + +#define VW_CACHE_MAX 1024 +static XWindowAttributes vw_cache_attr[VW_CACHE_MAX]; +static Window vw_cache_win[VW_CACHE_MAX]; + +static void set_attr(XWindowAttributes *attr, int j) { + memcpy((void *) (vw_cache_attr+j), (void *) attr, + sizeof(XWindowAttributes)); +} +#if 0 +static int get_attr(XWindowAttributes *attr, int j) { + memcpy((void *) attr, (void *) (vw_cache_attr+j), + sizeof(XWindowAttributes)); + return 1; +} +#endif + +static XWindowAttributes wattr; + +static XWindowAttributes *vw_lookup(Window win) { + static double last_purge = 0.0; + double now; + int i, j, k; + + if (win == None) { + return NULL; + } + + now = dnow(); + if (now > last_purge + cache_win) { + last_purge = now; + for (i=0; i= 0) { +MV_hit++; + return vw_cache_attr+j; + + } else if (k >= 0) { + XWindowAttributes attr2; + int rc = valid_window(win, &attr2, 1); + if (rc) { + vw_cache_win[k] = win; + set_attr(&attr2, k); + return vw_cache_attr+k; + } else { + return NULL; + } + } else { + /* Full */ + int rc = valid_window(win, &wattr, 1); + if (rc) { + return &wattr; + } else { + return NULL; + } + } +} + +static int check_depth(Window win, Window top, int doall) { + XWindowAttributes attr, *pattr; + + /* first see if it is (still) a valid window: */ +MV_count++; + + if (cache_win > 0.0) { + pattr = vw_lookup(win); + if (pattr == NULL) { + return 1; /* indicate done */ + } + } else { + if (! valid_window(win, &attr, 1)) { + return 1; /* indicate done */ + } + pattr = &attr; + } + + if (! doall && pattr->map_state != IsViewable) { + /* + * store results anyway... this may lead to table + * filling up, but currently this allows us to update + * state of onetime mapped windows. + */ + check_depth_win(win, top, pattr); + return 1; /* indicate done */ + } else if (check_depth_win(win, top, pattr)) { + return 1; /* indicate done */ + } else { + return 0; /* indicate not done */ + } +} + +static int check_depth_win(Window win, Window top, XWindowAttributes *attr) { + int store_it = 0; + /* + * only store windows with depth not equal to the default visual's + * depth note some windows can have depth == 0 ... (skip them). + */ + if (attr->depth > 0) { + if (depth == 24 && attr->depth != 24) { + store_it = 1; + } else if (depth <= 16 && root_cmap && attr->colormap != root_cmap) { + store_it = 1; + } + } + + if (store_it) { + int i, j = -1, none = -1, nomap = -1; + int new = 0; + if (attr->map_state == IsViewable) { + /* count the visible ones: */ + multivis_count++; + if (attr->depth == 24) { + multivis_24count++; + } +if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr->depth); + } + + /* try to find a table slot for this window: */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + if (none < 0 && windows_8bpp[i].win == None) { + /* found first None */ + none = i; + } + if (windows_8bpp[i].win == win) { + /* found myself */ + j = i; + break; + } + if (nomap < 0 && windows_8bpp[i].win != None && + windows_8bpp[i].map_state != IsViewable) { + /* found first unmapped */ + nomap = i; + } + } + if (j < 0) { + if (attr->map_state != IsViewable) { + /* no slot and not visible: not worth keeping */ + return 1; + } else if (none >= 0) { + /* put it in the first None slot */ + j = none; + new = 1; + } else if (nomap >=0) { + /* put it in the first unmapped slot */ + j = nomap; + } + /* otherwise we cannot store it... */ + } + +if (db24 > 1) fprintf(stderr, "multivis: 0x%lx ms: %d j: %d no: %d nm: %d dep=%d\n", win, attr->map_state, j, none, nomap, attr->depth); + + /* store if if we found a slot j: */ + if (j >= 0) { + Window w; + int x, y; + int now_vis = 0; + + if (attr->map_state == IsViewable && + windows_8bpp[j].map_state != IsViewable) { + now_vis = 1; + } +if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", win, j, attr->map_state, attr->depth); + windows_8bpp[j].win = win; + windows_8bpp[j].top = top; + windows_8bpp[j].depth = attr->depth; + windows_8bpp[j].map_state = attr->map_state; + windows_8bpp[j].cmap = attr->colormap; + windows_8bpp[j].map_installed = attr->map_installed; + windows_8bpp[j].w = attr->width; + windows_8bpp[j].h = attr->height; + windows_8bpp[j].fetched = 1; + windows_8bpp[j].last_fetched = dnow(); + + /* translate x y to be WRT the root window (not parent) */ + xtranslate(win, window, 0, 0, &x, &y, &w, 1); + windows_8bpp[j].x = x; + windows_8bpp[j].y = y; + + if (new || now_vis) { +if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, new, now_vis); + /* mark it immediately if a new one: */ + X_UNLOCK; /* dont forget the giant lock */ + mark_rect_as_modified(x, y, x + attr->width, + y + attr->height, 0); + X_LOCK; + } + } else { + /* + * Error: could not find a slot. + * perhaps keep age and expire old ones?? + */ +if (db24) fprintf(stderr, "multivis: CANNOT STORE 0x%lx j=%d\n", win, j); + for (i=0; i < MAX_8BPP_WINDOWS; i++) { +if (db24 > 1) fprintf(stderr, " ------------ 0x%lx i=%d\n", windows_8bpp[i].win, i); + } + + } + return 1; + } + return 0; +} + +/* polling line XImage */ +static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w) { + RAWFB_RET(NULL) + +#if NO_X11 + if (!xi || !visual || !win_depth || !w) {} + return NULL; +#else + if (xi == NULL || *w < dpy_x) { + char *d; + if (xi) { + XDestroyImage(xi); + } + if (win_depth != 24) { + if (win_depth > 8) { + d = (char *) malloc(dpy_x * 2); + } else { + d = (char *) malloc(dpy_x * 1); + } + } else { + d = (char *) malloc(dpy_x * 4); + } + *w = dpy_x; + xi = XCreateImage(dpy, visual, win_depth, ZPixmap, 0, d, + dpy_x, 1, 8, 0); + } + return xi; +#endif /* NO_X11 */ +} + +static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) { +#if NO_X11 + RAWFB_RET(1) + if (!x1 || !x2 || !y1 || !n || !mod) {} + return 1; +#else + int fac, n_off, w, xo, yo; + char *poll_fb, *dst, *src; + int w2, xl, xh, stride = 32; + int inrun = 0, rx1 = -1, rx2 = -1; + + static XImage *xi8 = NULL, *xi24 = NULL, *xi_r; + static int xi8_w = 0, xi24_w = 0; + + XErrorHandler old_handler = NULL; + XImage *xi; + Window c, win = windows_8bpp[n].win; + + static XWindowAttributes attr; + static Window last_win = None; + static double last_time = 0.0; + double now; + + sraRegionPtr rect; + int mx1, mx2, my1, my2; + int ns = NSCAN/2; + + RAWFB_RET(1) + + if (win == None) { + return 1; + } + if (windows_8bpp[n].map_state != IsViewable) { + return 1; + } + if (! xgetimage_8to24) { + return 1; + } + + X_LOCK; + now = dnow(); + if (last_win != None && win == last_win && now < last_time + 0.5) { + ; /* use previous attr */ + } else { + if (! valid_window(win, &attr, 1)) { + X_UNLOCK; + last_win = None; + return 0; + } + last_time = now; + last_win = win; + } + + if (attr.depth > 16 && attr.depth != 24) { + X_UNLOCK; + return 1; + } else if (attr.depth <= 16) { + xi = xi8 = p_xi(xi8, attr.visual, attr.depth, &xi8_w); + + poll_fb = poll8_fb; + if (attr.depth > 8) { + fac = 2; + } else { + fac = 1; + } + n_off = poll8_fb_w * y1 + x1; + } else { + xi = xi24 = p_xi(xi24, attr.visual, 24, &xi24_w); + + poll_fb = poll24_fb; + fac = 4; + n_off = poll24_fb_w * y1 + x1; + } + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + + /* xtranslate() not used to save two XSetErrorHandler calls */ + XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c); + + xo = x1 - xo; + yo = y1 - yo; + w = x2 - x1; + + if (trapped_xerror || xo < 0 || yo < 0 || xo + w > attr.width) { +if (db24 > 2) fprintf(stderr, "avoid bad match...\n"); + XSetErrorHandler(old_handler); + trapped_xerror = 0; + X_UNLOCK; + return 0; + } + + trapped_xerror = 0; + xi_r = XGetSubImage(dpy, win, xo, yo, w, 1, AllPlanes, ZPixmap, xi, + 0, 0); + XSetErrorHandler(old_handler); + + X_UNLOCK; + + if (! xi_r || trapped_xerror) { + trapped_xerror = 0; + return 0; + } + trapped_xerror = 0; + + src = xi->data; + dst = poll_fb + fac * n_off; + + inrun = 0; + + xl = x1; + while (xl < x2) { + xh = xl + stride; + if (xh > x2) { + xh = x2; + } + w2 = xh - xl; + if (memcmp(dst, src, fac * w2)) { + if (inrun) { + rx2 = xh; + } else { + rx1 = xl; + rx2 = xh; + inrun = 1; + } + } else { + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + inrun = 0; + } + } + + xl += stride; + dst += fac * stride; + src += fac * stride; + } + + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + } + return 1; +#endif /* NO_X11 */ +} + +static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod) { + int n_off, w, xl, xh, stride = 32; + char *dst, *src; + int inrun = 0, rx1 = -1, rx2 = -1; + sraRegionPtr rect; + int mx1, mx2, my1, my2; + int ns = NSCAN/2; + + if (depth != 24) { + return; + } + if (! cmap8to24_fb) { + return; + } + if (! xgetimage_8to24) { + return; + } + + n_off = main_bytes_per_line * y1 + 4 * x1; + + src = main_fb + n_off; + dst = cmap8to24_fb + n_off; + + inrun = 0; + + xl = x1; + while (xl < x2) { + xh = xl + stride; + if (xh > x2) { + xh = x2; + } + w = xh - xl; + if (memcmp(dst, src, 4 * w)) { + if (inrun) { + rx2 = xh; + } else { + rx1 = xl; + rx2 = xh; + inrun = 1; + } + } else { + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + + inrun = 0; + } + } + + xl += stride; + dst += 4 * stride; + src += 4 * stride; + } + + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + + inrun = 0; + } +} + +#define CMAPMAX 64 +static Colormap cmaps[CMAPMAX]; +static int ncmaps; + +static int poll_8bpp(sraRegionPtr mod, int validate) { + int i, y, ysh, map_count; + static int ycnt = 0; + sraRegionPtr line; + sraRect rect; + sraRectangleIterator *iter; + int br = 0, area = 0; + static double last_call = 0.0; + + map_count = get_8bpp_regions(validate); + +if (db24 > 1) fprintf(stderr, "poll_8bpp mc: %d\n", map_count); + + if (! map_count) { + return 0; + } + + set_poll_fb(); + + ysh = scanlines[(ycnt++) % NSCAN]; +if (db24 > 2) fprintf(stderr, "poll_8bpp: ysh: %2d %.4f\n", ysh, dnow() - last_call); + last_call = dnow(); + + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr reg = windows_8bpp[i].clip_region; + + if (! reg || sraRgnEmpty(reg)) { + continue; + } + y = ysh; + while (y < dpy_y) { + line = sraRgnCreateRect(0, y, dpy_x, y+1); + + if (sraRgnAnd(line, reg)) { + iter = sraRgnGetIterator(line); + while (sraRgnIteratorNext(iter, &rect)) { + if (! poll_line(rect.x1, rect.x2, + rect.y1, i, mod)) { + br = 1; + break; /* exception */ + } + } + sraRgnReleaseIterator(iter); + } + + sraRgnDestroy(line); + y += NSCAN; + if (br) break; + } + if (br) break; + } + + iter = sraRgnGetIterator(mod); + while (sraRgnIteratorNext(iter, &rect)) { + area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1)); + } + sraRgnReleaseIterator(iter); + + return area; +} + +static void poll_8bpp_complement(sraRegionPtr mod) { + int i, y, ysh; + static int ycnt = 0; + sraRegionPtr disp, line; + sraRect rect; + sraRectangleIterator *iter; + + disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y); + + ysh = scanlines[(ycnt++) % NSCAN]; + + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr reg = windows_8bpp[i].clip_region; + + if (! reg) { + continue; + } + if (windows_8bpp[i].map_state != IsViewable) { + continue; + } + sraRgnSubtract(disp, reg); + } + + y = ysh; + while (y < dpy_y) { + line = sraRgnCreateRect(0, y, dpy_x, y+1); + + if (sraRgnAnd(line, disp)) { + iter = sraRgnGetIterator(line); + while (sraRgnIteratorNext(iter, &rect)) { + poll_line_complement(rect.x1, rect.x2, + rect.y1, mod); + } + sraRgnReleaseIterator(iter); + } + + sraRgnDestroy(line); + + y += NSCAN; + } + + sraRgnDestroy(disp); +} + +static void mark_rgn_rects(sraRegionPtr mod) { + sraRect rect; + sraRectangleIterator *iter; + int area = 0; + + if (sraRgnEmpty(mod)) { + return; + } + + iter = sraRgnGetIterator(mod); + while (sraRgnIteratorNext(iter, &rect)) { + mark_rect_as_modified(rect.x1, rect.y1, rect.x2, rect.y2, 0); + area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1)); + } + sraRgnReleaseIterator(iter); + +if (db24 > 1) fprintf(stderr, " mark_rgn_rects area: %d\n", area); +} + +static int get_8bpp_regions(int validate) { + + XWindowAttributes attr; + int i, k, mapcount = 0; + + /* initialize color map list */ + ncmaps = 0; + for (i=0; i < CMAPMAX; i++) { + cmaps[i] = (Colormap) 0; + } + + /* loop over the table of 8bpp windows: */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr tmp_reg, tmp_reg2; + Window c, w = windows_8bpp[i].win; + int x, y; + + if (windows_8bpp[i].clip_region) { + sraRgnDestroy(windows_8bpp[i].clip_region); + } + windows_8bpp[i].clip_region = NULL; + + if (w == None) { + continue; + } + +if (db24 > 1) fprintf(stderr, "get_8bpp_regions: 0x%lx ms=%d dep=%d i=%d\n", w, windows_8bpp[i].map_state, windows_8bpp[i].depth, i); + if (validate) { + /* + * this could be slow: validating 8bpp windows each + * time... + */ + + X_LOCK; + if (! valid_window(w, &attr, 1)) { + X_UNLOCK; + windows_8bpp[i].win = None; + windows_8bpp[i].top = None; + windows_8bpp[i].map_state = IsUnmapped; + windows_8bpp[i].cmap = (Colormap) 0; + windows_8bpp[i].fetched = 0; + windows_8bpp[i].last_fetched = -1.0; + continue; + } + X_UNLOCK; + + windows_8bpp[i].depth = attr.depth; + windows_8bpp[i].map_state = attr.map_state; + windows_8bpp[i].cmap = attr.colormap; + windows_8bpp[i].map_installed = attr.map_installed; + windows_8bpp[i].w = attr.width; + windows_8bpp[i].h = attr.height; + windows_8bpp[i].fetched = 1; + windows_8bpp[i].last_fetched = dnow(); + + if (attr.map_state != IsViewable) { + continue; + } + + X_LOCK; + xtranslate(w, window, 0, 0, &x, &y, &c, 1); + X_UNLOCK; + windows_8bpp[i].x = x; + windows_8bpp[i].y = y; + + } else { + /* this will be faster: no call to X server: */ + if (windows_8bpp[i].map_state != IsViewable) { + continue; + } + attr.depth = windows_8bpp[i].depth; + attr.map_state = windows_8bpp[i].map_state; + attr.colormap = windows_8bpp[i].cmap; + attr.map_installed = windows_8bpp[i].map_installed; + attr.width = windows_8bpp[i].w; + attr.height = windows_8bpp[i].h; + + x = windows_8bpp[i].x; + y = windows_8bpp[i].y; + } + + mapcount++; + + /* tmp region for this 8bpp rectangle: */ + tmp_reg = sraRgnCreateRect(nfix(x, dpy_x), nfix(y, dpy_y), + nfix(x + attr.width, dpy_x+1), nfix(y + attr.height, dpy_y+1)); + + /* loop over all toplevels, top to bottom clipping: */ + for (k = stack_list_num - 1; k >= 0; k--) { + Window swin = stack_list[k].win; + int sx, sy, sw, sh; + +if (db24 > 1 && stack_list[k].map_state == IsViewable) fprintf(stderr, "Stack win: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state); + + if (swin == windows_8bpp[i].top) { + /* found our top level: we skip the rest. */ +if (db24 > 1) fprintf(stderr, "found top: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state); + break; + } + if (stack_list[k].map_state != IsViewable) { + /* skip unmapped ones: */ + continue; + } + + /* make a temp rect for this toplevel: */ + sx = stack_list[k].x; + sy = stack_list[k].y; + sw = stack_list[k].width; + sh = stack_list[k].height; + +if (db24 > 1) fprintf(stderr, "subtract: 0x%lx %d -- %d %d %d %d\n", swin, k, sx, sy, sw, sh); + + tmp_reg2 = sraRgnCreateRect(nfix(sx, dpy_x), + nfix(sy, dpy_y), nfix(sx + sw, dpy_x+1), + nfix(sy + sh, dpy_y+1)); + + /* subtract it from the 8bpp window region */ + sraRgnSubtract(tmp_reg, tmp_reg2); + + sraRgnDestroy(tmp_reg2); + + if (sraRgnEmpty(tmp_reg)) { + break; + } + } + + if (sraRgnEmpty(tmp_reg)) { + /* skip this 8bpp if completely clipped away: */ + sraRgnDestroy(tmp_reg); + continue; + } + + /* otherwise, store any new colormaps: */ + if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) { + int m, seen = 0; + for (m=0; m < ncmaps; m++) { + if (cmaps[m] == attr.colormap) { + seen = 1; + break; + } + } + if (!seen && attr.depth <= 16) { + /* store only new ones: */ + cmaps[ncmaps++] = attr.colormap; + } + } + + windows_8bpp[i].clip_region = tmp_reg; + } + + return mapcount; +} + +static XColor *color[CMAPMAX]; +static unsigned int *rgb[CMAPMAX]; +static int cmap_failed[CMAPMAX]; +static int color_init = 0; +int histo[65536]; + +static int get_cmap(int j, Colormap cmap) { +#if NO_X11 + RAWFB_RET(0) + if (!j || !cmap) {} + return 0; +#else + int i, ncells, ncolor; + XErrorHandler old_handler = NULL; + + RAWFB_RET(0) + + if (depth > 16) { + /* 24 */ + ncolor = NCOLOR; + } else if (depth > 8) { + ncolor = 1 << depth; + } else { + ncolor = NCOLOR; + } + if (!color_init) { + int cm; + for (cm = 0; cm < CMAPMAX; cm++) { + color[cm] = (XColor *) malloc(ncolor * sizeof(XColor)); + rgb[cm] = (unsigned int *) malloc(ncolor * sizeof(unsigned int)); + } + color_init = 1; + } + + if (depth <= 16) { + /* not working properly for depth 24... */ + X_LOCK; + ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); + X_UNLOCK; + } else { + ncells = NCOLOR; + } + + if (depth > 16) { + ; + } else if (ncells > ncolor) { + ncells = ncolor; + } else if (ncells == 8 && depth != 3) { + /* XXX. see set_colormap() */ + ncells = 1 << depth; + } + + /* initialize XColor array: */ + for (i=0; i < ncells; i++) { + color[j][i].pixel = i; + color[j][i].pad = 0; + } +if (db24 > 1) fprintf(stderr, "get_cmap: %d 0x%x ncolor=%d ncells=%d\n", j, (unsigned int) cmap, ncolor, ncells); + + /* try to query the colormap, trap errors */ + X_LOCK; + trapped_xerror = 0; + old_handler = XSetErrorHandler(trap_xerror); + XQueryColors(dpy, cmap, color[j], ncells); + XSetErrorHandler(old_handler); + X_UNLOCK; + + if (trapped_xerror) { + trapped_xerror = 0; + return 0; + } + trapped_xerror = 0; + + /* now map each index to depth 24 RGB */ + for (i=0; i < ncells; i++) { + unsigned int red, green, blue; + /* strip out highest 8 bits of values: */ + red = (color[j][i].red & 0xff00) >> 8; + green = (color[j][i].green & 0xff00) >> 8; + blue = (color[j][i].blue & 0xff00) >> 8; + + /* + * the maxes should be at 255 already, + * but just in case... + */ + red = (main_red_max * red )/255; + green = (main_green_max * green)/255; + blue = (main_blue_max * blue )/255; + +if (db24 > 2) fprintf(stderr, " cmap[%02d][%03d]: %03d %03d %03d 0x%08x \n", j, i, red, green, blue, ( red << main_red_shift | green << main_green_shift | blue << main_blue_shift)); + + /* shift them over and or together for value */ + red = red << main_red_shift; + green = green << main_green_shift; + blue = blue << main_blue_shift; + + /* store it in the array to be used later */ + rgb[j][i] = red | green | blue; + } + return 1; +#endif /* NO_X11 */ +} + +static void do_8bpp_region(int n, sraRegionPtr mark) { + int k, cm = -1, failed = 0; + sraRectangleIterator *iter; + sraRegionPtr clip; + sraRect rect; + + if (! windows_8bpp[n].clip_region) { + return; + } + if (windows_8bpp[n].win == None) { + return; + } + if (windows_8bpp[n].map_state != IsViewable) { + return; + } +if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps); + + /* see if XQueryColors failed: */ + for (k=0; k rect.x2) { + int tmp = rect.x2; + rect.x2 = rect.x1; + rect.x1 = tmp; + } + if (rect.y1 > rect.y2) { + int tmp = rect.y2; + rect.y2 = rect.y1; + rect.y1 = tmp; + } + + transform_rect(rect, windows_8bpp[n].win, + windows_8bpp[n].depth, cm); + } + sraRgnReleaseIterator(iter); + sraRgnDestroy(clip); +} + +static XImage *cmap_xi(XImage *xi, Window win, int win_depth) { +#if NO_X11 + if (!xi || !win || !win_depth) {} + return NULL; +#else + XWindowAttributes attr; + char *d; + + if (xi) { + XDestroyImage(xi); + } + if (! dpy || ! valid_window(win, &attr, 1)) { + return (XImage *) NULL; + } + if (win_depth == 24) { + d = (char *) malloc(dpy_x * dpy_y * 4); + } else if (win_depth <= 16) { + if (win_depth > 8) { + d = (char *) malloc(dpy_x * dpy_y * 2); + } else { + d = (char *) malloc(dpy_x * dpy_y * 1); + } + } else { + return (XImage *) NULL; + } + return XCreateImage(dpy, attr.visual, win_depth, ZPixmap, 0, d, dpy_x, dpy_y, 8, 0); +#endif /* NO_X11 */ +} + + +static void transform_rect(sraRect rect, Window win, int win_depth, int cm) { +#if NO_X11 + RAWFB_RET_VOID + if (!rect.x1 || !win || !win_depth || !cm) {} + return; +#else + + char *src, *dst, *poll; + unsigned int *ui; + unsigned short *us; + unsigned char *uc; + int ps, pixelsize = bpp/8; + int poll_Bpl; + + int do_getimage = xgetimage_8to24; + int line, n_off, j, h, w; + unsigned int hi, idx; + XWindowAttributes attr; + XErrorHandler old_handler = NULL; + +if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rect.y1, rect.x2, rect.y2, cm); + + RAWFB_RET_VOID + + attr.width = 0; + attr.height = 0; + + /* now transform the pixels in this rectangle: */ + n_off = main_bytes_per_line * rect.y1 + pixelsize * rect.x1; + + h = rect.y2 - rect.y1; + w = rect.x2 - rect.x1; + + if (depth != 24) { + /* need to fetch depth 24 data. */ + do_getimage = 1; + } + +#if 0 + if (do_getimage) { + X_LOCK; + vw = valid_window(win, &attr, 1); + X_UNLOCK; + } + + if (do_getimage && vw) { +#else + if (do_getimage) { +#endif + static XImage *xi_8 = NULL; + static XImage *xi_24 = NULL; + XImage *xi = NULL, *xi_r; + Window c; + unsigned int wu, hu; + int xo, yo; + + wu = (unsigned int) w; + hu = (unsigned int) h; + + X_LOCK; +#define GETSUBIMAGE +#ifdef GETSUBIMAGE + if (win_depth == 24) { + if (xi_24 == NULL || xi_24->width != dpy_x || + xi_24->height != dpy_y) { + xi_24 = cmap_xi(xi_24, win, 24); + } + xi = xi_24; + } else if (win_depth <= 16) { + if (xi_8 == NULL || xi_8->width != dpy_x || + xi_8->height != dpy_y) { + if (win_depth > 8) { + /* XXX */ + xi_8 = cmap_xi(xi_8, win, 16); + } else { + xi_8 = cmap_xi(xi_8, win, 8); + } + } + xi = xi_8; + } +#endif + + if (xi == NULL) { + rfbLog("transform_rect: xi is NULL\n"); + X_UNLOCK; + clean_up_exit(1); + } + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + + XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c); + + xo = rect.x1 - xo; + yo = rect.y1 - yo; + +if (db24 > 1) fprintf(stderr, "xywh: %d %d %d %d vs. %d %d\n", xo, yo, w, h, attr.width, attr.height); + + if (trapped_xerror || xo < 0 || yo < 0) { + /* w > attr.width || h > attr.height */ + XSetErrorHandler(old_handler); + X_UNLOCK; + trapped_xerror = 0; +if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n"); + return; + } + trapped_xerror = 0; + +#ifndef GETSUBIMAGE + xi = XGetImage(dpy, win, xo, yo, wu, hu, AllPlanes, ZPixmap); + xi_r = xi; +#else + xi_r = XGetSubImage(dpy, win, xo, yo, wu, hu, AllPlanes, + ZPixmap, xi, 0, 0); +#endif + XSetErrorHandler(old_handler); + + X_UNLOCK; + + if (! xi_r || trapped_xerror) { + trapped_xerror = 0; +if (db24 > 1) fprintf(stderr, "xi-fail: 0x%p trap=%d %d %d %d %d\n", (void *)xi, trapped_xerror, xo, yo, w, h); + return; + } else { +if (db24 > 1) fprintf(stderr, "xi: 0x%p %d %d %d %d -- %d %d\n", (void *)xi, xo, yo, w, h, xi->width, xi->height); + } + trapped_xerror = 0; + + if (xi->depth > 16 && xi->depth != 24) { +#ifndef GETSUBIMAGE + X_LOCK; + XDestroyImage(xi); + X_UNLOCK; +#endif +if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); + return; + } + + set_poll_fb(); + + if (xi->depth == 24) { + /* line by line ... */ + int ps1 = 4, fac; + if (depth <= 8) { + fac = 4; + } else if (depth <= 16) { + fac = 2; + } else { + fac = 1; /* will not happen 24 on 24 */ + } + + src = xi->data; + dst = cmap8to24_fb + fac * n_off; + + poll = poll24_fb + (poll24_fb_w * rect.y1 + rect.x1) * 4; + poll_Bpl = poll24_fb_w * 4; + + for (line = 0; line < h; line++) { + memcpy(dst, src, w * ps1); + memcpy(poll, src, w * ps1); + + src += xi->bytes_per_line; + dst += main_bytes_per_line * fac; + poll += poll_Bpl; + } + } else if (xi->depth <= 16) { + int ps1, ps2, fac; + + if (depth <= 8) { + ps1 = 1; + ps2 = 4; + fac = 4; + } else if (depth <= 16) { + ps1 = 2; + ps2 = 4; + fac = 4; + } else { + /* should be 24 case */ + ps1 = 1; + ps2 = pixelsize; + fac = 1; + } + + src = xi->data; + dst = cmap8to24_fb + (fac/ps1) * n_off; + + poll = poll8_fb + poll8_fb_w * rect.y1 * ps1 + rect.x1 * ps1; + poll_Bpl = poll8_fb_w * ps1; + + /* line by line ... */ + for (line = 0; line < h; line++) { + /* pixel by pixel... */ + for (j = 0; j < w; j++) { + if (ps1 == 2) { + unsigned short *ptmp; + us = (unsigned short *) (src + ps1 * j); + idx = (int) (*us); + ptmp = (unsigned short *) (poll + ps1 * j); + *ptmp = *us; + } else { + uc = (unsigned char *) (src + ps1 * j); + idx = (int) (*uc); + *(poll + ps1 * j) = *uc; + } + ui = (unsigned int *) (dst + ps2 * j); + *ui = rgb[cm][idx]; + + } + src += xi->bytes_per_line; + dst += main_bytes_per_line * (fac/ps1); + poll += poll_Bpl; + } + } + +#ifndef GETSUBIMAGE + X_LOCK; + XDestroyImage(xi); + X_UNLOCK; +#endif + + } else if (! do_getimage) { + int fac; + + if (depth <= 16) { + /* cooked up depth 24 TrueColor */ + /* but currently disabled (high bits no useful?) */ + ps = 4; + fac = 4; + /* XXX not correct for depth > 8, but do we ever come here in that case? */ + src = cmap8to24_fb + 4 * n_off; + } else { + ps = pixelsize; + fac = 1; + src = cmap8to24_fb + n_off; + } + + /* line by line ... */ + for (line = 0; line < h; line++) { + /* pixel by pixel... */ + for (j = 0; j < w; j++) { + + /* grab 32 bit value */ + ui = (unsigned int *) (src + ps * j); + + /* extract top 8 bits (FIXME: masks?) */ + hi = (*ui) & 0xff000000; + + /* map to lookup index; rewrite pixel */ + idx = hi >> 24; + *ui = hi | rgb[cm][idx]; + } + src += main_bytes_per_line * fac; + } + } +#endif /* NO_X11 */ +} + +void bpp8to24(int x1, int y1, int x2, int y2) { + char *src, *dst; + unsigned char *uc; + unsigned short *us; + unsigned int *ui; + int idx, pixelsize = bpp/8; + int line, k, i, j, h, w; + int n_off; + sraRegionPtr rect; + int validate = 1; + static int last_map_count = 0, call_count = 0; + static double last_get_8bpp_validate = 0.0; + static double last_snapshot = 0.0; + double now; + double dt, d0 = 0.0, t2; + + RAWFB_RET_VOID + + if (! cmap8to24 || ! cmap8to24_fb) { + /* hmmm, why were we called? */ + return; + } + +if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, dnow() - last_get_8bpp_validate); + + call_count++; + + /* clip to display just in case: */ + if (!ncache) { + x1 = nfix(x1, dpy_x); + y1 = nfix(y1, dpy_y); + x2 = nfix(x2, dpy_x+1); + y2 = nfix(y2, dpy_y+1); + } + + if (wireframe_in_progress) { + /* + * draw_box() manages cmap8to24_fb for us so we get out as + * soon as we can. No need to cp main_fb -> cmap8to24_fb. + */ + return; + } + + /* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */ + + h = y2 - y1; + w = x2 - x1; + + if (depth == 24) { + /* pixelsize = 4 */ + n_off = main_bytes_per_line * y1 + pixelsize * x1; + + src = main_fb + n_off; + dst = cmap8to24_fb + n_off; + + /* otherwise, the pixel data as is */ + for (line = 0; line < h; line++) { + memcpy(dst, src, w * pixelsize); + src += main_bytes_per_line; + dst += main_bytes_per_line; + } + } else if (depth <= 16) { + /* need to cook up to depth 24 TrueColor */ + int ps1 = 1, ps2 = 4; + if (depth > 8) { + ps1 = 2; + } + + /* pixelsize = 1, 2 */ + n_off = main_bytes_per_line * y1 + pixelsize * x1; + + src = main_fb + n_off; + dst = cmap8to24_fb + (4/ps1) * n_off; + + set_root_cmap(); + if (root_cmap) { +#if 0 + unsigned int hi; +#endif + + /* line by line ... */ + for (line = 0; line < h; line++) { + /* pixel by pixel... */ + for (j = 0; j < w; j++) { + if (ps1 == 2) { + us = (unsigned short *) (src + ps1 * j); + idx = (int) (*us); + } else { + uc = (unsigned char *) (src + ps1 * j); + idx = (int) (*uc); + } + ui = (unsigned int *) (dst + ps2 * j); + +if (0 && line % 100 == 0 && j % 32 == 0) fprintf(stderr, "%d %d %u x1=%d y1=%d\n", line, j, root_rgb[idx], x1, y1); +#if 0 + if (do_hibits) { + hi = idx << 24; + *ui = hi | rgb[0][idx]; + } else { + } +#endif + *ui = root_rgb[idx]; +if (db24 > 2) histo[idx]++; + } + src += main_bytes_per_line; + dst += main_bytes_per_line * (4/ps1); + } + } + + } + + if (last_map_count > MAX_8BPP_WINDOWS/4) { + /* table is filling up... skip validating sometimes: */ + int skip = 3; + if (last_map_count > MAX_8BPP_WINDOWS/2) { + skip = 6; + } else if (last_map_count > 3*MAX_8BPP_WINDOWS/4) { + skip = 12; + } + if (call_count % skip != 0) { + validate = 0; + } + } + +if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} + + now = dnow(); + dt = now - last_get_8bpp_validate; + /* TUNABLES */ + if (dt < 0.003) { + ; /* XXX does this still give painting errors? */ + } else { + int snapit = 0; + double delay1, delay2, delay3; + if (poll_8to24_delay >= POLL_8TO24_DELAY) { + delay1 = 1.0 * poll_8to24_delay; + delay2 = 2.0 * poll_8to24_delay; + delay3 = 10. * poll_8to24_delay; + } else { + delay1 = 1.0 * POLL_8TO24_DELAY; /* 0.05 */ + delay2 = 2.0 * POLL_8TO24_DELAY; /* 0.1 */ + delay3 = 10. * POLL_8TO24_DELAY; /* 0.5 */ + } + if (cache_win > 1.0) { + delay2 *= 2; + delay3 *= 2; + } + if (dt < delay1) { + validate = 0; + } + if (last_map_count) { + if (now > last_snapshot + delay2) { + snapit = 1; + } + } else { + if (now > last_snapshot + delay3) { + snapit = 1; + } + } + + if (snapit) { + /* less problems if we update the stack frequently */ + snapshot_stack_list(0, 0.0); +if (0) fprintf(stderr, "SNAP time: %.4f\n", dnow() - now); + update_stack_list(); + last_snapshot = dnow(); +if (0) fprintf(stderr, "UPDA time: %.4f\n", last_snapshot - now); + } + +if (0) t2 = dnow(); + last_map_count = get_8bpp_regions(validate); + if (validate) { + last_get_8bpp_validate = dnow(); + } +if (0) fprintf(stderr, "get8bpp-%d: %.4f\n", validate, dnow() - t2); + } +if (db24) d0 = dnow(); + +if (db24 > 1) fprintf(stderr, "bpp8to24 w=%d h=%d m=%p c=%p r=%p ncmaps=%d\n", w, h, main_fb, cmap8to24_fb, rfb_fb, ncmaps); + + /* + * now go back and transform and 8bpp regions to TrueColor in + * cmap8to24_fb. + */ + if (last_map_count && (ncmaps || depth <= 16)) { + int i, j; + int win[MAX_8BPP_WINDOWS]; + int did[MAX_8BPP_WINDOWS]; + int count = 0; + + /* + * first, grab all of the associated colormaps from the + * X server. Hopefully just 1 or 2... + */ + for (j=0; j 2) fprintf(stderr, "cmap %d %.4f\n", (int) cmaps[j], dnow() - d0); + } + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr reg = windows_8bpp[i].clip_region; + if (reg) { + rect = sraRgnCreateRect(x1, y1, x2, y2); + if (sraRgnAnd(rect, reg)) { + win[count] = i; + did[count++] = 0; + } + sraRgnDestroy(rect); + } + } + + if (count) { + + rect = sraRgnCreateRect(x1, y1, x2, y2); + /* try to apply lower windows first */ + for (k=0; k < stack_list_num; k++) { + Window swin = stack_list[k].win; + for (j=0; j 2) {for(i=0; i<256;i++) {fprintf(stderr, " cmap histo[%03d] %d\n", i, histo[i]);}} +} + +void mark_8bpp(int mode) { + int i, cnt = 0; + Window top = None; + + RAWFB_RET_VOID + + if (! cmap8to24 || !cmap8to24_fb) { + return; + } + + if (mode == MARK_8BPP_TOP) { + int k; + for (k = stack_list_num - 1; k >= 0; k--) { + Window swin = stack_list[k].win; + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + if (windows_8bpp[i].win == None) { + continue; + } + if (windows_8bpp[i].map_state != IsViewable) { + continue; + } + if (swin == windows_8bpp[i].top) { + top = swin; + break; + } + } + if (top != None) { + break; + } + } + } + + /* for each mapped 8bpp window, mark it changed: */ + + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + int x1, y1, x2, y2, w, h, f = 32; + + f = 0; /* skip fuzz, may bring in other windows... */ + + if (windows_8bpp[i].win == None) { + continue; + } + if (mode == MARK_8BPP_TOP) { + if (windows_8bpp[i].top != top) { + continue; + } + } + if (windows_8bpp[i].map_state != IsViewable) { + XWindowAttributes attr; + int vw = 0; + + X_LOCK; + vw = valid_window(windows_8bpp[i].win, &attr, 1); + X_UNLOCK; + if (vw) { + if (attr.map_state != IsViewable) { + continue; + } + } else { + continue; + } + } + + x1 = windows_8bpp[i].x; + y1 = windows_8bpp[i].y; + w = windows_8bpp[i].w; + h = windows_8bpp[i].h; + + x2 = x1 + w; + y2 = y1 + h; + + if (mode == MARK_8BPP_POINTER) { + int b = 32; /* apply some fuzz for wm border */ + if (cursor_x < x1 - b || cursor_y < y1 - b) { + continue; + } + if (cursor_x > x2 + b || cursor_y > y2 + b) { + continue; + } + } + + /* apply fuzz f around each one; constrain to screen */ + x1 = nfix(x1 - f, dpy_x); + y1 = nfix(y1 - f, dpy_y); + x2 = nfix(x2 + f, dpy_x+1); + y2 = nfix(y2 + f, dpy_y+1); + +if (db24 > 1) fprintf(stderr, "mark_8bpp: 0x%lx %d %d %d %d\n", windows_8bpp[i].win, x1, y1, x2, y2); + + mark_rect_as_modified(x1, y1, x2, y2, 0); + cnt++; + } + if (cnt) { + /* push it to viewers if possible. */ + rfbPE(-1); + } +} + +#endif /* SKIP_8TO24 */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.h new file mode 100755 index 0000000..d83412b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_8TO24_H +#define _X11VNC_8TO24_H + +/* -- 8to24.h -- */ + +extern int multivis_count; +extern int multivis_24count; + +extern void check_for_multivis(void); +extern void bpp8to24(int, int, int, int); +extern void mark_8bpp(int); + +#endif /* _X11VNC_8TO24_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ChangeLog new file mode 100755 index 0000000..5e9a59c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ChangeLog @@ -0,0 +1,1218 @@ +2010-05-08 Karl Runge + * x11vnc: set cd->unixname in apply_opts. Print message in + vnc_reflect_resize. Some tweaks to prepare_x11vnc_dist.sh + +2010-05-01 Karl Runge + * x11vnc: X11VNC_DISABLE_SSL_CLIENT_MODE option to disable SSL + client role in reverse connections. Improvements to logging in + ultravnc_repeater, ULTRAVNC_REPEATER_NO_RFB option. Increase + SSL timeout and print message if 'repeater' mode is detected for + reverse SSL connection. Fix RECORD scroll XCopyArea detection + with recent gtk/gdk library; set X11VNC_SCROLL_MUST_EQUAL + to disable. Limit logging of RECORD error messages. + +2010-04-25 Karl Runge + * x11vnc: incorporate new ultravnc_dsm_helper.c, add pointer_mask + remote control query. Cut openssl default -ping delay. + +2010-04-18 Karl Runge + * x11vnc/misc: improvements to demo scripts + * x11vnc: Alias -coe for -connect_or_exit. more accurate + dotted_ip() and -listen6. Improvements to ipv6 mode. + http interface for X11VNC_HTTP_LISTEN_LOCALHOST. Print + warning about missing Xvfb, Xdummy, or Xvnc in -create. + Fix __LINUX_VIDEODEV2_H / HAVE_V4L2. Always print out info + about Xinerama screens. + * x11vnc/misc/enhanced_tightvnc_viewer: check for host cmd. + fix stunnel mode w/o proxy. Update to stunnel 4.33, Fix + build.unix with new stunnel on Solaris. ipv6 support for + unix ssvncviewer + +2010-04-09 Karl Runge + * classes/ssl: debugging and workarounds for java viewer + * x11vnc/misc: sync ssvnc, improve util scripts. + * x11vnc: exit(1) for -connect_or_exit failure, quiet query + mode for grab_state, etc. ipv6 support. STUNNEL_LISTEN for + particular interface. -input_eagerly in addition to -allinput. + quiet Xinerama message. + +2010-03-20 Karl Runge + * classes/ssl: Many improvements to Java SSL applet, onetimekey + serverCert param, debugging printout, user dialogs, catch + socket exceptions, autodetect x11vnc for GET=1. + * x11vnc: misc/scripts: desktop.cgi, inet6to4, panner.pl. + X11VNC_HTTPS_DOWNLOAD_WAIT_TIME, -unixpw %xxx documented, and + can run user cmd in UNIXPW_CMD. FD_XDMCP_IF for create script, + autodetect dm on udp6 only. Queries: pointer_x, pointer_y, + pointer_same, pointer_root. Switch on -xkd if keysyms per key > + 4 in all cases. daemon mode improvements for connect_switch, + inet6to4, ultravnc_repeater.pl. Dynamic change of -clip do + not create new fb if WxH is unchanged. + +2010-02-22 Karl Runge + * classes/ssl: Java SSL applet viewer now works with certificate + chains. + * x11vnc: Printout option -sslScripts. Suggest -auth guess + in error message. Set fake_screen width and height. Test + for +kb in Xvfb. + +2010-01-02 Karl Runge + * x11vnc: small tweaks to Xdummy, rx11vnc*. Apply + SMALL_FOOTPRINT to -appshare text. Copyright year change. + +2009-12-29 Karl Runge + * x11vnc: rename -create_x to -create_xsrv. Hopefully + done fixing Xdummy. + +2009-12-28 Karl Runge + * x11vnc: Fix problems in --without-x builds. Fix crash + with -QD query for dbus info. Adjust window size for + small screens in -gui. Improve F1 help for xdm, etc. + include ssvnc 1.0.25 source. + +2009-12-24 Karl Runge + * x11vnc: prepare_x11vnc_dist.sh for 0.9.10. -xdummy_xvfb, + -svc_xdummy_xvfb and -create_x shorthand. lxde session. + Xdummy improvements and root no longer required. + +2009-12-21 Karl Runge + * x11vnc: -DENC_HAVE_OPENSSL=0 to disable enc.h but still + have ssl. Tweak ps command in find_display. Try to handle + AIX su. Ignore an initial newline at login: for -unixpw. + +2009-12-18 Karl Runge + * x11vnc: fix keycode and other remote control actions under + DIRECT: with an extra XFlush and other safety measures. + fflush(stderr) much in su_verify. Make the -unixpw env. vars + UNIXPW_DISABLE_SSL and UNIXPW_DISABLE_LOCALHOST work correctly. + Make -loopbg actually imply -bg. Add tag=... to unixpw opts + to set FD_TAG. Prefer Xvfb over Xdummy. Reduce wait time + for https. Add 'Login succeeded' output to unixpw panel. + +2009-12-15 Karl Runge + * x11vnc: X11VNC_REMOTE, X11VNC_TICKER, and VNC_CONNECT properties + names can be changed via env. vars (e.g. for multiple + x11vnc instances.) The -quiet option documented better. + Add fakebuttonevent remote control action. Improve child + test for connecting to port 113. Add connect_switch and + ultravnc_repeater.pl to CVS. Report X server number of mouse + buttons. Change find_display script to check for stale pids + in /tmp/.XNN-lock. If root under find_display, try FD_XDM + if previous failed to find auth. Print error reasons for + -storepasswd failures. + +2009-12-06 Karl Runge + * x11vnc: findauth/-auth guess works with FD_XDM=1 for root + finding dm's xauthority. Work around for GDM's recent + 'xhost SI:localuser:root' usage. X11VNC_REOPEN_SLEEP_MAX + for longer lived -reopen-ing. X11VNC_EXTRA_HTTPS_PARAMS for + additional URL parameters, X11VNC_HTTP_LISTEN_LOCALHOST=1 to + force libvncserver http to listen on localhost. + +2009-12-04 Karl Runge + * classes/ssl: update binaries; new signing key; ss_vncviewer. + * x11vnc: add more wish possibilities for -gui. Declare crypt() + on all platforms (disable with -DDO_NOT_DECLARE_CRYPT.) + +2009-12-02 Karl Runge + * x11vnc: -appshare mode for sharing an application windows of the + entire desktop. map port + 5500 in reverse connect. Add id_cmd + remote control functions for id (and other) windows. Allow zero + port in SSL reverse connections. Adjust delays between multiple + reverse connections; X11VNC_REVERSE_SLEEP_MAX env var. Add some + missing mutex locks; add INPUT_LOCK and threads_drop_input. + More safety in -threads mode for new framebuffer change. Fix + some stderr leaking in -inetd mode. + +2009-11-18 Karl Runge + * x11vnc: use -timeout setting for reverse connections too. + Delay calling xfixes at the beginning of 1st connection to avoid + display manager Xorg server crash. Delay selwin creation at the + begin 1st connection to avoid being killed by display manager. + Options -findauth and '-auth guess'. Export icon_mode query. + Do not open X display in -rawfb mode unless asked. Bugfix for + -sid/-id handling window offscreen or bigger than display. + Search for windows with _DBUS_SESSION_BUS_PID to decide which + dbus_launch is ours. Fix missing displays in FIND_DISPLAY + script. Add X11VNC_SKIP_DISPLAY_NEGATE. Improvements to + 'x11vnc Properties' gui dialog and connecting with x11vnc via + socket (client list.) X11VNC_SYSTEM_GREETER1 for previous text + font size. Fix bug with unixpw and vencrypt plain login. + Have fast fb read rate keep waitms and defer the same. + More heuristics to check try if GDM is still running (window + names gdm-*) + +2009-10-17 Karl Runge + * x11vnc: support for -solid option in xfce desktop. + List -Q guess_dbus query. Implement -showrfbauth option. + Workaround for inane X_ShmAttach incompatibility in Xorg. + +2009-10-08 Karl Runge + * x11vnc: bcx_xattach/x2x desktop switching facility. + More remote control features: grab_state, ping:mystring, + grablocal, resend_cutbuffer, resend_clipboard, resend_primary, + keycode, keysym, ptr, sleep, get_xprop, set_xprop, wininfo, + pointer_pos, mouse_xy, noop, guess_dbus Add DIRECT: for + remote control w/o server. X11VNC_NO_CHECK_PM for more + quiet DIRECT: usage. Options -query_retries, -remote_prefix, + and X11VNC_SYNC_TIMEOUT for remote control. Add scripting + to remote control. ping clients during in unixpw login. + Option -unixpw_system_greeter as shortcut to XDM/GDM/etc panel. + Add clear_all, viewonly, nodisplay, to unixpw username:opts. + F1 help for options (including smaller console font). + Document FD_TAG. Eat multiple property change events in one + sitting (also PROP_DBG=1). Support more -ssl features (special + cert names, single port, client certs, etc.) in -stunnel + external SSL helper mode. Reorganize openssl code to allow + integration with stunnel features if not compiled with openssl. + X11VNC_HTTPS_VS_VNC_TIMEOUT Fix dbus session address for -solid + in gnome. Use dbus-launch in -create mode if available. + X11VNC_SKIP_DISPLAY=all in -find/-create mode. let noxauth + unset XAUTHORITY for use with su - $USER. CREATE_DISPLAY_EXEC + debugging. Add x_terminal_emulator to -create cmd search. + Option -extra_fbur to tune fb update requests tracking; make + default tracking more aggressive. RATE_VERB/CHECK_RATE env. for + fbur rate. Env. vars to set Tk gui fonts. Catch closed + socket reads/writes. Try to detect 'crazy' xdamage insertion, + e.g. from some xscreensavers (needs work.). Don't switch + on server autorepeat if any keys are pressed down to work + around Xorg server and/or gnome bug. If PATH is empty, set + it to minimal one. Fix bug with -bg and -dp/-dk printout if + logfile present. + * classes/ssl: license statement. + +2009-06-18 Karl Runge + * classes/ssl: java viewer now handles auth-basic proxy logins. + * misc/enhanced_tightvnc_viewer: update ssvnc. + +2009-06-14 Karl Runge + * x11vnc: Add X11VNC_REFLECT_PASSWORD env. var. for -reflect mode. + Message to user about compiz problems suggesting -noxdamage. + Improvements to single-port detection and logging. + +2009-05-21 Karl Runge + * x11vnc: Thread safety improvements. Add 'OpenOffice' to special + case list for scroll detection. Fix -clip mode under -rawfb. + Workaround Xorg bug that yields infinitely repeating keys + when 'xset r off' action is done with keys pressed. Env. var + X11VNC_IDLE_TIMEOUT. + +2009-03-12 Karl Runge + * x11vnc: Fix off-screen bug for -ncache_cr copyrect. + +2009-03-07 Karl Runge + * x11vnc: allow range for X11VNC_SKIP_DISPLAY, document grab + Xserver issue. Add progress_client() to proceed more quickly + thru handshake. Improvements to turbovnc hack. + +2009-02-28 Karl Runge + * x11vnc: add kludge to experiment with turbovnc. + +2009-02-25 Karl Runge + * x11vnc: fix some -QD cases for use in tkx11vnc. + +2009-02-21 Karl Runge + * x11vnc: add -noskip_lockkeys option for future use. + +2009-02-03 Karl Runge + * x11vnc: Add "sendbell" remote cmd. Fix copyrect updates under + -reflect. Workaround that checks valid window of selection + requestor. Wait on some ssl helper pids earlier. Workaround + XAUTHLOCALHOSTNAME for some new usage modes. Set fake fb to + requested bpp with correct masks. -padgeom once:... mode. + Set LIBXCB_ALLOW_SLOPPY_LOCK by default. rfbRandomBytes earlier. + * classes/ssl: Update jars. Add "TOP_" dropdown customization to + ultravnc java viewer applet FTP panel. + +2009-01-11 Karl Runge + * classes/ssl: Add configurable Ultra java applet Filexfer Drives + drop down (e.g. ftpDropDown=Home.Desktop.bin). Document all + applet parameters in classes/ssl/README. + +2009-01-10 Karl Runge + * x11vnc: fix failure of -8to24 on default depth 24 due to + nonstandard indexed color support changes. Fix small window + for failure after XSendEvent selection call; add env var. + X11VNC_SENDEVENT_SYNC=1 to take even more care. + +2009-01-03 Karl Runge + * x11vnc: add -rmflag option, -rawfb vt support, bpp < 8 support + for rawfb, find /dev/video better. Fix reverse SSL connection + for DH. Some improvements for CUPS TS helper, restart if needed. + +2008-12-10 Karl Runge + * x11vnc: 0.9.6 release. Some strtok bugfixes. rename -tlsvnc + to -anontls. Disable ssl caching. No cert creation prompting + in inetd or bg modes. waitpid a bit more carefully on ssl + helpers. Tune ssl initial timeouts. Let -create user specify + starting X display. fix -rfbport prompt gui for older tk. + -sslonly option. Error if no -ssl with related options. -rand + option. -ssl implies -ssl SAVE + +2008-11-22 Karl Runge + * x11vnc: x11vnc.desktop file. -reopen, -dhparams, -sslCRL, + -setdefer options. -rfbport PROMPT VeNCrypt and TLSVNC SSL/TLS + encryption support. Tweaks to choose_delay() algorithm. + -ssl ANON anonymouse Diffie-Hellman mode. Fix bugs in certs + management. Additions to tray=setpass naive user mode. + +2008-11-09 Karl Runge + * x11vnc: add zeroconf external helpers (avahi-publish and + dns-sd). Alias -zeroconf. Close pipeinput_fh on exit. + Kludge to make -solid work on MacOSX console. Attempt at + cpp macros to disable newer libvncserver interfaces. + +2008-10-29 Karl Runge + * x11vnc: -http_oneport for single port HTTP and VNC. + Improve find_display wrt lsof blocking with -b. + +2008-10-19 Karl Runge + * x11vnc: -chatwindow for chat window on X console using SSVNC + as a helper. Print suggestion for X_ShmAttach failure. + Allow -scale WxH for different X- and Y-scaling factors. + Workaround for missing -enc cipher EVP_aes_256_cfb. Modify + message digest and salt/IV parameters. Try to improve compile + time by breaking up large if blocks. + +2008-09-21 Karl Runge + * x11vnc: Add symmetric key encryption -enc cipher:keyfile, + works with SSVNC. Make -remap work on MacOSX console. + update to 0.9.5 strings. Add a couple menu items to tkx11vnc. + +2008-09-17 Karl Runge + * x11vnc: make -allow work in -ssl mode. + +2008-09-14 Karl Runge + * x11vnc: -sleepin m-n for random sleep. More mktemp and mkstemp + protections. SSL_INIT_TIMEOUT=n env. var. Fix macosx console + X call bug. Synchronize other projects sources. + +2008-09-06 Karl Runge + * x11vnc: kill gui_pid on exit in -connect/-connect_or_exit mode. + -grablocal n experiment (not compiled by default). -macuskbd + option for macosx for orig uskdb code. keycode=N remote contol + cmd. Find dpy look at non-NFS cookies in /tmp. Fix gui tray + insertion on recent gnome dt. Fix connect_file bug. Sync SSVNC + +2008-06-07 Karl Runge + * x11vnc: -clip xineramaN option, -DIGNORE_GETSPNAM for HP-UX. + Print info on SSH_CONNECTION override. + +2008-05-31 Karl Runge + * x11vnc: Improvements to nonstandard indexed color support, e.g. + depths 1, 4, 12, etc. instead of only 8. Only enable xinerama + xwarppointer if there is more than 1 subscreen. + +2008-05-07 Karl Runge + * x11vnc: add UltraVNC repeater proxy support. fix to setp gui + mode. -threads is now strongly discouraged. Read PORT= in url. + User can set nolisten for Xvfb in -create mode. clean up + wait_for_client() to some degree. + +2008-01-31 Karl Runge + * x11vnc: during speeds estimate, guard against client + disconnecting. ssvnc sync. + +2008-01-14 Karl Runge + * x11vnc: -ping option, fix memory corruption in copy_tiles + after xrandr resize. + +2007-12-16 Karl Runge + * x11vnc: setup remote-ctrl file by default on macosx. improve + tkx11vnc wrt attaching to existing server in icon/tray mode. + +2007-12-15 Karl Runge + * x11vnc: fix find_display and usleep() prototype on macosx. + -display console and check DISPLAY /tmp/...:0 on macosx. + implement -noxinerama. + +2007-11-12 Karl Runge + * x11vnc: add clear_locks (Caps_Lock, etc) action. Fix + ssh tunnel on Darwin. + +2007-10-27 Karl Runge + * x11vnc: fix ncache bug and others under -8to24, -ssh + option, socks and other proxies in -proxy option. + compiler warnings. fix TARGETS selection request bug + (java, konsole). + +2007-10-03 Karl Runge + * x11vnc: add xfce to createdisplay + +2007-09-26 Karl Runge + * x11vnc: COLUMNS=256 to find/create scripts. More ratecheck. + +2007-09-14 Karl Runge + * x11vnc: Add -sshxdmsvc. Fix find_display for inetd. Improve + -allinput method; env CHECK_RATE to watch for FBUR build up + (i.e. JFVNC). + +2007-09-11 Karl Runge + * x11vnc: fix wireframe crash under -clip. Add -redirect for + VNC redir. -rawfb nullbig, randbig, solid, swirl, etc. + FD_XDM mode to find_display. -listdpy. Add enlightenment. + Xvnc.redirect FINDDISPLAY-vnc_redirect. -xvnc, -xvnc_redirect, + -svc_xvnc. AUTO_PORT. + * ssvnc: sshvnc ssh-only, tsvnc Terminal Services modes. + Improvements to ss_vncviewer. Automatically find X dpy and + X login. Reorganize menus a bit. ~/.ssvncrc file. + +2007-09-04 Karl Runge + * x11vnc: Add -autoport and -finddpy utils. -xdummy creation. + tweak xkb tiebreaking again. Shut off -ncache in dev mode. + watch for xrandr events even if no -xrandr. Tips for types + of URLs for java viewers. Add check_redir_services() to + create_display and tsdo() redir helper utility (-tsd). + Improvements to Xdummy. Prevent dcop XAUTHORITY='' + +2007-08-19 Karl Runge + * x11vnc: better -xkb tie-breaking for up keystrokes. Add + Xsrv/FD_XSRV custom server to FINDCREATEDISPLAY list. + +2007-08-18 Karl Runge + * x11vnc: improve FINDCREATEDISPLAY (-create) script. Document + FD_GEOM, FD_SESS, FD_OPTS, FD_PROG env vars, add Xvnc support. + +2007-08-15 Karl Runge + * x11vnc: add reverse -connect support to -display WAIT: + i.e. -find, -create, -svc, ... mode. Document need for + -shared under -connect host1,host2,... Fix bug in -display + WAIT: mode if vnc client tries to only retrieve SSL cert. + +2007-08-03 Karl Runge + * x11vnc: add -xrefresh option, fix KDE .DCOPserver parse bug, + make sure UNIXPW_DISABLE_LOCALHOST/-unixpw_unsafe ignore + any SSH tunnel that would imply -localhost. + +2007-07-04 Karl Runge + * x11vnc: -debug_ncache, fix big fonts in tkx11vnc. + +2007-06-14 Karl Runge + * x11vnc: add detectors if ultravnc chat or file xfer took place, + if so ping clients more frequently. Fix compile bug if libssl + not available. + * ssvnc: add ultravnc ftp jar feature. Add certificate management + "Verify All Certs". + +2007-05-26 Karl Runge + * x11vnc: set to version 0.9.2, back to NCACHE -12 for testing. + in -unixpw, initial Escape means no echo username (see ssvnc). + +2007-05-21 Karl Runge + * x11vnc: set things up (NCACHE = -1) to not have -ncache + on by default; just give a blurb about it. + +2007-05-16 Karl Runge + * x11vnc: print out peer host and port for debugging SSL. + * ssvnc: rand check, SOCKS support, PORT=, Verify all Certs + and accepted certs logging. + +2007-05-06 Karl Runge + * x11vnc: lower -wait and -defer to 20ms. Change some SSL + debug output. Drop client doing ultravnc stuff in -unixpw + during login phase. + +2007-05-05 Karl Runge + * x11vnc: add groups handling for -users mode. + +2007-05-01 Karl Runge + * ssl: update to java viewer and utility scripts (add onetimekey). + * x11vnc: setsid() for -gone mode. setpgrp for -create script and + add -cc 4 to avoid DirectColor. + +2007-04-28 Karl Runge + * x11vnc: -users sslpeer= option. RFB_SSL_CLIENT_CERT var. + X11VNC_FINDDISPLAY_ALWAYS_FAILS var. -ncache default 10. + gid switch fix. + * ssvnc: Linux.i*86 fix and code sync. + +2007-04-07 Karl Runge + * x11vnc: add gnome, kde, etc. FINDCREATEDISPLAY tags. + In check_ncache periodically check for changed desktop. + +2007-03-24 Karl Runge + * x11vnc: reverse SSL connections. -sleepin option. + +2007-03-20 Karl Runge + * x11vnc: Add -httpsredir option for router port redirs. + set Xcursor bg/fg color values to zero. Env var to + force timeout: X11VNC_HTTPS_VS_VNC_TIMEOUT. Let user + supply nc=N at login prompt. Disable -ncache beta + test under -http/-httpdir. + +2007-03-13 Karl Runge + * x11vnc: fix crash for kde dcop. limit ncache beta + tester to 96MB viewers. + +2007-02-18 Karl Runge + * x11vnc: Get ultravnc textchat working with ssvnc. + +2007-02-16 Karl Runge + * x11vnc: add Files mode to user controlled input. more + ultra/tight filexfer tweaks. rfbversion remote control. + noncache/nc unixpw user opt. + +2007-02-15 Karl Runge + * x11vnc: tightvnc filetransfer off by default. avahi + fixes. FINDCREATEDISPLAY geometry. -noultraext. + +2007-02-12 Karl Runge + * x11vnc: add avahi (aka mDNS/Zeroconf/Bonjour...) + support thanks to Diego Pettenò. -avahi/-mdns. + Add -find and -create FINDISPLAY aliases. + +2007-02-11 Karl Runge + * x11vnc: add -grabalways, -forcedpms, -clientdpms, and + -noserverdpms (ultravnc viewer) for improvements in + the still approximate server locking. Add -loopbg + and -svc, -xdmsvc aliases. Bug fix create_display. + +2007-02-10 Karl Runge + * x11vnc: watch things like textchat, etc. more carefully + in unixpw state. Monitor broken XDAMAGE reports when + OpenGL apps like beryl are running. Implement simple + kbdReleaseAllKeys, setSingleWindow, setServerInput actions + (ultravnc extentions). Try to send XDM the username in + FINDCREATEDISPLAY, also try .dmrc before .xsession. + +2007-01-31 Karl Runge + * x11vnc: -reflect reflector/repeater mode with libvncclient. + -ncache tweaks: no kde animations and wm improvements, + fixes to FINDDISPLAY and FINDCREATEDISPLAY login modes, + MODTWEAK_LOWEST envvar for HP-UX keyboard workaround. + -N option for display and rfbport matching. + +2007-01-12 Karl Runge + * x11vnc: -N option, more -ncache improvements, kde/gnome. + +2007-01-03 Karl Runge + * x11vnc: more -ncache improvements. + +2007-01-01 Karl Runge + * x11vnc: more -ncache improvements. + +2006-12-28 Karl Runge + * x11vnc: more work on -ncache, add macosx support, fix X errors + and improve cache expiration algorithm. + +2006-12-17 Karl Runge + * x11vnc: first pass at client-side caching, -ncache option. + have -http guess ../classes/.. to run out of build area. + +2006-12-17 Karl Runge + * x11vnc: make -xwarppointer the default if xinerama is active. + +2006-12-09 Karl Runge + * java SSL viewer: guard against empty urlPrefix + * x11vnc: FINDCREATEDISPLAY support to create X session if + one cannot be found. close fds utility. Print VNC Viewer + is.. for find display mode. chvt(1) utility. + +2006-11-23 Karl Runge + * prepare_x11vnc_dist.sh: make ss_vncviewer installed 755. + * x11vnc: for HTTPONCE open new http port in -inetd mode. + -prog option to indicate full path to program (not know + when in -inetd and tcpd) + +2006-11-21 Karl Runge + * x11vnc: macosx: problem with padded framebuffer rows, wait for + user to switch back, CutText xfer support, ignore a few more + types of toplevels. Add local user wireframing. -dpms/-nodpms + option to work around kdesktop_lock problem. + +2006-11-13 Karl Runge + * x11vnc: Native Mac OS X support. + +2006-11-07 Karl Runge + * ssl_vncviewer: vnc:// direct connect, add -x to ssh, + SSL_VNC_LISTEN variable for direct proxy. + +2006-10-29 Karl Runge + * x11vnc: Add tip about how to reenable RECORD extension. + +2006-10-11 Karl Runge + * x11vnc: -cursor_drag for DnD, etc. + +2006-09-23 Karl Runge + * Java viewer: improvements to connection response, faster + connections. + * x11vnc: some cleanup for -unixpw login process. + +2006-09-20 Karl Runge + * x11vnc: -unixpw_cmd, -passwfile cmd:/custom:, -sslnofail, + -ultrafilexfer + +2006-09-17 Karl Runge + * x11vnc: move some info printout to -v, -verbose mode. Add + -connect_or_exit option. Have -rfbport 0 lead to no TCP + listening. Eliminate double certificates in .pem files. + Always print SSL certificate to the screen to aid pasting. + +2006-09-15 Karl Runge + * x11vnc: allow user set signals to ignore, clear DISPLAY in + -unixpw su_verify. -rawfb none same as null. + * rfbserver.c: shorten rfbEncodingNewFBSize message. + +2006-09-13 Karl Runge + * x11vnc: document 'ssh -t' improved keyboard response. add + extra rfbPE() around keystrokes. + misc/enhanced_tightvnc_viewer: incorporate scripts, documentation, + etc. for the enhanced tightvnc viewer package. + +2006-09-10 Karl Runge + * x11vnc: minor changes: REQ_ARGS for -sslGenCert, EV_SYN + SYN_REPORT check restore cursor most under -display WAIT. + +2006-08-10 Karl Runge + * x11vnc: first pass at touchscreens via uinput. + +2006-08-02 Karl Runge + * x11vnc: add -ssltimeout option; tweak ssl timeouts. + +2006-07-28 Karl Runge + * ssl_vncviewer: remove some bashisms, add features. + * x11vnc: -rotate option (e.g. handheld), fix FPE on tru64. + +2006-07-17 Karl Runge + * x11vnc: enable --without-x builds for -rawfb only (NO_X11) + +2006-07-11 Karl Runge + * x11vnc: more tweaks to UINPUT, mostly mouse motion. + +2006-07-08 Karl Runge + * x11vnc: add uinput support (-pipeinput UINPUT:...) for full + mouse and key input to linux console (e.g. for qt-embedded apps) + add -allinput for handleEventsEagerly. + +2006-07-04 Karl Runge + * x11vnc: 2nd -accept popup with WAIT, and UNIX: info for unixpw + login. Use RFB_CLIENT_ON_HOLD for -unixpw. -unixpw white arrow + -license option. Use getspnam if getpwnam is short. + abbrevs sc=, cm, ck for user:opts. + +2006-06-23 Karl Runge + * x11vnc: misc cleanup. + +2006-06-18 Karl Runge + * x11vnc: -grabkbd, -grabptr, -env options. under -unixpw + + WAIT let user add some options after his username (e.g. runge:3/4) + -allowedcmds to fine tune vs. -nocmds. general cleanup. + +2006-06-12 Karl Runge + * x11vnc: word tune SSL Java viewer; fix multi-certs bug. Add + -display WAIT:cmd=FINDDISPLAY builtin script and cmd=HTTPONCE + action. -http_ssl option for ssl subdir only. Add -rawfb RAND + test case. improve raw_xfer() for use in inetd https transfer. + fix bug SSH + -unixpw -> -localhost. fix bug setup cursors + in WAIT mode. Mac OS X pty tweak. + +2006-06-09 Karl Runge + * x11vnc: make -display WAIT + -unixpw work on Solaris. + +2006-06-08 Karl Runge + * x11vnc: XOpenDisplay wrapper for raw xauth data, -unixpw + su_verify() to run any cmd, -users unixpw= mode. -display WAIT:... + modes for delayed X display opening and dynamic choosing. + +2006-06-03 Karl Runge + * x11vnc: -capslock and -skip_lockkeys options. map some Alt keys + to Latin under linuxfb. switch to new stats API. Handle more + cases carefully when switching fb. + +2006-05-06 Karl Runge + * x11vnc: improved support for webcams and tv tuners with + video4linux /dev/video: -rawfb video, -freqtab etc. + Convenience option for linux VT's: -rawfb cons (LinuxVNC + method). -pipeinput builtins for video and console. + -24to32 option to avoid 24bpp problems. "snap:" method for + -rawfb. + +2006-04-26 Karl Runge + * x11vnc: skip exit in check_openssl() if not compiled with + libssl. set SKIP_HELP (again) in small footprint builds. + +2006-04-16 Karl Runge + * x11vnc: More web proxy work for Java SSL applet and wrapper + script ssl_vncviewer. Apache SSL gateway support for + incoming x11vnc connections. Handle "double proxy" case. + +2006-04-05 Karl Runge + * x11vnc: add FBPM support (-fbpm) for Suns. -rawfb ZERO for + testing. Basic key+cert management utilities: -sslGenCA, + -sslGenCert, -sslEncKey, -sslDelCert, -sslCertInfo, and + addln features. SSL proxy connection. -storepasswd with + no args or pw echo. + +2006-03-26 Karl Runge + * x11vnc: -xinerama now on by default. In -ssl mode accept https + applet downloads thru VNC port. -https option for 2nd https + port. Look for classes/ssl under -http. add Java URL messages + to final output lines. make -inetd work with -ssl (even for + https). fix -unixpw login prompt under -scale. guard against + clientData = NULL. + +2006-03-11 Karl Runge + * x11vnc: add -ssl mode using libssl. Include Xdummy in misc. + a few more macros for smallerfoot, etc. + +2006-03-08 Karl Runge + * x11vnc: manage CLIPBOARD in addition to PRIMARY. -debug_sel + Make reverse connections require passwords. -usepw option. + -storepasswd w/o args prompts and writes ~/.vnc/passwd. + +2006-03-06 Karl Runge + * x11vnc: switch remote control to X11VNC_REMOTE property. Put + in -unixpw constraints for reverse connections under -inetd. + -inetd won't quit when reverse conn client leaves. Allow keyboard + input for viewonly -unixpw logins. "%*" utils for testing + -unixpw. improve start time fix bugs, small screen in gui. + +2006-03-04 Karl Runge + * x11vnc: -unixpw on *bsd, hpux and tru64. Add -unixpw_nis for + non-shadow systems. check stunnel dying. check SSH_CONNECTION + in -unixpw. gui icon tweaks, unix username. + +2006-03-02 Karl Runge + * x11vnc: more tweaks to -unixpw mode. Add -gone popup mode. + Change filexfer via -R. Tune SMALL_FOOTPRINT. gui fixes. + +2006-02-24 Karl Runge + * x11vnc: -unixpw for Unix password auth, -stunnel to setup + stunnel(1) for an SSL tunnel on the server end. Add clipboard + input to per-client input controls. + +2006-02-20 Karl Runge + * x11vnc: add SIGINT SIGQUIT handling for run_user_command(), + set some signal handlers to SIG_DLF for forked children, + put a timeout on port 113 connection to viewer machine. + +2006-02-06 Karl Runge + * x11vnc: fix AIX build wrt h_errno. + +2006-02-06 Karl Runge + * x11vnc: -8to24 more speedups; tunables for very slow machines. + +2006-02-04 Karl Runge + * x11vnc: -8to24 speedups and improvements. + +2006-01-21 Karl Runge + * x11vnc: -8to24 opts, use XGetSubImage. fix -threads deadlocks and + -rawfb crash. + +2006-01-18 Karl Runge + * x11vnc: -8to24 now works on default depth 8 screens. + +2006-01-16 Karl Runge + * x11vnc: more tweaks to -8to24, add XGETIMAGE_8TO24 mode to call + XGetImage() on the 8bpp regions. + +2006-01-14 Karl Runge + * x11vnc: add -8to24 option for some multi-depth displays (but use + of -overlay is preferred if supported). + +2006-01-12 Karl Runge + * fix -DSMALL_FOOTPRINT=N builds. + +2006-01-11 Karl Runge + * x11vnc: close fd > 2 in run_user_command(), -nocmds in crash_debug, + fix 64bit bug for -solid. + +2006-01-08 Karl Runge + * x11vnc: the big split. opts: -afteraccept and -passwdfile read: + +2005-12-24 Karl Runge + * x11vnc: enhance -passwdfile features, filetransfer on by default, + call rfbRegisterTightVNCFileTransferExtension() earlier. + +2005-11-28 Karl Runge + * x11vnc: add -loop option. + +2005-11-25 Karl Runge + * x11vnc: throttle load if fb update requests not taking place. + * misc/x11vnc_pw: add utility script + +2005-10-22 Karl Runge + * add tightVNC FileTransfer (-filexfer) and -DFILEXFER=1 + * -slow_fb for special purpose infrequent polling. + * make -blackout work with copyrect clipping. + * -blackout noptr,WxH+X+Y,... to prevent pointer from going + into a blacked out region. + +2005-07-17 Karl Runge + * more improvements to gui UE. gui requests via client_sock + PASSWD_REQUIRED and PASSWD_UNLESS_NOPW build options. + +2005-07-12 Karl Runge + * gui: remove nevershared etc., parse cmd line, bug fixes. + * x11vnc: fix pointer queue buildup under -viewonly. + +2005-07-10 Karl Runge + * more improvements to gui, default values, save-settings.. + * x11vnc scary password warnings. Release settings. -QD option. + add \# to rc files and fix rcfile read bug. + +2005-07-09 Karl Runge + * add -grab_buster helper thread to break up grabs (might not be + need any longer due to gett XFlush-ing). Fix scrolls and + copyrect for -clip and -id cases. + +2005-07-06 Karl Runge + * many improvements to the gui. now embeds into system tray ok. + x11vnc -debug_grabs, -printgui, -nosync + +2005-07-01 Karl Runge + * support for simple "-gui tray" mode (small icon like the original + x0rfbserver had). Can't figure how to get a tray to swallow it.. + * passwd, viewpasswd changing in tray mode. + * allow typos like: x11vnc -R -scale 3/4 + +2005-06-26 Karl Runge + * track keycode state for heuristics, -sloppy_keys, -wmdt + * add -nodbg as option + +2005-06-21 Karl Runge + * reinstate "bad desktop" for wireframe. + * extra long info and tips of XOpenDisplay fails. + +2005-06-18 Karl Runge + * clean up some malloc/free problems (don't free the current cursor) + * set DISPLAY before calling gconf, dcop under -solid + * -inetd -q and no -o logfile implies closing stderr. + +2005-06-14 Karl Runge + * -DNOGUI and -DVIEWONLY build options + * -noskip_dups the default (windows viewer sends no ups when + repeating) + * HAVE_SOLARIS_XREADSCREEN and HAVE_IRIX_XREADDISPLAY + * Alt+Button+Motion to wireframe. tunable in WIREFRAME_PARMS + * copyrect now the default under -scale (works OK, but must + send a cleanup update) + * fix -pedantic and Sun cc warnings and errors (unsigned, etc..) + * print out fatal error messages under -quiet + * -seldir to control and debug selection transfers. + * fix crashes on 64bit wrt unsigned long in rich cursors. + * fix kde guessing errors + * more scrolling and wireframe tweaks. + +2005-06-03 Karl Runge + * make scrollcopyrect more or less usable under -scale + * add -fixscreen for periodic cleanup of painting errors. + * adjust keyrepeat scroll behavior. + +2005-05-30 Karl Runge + * alter "magic cleanup key sequences" (N*Alt_L and N*Super_L) + * dial down check_xrecord_reset() reset times. + +2005-05-24 Karl Runge + * more -scrollcopyrect: GrabServer detection, autorepeat throttling, + hack to clean screen 3,4,5 Alt_L in a row, mouse wheel detect. + * fix bug wrt switching to single_copytile, add Darwin to shm limit. + +2005-05-17 Karl Runge + * more -scrollcopyrect, -scr_term hacks for terminals. + * -wait_ui, -nowait_bog tunables. push cursor sooner. + +2005-05-14 Karl Runge + * much more work on "-scrollcopyrect" mode... getting usable. + * remove -pointer_mode 3, shift everyone back down + * -dbg "crash shell" for debugging + * -add_keysyms now the default, periodically clears if needed. + * try to autodetect if -xkb would be a good idea. + * improve keycode guessing for -xkb mode (force ISO_Level3_Shift) + * -remap DEAD, etc. for dead/mute keys remappings. + +2005-05-02 Karl Runge + * initial support for using RECORD to detect some types of window + scrolls. This is "-scrollcopyrect" mode, use -noscrollcopyrect + to disable. Much tuning and painting error repair still required. + * more build time customizations: REMOTE_DEFAULT, REMOTE_CONTROL, + EXTERNAL_COMMANDS, NOREPEAT, WIREFRAME*, SCROLL*, ... + * added bandwidth and latency measurements. + * added XListHosts to -privremote check. + * debug_* remote-control variables. + * removed OLD_TREE stuff. + +2005-04-19 Karl Runge + * somewhat safer remote-control defaults, and addnl options for + more safe operation: -privremote, -safer, -nocmds, -unsafe + * -wireframe, -wirecopyrect: instead of having user look at a + slowly moving, lurching window, guess when a window is being + moved/resized and just show a wireframe. -wirecopyrect means to + apply rfbDoCopyRegion to the detected move as well. + * debugging switches for X events and X damage: debug_xevents + debug_xdamage. + * -rawfb bugfixes. -noviewonly hack to still send UI to X. + +2005-04-11 Karl Runge + * fix -clip under -rawfb, fix offset bug under file lseeking. + * add -rawfb setup:cmd mode to initialize fb. example: misc/ranfb.pl + +2005-04-10 Karl Runge + * -rawfb non X-polling (i.e. shm, mmap, lseek). + * -pipeinput enable external user input processing command. + * -xtrap use XESimulateXEventRequest to inject user input. + * scaling blend for StaticGray, add :fb scaling option. + * default password macros. + * improve -norepeat use under -viewonly. + * -flag flagfile to aid wrapper scripts. + * add utility scripts, etc. dir ./misc + +2005-04-03 Karl Runge + * try DEC-XTRAP on X11R5 if XTestGrabControl is missing. + * -shiftcmap n, for 8bpp displays using < 256 color cells + and with pixel values shifted from zero. + * fix DAMAGE event leak after viewers disconnect. + * -http option to try to guess where the java viewer is. + +2005-03-29 Karl Runge + * build-time customizations X11VNC_SHARED, X11VNC_FOREVER, + REMOTE_CONTROL, SMALL_FOOTPRINT for CPPFLAGS + * fix event leaks for xkb BellNotify and ClientMessage and others, + esp. under -nofb. make nofb work with remote control. + * -nolookup for bad DNS setups. + * more playing with pointer_mode: check_user_input3() + +2005-03-19 Karl Runge + * scale cursors along with display. Use -scale_cursor to change + or disable cursor scaling. + * speed up scaling in some cases, :nb and integer magnification. + * provide alternative arrow cursors (1-6) via -arrow n. + * reset no autorepeat a couple times if something turns it off, + set with -norepeat N. + * do not take a nap if DAMAGE seems to be doing its job. + +2005-03-12 Karl Runge + * support for the X DAMAGE extension to receive damage + rectangle reports from the X server. On by default, disable + with -noxdamage. Currently only trusts small rects + (but see -xd_area n) and uses the rest as "hints" for the + scanline polling. + * -clip WxH+X+Y to show a clipped sub-region of the screen. + * use RFC 1413 (identd) to attach a name to a client in + friendly environments. + * fix XAUTHORITY wrt '-auth ... -gui other:0'. + +2005-03-04 Karl Runge + * add changes to couple with -listen option, in particular + the behavior of -localhost and remote control cmds. + * workarounds for old trees. + +2005-02-23 Karl Runge + * final changes for 0.7.1 release. + +2005-02-21 Karl Runge + * -nap is now the default, disable with -nonap + * set version to 0.7.1, word tune -help, etc. + +2005-02-14 Karl Runge + * cleanup -users stuff, add "lurk=" mode + * support cde in -solid + * simple gui mode for beginners, -gui ez,... + +2005-02-10 Karl Runge + * Add -input to fine tune client input (keystroke, mouse motion, + and button presses). Allow per-client setting via remote cntl. + * fix bug in get_remote_port, add ip2host for client info. + +2005-02-09 Karl Runge + * Add -users switch user mechanism and related utilities. + * fix -solid for gnome and kde. + * exit earlier on trapped XIO errors. + +2005-02-05 Karl Runge + * -solid solid color background when clients are connected. + * -opts/-? to show option names only. + +2005-01-23 Karl Runge + * sync with new draw cursor mechanism, keep old way in OLD_TREE. + * add -timeout option, change -alphablend to be default + * -R norepeat now forces the issue (Xsession may turn it back on). + * try :0 if no other info. + +2005-01-15 Karl Runge + * adjust alpha blending parameters, -alphablend, handle 24bpp. + * add -snapfb snapshot fb, not clear how useful it is.. + * more functions etc for -pointer_mode 4, still not finished. + * scan_for_updates() "count only" mode. + * increase max shm size on Linux. + * -oa -logappend, -pm, -speeds + * fix bugs in -allow, -R connect, screen == NULL + +2004-12-27 Karl Runge + * allow -DLIBVNCSERVER_HAVE_FOO=0 override everything + * get_xfixes_cursor() try to more carefully convert alpha channel + to opaque pixel. Options -alphacut, -alphafrac, -alpharemove + * more commands under remote control: rfbwait, rfbport, http, + httpport, httpdir, enablehttpproxy, desktop, alwaysshared, + dontdisconnect. Add to tkx11vnc. + +2004-12-22 Karl Runge + * final polishing for 0.7 release, tkx11vnc tweaks + * more careful rfbPE in pick_window, start check_user_input4() + +2004-12-19 Karl Runge + * cleanup putenv, snprint, other string manip. + * add -sync mode to remote control for better control + * allow -remote and -query at same time. + +2004-12-16 Karl Runge + * support for XFIXES extension to show the exact cursor shape, + working on Linux/Xorg and Solaris 10. disable with -noxfixes + * remote control mania - nearly everything can be changed dynamically! + see the -remote/-query (aka -R/-Q) options. e.g. -R scale:5/6 + * simple gui tkx11vnc based on the remote control mechanism, see -gui + * support for XRANDR extension, if the X screen changes size (see + xrandr(1)), x11vnc will resize the fb. Pays to have NewFBSize viewer + * -overlay support on IRIX with XReadDisplay (not tested). + * RFB_MODE is set to "accept" or "gone" in environment + * "-id pick" will let you pick the window (calls xwininfo(1)...) + * "-pointer_mode n" replaces -old_pointer (n=1) and -old_pointer2 (n=2) + a new mode n=3 is added (similary to nodragging, but dynamic). + * "-sb n" screen blank timeout option is now documented. + * renamed NON_CVS to OLD_TREE + +2004-08-31 Karl Runge + * new check_user_input() pointer input algorithm, it tries to avoid + extra-draws. still needs tuning, get previous one with -old_pointer2 + * add NON_CVS macro for building in older CVS trees. + +2004-08-29 Karl Runge + * remove old mouse patch code, now use rfbSetCursor (+ workarounds) + * changed cursor shape options (no more -mouse, ...) to '-cursor mode' + where 'mode' can be empty "X", "some", or "most". "some" adds + heuristics for two more cursors. + * -nocursorshape added. + * ifdef checks for XSHM and XTEST. Add *_wr wrappers as well. + * -vncconnect is now the default. + +2004-08-15 Karl Runge + * -overlay option to fix color problems on Sun machines with 8+24 + and 24+8 overlay visuals, uses Solaris XReadScreen(). + * expose -sid option (shifted -id windowid) to allow explicit + wrapping of XGetImage, etc for -overlay + * fix misc bugs: missing var types, hardwired blackouts sizes, + subwin desktop name crash. + +2004-08-03 Karl Runge + * add man page x11vnc.1 autogenerated from x11vnc -help; tweak + help output a little bit. Adjust autoconf to pick up manpage. + * add README from website docs. + * zero watch_bell and use_xkb_modtweak if no XKEYBOARD + +2004-07-31 Karl Runge + * -cursorpos now the default; make cursorpos work when scaling + * fix bug with multiple adds of the same keysym for -add_keysyms + * rewhack -help output again + * adjust version number and output. + +2004-07-28 Karl Runge + * -add_keysyms dynamically add missing keysyms to X server + +2004-07-26 Karl Runge + * first pass at doing modtweak via XKEYBOARD extension (-xkb) + * -skip_keycodes option for use with -xkb + * reset modtweak and xkb_modtweak on event MappingNotify. + * trap Xerror during XSendEvent/XChangeProperty. + * fix bug requesting PRIMARY way too often. + * more careful to check if XKeysymToString returns NULL. + * continuation lines "\" in x11vncrc. + * undoc'd expts: -isolevel3, -xkbcompat + +2004-07-19 Karl Runge + * ignore keysyms 5-8 for keycode keymapping. + * help to stdout for easy paging, add lastmod to help and -version. + +2004-07-15 Karl Runge + * make "modtweak" the default, disable with -nomodtweak. this + corrects ghost "< >" key on pc104 us in XFree86. + * fix bug wrt no got_keyboard_input under modtweak + +2004-07-10 Karl Runge + * -norepeat to turn off X server autorepeat when clients exist, + (this is workaround for the repeating keystroke bug. Note that + client side does autorepeating so not a big loss). + +2004-07-04 Karl Runge + * extend -allow to re-read a file with allowed IP addresses. + * improvements to -help text. + +2004-07-01 Karl Runge + * improve scaled grid calculation to prevent drift (which causes + drift in pixel weights and poorer tightvnc compression) + * add ":pad" scale option, detect small fraction scale = m/n. + +2004-06-28 Karl Runge + * round scaled width to multiple of 4 to make vncviewer happy. + * allow override of above ":n4" and allow 4 point interpolation + to be used even with shrinking ":in". + +2004-06-27 Karl Runge + * speed up scaling a bit for slow machines (still all floating point) + * add no blending option (-scale fraction:nb) + +2004-06-26 Karl Runge + * add -scale fract for global (not per-client) server-side scaling + working more or less OK, needs to be optimized at some point. + * remove -hints/-nohints options. + +2004-06-17 Karl Runge + * simple ~/.x11vncrc config file support, -rc, -norc + +2004-06-12 Karl Runge + * add -clear_mods -clear_keys for (rare) case where keys are + not being released (e.g. Ctrl-C x11vnc thru x11vnc). + * export RFB_SERVER_IP and RFB_SERVER_PORT to -accept program + so that the tcp 4-tuple is completely specified. + * add -storepasswd so storepasswd program not needed + +2004-06-05 Karl Runge + * rearrange file for easier maintenance, indicating file breakup. + * add RFB_CLIENT_COUNT, number of other connected clients to + -accept and -gone commands. + +2004-05-27 Karl Runge + * add view-only passwd via -viewpasswd and 2nd line of -passwdfile + +2004-05-21 Karl Runge + * -accept: add view-only decision and other improvements. + * add -gone command option for when a client leaves. + Thanks to Jesus Alvarez for these ideas. + * -passwdfile to keep passwd off of cmd line. + * -o logfile send stderr to a logfile. + +2004-05-14 Karl Runge + * improvements to -accept popup: yes/no buttons and timeout. + * less fprintf under -q so '-q -inetd' has no stderr output. + +2004-05-08 Karl Runge + * add -accept some-command/xmessage/popup to prompt local X11 user + or otherwise decide to accept an incoming client. + * clean up -Wall warnings. + +2004-05-05 Karl Runge + * enable mouse button -> keystrokes mapping in -buttonmap (mousewheel) + * enable keystroke -> mouse button mapping in -remap (touchpad paste) + (-remap incompat ':' -> '-', sorry...) + * shm OS blacklist (i.e. <= SunOS 5.8) -> -onetile + * revert to check_user_input() under -nofb + * cleanup: lastmod, remove tile_shm and update_client_pointer, + debug output, rfbPort failure. + * user friendly last line: 'The VNC desktop is hostname:0' + +2004-04-28 Karl Runge + * -auth cmdline option for xauthority. + * decrease default deferupdate under -nofb. + * update_client_pointer() from Edoardo Tirtarahardja. + * remove some assumptions about libvncserver defaults. + +2004-04-19 Karl Runge + * support for cursor positions updates -cursorpos + * option for SIGPIPE handling -sigpipe + +2004-04-13 Karl Runge + * solve problem with sending selection when client initializing + (not yet in RFB_NORMAL state). Increase delay to 15s as well. + * when threaded: limit rfbMaxClientWait to >= 20 secs and + increase it to a huge value unless -rfbwait is supplied. + +2004-04-08 Karl Runge + * added support for blacking out regions of the screen, primarily + for Xinerama usage, options: -blackout -xinerama + * Xinerama workaround mouse problem on 'embedded' system, + option -xwarppointer (XWarpPointer instead of XTEST) + * let -remap option take key remappings on cmdline as well as file. + * use cargs fix to test for invalid cmdline options. Add --option. + * remove copy_tile, use copy_tiles(..., 1) instead. + +2004-03-10 Karl Runge + * added reverse connection for vncconnect(1) and other means + -vncconnect, -connect host:port, and -connect watchfile + * added first pass at user keysym remapping feature via + -remap file. Ignores modifier state, need to generalize. + * debugging options for users -debug_pointer and -debug_keyboard + * clear -passwd from argv for privacy (if OS allows). + +2004-02-19 Karl Runge + * added handling of clipboard/selection exchange to/from clients, + even holds PRIMARY which Xvnc does not do. disable with -nosel. + use -noprimary to disable polling of PRIMARY selection. + * added -visual option to force framebuffer visual. not really + of general use, more for testing and workarounds (e.g. win2vnc + fails under 8bpp index color) + * improve cleanup and error handling WRT shm and other failures. + +2004-01-19 Karl Runge + * improvements to pointer event handling primarily during window + dragging. check_user_input() for non-threaded and pointer() + for threaded. Revert to old way via -old_pointer option. + * some memory I/O improvement by using copy_tiles() instead + of copy_tile(). New one does rows of tiles at same time. + Revert to old way via -old_copytile. + * handle case of more mouse buttons on client than on X server. + * added -buttonmap option for finer control over button differences. + +2004-01-09 Karl Runge + * options -allow / -localhost for simple IP based access screening + * option -nodragging to skip all screen updates during mouse drags + (thanks to Michal Sabala) + * option -input_skip to allow users to tune watch_loop dropthru rate + * try to avoid wasting RAM for framebuffer under -nofb + * cleanup wrt bpp vs. depth + +2003-12-08 Karl Runge + * add Xbell support using XKEYBOARD extension (disable: -nobell) + * add "-nofb" to disable framebuffer, i.e. mouse + keyboard only (!) + * add "-notruecolor" to force indexed 8bpp color (when 8bpp) + * make alias "-forever" for "-many" + +From Karl (x11vnc's father) on Apr 2, 2003: + +New option -nocursor to not display the vncviewer local cursor if user +does not want it (also caused some problems with older vncviewers) + +New option -mouse to show the position of the X server mouse (i.e. lagged +from the user's vnc cursor position). Also: -mouseX will try to show +the a different cursor (X) when on the root background. + +New option -many to wait for more connections rather than exiting when +the first client(s) disconnect. + +New option -flashcmap to try to follow installed colormaps under 8bpp +indexed color as pointer is moved. + +New option -nap to watch for low activity and throttle down the polling +rate. Useful on shared machines to keep the load down. + +Experimental option -id to show just that window and not +the whole display. Some remaining bugs and inconvenient behavior... +(e.g. new toplevels can be unseen) + +Fixed bug on multi-headed machines where the screen number was being +ignored in a number of places. + +Fixed bug wrt connect_once mode. Now just refuses new clients unless +shared rather than terminating all clients. + +Try to follow changing default colormap under 8bpp indexed color +as color cells are added. + +Needed to pick up HAVE_LIBPTHREAD from autoconf. + +defined a select() macro for usleep() since usleep is not always thread +safe. + +Catch and exit on errors in the shm setup work (XShmCreateImage, shmget,...) +and moved the creation and removal work to separate utility functions. + +Added signal and X error handlers to try to clean out the shm objects +before exiting on interrupt, etc. + +Improved performance a bit on the memcmp() in scan_display() by checking +the whole line first. + +Added a workaround when threaded where libvncserver may disconnect too +early if it does not hear from a client (a small heartbeat is sent). +This may not be needed any longer. + +If -desktop has not been prescribed, try to choose a title based on DISPLAY +and the hostname (and window name under -id). diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/Makefile.am new file mode 100755 index 0000000..c18f49d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/Makefile.am @@ -0,0 +1,36 @@ +if HAVE_SYSTEM_LIBVNCSERVER +LDADD = @SYSTEM_LIBVNCSERVER_LIBS@ @WSOCKLIB@ +else +LDADD = ../libvncserver/libvncserver.la ../libvncclient/libvncclient.la @WSOCKLIB@ +endif + +if OSX +x11vnc_LDFLAGS = -framework ApplicationServices -framework Carbon -framework IOKit -framework Cocoa +x11vnc_CFLAGS = -ObjC +endif + +SUBDIRS = misc +DIST_SUBDIRS = misc + +desktopdir = $(datadir)/applications +desktop_DATA = x11vnc.desktop + +man_MANS=x11vnc.1 +EXTRA_DIST=ChangeLog README tkx11vnc $(man_MANS) $(desktop_DATA) + +if CYGIPC +LD_CYGIPC=-lcygipc +endif + +bin_PROGRAMS=x11vnc +x11vnc_SOURCES = 8to24.c appshare.c avahi.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c linuxfb.c macosx.c macosxCG.c macosxCGP.c macosxCGS.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c uinput.c unixpw.c user.c userinput.c util.c v4l.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h avahi.h blackout_t.h cleanup.h connections.h cursor.h enc.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h macosx.h macosxCG.h macosxCGP.h macosxCGS.h nox11.h nox11_funcs.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h uinput.h unixpw.h user.h userinput.h util.h v4l.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h + +if HAVE_SYSTEM_LIBVNCSERVER +INCLUDES_LIBVNCSERVER = @SYSTEM_LIBVNCSERVER_CFLAGS@ +else +INCLUDES_LIBVNCSERVER = +endif +INCLUDES = -I$(top_srcdir) +INCLUDES += $(INCLUDES_LIBVNCSERVER) @X_CFLAGS@ @AVAHI_CFLAGS@ + +x11vnc_LDADD=$(LDADD) @SSL_LIBS@ @CRYPT_LIBS@ @X_LIBS@ @AVAHI_LIBS@ $(LD_CYGIPC) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/README b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/README new file mode 100755 index 0000000..d440a82 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/README @@ -0,0 +1,17770 @@ + +Copyright (C) 2002-2010 Karl J. Runge +All rights reserved. + +x11vnc README file Date: Sat May 8 19:32:50 EDT 2010 + +The following information is taken from these URLs: + + http://www.karlrunge.com/x11vnc/index.html + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + ... + +they contain the most up to date info. + + +======================================================================= +http://www.karlrunge.com/x11vnc/index.html: + + + _________________________________________________________________ + +x11vnc: a VNC server for real X displays + (to FAQ) (to Downloads) (to Building) (to Beta Test) + (to Donations) [PayPal] + + x11vnc allows one to view remotely and interact with real X displays + (i.e. a display corresponding to a physical monitor, keyboard, and + mouse) with any VNC viewer. In this way it plays the role for Unix/X11 + that WinVNC plays for Windows. + + It has built-in SSL/TLS encryption and 2048 bit RSA authentication, + including VeNCrypt support; UNIX account and password login support; + server-side scaling; single port HTTPS/HTTP+VNC; Zeroconf service + advertising; and TightVNC and UltraVNC file-transfer. It has also been + extended to work with non-X devices: natively on Mac OS X Aqua/Quartz, + webcams and TV tuner capture devices, and embedded Linux systems such + as Qtopia Core. Full IPv6 support is provided. More features are + described here. + + It also provides an encrypted Terminal Services mode (-create, -svc, + or -xdmsvc options) based on Unix usernames and Unix passwords where + the user does not need to memorize his VNC display/port number. + Normally a virtual X session (Xvfb) is created for each user, but it + also works with X sessions on physical hardware. See the tsvnc + terminal services mode of the SSVNC viewer for one way to take + advantage of this mode. + + I wrote x11vnc back in 2002 because x0rfbserver was basically + impossible to build on Solaris and had poor performance. The primary + x0rfbserver build problems centered around esoteric C++ toolkits. + x11vnc is written in plain C and needs only standard libraries and so + should work on nearly all Unixes, even very old ones. I also created + enhancements to improve the interactive response, added many features, + and etc. + + This page including the FAQ contains much information [*]; solutions + to many problems; and interesting applications, but nevertheless + please feel free to contact me if you have problems or questions (and + if I save you time or expense by giving you some of my time, please + consider a PayPal Donation.) Do check the FAQ and this page first; I + realize the pages are massive, but you can often use your browser's + find-in-page search action using a keyword to find the answer to your + problem or question. + + SSVNC: An x11vnc side-project provides an Enhanced TightVNC Viewer + package (SSVNC) for Unix, Windows, and Mac OS X with automatic SSL + and/or SSH tunnelling support, SSL Certificate creation, Saved + connection profiles, Zeroconf, VeNCrypt, and built-in Proxy support. + Added features for the TightVNC Unix viewer: NewFBSize, ZRLE encoding, + Viewer-side Scaling, cursor alphablending, low color modes, and + enhanced popup menu; UltraVNC extensions support for: File Transfer, + Text Chat, Single Window, Server Input, and 1/n Scaling extensions, + and UltraVNC DSM encryption. The SSVNC bundle could be placed on, say, + a USB memory stick for SSL/SSH VNC viewing from nearly any networked + computer. + + _________________________________________________________________ + + Announcements: + + Important: If you created any permanent SSL certificates (e.g. via + "x11vnc -ssl SAVE ...") on a Debian or Ubuntu system from Sept. 2006 + through May 2008, then those keys are likely extremely weak and can be + easily cracked. The certificate files should be deleted and recreated + on a non-Debian system or an updated one. See + http://www.debian.org/security/2008/dsa-1571 for details. The same + applies to SSH keys (not used by x11vnc directly, but many people use + SSH tunnels for VNC access.) + + FAQ moved: The huge FAQ has finally been moved to its own page. If you + are trying to follow someone's link to an FAQ once on this page it is + now a broken link. Try inserting the string "faq.html", e.g.: +from: http://www.karlrunge.com/x11vnc/#faq-singleclick +to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick + + Apologies for the inconvenience, unfortunately it is not possible to + automatically redirect to the new page since the '#' anchor is not + sent to the webserver. + + _________________________________________________________________ + + Background: + + VNC (Virtual Network Computing) is a very useful network graphics + protocol (applications running on one computer but displaying their + windows on another) in the spirit of X, however, unlike X, the + viewing-end is very simple and maintains no state. It is a remote + framebuffer (RFB) protocol. + + Some VNC links: + * http://www.realvnc.com + * http://www.tightvnc.com + * http://www.ultravnc.com/ + * http://www.testplant.com/products/vine_server/OS_X + + For Unix, the traditional VNC implementation includes a "virtual" X11 + server Xvnc (usually launched via the vncserver command) that is not + associated with a physical display, but provides a "fake" one X11 + clients (xterm, firefox, etc.) can attach to. A remote user then + connects to Xvnc via the VNC client vncviewer from anywhere on the + network to view and interact with the whole virtual X11 desktop. + + The VNC protocol is in most cases better suited for remote connections + with low bandwidth and high latency than is the X11 protocol because + it involves far fewer "roundtrips" (an exception is the cached pixmap + data on the viewing-end provided by X.) Also, with no state maintained + the viewing-end can crash, be rebooted, or relocated and the + applications and desktop continue running. Not so with X11. + + So the standard Xvnc/vncserver program is very useful, I use it for + things like: + * Desktop conferencing with other users (e.g. code reviews.) + * Long running apps/tasks I want to be able to view from many places + (e.g. from home and work.) + * Motif, GNOME, and similar applications that would yield very poor + performance over a high latency link. + + However, sometimes one wants to connect to a real X11 display (i.e. + one attached to a physical monitor, keyboard, and mouse: a Workstation + or a SunRay session) from far away. Maybe you want to close down an + application cleanly rather than using kill, or want to work a bit in + an already running application, or would like to help a distant + colleague solve a problem with their desktop, or would just like to + work out on the deck for a while. This is where x11vnc is useful. + _________________________________________________________________ + + How to use x11vnc: + + In this basic example let's assume the remote machine with the X + display you wish to view is "far-away.east:0" and the workstation you + are presently working at is "sitting-here.west". + + Step 0. Download x11vnc (see below) and have it available to run on + far-away.east (on some linux distros it is as easy as "apt-get install + x11vnc", "emerge x11vnc", etc.) Similarly, have a VNC viewer (e.g. + vncviewer) ready to run on sitting-here.west. We recommend TightVNC + Viewers (see also our SSVNC viewer.) + + Step 1. By some means log in to far-away.east and get a command shell + running there. You can use ssh, or even rlogin, telnet, or any other + method to do this. We do this because the x11vnc process needs to be + run on the same machine the X server process is running on (otherwise + things would be extremely slow.) + + Step 2. In that far-away.east shell (with command prompt "far-away>" + in this example) run x11vnc directed at the far-away.east X session + display: + + far-away> x11vnc -display :0 + + You could have also set the environment variable DISPLAY=:0 instead of + using "-display :0". This step attaches x11vnc to the far-away.east:0 + X display (i.e. no viewer clients yet.) + + Common Gotcha: To get X11 permissions right, you may also need to set + the XAUTHORITY environment variable (or use the -auth option) to point + to the correct MIT-MAGIC-COOKIE file (e.g. /home/joe/.Xauthority.) If + x11vnc does not have the authority to connect to the display it exits + immediately. More on how to fix this below. + + If you suspect an X11 permissions problem do this simple test: while + sitting at the physical X display open a terminal window + (gnome-terminal, xterm, etc.) You should be able to run x11vnc + successfully in that terminal without any need for command line + options. If that works OK then you know X11 permissions are the only + thing preventing it from working when you try to start x11vnc via a + remote shell. Then fix this with the tips below. + + Note as of Feb/2007 you can also try the -find option instead of + "-display ..." and see if that finds your display and Xauthority. Note + as of Dec/2009 the -findauth and "-auth guess" options may be helpful + as well. + (End of Common Gotcha) + + When x11vnc starts up there will then be much chatter printed out (use + "-q" to quiet it), until it finally says something like: + . + . + 13/05/2004 14:59:54 Autoprobing selected port 5900 + 13/05/2004 14:59:54 screen setup finished. + 13/05/2004 14:59:54 + 13/05/2004 14:59:54 The VNC desktop is far-away:0 + PORT=5900 + + which means all is OK, and we are ready for the final step. + + Step 3. At the place where you are sitting (sitting-here.west in this + example) you now want to run a VNC viewer program. There are VNC + viewers for Unix, Windows, MacOS, Java-enabled web browsers, and even + for PDA's like the Palm Pilot and Cell Phones! You can use any of them + to connect to x11vnc (see the above VNC links under "Background:" on + how to obtain a viewer for your platform or see this FAQ. For Solaris, + vncviewer is available in the Companion CD package SFWvnc.) + + In this example we'll use the Unix vncviewer program on sitting-here + by typing the following command in a second terminal window: + + sitting-here> vncviewer far-away.east:0 + + That should pop up a viewer window on sitting-here.west showing and + allowing interaction with the far-away.east:0 X11 desktop. Pretty + nifty! When finished, exit the viewer: the remote x11vnc process will + shutdown automatically (or you can use the -forever option to have it + wait for additional viewer connections.) + + Common Gotcha: Nowadays there will likely be a host-level firewall on + the x11vnc side that is blocking remote access to the VNC port (e.g. + 5900.) You will either have to open up that port (or a range of ports) + in your firewall administration tool, or try the SSH tunnelling method + below (even still the firewall must allow in the SSH port, 22.) + + + Shortcut: Of course if you left x11vnc running on far-away.east:0 in a + terminal window with the -forever option or as a service, you'd only + have to do Step 3 as you moved around. Be sure to use a VNC Password + or other measures if you do that. + + + Super Shortcut: Here is a potentially very easy way to get all of it + working. + * Have x11vnc (0.9.3 or later) available to run on the remote host + (i.e. in $PATH.) + * Download and unpack a SSVNC bundle (1.0.19 or later, e.g. + ssvnc_no_windows-1.0.23.tar.gz) on the Viewer-side machine. + * Start the SSVNC Terminal Services mode GUI: ./ssvnc/bin/tsvnc + * Enter your remote username@hostname (e.g. fred@far-away.east) in + the "VNC Terminal Server" entry. + * Click "Connect". + + That will do an SSH to username@hostname and start up x11vnc and then + connect a VNC Viewer through the SSH encrypted tunnel. + + There are a number of things assumed here, first that you are able to + SSH into the remote host; i.e. that you have a Unix account there and + the SSH server is running. On Unix and MacOS X it is assumed that the + ssh client command is available on the local machine (on Windows a + plink binary is included in the SSVNC bundle.) Finally, it is assumed + that you are already logged into an X session on the remote machine, + e.g. your workstation (otherwise, a virtual X server, e.g. Xvfb, will + be started for you.) + + In some cases the remote SSH server will not run commands with the + same $PATH that you normally have in your shell there. In this case + click on Options -> Advanced -> X11VNC Options, and type in the + location of the x11vnc binary under "Full Path". (End of Super + Shortcut) + + + Desktop Sharing: The above more or less assumed nobody was sitting at + the workstation display "far-away.east:0". This is often the case: a + user wants to access her workstation remotely. Another usage pattern + has the user sitting at "far-away.east:0" and invites one or more + other people to view and interact with his desktop. Perhaps the user + gives a demo or presentation this way (using the telephone for vocal + communication.) A "Remote Help Desk" mode would be similar: a + technician connects remotely to the user's desktop to interactively + solve a problem the user is having. + + For these cases it should be obvious how it is done. The above steps + will work, but more easily the user sitting at far-away.east:0 simply + starts up x11vnc from a terminal window, after which the guests would + start their VNC viewers. For this usage mode the "-connect + host1,host2" option may be of use to automatically connect to the + vncviewers in "-listen" mode on the list of hosts. + _________________________________________________________________ + + Tunnelling x11vnc via SSH: + + The above example had no security or privacy at all. When logging into + remote machines (certainly when going over the internet) it is best to + use ssh, or use a VPN (for a VPN, Virtual Private Network, the above + example should be pretty safe.) + + For x11vnc one can tunnel the VNC protocol through an encrypted ssh + channel. It would look something like running the following commands: + sitting-here> ssh -t -L 5900:localhost:5900 far-away.east 'x11vnc -localhost +-display :0' + + (you will likely have to provide passwords/passphrases to login from + sitting-here into your far-away.east Unix account; we assume you have + a login account on far-away.east and it is running the SSH server) + + And then in another terminal window on sitting-here run the command: + sitting-here> vncviewer -encodings "copyrect tight zrle hextile" localhost:0 + + Note: The -encodings option is very important: vncviewer will often + default to "raw" encoding if it thinks the connection is to the local + machine, and so vncviewer gets tricked this way by the ssh + redirection. "raw" encoding will be extremely slow over a networked + link, so you need to force the issue with -encodings "copyrect tight + ...". Nowadays, not all viewers use the -encodings option, try + "-PreferredEncoding=ZRLE" (although the newer viewers seem to + autodetect well when to use raw or not.) + + Note that "x11vnc -localhost ..." limits incoming vncviewer + connections to only those from the same machine. This is very natural + for ssh tunnelling (the redirection appears to come from the same + machine.) Use of a VNC password is also strongly recommended. + + Note also the -t we used above (force allocate pseudoterminal), it + actually seems to improve interactive typing response via VNC! + + You may want to add the -C option to ssh to enable compression. The + VNC compression is not perfect, and so this may help a bit. However, + over a fast LAN you probably don't want to enable SSH compression + because it can slow things down. Try both and see which is faster. + + If your username is different on the remote machine use something + like: "fred@far-away.east" in the above ssh command line. + + Some VNC viewers will do the ssh tunnelling for you automatically, the + TightVNC Unix vncviewer does this when the "-via far-away.east" option + is supplied to it (this requires x11vnc to be already running on + far-away.east or having it started by inetd(8).) See the 3rd script + example below for more info. + + SSVNC: You may also want to look at the Enhanced TightVNC Viewer + (ssvnc) bundles because they contain scripts and GUIs to automatically + set up SSH tunnels (e.g. the GUI, "ssvnc", does it automatically and + so does this command: "ssvnc_cmd -ssh user@far-away.east:0") and can + even start up x11vnc as well. + + The Terminal Services mode of SSVNC is perhaps the easiest way to use + x11vnc. You just need to have x11vnc available in $PATH on the remote + side (and can SSH to the host), and then on the viewer-side you type + something like: + tsvnc fred@far-away.east + + everything else is done automatically for you. Normally this will + start a virtual Terminal Services X session (RAM-only), but if you + already have a real X session up on the physical hardware it will find + that one for you. + + Gateways: If the machine you SSH into is not the same machine with + the X display you wish to view (e.g. your company provides incoming + SSH access to a gateway machine), then you need to change the above + to, e.g.: "-L 5900:OtherHost:5900": + sitting-here> ssh -t -L 5900:OtherHost:5900 gateway.east + + Where gateway.east is the internet hostname (or IP) of the gateway + machine (SSH server.) 'OtherHost' might be, e.g., freds-pc or + 192.168.2.33 (it is OK for these to be private hostnames or private IP + addresses, the host in -L is relative to the remote server side.) + + Once logged in, you'll need to do a second login (ssh, rsh, etc.) to + the workstation machine 'OtherHost' and then start up x11vnc on it (if + it isn't already running.) (The "-connect gateway:59xx" option may be + another alternative here with the viewer already in -listen mode.) For + an automatic way to use a gateway and have all the network traffic + encrypted (including inside the firewall) see Chaining SSH's. + + These gateway access modes also can be done automatically for you via + the "Proxy/Gateway" setting in SSVNC (including the Chaining SSH's + case, "Double Proxy".) + + Firewalls/Routers: + + A lot of people have inexpensive devices for home or office that act + as a Firewall and Router to the machines inside on a private LAN. One + can usually configure the Firewall/Router from inside the LAN via a + web browser. + + Often having a Firewall/Router sitting between the vncviewer and + x11vnc will make it impossible for the viewer to connect to x11vnc. + + One thing that can be done is to redirect a port on the + Firewall/Router to, say, the SSH port (22) on an inside machine (how + to do this depends on your particular Firewall/Router, often the + router config URL is http://192.168.100.1 See www.portforward.com for + more info.) This way you reach these computers from anywhere on the + Internet and use x11vnc to view X sessions running on them. + + Suppose you configured the Firewall/Router to redirect these ports to + two internal machines: + Port 12300 -> 192.168.1.3, Port 22 (SSH) + Port 12301 -> 192.168.1.4, Port 22 (SSH) + + (where 192.168.1.3 is "jills-pc" and 192.168.1.4 is "freds-pc".) Then + the ssh's would look something like: + sitting-here> ssh -t -p 12300 -L 5900:localhost:5900 jill@far-away.east 'x11v +nc -localhost -display :0' + sitting-here> ssh -t -p 12301 -L 5900:localhost:5900 fred@far-away.east 'x11v +nc -localhost -display :0' + + Where far-away.east means the hostname (or IP) that the + Router/Firewall is using (for home setups this is usually the IP + gotten from your ISP via DHCP, the site http://www.whatismyip.com/ is + a convenient way to determine what it is.) + + It is a good idea to add some obscurity to accessing your system via + SSH by using some high random port (e.g. 12300 in the above example.) + If you can't remember it, or are otherwise not worried about port + scanners detecting the presence of your SSH server and there is just + one internal PC involved you could map 22: + Port 22 -> 192.168.1.3, Port 22 (SSH) + + Again, this SSH gateway access can be done automatically for you via + the "Proxy/Gateway" setting in SSVNC. And under the "Remote SSH + Command" setting you can enter the x11vnc -localhost -display :0. + + Host-Level-Firewalls: even with the hardware Firewall/Router problem + solved via a port redirection, most PC systems have their own Host + level "firewalls" enabled to protect users from themselves. I.e. the + system itself blocks all incoming connections. So you will need to see + what is needed to configure it to allow in the port (e.g. 22) that you + desire. E.g. Yast, Firestarter, iptables(1), etc.. + + VNC Ports and Firewalls: The above discussion was for configuring the + Firewall/Router to let in port 22 (SSH), but the same thing can be + done for the default VNC port 5900: + Port 5900 -> 192.168.1.3, Port 5900 (VNC) + Port 5901 -> 192.168.1.4, Port 5900 (VNC) + + (where 192.168.1.3 is "jills-pc" and 192.168.1.4 is "freds-pc".) This + could be used for normal, unencrypted connections and also for SSL + encrypted ones. + + The VNC displays to enter in the VNC viewer would be, say, + "far-away.east:0" to reach jills-pc and "far-away.east:1" to reach + freds-pc. We assume above that x11vnc is using port 5900 (and any + Host-Level-firewalls on jills-pc has been configured to let that port + in.) Use the "-rfbport" option to tell which port x11vnc should listen + on. + + For a home system one likely does not have a hostname and would have + to use the IP address, say, "24.56.78.93:0". E.g.: + vncviewer 24.56.78.93:0 + + You may want to choose a more obscure port on the router side, e.g. + 5944, to avoid a lot of port scans finding your VNC server. For 5944 + you would tell the viewer to use: + vncviewer 24.56.78.93:44 + + The IP address would need to be communicated to the person running the + VNC Viewer. The site http://www.whatismyip.com/ can help here. + + _________________________________________________________________ + + Scripts to automate ssh tunneling: As discussed below, there may be + some problems with port 5900 being available. If that happens, the + above port and display numbers may change a bit (e.g. -> 5901 and :1). + However, if you "know" port 5900 will be free on the local and remote + machines, you can easily automate the above two steps by using the + x11vnc option -bg (forks into background after connection to the + display is set up) or using the -f option of ssh. Some example scripts + are shown below. Feel free to try the ssh -C to enable its compression + and see if that speeds things up noticeably. + _________________________________________________________________ + + #1. A simple example script, assuming no problems with port 5900 being + taken on the local or remote sides, looks like: +#!/bin/sh +# usage: x11vnc_ssh : +# e.g.: x11vnc_ssh snoopy.peanuts.com:0 +# (user@host:N also works) + +host=`echo $1 | awk -F: '{print $1}'` +disp=`echo $1 | awk -F: '{print $2}'` +if [ "x$disp" = "x" ]; then disp=0; fi + +cmd="x11vnc -display :$disp -localhost -rfbauth .vnc/passwd" +enc="copyrect tight zrle hextile zlib corre rre raw" + +ssh -f -t -L 5900:localhost:5900 $host "$cmd" + +for i in 1 2 3 +do + sleep 2 + if vncviewer -encodings "$enc" :0; then break; fi +done + + See also rx11vnc.pl below. + _________________________________________________________________ + + #2. Another method is to start the VNC viewer in listen mode + "vncviewer -listen" and have x11vnc initiate a reverse connection + using the -connect option: +#!/bin/sh +# usage: x11vnc_ssh : +# e.g.: x11vnc_ssh snoopy.peanuts.com:0 +# (user@host:N also works) + +host=`echo $1 | awk -F: '{print $1}'` +disp=`echo $1 | awk -F: '{print $2}'` +if [ "x$disp" = "x" ]; then disp=0; fi + +cmd="x11vnc -display :$disp -localhost -connect localhost" # <== note new opt +ion +enc="copyrect tight zrle hextile zlib corre rre raw" + +vncviewer -encodings "$enc" -listen & +pid=$! +ssh -t -R 5500:localhost:5500 $host "$cmd" +kill $pid + + Note the use of the ssh option "-R" instead of "-L" to set up a remote + port redirection. + _________________________________________________________________ + + #3. A third way is specific to the TightVNC vncviewer special option + -via for gateways. The only tricky part is we need to start up x11vnc + and give it some time (5 seconds in this example) to start listening + for connections (so we cannot use the TightVNC default setting for + VNC_VIA_CMD): +#!/bin/sh +# usage: x11vnc_ssh : +# e.g.: x11vnc_ssh snoopy.peanuts.com:0 + +host=`echo $1 | awk -F: '{print $1}'` +disp=`echo $1 | awk -F: '{print $2}'` +if [ "x$disp" = "x" ]; then disp=0; fi + +VNC_VIA_CMD="ssh -f -t -L %L:%H:%R %G x11vnc -localhost -rfbport 5900 -display +:$disp; sleep 5" +export VNC_VIA_CMD + +vncviewer -via $host localhost:0 # must be TightVNC vncviewer. + + Of course if you already have the x11vnc running waiting for + connections (or have it started out of inetd(8)), you can simply use + the TightVNC "vncviewer -via gateway host:port" in its default mode to + provide secure ssh tunnelling. + _________________________________________________________________ + + + + VNC password file: Also note in the #1. example script that the option + "-rfbauth .vnc/passwd" provides additional protection by requiring a + VNC password for every VNC viewer that connects. The vncpasswd or + storepasswd programs, or the x11vnc -storepasswd option can be used to + create the password file. x11vnc also has the slightly less secure + -passwdfile and "-passwd XXXXX" options to specify passwords. + + Very Important: It is up to YOU to tell x11vnc to use password + protection (-rfbauth or -passwdfile), it will NOT do it for you + automatically or force you to (use -usepw if you want to be forced + to.) The same goes for encrypting the channel between the viewer and + x11vnc: it is up to you to use ssh, stunnel, -ssl mode, a VPN, etc. + (use the Enhanced TightVNC Viewer (SSVNC) GUI if you want to be forced + to use SSL or SSH.) For additional safety, also look into the -allow + and -localhost options and building x11vnc with tcp_wrappers support + to limit host access. + + _________________________________________________________________ + + Tunnelling x11vnc via SSL/TLS: + + One can also encrypt the VNC traffic using an SSL/TLS tunnel such as + stunnel.mirt.net (also stunnel.org) or using the built-in (Mar/2006) + -ssl openssl mode. A SSL-enabled Java applet VNC Viewer is also + provided in the x11vnc package (and https can be used to download it.) + + Although not as ubiquitous as ssh, SSL tunnelling still provides a + useful alternative. See this FAQ on -ssl and -stunnel modes for + details and examples. + + The Enhanced TightVNC Viewer (SSVNC) bundles contain some convenient + utilities to automatically set up an SSL tunnel from the viewer-side + (i.e. to connect to "x11vnc -ssl ...".) And many other enhancements + too. + _________________________________________________________________ + + Downloading x11vnc: + + x11vnc is a contributed program to the LibVNCServer project at + SourceForge.net. I use libvncserver for all of the VNC aspects; I + couldn't have done without it. The full source code may be found and + downloaded (either file-release tarball or GIT tree) from the above + link. As of May 2010, the x11vnc-0.9.10.tar.gz source package is + released (recommended download). The x11vnc 0.9.10 release notes. + + The x11vnc package is the subset of the libvncserver package needed to + build the x11vnc program. Also, you can get a copy of my latest, + bleeding edge x11vnc-0.9.11-dev.tar.gz tarball to build the most up to + date one. + + Precompiled Binaries/Packages: See the FAQ below for information + about where you might obtain a precompiled x11vnc binary from 3rd + parties and some ones I create. + + VNC Viewers: To obtain VNC viewers for the viewing side (Windows, Mac + OS, or Unix) try these links: + * http://www.tightvnc.com/download.html + * http://www.realvnc.com/download-free.html + * http://sourceforge.net/projects/cotvnc/ + * http://www.ultravnc.com/ + * Our Enhanced TightVNC Viewer (SSVNC) + + [ssvnc.gif] + + + More tools: Here is a ssh/rsh wrapper script rx11vnc that attempts to + automatically do the above Steps 1-3 for you (provided you have + ssh/rsh login permission on the machine x11vnc is to be run on.) The + above example would be: "rx11vnc far-away.east:0" typed into a shell + on sitting-here.west. Also included is an experimental script + rx11vnc.pl that attempts to tunnel the vnc traffic through an ssh port + redirection (and does not assume port 5900 is free.) Have a look at + them to see what they do and customize as needed: + * rx11vnc wrapper script + * rx11vnc.pl wrapper script to tunnel traffic thru ssh + + _________________________________________________________________ + + Building x11vnc: + + Make sure you have all the needed build/compile/development packages + installed (e.g. Linux distributions foolishly don't install them by + default.) See this build FAQ for more details. + + If your OS has libjpeg.so and libz.so in standard locations you can + build as follows (example given for the 0.9.10 release of x11vnc: + replace with the version you downloaded): +(un-tar the x11vnc+libvncserver tarball) +# gzip -dc x11vnc-0.9.10.tar.gz | tar -xvf - + +(cd to the source directory) +# cd x11vnc-0.9.10 + +(run configure and then run make) +# ./configure +# make + +(if all went OK, copy x11vnc to the desired destination, e.g. $HOME/bin) +# cp ./x11vnc/x11vnc $HOME/bin + + Or do make install, it will probably install to /usr/local/bin (run + ./configure --help for information on customizing your configuration, + e.g. --prefix=/my/place.) You can now run it via typing "x11vnc", + "x11vnc -help | more", "x11vnc -forever -shared -display :0", etc. + + + Note: Currently gcc is recommended to build libvncserver. In some + cases it will build with non-gcc compilers, but the resulting binary + sometimes fails to run properly. For Solaris pre-built gcc binaries + are at http://www.sunfreeware.com/. Some Solaris pre-built x11vnc + binaries are here. + + However, one user reports it does work fine when built with Sun Studio + 10, so YMMV. In fact, here is a little build script to do this on + Solaris 10: +#!/bin/sh +PATH=/usr/ccs/bin:/opt/SUNWspro/bin:$PATH; export PATH + +CC='cc' \ +CFLAGS='-xO4' \ +LDFLAGS='-L/usr/sfw/lib -L/usr/X11/lib -R/usr/sfw/lib -R/usr/X11/lib' \ +CPPFLAGS='-I /usr/sfw/include -I/usr/X11/include' \ +./configure + +MAKE="make -e" +AM_CFLAGS="" +export MAKE AM_CFLAGS +$MAKE + + In general you can use the "make -e" trick if you don't like + libvncserver's choice of AM_CFLAGS. See the build scripts below for + more ideas. Scripts similar to the above have been shown to work with + vendor C compilers on HP-UX (ccom: HP92453-01) and Tru64 (Compaq C + V6.5-011.) + + You can find information on Misc. Build problems here. + + _________________________________________________________________ + + Building on Solaris, FreeBSD, etc: Depending on your version of + Solaris or other Unix OS the jpeg and/or zlib libraries may be in + non-standard places (e.g. /usr/local, /usr/sfw, /opt/sfw, etc.) + + Note: If configure cannot find these two libraries then TightVNC and + ZRLE encoding support will be disabled, and you don't want that!!! The + TightVNC encoding gives very good compression and performance, it even + makes a noticeable difference over a fast LAN. + + + Shortcuts: On Solaris 10 you can pick up almost everything just by + insuring that your PATH has /usr/sfw/bin (for gcc) and /usr/ccs/bin + (for other build tools), e.g.: + env PATH=/usr/sfw/bin:/usr/ccs/bin:$PATH sh -c './configure; make' + + (The only thing this misses is /usr/X11/lib/libXrandr.so.2, which is + for the little used -xrandr option, see the script below to pick it up + as well.) + + + libjpeg is included in Solaris 9 and later (/usr/sfw/include and + /usr/sfw/lib), and zlib in Solaris 8 and later (/usr/include and + /usr/lib.) So on Solaris 9 you can pick up everything with something + like this: + env PATH=/usr/local/bin:/usr/ccs/bin:$PATH sh -c './configure --with-jpeg=/us +r/sfw; make' + + assuming your gcc is in /usr/local/bin and x11vnc 0.7.1 or later. + These are getting pretty long, see those assignments split up in the + build script below. + + + If your system does not have these libraries at all you can get the + source for the libraries to build them: libjpeg is available at + ftp://ftp.uu.net/graphics/jpeg/ and zlib at http://www.gzip.org/zlib/. + See also http://www.sunfreeware.com/ for Solaris binary packages of + these libraries as well as for gcc. Normally they will install into + /usr/local but you can install them anywhere with the + --prefix=/path/to/anywhere, etc. + + + Here is a build script that indicates one way to pass the library + locations information to the libvncserver configuration via the + CPPFLAGS and LDFLAGS environment variables. +---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8 +<--- +#!/bin/sh + +# Build script for Solaris, etc, with gcc, libjpeg and libz in +# non-standard locations. + +# set to get your gcc, etc: +# +PATH=/path/to/gcc/bin:/usr/ccs/bin:/usr/sfw/bin:$PATH + +JPEG=/path/to/jpeg # set to maybe "/usr/local", "/usr/sfw", or "/opt/sfw" +ZLIB=/path/to/zlib # set to maybe "/usr/local", "/usr/sfw", or "/opt/sfw" + +# Below we assume headers in $JPEG/include and $ZLIB/include and the +# shared libraries are in $JPEG/lib and $ZLIB/lib. If your situation +# is different change the locations in the two lines below. +# +CPPFLAGS="-I $JPEG/include -I $ZLIB/include" +LDFLAGS="-L$JPEG/lib -R $JPEG/lib -L$ZLIB/lib -R $ZLIB/lib" + +# These two lines may not be needed on more recent Solaris releases: +# +CPPFLAGS="$CPPFLAGS -I /usr/openwin/include" +LDFLAGS="$LDFLAGS -L/usr/openwin/lib -R /usr/openwin/lib" + +# These are for libXrandr.so on Solaris 10: +# +CPPFLAGS="$CPPFLAGS -I /usr/X11/include" +LDFLAGS="$LDFLAGS -L/usr/X11/lib -R /usr/X11/lib" + +# Everything needs to built with _REENTRANT for thread safe errno: +# +CPPFLAGS="$CPPFLAGS -D_REENTRANT" + +export PATH CPPFLAGS LDFLAGS + +./configure +make + +ls -l ./x11vnc/x11vnc + +---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8 +<--- + + Then do make install or copy the x11vnc binary to your desired + destination. + + BTW, To run a shell script, just cut-and-paste the above into a file, + say "myscript", then modify the "/path/to/..." items to correspond to + your system/environment, and then type: "sh myscript" to run it. + + Note that on Solaris make is /usr/ccs/bin/make, so that is why the + above puts /usr/ccs/bin in PATH. Other important build utilities are + there too: ld, ar, etc. Also, it is probably a bad idea to have + /usr/ucb in your PATH while building. + + Starting with the 0.7.1 x11vnc release the "configure --with-jpeg=DIR + --with-zlib=DIR" options are handy if you want to avoid making a + script. + + If you need to link OpenSSL libssl.a on Solaris see this method. + + If you need to build on Solaris 2.5.1 or earlier or other older Unix + OS's, see this workaround FAQ. + + + Building on FreeBSD, OpenBSD, ...: The jpeg libraries seem to be in + /usr/local or /usr/pkg on these OS's. You won't need the openwin stuff + in the above script (but you may need /usr/X11R6/....) Also starting + with the 0.7.1 x11vnc release, this usually works: + ./configure --with-jpeg=/usr/local + make + + + Building on HP-UX: For jpeg and zlib you will need to do the same + sort of thing as described above for Solaris. You set CPPFLAGS and + LDFLAGS to find them (see below for an example.) You do not need to do + any of the above /usr/openwin stuff. Also, HP-UX does not seem to + support -R, so get rid of the -R items in LDFLAGS. Because of this, at + runtime you may need to set LD_LIBRARY_PATH or SHLIB_PATH to indicate + the directory paths so the libraries can be found. It is a good idea + to have static archives, e.g. libz.a and libjpeg.a for the nonstandard + libraries so that they get bolted into the x11vnc binary (and so won't + get "lost".) + + Here is what we recently did to build x11vnc 0.7.2 on HP-UX 11.11 +./configure --with-jpeg=$HOME/hpux/jpeg --with-zlib=$HOME/hpux/zlib +make + + Where we had static archives (libjpeg.a, libz.a) only and header files + in the $HOME/hpux/... directories as discussed for the build script. + + On HP-UX 11.23 and 11.31 we have had problems compiling with gcc. + "/usr/include/rpc/auth.h:87: error: field 'syncaddr' has incomplete + type". As a workaround for x11vnc 0.9.4 and later set your CPPFLAGS to + include: + CPPFLAGS="-DIGNORE_GETSPNAM" + export CPPFLAGS + + This disables a very rare usage mode for -unixpw_nis by not trying + getspnam(3). + + Using HP-UX's C compiler on 11.23 and 11.31 we have some severe + compiler errors that have not been worked around yet. If you need to + do this, contact me and I will give you a drastic recipe that will + produce a working binary. + + + Building on AIX: AIX: one user had to add the "X11.adt" package to + AIX 4.3.3 and 5.2 to get build header files like XShm.h, etc. You may + also want to make sure that /usr/lpp/X11/include, etc is being picked + up by the configure and make. + + For a recent build on AIX 5.3 we needed to add these CFLAGS to be able + to build with gcc: + env CFLAGS='-maix64 -Xlinker -bbigtoc' ./configure ... + + we also built our own libjpeg and libz using -maix64. + + BTW, one way to run an Xvfb-like virtual X server for testing on AIX + is something like "/usr/bin/X11/X -force -vfb -ac :1". + + + Building on Mac OS X: There is now native Mac OS X support for + x11vnc by using the raw framebuffer feature. This mode does not use or + need X11 at all. To build you may need to disable X11: +./configure --without-x ... +make + + However, if your system has the Mac OS X build package for X11 apps + you will not need to supply the "--without-x" option (in this case the + resulting x11vnc would be able to export both the native Mac OS X + display and windows displayed in the XDarwin X server.) Be sure to + include the ./configure option to find libjpeg on your system. + + + OpenSSL: Starting with version 0.8.3 x11vnc can now be built with + SSL/TLS support. For this to be enabled the libssl.so library needs to + be available at build time. So you may need to have additional + CPPFLAGS and LDFLAGS items if your libssl.so is in a non-standard + place. As of x11vnc 0.9.4 there is also the --with-ssl=DIR configure + option. + + On Solaris using static archives libssl.a and libcrypto.a instead of + .so shared libraries (e.g. from www.sunfreeware.com), we found we + needed to also set LDFLAGS as follows to get the configure to work: +env LDFLAGS='-lsocket -ldl' ./configure --with-ssl=/path/to/openssl ... +make + + _________________________________________________________________ + + Beta Testing: + + I don't have any formal beta-testers for the releases of x11vnc, so + I'd appreciate any additional testing very much. + + Thanks to those who suggested features and helped beta test x11vnc + 0.9.10 released in May 2010! + + Please help test and debug the 0.9.11 version for release sometime in + Summer 2010. + + The version 0.9.11 beta tarball is kept here: + x11vnc-0.9.11-dev.tar.gz + + There are also some Linux, Solaris, Mac OS X, and other OS test + binaries here. Please kick the tires and report bugs, performance + regressions, undesired behavior, etc. to me. + + To aid testing of the built-in SSL/TLS support for x11vnc, a number of + VNC Viewer packages for Unix, Mac OS X, and Windows have been created + that provide SSL Support for the TightVNC Viewer (this is done by + wrapper scripts and a GUI that starts STUNNEL.) It should be pretty + convenient for automatic SSL and SSH connections. It is described in + detail at and can be downloaded from the Enhanced TightVNC Viewer + (SSVNC) page. The SSVNC Unix viewer also supports x11vnc's symmetric + key encryption ciphers (see the 'UltraVNC DSM Encryption Plugin' + settings panel.) + + + Here are some features that will appear in the 0.9.11 release: + * Coming Soon. + + + Here are some features that appeared in the 0.9.10 release: + * The included SSL enabled Java applet viewer now supports Chained + SSL Certificates. The debugCerts=yes applet parameter aids + troubleshooting certificate validation. The x11vnc -ssl mode has + always supported chained SSL certificates (simply put the + intermediate certificates, in order, after the server certificate + in the pem file.) + * A demo CGI script desktop.cgi shows how to create an SSL + encrypted, multi-user x11vnc web login desktop service. The script + requires x11vnc version 0.9.10. The user logs into a secure web + site and gets his/her own virtual desktop (Xvfb.) x11vnc's SSL + enabled Java Viewer Applet is launched by the web browser for + secure viewing (and so no software needs to be installed on the + viewer-side.) One can use the desktop.cgi script for ideas to + create their own fancier or customized web login desktop service + (e.g. user-creation, PHP, SQL, specialized desktop application, + etc.) More info here. There is also an optional 'port redirection' + mode that allows redirection to other SSL enabled VNC servers + running inside the firewall. + * Built-in support for IPv6 (128 bit internet addresses) is now + provided. See the -6 and -connect options for details. + Additionally, in case there are still problems with built-in IPv6 + support, a transitional tool is provided in inet6to4 that allows + x11vnc (or any other IPv4 application) to receive connections over + IPv6. + * The Xdummy wrapper script for Xorg's dummy driver is updated and + no longer requires being run as root. New service options are + provided to select Xdummy over Xvfb as the virtual X server to be + created. + * The "%" unix password verification tricks for the -unixpw option + are now documented. They have also been extended to run a command + as the user if one sets the environment variable UNIXPW_CMD. The + desktop.cgi demo script takes advantage of this new feature. + * A bug has been fixed that would prevent the Java applet viewer + from being downloaded successfully in single-port HTTPS/VNC inetd + mode. The env. var. X11VNC_HTTPS_DOWNLOAD_WAIT_TIME can be used to + adjust for how many seconds a -inetd or -https httpd download is + waited for (default 15 seconds.) The applet will now autodetect + x11vnc and use GET=1 for faster connecting. Many other + improvements and fixes. + * The TightVNC security type (TightVNC features enabler) now works + for RFB version 3.8. + * The X property X11VNC_TRAP_XRANDR can be set on a desktop to force + x11vnc to use the -xrandr screen size change trapping code. + * New remote control query options: pointer_x, pointer_y, + pointer_same, pointer_root, and pointer_mask. A demo script using + them misc/panner.pl is provided. + * The -sslScripts option prints out the SSL certificate management + scripts. + + + Here are some features that appeared in the 0.9.9 release (Dec/2009): + * The -unixpw_system_greeter option, when used in combined unixpw + and XDMCP FINDCREATEDISPLAY mode (for example: -xdmsvc), enables + the user to press Escape to jump directly to the XDM/GDM/KDM login + greeter screen. This way the user avoids entering his unix + password twice at X session creation time. Also, the unixpw login + panel now has a short help displayed if the user presses 'F1'. + * x11vnc now tries to be a little bit more aggressive in keeping up + with VNC client's framebuffer update requests. Some broken VNC + clients like Eggplant and JollysFastVNC continuously spray these + requests at VNC servers (regardless of whether they have received + any updates or not.) Under some circumstances this could lead to + x11vnc falling behind. The -extra_fbur option allows one to fine + tune the setting. Additionally, one may also dial down delays: + e.g. "-defer 5" and "-wait 5" (or to 1 or even 0) or -nonap or + -allinput to keep up with these VNC clients at the expense of + increased system load. + * Heuristics are applied to try to determine if the X display is + currently in a Display Manager Greeter Login panel (e.g. GDM) If + so, x11vnc's creation of any windows and use of XFIXES are + delayed. This is to try to avoid x11vnc being killed after the + user logs in if the GDM KillInitClients=true is in effect. So one + does not need to set KillInitClients=false. Note that in recent + GDM the KillInitClients option has been removed. Also delayed is + the use of the XFIXES cursor fetching functionality; this avoids + an Xorg bug that causes Xorg to crash right after the user logs + in. + * A new option -findauth runs the FINDDISPLAY script that applies + heuristics that try to determine the XAUTHORITY file. The use of + '-auth guess' will use the XAUTHORITY that -findauth reveals. This + can be handy in with the lastest GDM where the ability to store + cookies in ~/.Xauthority has been removed. If x11vnc is running as + root (e.g. inetd) and you add -env FD_XDM=1 to the above -findauth + or -auth guess command lines, it will find the correct XAUTHORITY + for the given display (this works for XDM/GDM/KDM if the login + greeter panel is up or if someone has already logged into an X + session.) + * The FINDDISPLAY and FINDCREATEDISPLAY modes (i.e. "-display + WAIT:cmd=...", -find, -create) now work correctly for the + user-supplied login program scheme "-unixpw_cmd ...", as long as + the login program supports running commands specified in the + environment variable "RFB_UNIXPW_CMD_RUN" as the logged-in user. + The mode "-unixpw_nis ..." has also been made more consistent. + * The -stunnel option (like -ssl but uses stunnel as an external + helper program) now works with the -ssl "SAVE" and "TMP" special + certificate names. The -sslverify and -sslCRL options now work + correctly in -stunnel mode. Single port HTTPS connections are also + supported for this mode. + * There is an experimental Application Sharing mode that improves + upon the -id/-sid single window sharing: -appshare (run "x11vnc + -appshare -help" for more info.) It is still very primitive and + approximate, but at least it displays multiple top-level windows. + * The remote control command -R can be used to instruct x11vnc to + resend its most recent copy of the Clipboard, Primary, or + Cutbuffer selections: "x11vnc -R resend_clipboard", "x11vnc -R + resend_primary", and "x11vnc -R resend_cutbuffer". + * The fonts in the GUI (-gui) can now by set via environment + variables, e.g. -env X11VNC_FONT_BOLD='Helvetica -16 bold' and + -env X11VNC_FONT_FIXED='Courier -14'. + * The XDAMAGE mechanism is now automatically disabled for a period + of time if a game or screensaver generates too many XDAMAGE + rectangles per second. This avoids the X11 event queue from + soaking up too much memory. + * There is an experimental workaround: "-env X11VNC_WATCH_DX_DY=1" + that tries to avoid problems with poorly constructed menu themes + that place the initial position of the mouse cursor inside a menu + item's active zone. More information can be found here. + + + Here are some features that appeared in the 0.9.8 release (Jul/2009): + * Stability improvements to -threads mode. Running x11vnc this way + is more reliable now. Threaded operation sometimes gives better + interactive response and faster updates: try it out. The threaded + mode now supports multiple VNC viewers using the same VNC + encoding. The threaded mode can also yield a performance + enhancement in the many client case (e.g. class-room broadcast.) + We have tested with 30 to 50 simultaneous clients. See also + -reflect. + For simultaneous clients: the ZRLE encoding is thread safe on all + platforms, and the Tight and Zlib encodings are currently only + thread safe on Linux where thread local storage, __thread, is + used. If your non-Linux system and compiler support __thread one + can supply -DTLS=__thread to enable it. When there is only one + connected client, all encodings are safe on all platforms. Note + that some features (e.g. scroll detection and -ncache) may be + disabled or run with reduced functionality in -threads mode. + * Automatically tries to work around an Xorg server and GNOME bug + involving infinitely repeating keys when turning off key + repeating. Use -repeat if the automatic workaround fails. + * Improved reliability of the Single Port SSL VNC and HTTPS java + viewer applet delivery mechanism. + * The -clip mode works under -rawfb. + + + Here are some features that appeared in the 0.9.7 release (Mar/2009): + * Support for polling Linux Virtual Terminals (also called virtual + consoles) directly instead of using /dev/fb. The option to use is, + for example, "-rawfb vt2" for Virtual Terminal 2, etc. In this + case the special file /dev/vcsa2 is used to retrieve vt2's current + text. Text and colors are shown, but no graphics. + * Support for less than 8 bits per pixel framebuffers (e.g. 4 or 1 + bpp) in the -rawfb mode. + * The SSL enabled UltraVNC Java viewer applet now has a [Home] entry + in the "drives" drop down menu. This menu can be configured with + the ftpDropDown applet parameter. All of the applet parameters are + documented in classes/ssl/README. + * Experimental support for VirtualGL's TurboVNC (an enhanced + TightVNC for fast LAN high framerate usage.) + * The CUPS Terminal Services helper mode has been improved. + * Improvements to the -ncache_cr that allows smooth opaque window + motions using the 'copyrect' encoding when using -ncache mode. + * The -rmflag option enables a way to indicate to other processes + x11vnc has exited. + * Reverse connections using anonymous Diffie Hellman SSL encryption + now work. + + + Here are some features that appeared in the 0.9.6 release (Dec/2008): + * Support for VeNCrypt SSL/TLS encrypted connections. It is enabled + by default in the -ssl mode. VNC Viewers like vinagre, + gvncviewer/gtk-vnc, the vencrypt package, SSVNC, and others + support this encryption mode. It can also be used with the -unixpw + option to enable Unix username and password authentication + (VeNCrypt's "*Plain" modes.) A similar but older VNC security type + "ANONTLS" (used by vino) is supported as well. See the -vencrypt + and -anontls options for additional control. The difference + between x11vnc's normal -ssl mode and VeNCrypt is that the former + wraps the entire VNC connection in SSL (like HTTPS does for HTTP, + i.e. "vncs://") while VeNCrypt switches on the SSL/TLS at a + certain point during the VNC handshake. Use -sslonly to disable + both VeNCrypt and ANONTLS (vino.) + * The "-ssl ANON" option enables Anonymous Diffie-Hellman (ADH) key + exchange for x11vnc's normal SSL/TLS operation. Note that + Anonymous Diffie-Hellman uses encryption for privacy, but provides + no authentication and so is susceptible to Man-In-The-Middle + attacks (and so we do not recommend it: we prefer you use "-ssl + SAVE", etc. and have the VNC viewer verify the cert.) The ANONTLS + mode (vino) only supports ADH. VeNCrypt mode supports both ADH and + regular X509 SSL certificates modes. For these ADH is enabled by + default. See -vencrypt and -anontls for how to disable ADH. + * For x11vnc's SSL/TLS modes, one can now specify a Certificate + Revocation List (CRL) with the -sslCRL option. This will only be + useful for wide deployments: say a company-wide x11vnc SSL access + deployment using a central Certificate Authority (CA) via + -sslGenCA and -sslGenCert. This way if a user has his laptop lost + or stolen, you only have to revoke his key instead of creating a + new Certificate Authority and redeploying new keys to all users. + * The default SSL/TLS mode, "-ssl" (no pem file parameter supplied), + is now the same as "-ssl SAVE" and will save the generated + self-signed cert in "~/.vnc/certs/server.pem". Previously "-ssl" + would create a temporary self-signed cert that was discarded when + x11vnc exited. The reason for the change is to at least give the + chance for the VNC Viewer side (e.g. SSVNC) to remember the cert + to authenticate subsequent connections to the same x11vnc server. + Use "-ssl TMP" to regain the previous behavior. Use "-ssl + SAVE_NOPROMPT" to avoid being prompted about using passphrase when + the certificate is created. + * The option -http_oneport enables single-port HTTP connections via + the Java VNC Viewer. So, for example, the web browser URL + "http://myhost.org:5900" works the same as + "http://myhost.org:5800", but with the convenience of only + involving one port instead of two. This works for both unencrypted + connections and for SSH tunnels (see -httpsredir if the tunnel + port differs.) Note that HTTPS single-port operation in -ssl SSL + encrypted mode has been available since x11vnc version 0.8.3. + * For the -avahi/-zeroconf Service Advertizing mode, if x11vnc was + not compiled with the avahi-client library, then an external + helper program, either avahi-publish(1) (on Unix) or dns-sd(1) (on + Mac OS X), is used instead. + * The "-rfbport PROMPT" option will prompt the user via the GUI to + select the VNC port (e.g. 5901) to listen on, and a few other + basic settings. This enables a handy GUI mode for naive users: + x11vnc -gui tray=setpass -rfbport PROMPT -logfile $HOME/.x11vnc.log.%VNCDISP +LAY + suitable for putting in a launcher or menu, e.g. x11vnc.desktop. + The -logfile expansion is new too. In the GUI, the tray=setpass + Properties panel has been improved. + * The -solid solid background color option now works for the Mac OS + X console. + * The -reopen option instructs x11vnc to try to reopen the X display + if it is prematurely closed by, say, the display manager (e.g. + GDM.) + + + Here are some features that appeared in the 0.9.5 release (Oct/2008): + * Symmetric key encryption ciphers. ARC4, AES-128, AES-256, + blowfish, and 3des are supported. Salt and initialization vector + seeding is provided. These compliment the more widely used SSL and + SSH encryption access methods. SSVNC also supports these + encryption modes. + * Scaling differently along the X- and Y-directions. E.g. "-scale + 1280x1024" or "-scale 0.8x0.75" Also, "-geometry WxH" is an + alias for "-scale WxH" + * By having SSVNC version 1.0.21 or later available in your $PATH, + the -chatwindow option allows a UltraVNC Text Chat window to + appear on the local X11 console/display (this way the remote + viewer can chat with the person at the physical display; e.g. + helpdesk mode.) This also works on the Mac OS X console if the + Xquartz X11 server (enabled by default on leopard) is running for + the chatwindow. + * The HTTP Java viewer applet jar, classes/VncViewer.jar, has been + updated with an improved implementation based on the code used by + the classes/ssl applets. + + + Here are some features that appeared in the 0.9.4 release (Sep/2008): + * Improvements to the -find and -create X session finding or + creating modes: new desktop types and service redirection options. + Personal cupsd daemon and SSH port redirection helper for use with + SSVNC's Terminal Services feature. + * Reverse VNC connections via -connect work in the -find, -create + and related -display WAIT:... modes. + * Reverse VNC connections (either normal or SSL) can use a Web Proxy + or a SOCKS proxy, or a SSH connection, or even a CGI URL to make + the outgoing connection. See: -proxy. Forward connections can also + use: -ssh. + * Reverse VNC connections via the UltraVNC repeater proxy (either + normal or SSL) are supported. Use either the "-connect + repeater=ID:NNNN+host:port" or "-connect + repeater://host:port+ID:NNNN" notation. The SSVNC VNC viewer also + supports the UltraVNC repeater. Also, a perl repeater implemention + is here: ultravnc_repeater.pl + * Support for indexed colormaps (PseudoColor) with depths other than + 8 (from 1 to 16 now work) for non-standard hardware. Option + "-advertise_truecolor" to handle some workaround in this mode. + * Support for the ZYWRLE encoding, this is the RealVNC ZRLE encoding + extended to do motion video and photo regions more efficiently by + way of a Wavelet based transformation. + * The -finddpy and -listdpy utilities help to debug and configure + the -find, -create, and -display WAIT:... modes. + * Some automatic detection of screen resizes are handled even if the + -xrandr option is not supplied. + * The -autoport options gives more control over the VNC port x11vnc + chooses. + * The -ping secs can be used to help keep idle connections alive. + * Pasting of the selection/clipboard into remote applications (e.g. + Java) has been improved. + * Fixed a bug if a client disconnects during the 'speed-estimation' + phase. + * To unset Caps_Lock, Num_Lock and raise all keys in the X server + use -clear_all. + * Usage with dvorak keyboards has been improved. See also: -xkb. + * The Java Viewer applet source code is now included in the + x11vnc-0.9.*.tar.gz tarball. This means you can now build the Java + viewer applet jar files from source. If you stopped shipping the + Java viewer applet jar files due to lack of source code, you can + start again. + + + Here are some features that appeared in the 0.9.3 release (Oct/2007): + * Viewer-side pixmap caching. A large area of pixels (at least 2-3 + times as big as the framebuffer itself; the bigger the better... + default is 10X) is placed below the framebuffer to act as a + buffer/cache area for pixel data. The VNC CopyRect encoding is + used to move it around, so any viewer can take advantage of it. + Until we start modifying viewers you will be able to see the cache + area if you scroll down (this makes it easier to debug!) For + testing the default is "-ncache 10". The unix Enhanced TightVNC + Viewer ssvnc has a nice -ycrop option to help hide the pixel cache + area from view. + + + Here are some features that appeared in the 0.9.2 release (Jun/2007): + * Building with no OpenSSL libssl available (or with --without-ssl) + has been fixed. + * One can configure x11vnc via "./configure + --with-system-libvncserver" to use a system installed libvncserver + library instead of the one bundled in the release tarball. + * If UltraVNC file transfer or chat is detected, then VNC clients + are "pinged" more often to prevent these side channels from + becoming serviced too infrequently. + * In -unixpw mode in the username and password dialog no text will + be echoed if the first character sent is "Escape". This enables a + convenience feature in SSVNC to send the username and password + automatically. + + + Here are some features that appeared in the 0.9.1 release (May/2007): + * The UltraVNC Java viewer has been enhanced to support SSL (as the + TightVNC viewer had been previously.) The UltraVNC Java supports + ultravnc filetransfer, and so can be used as a VNC viewer on Unix + that supports ultravnc filetransfer. It is in the + classes/ssl/UltraViewerSSL.jar file (that is pointed to by + ultra.vnc.) The signed applet SignedUltraViewerSSL.jar version + (pointed to by ultrasigned.vnc) will be needed to access the local + drive if you are using it for file transfer via a Web browser. + Some other bugs in the UltraVNC Java viewer were fixed and a few + improvements to the UI made. + * A new Unix username login mode for VNC Viewers authenticated via a + Client SSL Certificate: "-users sslpeer=". The emailAddress + subject field is inspected for username@hostname and then acts as + though "-users +username" has been supplied. This way the Unix + username is identified by (i.e. simply extracted from) the Client + SSL Certificate. This could be useful with -find, -create and -svc + modes if you are also have set up and use VNC Client SSL + Certificate authentication. + * For external display finding/creating programs (e.g. WAIT:cmd=...) + if the VNC Viewer is authenticated via a Client SSL Certificate, + then that Certificate is available in the environment variable + RFB_SSL_CLIENT_CERT. + + + Here are some features that appeared in the 0.9 release (Apr/2007): + * VNC Service advertising via mDNS / ZeroConf / BonJour with the + Avahi client library. Enable via "-avahi" or "-zeroconf". + * Implementations of UltraVNC's TextChat, SingleWindow, and + ServerInput extensions (requires ultravnc viewer or ssvnc Unix + viewer.) They toggle the selection of a single window (-id), and + disable (friendly) user input and viewing (monitor blank) at the + VNC server. + * Short aliases "-find", "-create", "-svc", and "-xdmsvc" for + commonly used FINDCREATEDISPLAY usage modes. + * Reverse VNC connections (viewer listening) now work in SSL (-ssl) + mode. + * New options to control the Monitor power state and keyboard/mouse + grabbing: -forcedpms, -clientdpms, -noserverdpms, and -grabalways. + * A simple way to emulate inetd(8) to some degree via the "-loopbg" + option. + * Monitor the accuracy of XDAMAGE and apply "-noxdamage" if it is + not working well. OpenGL applications like like beryl and MythTv + have been shown to make XDAMAGE not work properly. + * For Java SSL connections involving a router/firewall port + redirection, an option -httpsredir to spare the user from needing + to include &PORT=NNN in the browser URL. + + + Here are some features that appeared in the 0.8.4 release (Feb/2007): + * Native Mac OS X Aqua/Quartz support. (i.e. OSXvnc alternative; + some activities are faster) + * A new login mode: "-display WAIT:cmd=FINDCREATEDISPLAY -unixpw + ..." that will Create a new X session (either virtual or real and + with or without a display manager, e.g. kdm) for the user if it + cannot find the user's X session display via the FINDDISPLAY + method. See the -svc and the -xdmsvc aliases. + * x11vnc can act as a VNC reflector/repeater using the "-reflect + host:N" option. Instead of polling an X display, the remote VNC + Server host:N is connected to and re-exported via VNC. This is + intended for use in broadcasting a display to many (e.g. > 16; + classroom or large demo) VNC viewers where bandwidth and other + resources are conserved by spreading the load over a number of + repeaters. + * Wireframe copyrect detection for local user activity (e.g. someone + sitting at the physical display moving windows) Use + -nowireframelocal to disable. + * The "-N" option couples the VNC Display number to the X Display + number. E.g. if your X DISPLAY is :2 then the VNC display will be + :2 (i.e. using port 5902.) If that port is taken x11vnc will exit. + * Option -nodpms to avoid problems with programs like KDE's + kdesktop_lock that keep restarting the screen saver every few + seconds. + * To automatically fix the common mouse motion problem on XINERAMA + (multi-headed) displays, the -xwarppointer option is enabled by + default when XINERAMA is active. + + If you have a Mac please try out the native Mac OS X support, build + with "./configure --without-x", or download a binary mentioned above, + (even if you don't plan on ever using it in this mode!), and let me + know how it went. Thanks. + + + Here are some features that appeared in the 0.8.3 release (Nov/2006): + * The -ssl option provides SSL encryption and authentication + natively via the www.openssl.org library. One can use from a + simple self-signed certificate server certificate up to full CA + and client certificate authentication schemes. + * Similar to -ssl, the -stunnel option starts up a SSL tunnel server + stunnel (that must be installed separately on the system: + stunnel.mirt.net ) to allow only encrypted SSL connections from + the network. + * The -sslverify option allows for authenticating VNC clients via + their certificates in either -ssl or -stunnel modes. + * Certificate creation and management tools are provide in the + -sslGenCert, -sslGenCA, and related options. + * An SSL enabled Java applet VNC Viewer applet is provided by x11vnc + in classes/ssl/VncViewer.jar. In addition to normal HTTP, the + applet may be loaded into the web browser via HTTPS (HTTP over + SSL.) (one can use the VNC port, e.g. https://host:5900/, or also + the separate -https port option.) A wrapper shell script + ss_vncviewer is also provided that sets up a stunnel client-side + tunnel on Unix systems. See Enhanced TightVNC Viewer (SSVNC) for + other SSL/SSH viewer possibilities. + * The -unixpw option supports Unix username and password + authentication (a simpler variant is the -unixpw_nis option that + works in environments where the encrypted passwords are readable, + e.g. NIS.) The -ssl or -localhost + -stunnel options are enforced + in this mode to prevent password sniffing. As a convenience, these + requirements are lifted if a SSH tunnel can be deduced (but + -localhost still applies.) + * Coupling -unixpw with "-display WAIT:cmd=FINDDISPLAY" or "-display + WAIT:cmd=FINDCREATEDISPLAY" provides a way to allow a user to + login with their UNIX password and have their display connected to + automatically. See the -svc and the -xdmsvc aliases. + * Hooks are provided in the -unixpw_cmd and "-passwdfile + cmd:,custom:..." options to allow you to supply your own + authentication and password lookup programs. + * x11vnc can be configured and built to not depend on X11 libraries + "./configure --without-x" for -rawfb only operation (e.g. embedded + linux console devices.) + * The -rotate option enables you to rotate or reflect the screen + before exporting via VNC. This is intended for use on handhelds + and other devices where the rotation orientation is not "natural". + * The "-ultrafilexfer" alias is provided and improved UltraVNC + filetransfer rates have been achieved. + * Under the "-connect_or_exit host" option x11vnc will exit + immediately unless the reverse connection to host succeeds. The + "-rfbport 0" option disables TCP listening for connections (useful + for this mode.) + * The "-rawfb rand" and "-rawfb none" options are useful for testing + automation scripts, etc., without requiring a full desktop. + * Reduced spewing of information at startup, use "-verbose" (also + "-v") to turn it back on for debugging or if you are going to send + me a problem report. + + Here are some Previous Release Notes + _________________________________________________________________ + + Some Notes: + + Both a client and a server: It is sometimes confusing to people that + x11vnc is both a client and a server at the same time. It is an X + client because it connects to the running X server to do the screen + polls. Think of it as a rather efficient "screenshot" program running + continuously. It is a server in the sense that it is a VNC server that + VNC viewers on the network can connect to and view the screen + framebuffer it manages. + + When trying to debug problems, remember to think of both roles. E.g. + "how is x11vnc connecting to the X server?", "how is the vncviewer + connecting to x11vnc?", "what permits/restricts the connection?". Both + links may have reachability, permission, and other issues. + + Network performance: Whether you are using Xvnc or x11vnc it is + always a good idea to have a solid background color instead of a + pretty background image. Each and every re-exposure of the background + must be resent over the network: better to have that background be a + solid color that compresses very well compared to a photo image. (This + is one place where the X protocol has an advantage over the VNC + protocol.) I suggest using xsetroot, dtstyle or similar utility to set + a solid background while using x11vnc. You can turn the pretty + background image back on when you are using the display directly. + Update: As of Feb/2005 x11vnc has the -solid [color] option that works + on recent GNOME, KDE, and CDE and also on classic X (background image + is on the root window.) Update: As of Oct/2007 x11vnc has the -ncache + option that does a reasonable job caching the background (and other) + pixmap data on the viewer side. + + I also find the TightVNC encoding gives the best response for my usage + (Unix <-> Unix over cable modem.) One needs a tightvnc-aware vncviewer + to take advantage of this encoding. + + TCP port issues: Notice the lines + 18/07/2003 14:36:31 Autoprobing selected port 5900 + PORT=5900 + + in the output. 5900 is the default VNC listening port (just like 6000 + is X11's default listening port.) Had port 5900 been taken by some + other application, x11vnc would have next tried 5901. That would mean + the viewer command above should be changed to vncviewer + far-away.east:1. You can force the port with the "-rfbport NNNN" + option where NNNN is the desired port number. If that port is already + taken, x11vnc will exit immediately. The "-N" option will try to match + the VNC display number to the X display. (also see the "SunRay + Gotcha" note below) + + Options: x11vnc has (far too) many features that may be activated + via its command line options. Useful options are, e.g., -scale to do + server-side scaling, and -rfbauth passwd-file to use VNC password + protection (the vncpasswd or storepasswd programs, or the x11vnc + -storepasswd option can be used to create the password file.) + + Algorithm: How does x11vnc do it? Rather brute-forcedly: it + continuously polls the X11 framebuffer for changes using + XShmGetImage(). When changes are discovered, it instructs libvncserver + which rectangular regions of the framebuffer have changed, and + libvncserver compresses the changes and sends them off to any + connected VNC viewers. A number of applications do similar things, + such as x0rfbserver, krfb, x0vncserver, vino. x11vnc uses a 32 x 32 + pixel tile model (the desktop is decomposed into roughly 1000 such + tiles), where changed tiles are found by pseudo-randomly polling 1 + pixel tall horizontal scanlines separated vertically by 32 pixels. + This is a surprisingly effective algorithm for finding changed + regions. For keyboard and mouse user input the XTEST extension is used + to pass the input events to the X server. To detect XBell "beeps" the + XKEYBOARD extension is used. If available, the XFIXES extension is + used to retrieve the current mouse cursor shape. Also, if available + the X DAMAGE extension is used to receive hints from the X server + where modified regions on the screen are. This greatly reduces the + system load when not much is changing on the screen and also improves + how quickly the screen is updated. + + Barbershop mirrors effect: What if x11vnc is started up, and + vncviewer is then started up on the same machine and displayed on the + same display x11vnc is polling? One might "accidentally" do this when + first testing out the programs. You get an interesting + recursive/feedback effect where vncviewer images keep popping up each + one contained in the previous one and slightly shifted a bit by the + window manager decorations. There will be an even more interesting + effect if -scale is used. Also, if the XKEYBOARD is supported and the + XBell "beeps" once, you get an infinite loop of beeps going off. + Although all of this is mildly exciting it is not much use: you will + normally run and display the viewer on a different machine! + _________________________________________________________________ + + Sun Ray Notes: + + You can run x11vnc on your (connected or disconnected) SunRay session. + Here are some notes on SunRay usage with x11vnc. + + _________________________________________________________________ + + Limitations: + + * Due to the polling nature, some activities (opaque window moves, + scrolling), can be pretty choppy/ragged and others (exposures of + large areas) slow. Experiment with interacting a bit differently + than you normally do to minimize the effects (e.g. do fullpage + paging rather than line-by-line scrolling, and move windows in a + single, quick motion.) Recent work has provided the + -scrollcopyrect and -wireframe speedups using the CopyRect VNC + encoding and other things, but they only speed up some activities, + not all. + * A rate limiting factor for x11vnc performance is that graphics + hardware is optimized for writing, not reading (x11vnc reads the + video framebuffer for the screen image data.) The difference can + be a factor of 10 to 1000, and so it usually takes about 0.5-1 sec + to read in the whole video hardware framebuffer (e.g. 5MB for + 1280x1024 at depth 24 with a read rate of 5-10MB/sec.) So whenever + activity changes most of the screen (e.g. moving or iconifying a + large window) there is a delay of 0.5-1 sec while x11vnc reads the + changed regions in. + A slow framebuffer read rate will often be the performance + bottleneck on a fast LAN (whereas on slower links the reduced + network bandwidth becomes the bottleneck.) + Note: A quick way to get a 2X speedup of this for x11vnc is to + switch your X server from depth 24 (32bpp) to depth 16 (16bpp.) + You get a 4X speedup going to 8bpp, but the lack of color cells is + usually unacceptable. + To get a sense of the read and write speeds of your video card, + you can run benchmarks like: "x11perf -getimage500", "x11perf + -putimage500", "x11perf -shmput500" and for XFree86 displays with + direct graphics access the "dga" command (press "b" to run the + benchmark and then after a few seconds press "q" to quit.) Even + this "dd if=/dev/fb0 of=/dev/null" often gives a good estimate. + x11vnc also prints out its estimate: + 28/02/2009 11:11:07 Autoprobing TCP port + 28/02/2009 11:11:07 Autoprobing selected port 5900 + 28/02/2009 11:11:08 fb read rate: 10 MB/sec + 28/02/2009 11:11:08 screen setup finished. + We have seen a few cases where the hardware fb read speed is + greater than 65 MB/sec: on high end graphics workstations from SGI + and Sun, and also from a Linux user using nvidia proprietary + drivers for his nvidia video card. Update 2008: thankfully, these + sped up drivers are becoming more common on Linux and *BSD systems + and that makes x11vnc run somewhat more quickly. Sometimes they + have a read rate of over 400 MB/sec. + On XFree86/Xorg it is actually possible to increase the + framebuffer read speed considerably (10-100 times) by using the + Shadow Framebuffer (a copy of the framebuffer is kept in main + memory and this can be read much more quickly.) To do this one + puts the line Option "ShadowFB" "true" in the Device section of + the /etc/X11/XF86Config or /etc/X11/xorg.conf file. Note that this + disables 2D acceleration at the physical display and so that might + be unacceptable if one plays games, etc. on the machine's local + display. Nevertheless this could be handy in some circumstances, + e.g. if the slower speed while sitting at the physical display was + acceptable (this seems to be true for most video cards these + days.) Unfortunately it does not seem shadowfb can be turned on + and off dynamically... + Another amusing thing one can do is use Xvfb as the X server, e.g. + "xinit $HOME/.xinitrc -- /usr/X11R6/bin/Xvfb :1 -screen 0 + 1024x768x16" x11vnc can poll Xvfb efficiently via main memory. + It's not exactly clear why one would want to do this instead of + using vncserver/Xvnc, (perhaps to take advantage of an x11vnc + feature, such as framebuffer scaling or built-in SSL encryption), + but we mention it because it may be of use for special purpose + applications. You may need to use the "-cc 4" option to force Xvfb + to use a TrueColor visual instead of DirectColor. See also the + description of the -create option that does all of this + automatically for you (be sure to install the Xvfb package, e.g. + apt-get install xvfb.) + Also, a faster and more accurate way is to use the "dummy" + Xorg/XFree86 device driver (or our Xdummy wrapper script.) See + this FAQ for details. + * Somewhat surprisingly, the X11 mouse (cursor) shape is write-only + and cannot be queried from the X server. So traditionally in + x11vnc the cursor shape stays fixed at an arrow. (see the "-cursor + X" and "-cursor some" options, however, for a partial hack for the + root window, etc.) However, on Solaris using the SUN_OVL overlay + extension, x11vnc can show the correct mouse cursor when the + -overlay option is also supplied. A similar thing is done on IRIX + as well when -overlay is supplied. + More generally, as of Dec/2004 x11vnc supports the new XFIXES + extension (in Xorg and Solaris 10) to query the X server for the + exact cursor shape, this works pretty well except that cursors + with transparency (alpha channel) need to approximated to solid + RGB values (some cursors look worse than others.) + * Audio from applications is of course not redirected (separate + redirectors do exist, e.g. esd, see the FAQ on this below.) The + XBell() "beeps" will work if the X server supports the XKEYBOARD + extension. (Note that on Solaris XKEYBOARD is disabled by default. + Passing +kb to Xsun enables it.) + * The scroll detection algorithm for the -scrollcopyrect option can + give choppy or bunched up transient output and occasionally + painting errors. + * Using -threads can expose some bugs/crashes in libvncserver. + + Please feel free to contact me if you have any questions, problems, or + comments about x11vnc, etc. Please be polite, thorough, and not + demanding (sadly, the number of people contacting me that are rude and + demanding is increasing dramatically.) + Also, some people ask if they can make a donation, see this link for + that. + +======================================================================= +http://www.karlrunge.com/x11vnc/faq.html: + + + x11vnc Home Donations + _________________________________________________________________ + + x11vnc FAQ: + + + [Building and Starting] + + Q-1: I can't get x11vnc to start up. It says "XOpenDisplay failed + (null)" or "Xlib: connection to ":0.0" refused by server Xlib: No + protocol specified" and then exits. What do I need to do? + + Q-2: I can't get x11vnc and/or libvncserver to compile. + + Q-3: I just built x11vnc successfully, but when I use it my keystrokes + and mouse button clicks are ignored (I am able to move the mouse + though.) + + Q-4: Help, I need to run x11vnc on Solaris 2.5.1 (or other old + Unix/Linux) and it doesn't compile! + + Q-5: Where can I get a precompiled x11vnc binary for my Operating + System? + + Q-6: Where can I get a VNC Viewer binary (or source code) for the + Operating System I will be viewing from? + + Q-7: How can I see all of x11vnc's command line options and + documentation on how to use them? + + Q-8: I don't like typing arcane command line options every time I + start x11vnc. What can I do? Is there a config file? Or a GUI? + + Q-9: How can I get the GUI to run in the System Tray, or at least be a + smaller, simpler icon? + + Q-10: How can I get x11vnc to listen on a different port besides the + default VNC port (5900)? + + Q-11: My Firewall/Router doesn't allow VNC Viewers to connect to + x11vnc. + + Q-12: Is it possible for a VNC Viewer and a VNC Server to connect to + each other even though both are behind Firewalls that block all + incoming connections? + + Q-13: Can I make x11vnc more quiet and also go into the background + after starting up? + + Q-14: Sometimes when a VNC viewer dies abruptly, x11vnc also dies with + the error message like: "Broken pipe". I'm using the -forever mode and + I want x11vnc to keep running. + + Q-15: The Windows TightVNC 1.3.9 Viewer cannot connect to x11vnc. + + Q-16: KDE's krdc VNC viewer cannot connect to x11vnc. + + Q-17: When I start x11vnc on an Alpha Tru64 workstation the X server + crashes! + + Q-18: When running x11vnc on an IBM AIX workstation after a few + minutes the VNC connection freezes. + + Q-19: Are there any build-time customizations possible, e.g. change + defaults, create a smaller binary, etc? + + [Win2VNC Related] + + Q-20: I have two separate machine displays in front of me, one Windows + the other X11: can I use x11vnc in combination with Win2VNC in + dual-screen mode to pass the keystrokes and mouse motions to the X11 + display? + + Q-21: I am running Win2VNC on my Windows machine and "x11vnc -nofb" on + Unix to pass keyboard and mouse to the Unix monitor. Whenever I start + Win2VNC it quickly disconnects and x11vnc says: + rfbProcessClientNormalMessage: read: Connection reset by peer + + Q-22: Can I run "x11vnc -nofb" on a Mac OS X machine to redirect mouse + and keyboard input to it from Windows and X11 machines via Win2VNC and + x2vnc, respectively? + + [Color Issues] + + Q-23: The X display I run x11vnc on is only 8 bits per pixel (bpp) + PseudoColor (i.e. only 256 distinct colors.) The x11vnc colors may + start out OK, but after a while they are incorrect in certain windows. + + Q-24: Color problems: Why are the colors for some windows incorrect in + x11vnc? BTW, my X display has nice overlay/multi-depth visuals of + different color depths: e.g. there are both depth 8 and 24 visuals + available at the same time. + + Q-25: I am on a high color system (depth >= 24) but I seem to have + colormap problems. They either flash or everything is very dark. + + Q-26: How do I figure out the window id to supply to the -id windowid + option? + + Q-27: Why don't menus or other transient windows come up when I am + using the -id windowid option to view a single application window? + + Q-28: My X display is depth 24 at 24bpp (instead of the normal depth + 24 at 32bpp.) I'm having lots of color and visual problems with x11vnc + and/or vncviewer. What's up? + + [Xterminals] + + Q-29: Can I use x11vnc to view and interact with an Xterminal (e.g. + NCD) that is not running UNIX and so x11vnc cannot be run on it + directly? + + Q-30: How do I get my X permissions (MIT-MAGIC-COOKIE file) correct + for a Unix/Linux machine acting as an Xterminal? + + [Sun Rays] + + Q-31: I'm having trouble using x11vnc with my Sun Ray session. + + [Remote Control] + + Q-32: How do I stop x11vnc once it is running in the background? + + Q-33: Can I change settings in x11vnc without having to restart it? + Can I remote control it? + + [Security and Permissions] + + Q-34: How do I create a VNC password for use with x11vnc? + + Q-35: Can I make it so -storepasswd doesn't show my password on the + screen? + + Q-36: Can I have two passwords for VNC viewers, one for full access + and the other for view-only access to the display? + + Q-37: Can I have as many full-access and view-only passwords as I + like? + + Q-38: Does x11vnc support Unix usernames and passwords? Can I further + limit the set of Unix usernames who can connect to the VNC desktop? + + Q-39: Can I supply an external program to provide my own custom login + method (e.g. Dynamic/One-time passwords or non-Unix (LDAP) usernames + and passwords)? + + Q-40: Why does x11vnc exit as soon as the VNC viewer disconnects? And + why doesn't it allow more than one VNC viewer to connect at the same + time? + + Q-41: Can I limit which machines incoming VNC clients can connect + from? + + Q-42: How do I build x11vnc/libvncserver with libwrap (tcp_wrappers) + support? + + Q-43: Can I have x11vnc only listen on one network interface (e.g. + internal LAN) rather than having it listen on all network interfaces + and relying on -allow to filter unwanted connections out? + + Q-44: Now that -localhost implies listening only on the loopback + interface, how I can occasionally allow in a non-localhost via the -R + allowonce remote control command? + + Q-45: Can I fine tune what types of user input are allowed? E.g. have + some users just be able to move the mouse, but not click or type + anything? + + Q-46: Can I prompt the user at the local X display whether the + incoming VNC client should be accepted or not? Can I decide to make + some clients view-only? How about running an arbitrary program to make + the decisions? + + Q-47: I start x11vnc as root because it is launched via inetd(8) or a + display manager like gdm(1). Can I have x11vnc later switch to a + different user? + + Q-48: I use a screen-lock when I leave my workstation (e.g. + xscreensaver or xlock.) When I remotely access my workstation desktop + via x11vnc I can unlock the desktop fine, but I am worried people will + see my activities on the physical monitor. What can I do to prevent + this, or at least make it more difficult? + + Q-49: Can I have x11vnc automatically lock the screen when I + disconnect the VNC viewer? + + [Encrypted Connections] + + Q-50: How can I tunnel my connection to x11vnc via an encrypted SSH + channel between two Unix machines? + + Q-51: How can I tunnel my connection to x11vnc via an encrypted SSH + channel from Windows using an SSH client like Putty? + + Q-52: How can I tunnel my connection to x11vnc via an encrypted SSL + channel using an external tool like stunnel? + + Q-53: Does x11vnc have built-in SSL tunneling? + + Q-54: How do I use VNC Viewers with built-in SSL tunneling? + + Q-55: How do I use the Java applet VNC Viewer with built-in SSL + tunneling when going through a Web Proxy? + + Q-56: Can Apache web server act as a gateway for users to connect via + SSL from the Internet with a Web browser to x11vnc running on their + workstations behind a firewall? + + Q-57: Can I create and use my own SSL Certificate Authority (CA) with + x11vnc? + + [Display Managers and Services] + + Q-58: How can I run x11vnc as a "service" that is always available? + + Q-59: How can I use x11vnc to connect to an X login screen like xdm, + GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into an X + session yet.) + + Q-60: Can I run x11vnc out of inetd(8)? How about xinetd(8)? + + Q-61: Can I have x11vnc advertise its VNC service and port via mDNS / + Zeroconf (e.g. Avahi) so VNC viewers on the local network can detect + it automatically? + + Q-62: Can I have x11vnc allow a user to log in with her UNIX username + and password and then have it find her X session display on that + machine and then attach to it? How about starting an X session if one + cannot be found? + + Q-63: Can I have x11vnc restart itself after it terminates? + + Q-64: How do I make x11vnc work with the Java VNC viewer applet in a + web browser? + + Q-65: Are reverse connections (i.e. the VNC server connecting to the + VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? + + Q-66: Can reverse connections be made to go through a Web or SOCKS + proxy or SSH? + + Q-67: Can x11vnc provide a multi-user desktop web login service as an + Apache CGI or PHP script? + + Q-68: Can I use x11vnc as a replacement for Xvnc? (i.e. not for a real + display, but for a virtual one I keep around.) + + Q-69: How can I use x11vnc on "headless" machines? Why might I want + to? + + [Resource Usage and Performance] + + Q-70: I have lots of memory, but why does x11vnc fail with shmget: + No space left on device or Minor opcode of failed request: 1 + (X_ShmAttach)? + + Q-71: How can I make x11vnc use less system resources? + + Q-72: How can I make x11vnc use MORE system resources? + + Q-73: I use x11vnc over a slow link with high latency (e.g. dialup + modem or broadband), is there anything I can do to speed things up? + + Q-74: Does x11vnc support the X DAMAGE Xserver extension to find + modified regions of the screen quickly and efficiently? + + Q-75: My OpenGL application shows no screen updates unless I supply + the -noxdamage option to x11vnc. + + Q-76: When I drag windows around with the mouse or scroll up and down + things really bog down (unless I do the drag in a single, quick + motion.) Is there anything to do to improve things? + + Q-77: Why not do something like wireframe animations to avoid the + windows "lurching" when being moved or resized? + + Q-78: Can x11vnc try to apply heuristics to detect when a window is + scrolling its contents and use the CopyRect encoding for a speedup? + + Q-79: Can x11vnc do client-side caching of pixel data? I.e. so when + that pixel data is needed again it does not have to be retransmitted + over the network. + + Q-80: Does x11vnc support TurboVNC? + + [Mouse Cursor Shapes] + + Q-81: Why isn't the mouse cursor shape (the little icon shape where + the mouse pointer is) correct as I move from window to window? + + Q-82: When using XFIXES cursorshape mode, some of the cursors look + really bad with extra black borders around the cursor and other cruft. + How can I improve their appearance? + + Q-83: In XFIXES mode, are there any hacks to handle cursor + transparency ("alpha channel") exactly? + + [Mouse Pointer] + + Q-84: Why does the mouse arrow just stay in one corner in my + vncviewer, whereas my cursor (that does move) is just a dot? + + Q-85: Can I take advantage of the TightVNC extension to the VNC + protocol where Cursor Positions Updates are sent back to all connected + clients (i.e. passive viewers can see the mouse cursor being moved + around by another viewer)? + + Q-86: Is it possible to swap the mouse buttons (e.g. left-handed + operation), or arbitrarily remap them? How about mapping button clicks + to keystrokes, e.g. to partially emulate Mouse wheel scrolling? + + [Keyboard Issues] + + Q-87: How can I get my AltGr and Shift modifiers to work between + keyboards for different languages? + + Q-88: When I try to type a "<" (i.e. less than) instead I get ">" + (i.e. greater than)! Strangely, typing ">" works OK!! + + Q-89: Extra Character Inserted, E.g.: When I try to type a "<" (i.e. + less than) instead I get "<," (i.e. an extra comma.) + + Q-90: I'm using an "international" keyboard (e.g. German "de", or + Danish "dk") and the -modtweak mode works well if the VNC viewer is + run on a Unix/Linux machine with a similar keyboard. But if I run + the VNC viewer on Unix/Linux with a different keyboard (e.g. "us") or + Windows with any keyboard, I can't type some keys like: "@", "$", + "<", ">", etc. How can I fix this? + + Q-91: When typing I sometimes get double, triple, or more of my + keystrokes repeated. I'm sure I only typed them once, what can I do? + + Q-92: The x11vnc -norepeat mode is in effect, but I still get repeated + keystrokes!! + + Q-93: After using x11vnc for a while, I find that I cannot type some + (or any) characters or my mouse clicks and drags no longer have any + effect, or they lead to strange effects. What happened? + + Q-94: The machine where I run x11vnc has an AltGr key, but the local + machine where I run the VNC viewer does not. Is there a way I can map + a local unused key to send an AltGr? How about a Compose key as well? + + Q-95: I have a Sun machine I run x11vnc on. Its Sun keyboard has just + one Alt key labelled "Alt" and two Meta keys labelled with little + diamonds. The machine where I run the VNC viewer only has Alt keys. + How can I send a Meta keypress? (e.g. emacs needs this) + + Q-96: Running x11vnc on HP-UX I cannot type "#" I just get a "3" + instead. + + Q-97: Can I map a keystroke to a mouse button click on the remote + machine? + + Q-98: How can I get Caps_Lock to work between my VNC viewer and + x11vnc? + + [Screen Related Issues and Features] + + Q-99: The remote display is larger (in number of pixels) than the + local display I am running the vncviewer on. I don't like the + vncviewer scrollbars, what I can do? + + Q-100: Does x11vnc support server-side framebuffer scaling? (E.g. to + make the desktop smaller.) + + Q-101: Does x11vnc work with Xinerama? (i.e. multiple monitors joined + together to form one big, single screen.) + + Q-102: Can I use x11vnc on a multi-headed display that is not Xinerama + (i.e. separate screens :0.0, :0.1, ... for each monitor)? + + Q-103: Can x11vnc show only a portion of the display? (E.g. for a + special purpose application or a very large screen.) + + Q-104: Does x11vnc support the XRANDR (X Resize, Rotate and + Reflection) extension? Whenever I rotate or resize the screen x11vnc + just seems to crash. + + Q-105: Independent of any XRANDR, can I have x11vnc rotate and/or + reflect the screen that the VNC viewers see? (e.g. for a handheld + whose screen is rotated 90 degrees.) + + Q-106: Why is the view in my VNC viewer completely black? Or why is + everything flashing around randomly? + + Q-107: I use Linux Virtual Terminals (VT's) to implement 'Fast User + Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, + Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those + keystrokes to switch between their sessions.) How come the view in a + VNC viewer connecting to x11vnc is either completely black or + otherwise all messed up unless the X session x11vnc is attached to is + in the active VT? + + Q-108: I am using x11vnc where my local machine has "popup/hidden + taskbars" and the remote display where x11vnc runs also has + "popup/hidden taskbars" and they interfere and fight with each other. + What can I do? + + Q-109: Help! x11vnc and my KDE screensaver keep switching each other + on and off every few seconds. + + Q-110: I am running the beryl 3D window manager (or compiz, MythTv, + Google Earth, or some other OpenGL app) and I do not get screen + updates in x11vnc. + + Q-111: Can I use x11vnc to view my VMWare session remotely? + + [Exporting non-X11 devices via VNC] + + Q-112: Can non-X devices (e.g. a raw framebuffer) be viewed (and even + controlled) via VNC with x11vnc? + + Q-113: Can I export the Linux Console (Virtual Terminals) via VNC + using x11vnc? + + Q-114: Can I export via VNC a Webcam or TV tuner framebuffer using + x11vnc? + + Q-115: Can I connect via VNC to a Qt-embedded/Qtopia application + running on my handheld or PC using the Linux console framebuffer (i.e. + not X11)? + + Q-116: Now that non-X11 devices can be exported via VNC using x11vnc, + can I build it with no dependencies on X11 header files and libraries? + + Q-117: Does x11vnc support Mac OS X Aqua/Quartz displays natively + (i.e. no X11 involved)? + + Q-118: Can x11vnc be used as a VNC reflector/repeater to improve + performance for the case of a large number of simultaneous VNC viewers + (e.g. classroom broadcasting or a large demo)? + + Q-119: Can x11vnc be used during a Linux, Solaris, etc. system + Installation so the Installation can be done remotely? + + [Misc: Clipboard, File Transfer/Sharing, Printing, Sound, Beeps, + Thanks, etc.] + + Q-120: Does the Clipboard/Selection get transferred between the + vncviewer and the X display? + + Q-121: Can I use x11vnc to record a Shock Wave Flash (or other format) + video of my desktop, e.g. to record a tutorial or demo? + + Q-122: Can I transfer files back and forth with x11vnc? + + Q-123: Which UltraVNC extensions are supported? + + Q-124: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for + Unix? I.e. something very simple for a naive user to initiate a + reverse vnc connection from their Unix desktop to a helpdesk + operator's VNC Viewer. + + Q-125: Can I (temporarily) mount my local (viewer-side) Windows/Samba + File share on the machine where x11vnc is running? + + Q-126: Can I redirect CUPS print jobs from the remote desktop where + x11vnc is running to a printer on my local (viewer-side) machine? + + Q-127: How can I hear the sound (audio) from the remote applications + on the desktop I am viewing via x11vnc? + + Q-128: Why don't I hear the "Beeps" in my X session (e.g. when typing + tput bel in an xterm)? + + Q-129: Does x11vnc work with IPv6? + + Q-130: Thanks for your program or for your help! Can I make a + donation? + _________________________________________________________________ + + + [Building and Starting] + + Q-1: I can't get x11vnc to start up. It says "XOpenDisplay failed + (null)" or "Xlib: connection to ":0.0" refused by server Xlib: No + protocol specified" and then exits. What do I need to do? + + For the former error, you need to specify the X display to connect to + (it also needs to be on the same machine the x11vnc process is to run + on.) Set your DISPLAY environment variable (or use the -display + option) to specify it. Nearly always the correct value will be ":0" + (in fact, x11vnc will now assume :0 if given no other information.) + + + For the latter error, you need to set up the X11 permissions + correctly. + + To make sure X11 permissions are the problem do this simple test: + while sitting at the physical X display open a terminal window + (gnome-terminal, xterm, etc.) You should be able to run x11vnc + successfully without any need for special steps or command line + options in that terminal (i.e. just type "x11vnc".) If that works OK + then you know X11 permissions are the only thing preventing it from + working when you try to start x11vnc via, say, a remote shell. + + How to Solve: See the xauth(1), Xsecurity(7), and xhost(1) man pages + or this Howto for much info on X11 permissions. For example, you may + need to set your XAUTHORITY environment variable (or use the -auth + option) to point to the correct MIT-MAGIC-COOKIE file (e.g. + /home/joe/.Xauthority or /var/gdm/:0.Xauth or /var/lib/kdm/A:0-crWk72K + or /tmp/.gdmzndVlR, etc, etc.), or simply be sure you run x11vnc as + the correct user (i.e. the user who is logged into the X session you + wish to view.) + + Note: The MIT cookie file contains the secret key that allows x11vnc + to connect to the desired X display. + + If, say, sshd has set XAUTHORITY to point to a random file it has + created for X forwarding that will cause problems. (Under some + circumstances even su(1) and telnet(1) can set XAUTHORITY. See also + the gdm parameter NeverPlaceCookiesOnNFS that sets XAUTHORITY to a + random filename in /tmp for the whole X session.) + + Running x11vnc as root is often not enough: you need to know where the + MIT-MAGIC-COOKIE file for the desired X display is. + + Example solution: + x11vnc -display :0 -auth /var/gdm/:0.Xauth + + (this is for the display manager gdm and requires root permission to + read the gdm cookie file, see this faq for other display manager + cookie file names.) + + Note as of Feb/2007 you can also try the -find option instead of + "-display ..." and see if that finds your display and Xauthority. + + Less safe, but to avoid figuring out where the correct XAUTHORITY file + is, if the person sitting at the physical X session types "xhost + +localhost" then one should be able to attach x11vnc to the session + (from the same machine.) The person could then type "xhost -localhost" + after x11vnc has connected to go back to the default permissions. + Also, for some situations the "-users lurk=" option may soon be of use + (please read the documentation on the -users option.) + + To test out your X11 permissions from a remote shell, set DISPLAY and + possibly XAUTHORITY (see your shell's man page, bash(1), tcsh(1), on + how to set environment variables) and type xdpyinfo in the same place + you will be typing (or otherwise running) x11vnc. If information is + printed out about the X display (screen sizes, supported extensions, + color visuals info) that means the X11 permissions are set up + properly: xdpyinfo successfully connected to DISPLAY! You could also + type xclock and make sure no errors are reported (a clock should + appear on the X display, press Ctrl-C to stop it.) If these work, then + typing "x11vnc" in the same environment should also work. + + Important: if you cannot get your X11 permissions so that the xdpyinfo + or xclock tests work, x11vnc also will not work (all of these X + clients must be allowed to connect to the X server to function + properly.) + + Firewalls: Speaking of permissions, it should go without saying that + the host-level firewall will need to be configured to allow + connections in on a port. E.g. 5900 (default VNC port) or 22 (default + SSH port for tunnelling VNC.) Most systems these days have firewalls + turned on by default, so you will actively have to do something to + poke a hole in the firewall at the desired port number. See your + system administration tool for Firewall settings (Yast, Firestarter, + etc.) + + + Q-2: I can't get x11vnc and/or libvncserver to compile. + + Make sure you have gcc (or other C compiler) and all of the required + libraries and the corresponding -dev/-devel packages installed. These + include Xorg/XFree86, libX11, libjpeg, libz, libssl, ... and don't + forget the devs: libjpeg-dev, libssl-dev ... + + The most common build problem that people encounter is that the + necessary X11 libraries are installed on their system however it does + not have the corresponding -dev/-devel packages installed. These dev + packages include C header files and build-time .so symlink. It is a + shame the current trend in distros is to not install the dev package + by default when the the library runtime package is installed... (it + diminishes the power of open source) + + As of Nov/2006 here is a list of libraries that x11vnc usually likes + to use: +libc.so libX11.so libXtst.so libXext.so +libXfixes.so libXdamage.so libXinerama.so libXrandr.so +libz.so libjpeg.so libpthread.so +libssl.so libcrypto.so libcrypt.so + + although x11vnc will be pretty usable with the subset: libc.so, + libX11.so, libXtst.so, libXext.so, libz.so, and libjpeg.so. + + After running the libvncserver configure, carefully examine the output + and the messages in the config.log file looking for missing + components. For example, if the configure output looks like: + checking how to run the C preprocessor... gcc -E + checking for X... no + checking for XkbSelectEvents in -lX11... no + checking for XineramaQueryScreens in -lXinerama... no + checking for XTestFakeKeyEvent in -lXtst... no + + or even worse: + checking for C compiler default output file name... configure: error: + C compiler cannot create executables + See `config.log' for more details. + + there is quite a bit wrong with the build environment. Hopefully + simply adding -dev packages and/or gcc or make will fix it. + + For Debian the list seems to be: + gcc + make + libc6-dev + libjpeg8-dev (formerly libjpeg62-dev) + libx11-dev + x11proto-core-dev (formerly x-dev) + libxext-dev + libxtst-dev + libxdamage-dev + libxfixes-dev + libxrandr-dev + libxinerama-dev + libxss-dev (formerly xlibs-static-dev) + zlib1g-dev + libssl-dev + libavahi-client-dev + linux-libc-dev (only needed for linux console rawfb support) + + Note that depending on your OS version the above names may have been + changed and/or additional packages may be needed. + + For Redhat the list seems to be: + gcc + make + glibc-devel + libjpeg-devel + libX11-devel + xorg-x11-proto-devel + libXdamage-devel + libXfixes-devel + libXrandr-devel + zlib-devel + openssl-devel + avahi-devel + kernel-headers (only needed for linux console rawfb support) + + For other distros or OS's the package names may not be the same but + will look similar. Also, distros tend to rename packages as well so + the above list may be out of date. So only use the above lists as + hints for the package names that are needed. + + Have a look at Misc. Build Problems for additional fixes. + + Note: there is growing trend in Linux and other distros to slice up + core X11 software into more and smaller packages. So be prepared for + more headaches compiling software... + + + Q-3: I just built x11vnc successfully, but when I use it my keystrokes + and mouse button clicks are ignored (I am able to move the mouse + though.) + + This is most likely due to you not having a working build environment + for the XTEST client library libXtst.so. The library is probably + present on your system, but the package installing the build header + file is missing. + + If you were watching carefully while configure was running you would + have seen: + checking for XTestFakeKeyEvent in -lXtst... no + + The solution is to add the necessary build environment package (and + the library package if that is missing too.) On Debian the build + package is libxtst-dev. Other distros/OS's may have it in another + package. + + x11vnc will build without support for this library (e.g. perhaps one + wants a view-only x11vnc on a stripped down or embedded system...) And + at runtime it will also continue to run even if the X server it + connects to does not support XTEST. In both cases it cannot inject + keystrokes or button clicks since XTEST is needed for that (it can + still move the mouse pointer using the X API XWarpPointer().) + + You will see a warning message something like this at run time: + 20/03/2005 22:33:09 WARNING: XTEST extension not available (either missing fr +om + 20/03/2005 22:33:09 display or client library libXtst missing at build time +.) + 20/03/2005 22:33:09 MOST user input (pointer and keyboard) will be DISCARDE +D. + 20/03/2005 22:33:09 If display does have XTEST, be sure to build x11vnc wit +h + 20/03/2005 22:33:09 a working libXtst build environment (e.g. libxtst-dev, + 20/03/2005 22:33:09 or other packages.) + 20/03/2005 22:33:09 No XTEST extension, switching to -xwarppointer mode for + 20/03/2005 22:33:09 pointer motion input. + + Also, as of Nov/2006 there will be a configure build time warning as + well: + ... + checking for XFixesGetCursorImage in -lXfixes... yes + checking for XDamageQueryExtension in -lXdamage... yes + configure: WARNING: + ========================================================================== + A working build environment for the XTEST extension was not found (libXtst). + An x11vnc built this way will be only barely usable. You will be able to + move the mouse but not click or type. There can also be deadlocks if an + application grabs the X server. + + It is recommended that you install the necessary development packages + for XTEST (perhaps it is named something like libxtst-dev) and run + configure again. + ========================================================================== + + + Q-4: Help, I need to run x11vnc on Solaris 2.5.1 (or other old + Unix/Linux) and it doesn't compile! + + We apologize that x11vnc does not build cleanly on older versions of + Solaris, Linux, etc.: very few users are on these old releases. + + We have heard that since Dec/2004 a Solaris 2.6 built x11vnc will run + on Solaris Solaris 2.5 and 2.5.1 (since a workaround for XConvertCase + is provided.) + + In any event, here is a workaround for Solaris 2.5.1 (and perhaps + earlier and perhaps non-Solaris): + + First use the environment settings (CPPFLAGS, LDFLAGS, etc.) in the + above Solaris build script to run the configure command. That should + succeed without failure. Then you have to hand edit the autogenerated + rfb/rfbconfig.h file in the source tree, and just before the last + #endif at the bottom of that file insert these workaround lines: +struct timeval _tmp_usleep_tv; +#define usleep(x) \ + _tmp_usleep_tv.tv_sec = (x) / 1000000; \ + _tmp_usleep_tv.tv_usec = (x) % 1000000; \ + select(0, NULL, NULL, NULL, &_tmp_usleep_tv); +int gethostname(char *name, int namelen); +long random(); +int srandom(unsigned int seed); +#undef LIBVNCSERVER_HAVE_LIBPTHREAD +#define SHUT_RDWR 2 +typedef unsigned int in_addr_t; +#define snprintf(a, n, args...) sprintf((a), ## args) + + Then run make with the Solaris build script environment, everything + should compile without problems, and the resulting x11vnc binary + should work OK. If some non-x11vnc related programs fail (e.g. test + programs) and the x11vnc binary is not created try "make -k" to have + it keep going. Similar sorts of kludges in rfb/rfbconfig.h can be done + on other older OS (Solaris, Linux, ...) releases. + + Here are some notes for similar steps that need to be done to build on + SunOS 4.x + + Please let us know if you had to use the above workaround (and whether + it worked or not.) If there is enough demand we will try to push clean + compilations back to earlier Solaris, Linux, etc, releases. + + + Q-5: Where can I get a precompiled x11vnc binary for my Operating + System? + + Hopefully the build steps above and FAQ provide enough info for a + painless compile for most environments. Please report problems with + the x11vnc configure, make, etc. on your system (if your system is + known to compile other GNU packages successfully.) + + There are precompiled x11vnc binaries built by other groups that are + available at the following locations: + Slackware: (.tgz) http://www.linuxpackages.net/ + + SuSE: (.rpm) http:/software.opensuse.org/ Gentoo: (info) + http://gentoo-wiki.com/ and http://gentoo-portage.com/ FreeBSD: (.tbz) + http://www.freebsd.org/ http://www.freshports.org/net/x11vnc NetBSD: + (src) http://pkgsrc.se/x11/x11vnc OpenBSD: (.tgz) http://openports.se/ + Arch Linux: (.tgz) http://www.archlinux.org/ Nokia 770 (.deb) + http://mike.saunby.googlepages.com/x11vncfornokia7702 Sharp Zaurus + http://www.focv.com/ Debian: (.deb) http://packages.debian.org/x11vnc + Redhat/Fedora: (.rpm) http://packages.sw.be/x11vnc RPMforge + http://dag.wieers.com/rpm/packages/x11vnc/ (N.B.: unmaintained after + 0.9.3) Solaris: (pkg) http://www.sunfreeware.com/ + + If the above binaries don't work and building x11vnc on your OS fails + (and all else fails!) you can try one of My Collection of x11vnc + Binaries for various OS's and x11vnc releases. + + As a general note, the x11vnc program is simple enough you don't + really need to install a package: the binary will in most cases work + as is and from any location (as long as your system libraries are not + too old, etc.) So, for Linux distributions that are not one of the + above, the x11vnc binary from the above packages has a good chance of + working. You can "install" it by just copying the x11vnc binary to the + desired directory in your PATH. Tip on extracting files from a Debian + package: extract the archive via a command like: "ar x + x11vnc_0.6-2_i386.deb" and then you can find the binary in the + resulting data.tar.gz tar file. Also, rpm2cpio(1) is useful in + extracting files from rpm packages. + + If you use a standalone binary like this and also want x11vnc to serve + up the Java VNC Viewer jar file (either SSL enabled or regular one), + then you will need to extract the classes subdirectory from the source + tarball and point x11vnc to it via the -httpdir option. E.g.: + x11vnc -httpdir /path/to/x11vnc-0.9.9/classes/ssl ... + + + Q-6: Where can I get a VNC Viewer binary (or source code) for the + Operating System I will be viewing from? + + To obtain VNC viewers for the viewing side (Windows, Mac OS, or Unix) + try here: + * http://www.tightvnc.com/download.html + * http://www.realvnc.com/download-free.html + * http://sourceforge.net/projects/cotvnc/ + * http://www.ultravnc.com/ + * Our Enhanced TightVNC Viewer (SSVNC) + + [ssvnc.gif] + + + Q-7: How can I see all of x11vnc's command line options and + documentation on how to use them? + + Run: x11vnc -opts to list just the option names or run: x11vnc + -help for long descriptions about each option. The output is listed + here as well. Yes, x11vnc does have a lot of options, doesn't it... + + + Q-8: I don't like typing arcane command line options every time I + start x11vnc. What can I do? Is there a config file? Or a GUI? + + You could create a shell script that calls x11vnc with your options: +#!/bin/sh +# +# filename: X11vnc (i.e. not "x11vnc") +# It resides in a directory in $PATH. "chmod 755 X11vnc" has been run on it. +# +x11vnc -wait 50 -localhost -rfbauth $HOME/.vnc/passwd -display :0 $* + + a similar thing can be done via aliases in your shell (bash, tcsh, + csh, etc..) + + Or as of Jun/2004 you can use the simple $HOME/.x11vncrc config file + support. If that file exists, each line is taken as a command line + option. E.g. the above would be: +# this is a comment in my ~/.x11vncrc file +wait 50 # this is a comment to the end of the line. +-localhost # note: the leading "-" is optional. +rfbauth /home/fred/.vnc/passwd +display :0 + + As of Dec/2004 there is now a simple Tcl/Tk GUI based on the + remote-control functionality ("-R") that was added. The /usr/bin/wish + program is needed for operation. The gui is not particularly + user-friendly, it just provides a point and click mode to set all the + many x11vnc parameters and obtain help on them. It is also very useful + for testing. See the -gui option for more info. Examples: "x11vnc ... + -gui" and "x11vnc ... -gui other:0" in the latter case the gui is + displayed on other:0, not the X display x11vnc is polling. There is + also a "-gui tray" system tray mode. + + [tkx11vnc.gif] + + NOTE: You may need to install the "wish" or "tk" or "tk8.4" package + for the gui mode to work (the package name depends on your OS/distro.) + The tcl/tk "wish" interpreter is used. In debian (and so ubuntu too) + one would run "apt-get install tk" or perhaps "apt-get install tk8.4" + + + Q-9: How can I get the GUI to run in the System Tray, or at least be a + smaller, simpler icon? + + As of Jul/2005 the gui can run in a more friendly small icon mode + "-gui icon" or in the system tray: "-gui tray". It has balloon status, + a simple menu, and a Properities dialog. The full, complicated, gui is + only available under "Advanced". Other improvements were added as + well. Try "Misc -> simple_gui" for a gui with fewer esoteric menu + items. + + If the gui fails to embed itself in the system tray, do a retry via + "Window View -> icon" followed by "Window View -> tray" with the popup + menu. + + For inexperienced users starting up x11vnc and the GUI while sitting + at the physical X display (not remotely), using something like "x11vnc + -display :0 -gui tray=setpass" might be something for them that they + are accustomed to in a Desktop environment (it prompts for an initial + password, etc.) This is a basic "Share My Desktop" usage mode. + + As of Nov/2008 in x11vnc 0.9.6 there is a desktop menu item + (x11vnc.desktop) that runs this command: + x11vnc -gui tray=setpass -rfbport PROMPT -logfile %HOME/.x11vnc.log.%VNCDISP +LAY + + which also prompts for which VNC port to use and a couple other + parameters. + + + Q-10: How can I get x11vnc to listen on a different port besides the + default VNC port (5900)? + + Use something like, e.g., "x11vnc -rfbport 5901" to force it to use + port 5901 (this is VNC display :1.) If something else is using that + port x11vnc will exit immediately. If you do not supply the -rfbport + option, it will autoprobe starting at 5900 and work its way up to 5999 + looking for a free port to listen on. In that case, watch for the + PORT=59xx line to see which port it found, then subtract 5900 from it + for the VNC display number to enter into the VNC Viewer(s). + + The "-N" option will try to match the VNC display number to the X + display (e.g. X11 DISPLAY of :5 (port 6005) will have VNC display :5 + (port 5905).) + + Also see the "-autoport n" option to indicated at which value the auto + probing should start at. + + + Q-11: My Firewall/Router doesn't allow VNC Viewers to connect to + x11vnc. + + See the Firewalls/Routers discussion. + + + Q-12: Is it possible for a VNC Viewer and a VNC Server to connect to + each other even though both are behind Firewalls that block all + incoming connections? + + This is very difficult or impossible to do unless a third machine, + reachable by both, is used as a relay. So we assume a third machine is + somehow being used as a relay. + + (Update: It may be possible to do "NAT-2-NAT" without a relay machine + by using a UDP tunnel such as http://samy.pl/pwnat/. All that is + required is that both NAT firewalls allow in UDP packets from an IP + address to which a UDP packet has recently been sent to. If you try it + out let us know how it went.) + + In the following discussion, we will suppose port 5950 is being used + on the relay machine as the VNC port for the rendezvous. + + A way to rendezvous is to have the VNC Server start a reverse + connection to the relay machine: + x11vnc -connect third-machine.net:5950 ... + + and the VNC viewer forward connects as usual: + vncviewer third-machine.net:50 + + Or maybe two ports would be involved, e.g. the viewer goes to display + :51 (5951.) It depends on the relay software being used. + + What software to run on third-machine? A TCP relay of some sort could + be used... Try a google search on "tcp relay" or "ip relay". However, + note that this isn't a simple redirection because it hooks up two + incoming connections. You can look at our UltraVNC repeater + implementation ultravnc_repeater.pl for ideas and possibly to + customize. + + Also, if you are not the admin of third-machine you'd have to convince + the owner to allow you to install this software (and he would likely + need to open his server's firewall to allow the port through.) + + It is recommended that SSL is used for encryption (e.g. "-ssl SAVE") + when going over the internet. + + We have a prototype for performing a rendezvous via a Web Server + acting as the relay machine. Download the vncxfer CGI script and see + the instructions at the top. + + Once that CGI script is set up on the website, both users go to, say, + http://somesite.com/vncxfer (or maybe a "/cgi-bin" directory or ".cgi" + suffix must be used.) Previously, both have agreed on the same session + name (say by phone or email) , e.g. "5cows", and put that into the + entry form on the vncxfer starting page (hopefully separated by a few + seconds, so the relay helper can fully start up at the first request.) + + The page returned tells them the hostname and port number and possible + command to use for forward (VNC Viewer) and reverse (VNC Server, i.e. + x11vnc) connections as described above. + + Also since Oct/2007, x11vnc can connect directly (no web browser), + like this: + x11vnc ... -connect localhost:0 -proxy 'http://somesite.com/vncxfer?session= +5cows&' + + Unfortunately the prototype requires that the Web server's firewall + allow in the port (e.g. 5950) used for the rendezvous. Most web + servers are not configured to do this, so you would need to ask the + admin to do this for you. Nearly all free webspace sites, e.g. + www.zendurl.com, will not allow your CGI script to be an open relay + like this. (If you find one that does allow this, let me know!) + + Maybe someday a clever trick will be thought up to relax the listening + port requirement (e.g. use HTTP/CGI itself for the transfer... it is + difficult to emulate a full-duplex TCP connection with them.) + + See also the Firewalls/Routers discussion and Reverse Connection Proxy + discussion. + + + SSH method: If both users (i.e. one on Viewer-side and the other on + x11vnc server side) have SSH access to a common machine on the + internet (or otherwise mutually reachable), then SSH plumbing can be + used to solve this problem. The users create SSH tunnels going through + the SSH login machine. + + Instead of assuming port 5900 is free on the SSH machine, we will + assume both users agreed to use 5933. This will illustrate how to use + a different port for the redir. It could be any port, what matters is + that both parties refer to the same one. + + Set up the Tunnel from the VNC Server side: + ssh -t -R 5933:localhost:5900 user@third-machine.net + + Set up the Tunnel from the VNC Viewer side: + ssh -t -L 5900:localhost:5933 user@third-machine.net + + Run Server on the VNC Server side: + x11vnc -rfbport 5900 -localhost ... + + Run Viewer on the VNC Viewer side: + vncviewer -encodings "copyrect tight zrle hextile" localhost:0 + + (we assume the old-style -encodings option needs to be used. See here + for details.) + + If the SSH machine has been configured (see sshd_config(5)) with the + option GatewayPorts=yes, then the tunnel set up by the VNC Server will + be reachable directly by the VNC viewer (as long as the SSH machine's + firewall does not block the port, 5933 in this example.) So in that + case the Viewer side does not need to run any ssh command, but rather + only runs: + vncviewer third-machine.net:33 + + In this case we recommend SSL be used for encryption. + + The creation of both tunnels can be automated. As of Oct/2007 the -ssh + x11vnc option is available and so only this command needs to be run on + the VNC Server side: + x11vnc -ssh user@third-machine.net:33 ... + + (the SSH passphrase may need to be supplied.) + + To automate on the VNC Viewer side, the user can use the Enhanced + TightVNC Viewer (SSVNC) by: + * Clicking on 'Use SSH' + * Entering user@third-machine.net:33 into 'VNC Host:Display' entry + box + * Clicking on 'Connect' + + As above, if the SSH GatewayPorts=yes setting is configured the Viewer + side doesn't need to create a SSH tunnel. In SSVNC the Viewer user + could instead select 'Use SSL' and then, e.g., on the Server side + supply "-ssl SAVE" to x11vnc. Then end-to-end SSL encryption would be + used (in addition to the SSH encryption on the Server-side leg.) + + + Q-13: Can I make x11vnc more quiet and also go into the background + after starting up? + + Use the -q and -bg options, respectively. (also: -quiet is an alias + for -q) + + Note that under -bg the stderr messages will be lost unless you use + the "-o logfile" option. + + + Q-14: Sometimes when a VNC viewer dies abruptly, x11vnc also dies with + the error message like: "Broken pipe". I'm using the -forever mode and + I want x11vnc to keep running. + + As of Jan/2004 the SIGPIPE signal is ignored. So if a viewer client + terminates abruptly, libvncserver will notice on the next I/O + operation and will close the connection and continue on. + + Up until of Apr/2004 the above fix only works for BSD signal systems + (Linux, FreeBSD, ...) For SYSV systems there is a workaround in place + since about Jun/2004. + + + Q-15: The Windows TightVNC 1.3.9 Viewer cannot connect to x11vnc. + + This appears to be fixed in x11vnc version 0.9 and later. If you need + to use an earlier version of x11vnc, try using the "-rfbversion 3.7" + option. In general sometimes one can get a misbehaving viewer to work + by supplying rfb versions 3.7 or 3.3. + + + Q-16: KDE's krdc VNC viewer cannot connect to x11vnc. + + This has been fixed in x11vnc version 0.8.4. More info here, here, and + here. + + + Q-17: When I start x11vnc on an Alpha Tru64 workstation the X server + crashes! + + This is a bug in the X server obviously; an X client should never be + able to crash it. + + The problem seems to be with the RECORD X extension and so a + workaround is to use the "-noxrecord" x11vnc command line option. + + + Q-18: When running x11vnc on an IBM AIX workstation after a few + minutes the VNC connection freezes. + + One user reports when running x11vnc on AIX 5.3 in his CDE session + after a few minutes or seconds x11vnc will "freeze" (no more updates + being sent, etc.) The freezing appeared to be worse for versions later + than 0.9.2. + + The problem seems to be with the RECORD X extension on AIX and so a + workaround is to use the "-noxrecord" x11vnc command line option. The + user found no freezes occurred when using that option. + + + Q-19: Are there any build-time customizations possible, e.g. change + defaults, create a smaller binary, etc? + + There are some options. They are enabled by adding something like + -Dxxxx=1 to the CPPFLAGS environment variable before running configure + (see the build notes for general background.) +/* + * Mar/2006 + * Build-time customization via CPPFLAGS. + * + * Summary of options to include in CPPFLAGS for custom builds: + * + * -DVNCSHARED to have the vnc display shared by default. + * -DFOREVER to have -forever on by default. + * -DNOREPEAT=0 to have -repeat on by default. + * -DADDKEYSYMS=0 to have -noadd_keysyms the default. + * + * -DREMOTE_DEFAULT=0 to disable remote-control on by default (-yesremote.) + * -DREMOTE_CONTROL=0 to disable remote-control mechanism completely. + * -DEXTERNAL_COMMANDS=0 to disable the running of all external commands. + * -DFILEXFER=0 disable filexfer. + * + * -DHARDWIRE_PASSWD=... hardwired passwords, quoting necessary. + * -DHARDWIRE_VIEWPASSWD=... + * -DNOPW=1 make -nopw the default (skip warning) + * -DUSEPW=1 make -usepw the default + * -DPASSWD_REQUIRED=1 exit unless a password is supplied. + * -DPASSWD_UNLESS_NOPW=1 exit unless a password is supplied and no -nopw. + * + * -DWIREFRAME=0 to have -nowireframe as the default. + * -DWIREFRAME_COPYRECT=0 to have -nowirecopyrect as the default. + * -DWIREFRAME_PARMS=... set default -wirecopyrect parameters. + * -DSCROLL_COPYRECT=0 to have -noscrollcopyrect as the default. + * -DSCROLL_COPYRECT_PARMS=... set default -scrollcopyrect parameters. + * -DSCALING_COPYRECT=0 + * -DXDAMAGE=0 to have -noxdamage as the default. + * -DSKIPDUPS=0 to have -noskip_dups as the default or vice versa. + * + * -DPOINTER_MODE_DEFAULT={0,1,2,3,4} set default -pointer_mode. + * -DBOLDLY_CLOSE_DISPLAY=0 to not close X DISPLAY under -rawfb. + * -DSMALL_FOOTPRINT=1 for smaller binary size (no help, no gui, etc) + * use 2 or 3 for even smaller footprint. + * -DNOGUI do not include the gui tkx11vnc. + * -DPOLL_8TO24_DELAY=N + * -DDEBUG_XEVENTS=1 enable printout for X events. + * + * Set these in CPPFLAGS before running configure. E.g.: + * + * % env CPPFLAGS="-DFOREVER -DREMOTE_CONTROL=0" ./configure + * % make + */ + + If other things (e.g. "-I ...") are needed in CPPFLAGS add them as + well. + + On some systems is seems you need to set LC_ALL=C for configure to + work properly... + + Be careful the following two variables: HARDWIRE_PASSWD and + HARDWIRE_VIEWPASSWD. If set (remember to include the double quotes + around the string), they will be used as default values for the + -passwd and -viewpasswd options. Of course the strings will exist + unobscured in the x11vnc binary: it better not be readable by + unintendeds. Perhaps this is of use in remote access for an embedded + application, etc... + + Let us know if more build-time customizations would be useful. + + + [Win2VNC Related] + + Q-20: I have two separate machine displays in front of me, one Windows + the other X11: can I use x11vnc in combination with Win2VNC in + dual-screen mode to pass the keystrokes and mouse motions to the X11 + display? + + Yes, for best response start up x11vnc with the "-nofb" option + (disables framebuffer polling, and does other optimizations) on the + secondary display (X11) machine. Then start up Win2VNC on the primary + display (Windows) referring it to the secondary display. + + This will also work X11 to X11 using x2vnc, however you would probably + just want to avoid VNC and use x2x for that. + + For reference, here are some links to Win2VNC-like programs for + multiple monitor setups: + * Original Win2VNC + * Enhanced Win2VNC (broken?) and sourceforge link + * x2vnc + * x2x + * zvnc (MorphOS) + + All of them will work with x11vnc (except x2x where it is not needed.) + + + Q-21: I am running Win2VNC on my Windows machine and "x11vnc -nofb" on + Unix to pass keyboard and mouse to the Unix monitor. Whenever I start + Win2VNC it quickly disconnects and x11vnc says: + rfbProcessClientNormalMessage: read: Connection reset by peer + + Is the default visual of the X display you run x11vnc on low color + (e.g. 8 bit per pixel PseudoColor)? (you can run xdpyinfo to check, + look in the "screen" section.) There seems to be a bug in Win2VNC in + that it cannot deal correctly with colormaps (PseudoColor is the most + common example of a visual with a colormap.) + + If so, there are a couple options. 1) Can you set the default visual + on your display to be depth 24 TrueColor? Sun machines often have 8+24 + overlay/multi-depth visuals, and you can make the default visual depth + 24 TrueColor (see fbconfig(1) and Xsun(1).) 2) As of Feb/2004 x11vnc + has the -visual option to allow you to force the framebuffer visual to + whatever you want (this usually messes up the colors unless you are + very clever.) In this case, the option provides a convenient + workaround for the Win2VNC bug: + x11vnc -nofb -visual TrueColor -display :0 ... + + So the visual will be set to 8bpp TrueColor and Win2VNC can handle + this. Since Win2VNC does not use the framebuffer data there should be + no problems in doing this. + + Q-22: Can I run "x11vnc -nofb" on a Mac OS X machine to redirect mouse + and keyboard input to it from Windows and X11 machines via Win2VNC and + x2vnc, respectively? + + Yes, as of Nov/2006 you can. There may be a trick or two you'll need + to do to get the Clipboard exchange between the machines to work. + + + + [Color Issues] + + Q-23: The X display I run x11vnc on is only 8 bits per pixel (bpp) + PseudoColor (i.e. only 256 distinct colors.) The x11vnc colors may + start out OK, but after a while they are incorrect in certain windows. + + Use the -flashcmap option to have x11vnc watch for changes in the + colormap, and propagate those changes back to connected clients. This + can be slow (since the whole screen must be updated over the network + whenever the colormap changes.) This flashing colormap behavior often + happens if an application installs its own private colormap when the + mouse is in its window. "netscape -install" is a well-known historical + example of this. Consider reconfiguring the system to 16 bpp or depth + 24 TrueColor if at all possible. + + Also note the option -8to24 (Jan/2006) can often remove the need for + flashing the colormap. Everything is dynamically transformed to depth + 24 at 32 bpp using the colormaps. There may be painting errors however + (see the following FAQ for tips on reducing and correcting them.) + + In some rare cases (SCO unixware) the -notruecolor option has + corrected colors on 8bpp displays. The red, green, and blue masks were + non-zero in 8bpp PseudoColor on an obscure setup, and this option + corrected the problems. + + + Q-24: Color problems: Why are the colors for some windows incorrect in + x11vnc? BTW, my X display has nice overlay/multi-depth visuals of + different color depths: e.g. there are both depth 8 and 24 visuals + available at the same time. + + You may want to review the previous question regarding 8 bpp + PseudoColor. + + On some hardware (Sun/SPARC and SGI), the -overlay option discussed a + couple paragraphs down may solve this for you (you may want to skip to + it directly.) On other hardware the less robust -8to24 option may help + (also discussed below.) + + Run xdpyinfo(1) to see what the default visual is and what the depths + of the other visuals are. Does the default visual have a depth of 8 + but there are other visuals of depth 24? If it does, can you possibly + re-configure your X server to make a depth 24 visual the default? If + you can do it, this will save you a lot of grief WRT colors and x11vnc + (and for general usage too!) Here is how I do this on an old + Sparcstation 20 running Solaris 9 with SX graphics + xinit -- -dev /dev/fb defclass TrueColor defdepth 24 + + and it works nicely (note: to log into console from the dtlogin + window, select "Options -> Command Line Login", then login and enter + the above command.) See the -dev section of the Xsun(1) manpage for a + description of the above arguments. If you have root permission, a + more permanent and convenient thing to do is to record the arguments + in a line like: + :0 Local local_uid@console root /usr/openwin/bin/Xsun -dev /dev/fb defclass +TrueColor defdepth 24 + + in /etc/dt/config/Xservers (copy /usr/dt/config/Xservers.) Also look + at the fbconfig(1) and related manpages (e.g. ffbconfig, m64config, + pgxconfig, SUNWjfb_config, etc ...) for hardware framebuffer settings + that may achieve the same effect. + + In general for non-Sun machines, look at the "-cc class" and related + options in your X server manpage (perhaps Xserver(1)), it may allow + modifying the default visual (e.g. "-cc 4", see for the + visual class numbers.) On XFree86 some video card drivers (e.g. Matrox + mga) have settings like Option "Overlay" "24,8" to support multi-depth + overlays. For these, use the "-cc 4" X server command line option to + get a depth 24 default visual. + + + The -overlay mode: Another option is if the system with overlay + visuals is a Sun system running Solaris or SGI running IRIX you can + use the -overlay x11vnc option (Aug/2004) to have x11vnc use the + Solaris XReadScreen(3X11) function to poll the "true view" of the + whole screen at depth 24 TrueColor. XReadDisplay(3X11) is used on + IRIX. This is useful for Legacy applications (older versions of + Cadence CAD apps are mentioned by x11vnc users) that require the + default depth be 8bpp, or the app will use a 8bpp visual even if depth + 24 visuals are available, and so the default depth workaround + described in the previous paragraph is not sufficient for these apps. + + It seems that Xorg is working toward supporting XReadDisplay(3X11) as + part of the RENDER extension work. When it does support it and + provides a library API x11vnc will be modified to take advantage of + the feature to support -overlay on Linux, *BSD, etc. Until then see + the -8to24 mode below. + + Misc. notes on -overlay mode: An amusing by-product of -overlay mode + is that the mouse cursor shape is correct! (i.e. XFIXES is not + needed.) The -overlay mode may be somewhat slower than normal mode due + to the extra framebuffer manipulations that must be performed. Also, + on Solaris there is a bug in that for some popup menus, the windows + they overlap will have painting errors (flashing colors) while the + popup is up (a workaround is to disable SaveUnders by passing -su to + Xsun, e.g. in your /etc/dt/config/Xservers file.) + + + The -8to24 mode: The -8to24 x11vnc option (Jan/2006) is a kludge to + try to dynamically rewrite the pixel values so that the 8bpp part of + the screen is mapped onto depth 24 TrueColor. This is less robust than + the -overlay mode because it is done by x11vnc outside of the X + server. So only use it on OS's that do not support -overlay. The + -8to24 mode will work if the default visual is depth 24 or depth 8. It + scans for any windows within 3 levels of the root window that are 8bpp + (i.e. legacy application), or in general ones that are not using the + default visual. For the windows it finds it uses XGetSubImage() to + retrieve the pixels values and uses the correct indexed colormap to + create a depth 24 TrueColor view of the whole screen. This depth 24, + 32bpp view is exported via VNC. + + Even on pure 8bpp displays it can be used as an alternative to + -flashcmap to avoid color flashing completely. + + This scheme is approximate and can often lead to painting errors. You + can manually correct most painting errors by pressing 3 Alt_L's in a + row, or by using something like: -fixscreen V=3.0 to automatically + refresh the screen every 3 seconds. Also -fixscreen 8=3.0 has been + added to just refresh the non-default visual parts of the screen. + + In general the scheme uses many resources and may give rise to + sluggish behavior. If multiple windows are using different 8bpp + indexed colormaps all but one window may need to be iconified for the + colors to be correct. There are a number of tunable parameters to try + to adjust performance and painting accuracy. The option -8to24 + nogetimage can give a nice speedup if the default depth 24 X server + supports hiding the 8bpp bits in bits 25-32 of the framebuffer data. + On very slow machines -8to24 poll=0.2,cachewin=5.0 gives an useful + speedup. See the -8to24 help description for information on tunable + parameters, etc. + + + Colors still not working correctly? Run xwininfo on the application + with the incorrect colors to verify that the depth of its visual is + different from the default visual depth (gotten from xdpyinfo.) One + possible workaround in this case is to use the -id option to point + x11vnc at the application window itself. If the application is + complicated (lots of toplevel windows and popup menus) this may not be + acceptable, and may even crash x11vnc (but not the application.) See + also -appshare. + + It is theoretically possible to solve this problem in general (see + xwd(1) for example), but it does not seem trivial or sufficiently fast + for x11vnc to be able to do so in real time. The -8to24 method does + this approximately and is somewhat usable. Fortunately the -overlay + option works for Solaris machines with overlay visuals where most of + this problem occurs. + + + Q-25: I am on a high color system (depth >= 24) but I seem to have + colormap problems. They either flash or everything is very dark. + + This can happen if the default Visual (use xdpyinfo to list them) is + DirectColor instead of TrueColor. These are both usually used in high + color modes, but whereas TrueColor uses static ramps for the Red, + Green, and Blue components, DirectColor has arbitrary colormaps for + the Red, Green, and Blue Components. Currently x11vnc cannot decode + these colormaps and treats them just like TrueColor. + + The only workaround so far is to restart the X server with the "-cc 4" + option to force TrueColor as the default visual (DirectColor is "-cc + 5"; see /usr/include/X11/X.h.) The only place we have seen this is + with the virtual framebuffer server Xvfb on Xorg 7.2. So in that case + you probably should restart it with something like this: "Xvfb :1 -cc + 4 -screen 0 1280x1024x24". It should be possible for x11vnc to handle + DirectColor, but this hasn't been implemented due to its rare usage. + + You may also see this problem on an X display with a TrueColor default + visual where an application chooses a DirectColor visual for its + window(s). It seems the application also needs to install its own + colormap for the visual for the colors to be messed up in x11vnc. One + can make xwud do this for example. + + + Q-26: How do I figure out the window id to supply to the -id windowid + option? + + Run the xwininfo program in a terminal. It will ask you to click on + the desired application window. After clicking, it will print out much + information, including the window id (e.g. 0x6000010.) Also, the + visual and depth of the window printed out is often useful in + debugging x11vnc color problems. + + Also, as of Dec/2004 you can use "-id pick" to have x11vnc run + xwininfo(1) for you and after you click the window it extracts the + windowid. Besides "pick" there is also "id:root" to allow you to go + back to root window when doing remote-control. + + + Q-27: Why don't menus or other transient windows come up when I am + using the -id windowid option to view a single application window? + + This is related to the behavior of the XGetImage(3X11) and + XShmGetImage() interfaces regarding backingstore, saveunders, etc. The + way the image is retrieved depends on some aspects of how the X server + maintains the display image data and whether other windows are + clipping or obscuring it. See the XGetImage(3X11) man page for more + details. If you disable BackingStore and SaveUnders in the X server + you should be able to see these transient windows. + + If things are not working and you still want to do the single window + polling, try the -sid windowid option ("shifted" windowid.) + + Update: as of Nov/2009 in the 0.9.9 x11vnc development tarball, there + is an experimental Application Sharing mode that improves upon the + -id/-sid single window sharing: -appshare (run "x11vnc -appshare + -help" for more info.) It is still very primitive and approximate, but + at least it displays multiple top-level windows. + + + Q-28: My X display is depth 24 at 24bpp (instead of the normal depth + 24 at 32bpp.) I'm having lots of color and visual problems with x11vnc + and/or vncviewer. What's up? + + First off, depth 24 at 24bpp (bpp=bits-per-pixel) is fairly uncommon + and can cause problems in general. It also can be slower than depth 24 + at 32bpp. You might want to switch to 32bpp (for XFree86 see the + "-fbbpp 32", DefaultFbBpp, FbBpp and related options.) Perhaps you + have 24bpp because the video memory of the machine is low and the + screen wouldn't fit in video RAM at 32bpp. For this case depth 16 at + 16bpp might be an acceptable option. + + In any event x11vnc should handle depth 24 at 24bpp (although + performance may be slower, and you may need to use the ZRLE encoding + instead of Tight.) There are some caveats involving the viewer + however: + + The RealVNC Unix viewer cannot handle 24bpp from the server, it will + say: "main: setPF: not 8, 16 or 32 bpp?" and exit. I have not checked + the RealVNC Windows viewer. + + So you need to use the TightVNC Unix viewer. However there are some + problems with that too. It seems libvncserver does not do 24bpp + correctly with the Tight encoding. The colors and screen ultimately + get messed up. So you have to use a different encoding with the + TightVNC vncviewer, try "zlib", "hextile", or one of the other + encodings (e.g. vncviewer -encodings "zlib hextile" ....) I have not + checked the TightVNC or UltraVNC Windows viewers. + + It appears the older RealVNC Unix viewers (e.g. 3.3.3 and 3.3.7) can + handle 24bpp from the server, so you may want to use those. They + evidently request 32 bpp and libvncserver obliges. + + Update: as of Apr/2006 you can use the -24to32 option to have x11vnc + dynamically transform the 24bpp pixel data to 32bpp. This extra + transformation could slow things down further however. + + Now coming the opposite direction if you are running the vncviewer on + the 24bpp display, TightVNC will fail with "Can't cope with 24 + bits-per-pixel. Sorry." and RealVNC will fail with "main: Error: + couldn't find suitable pixmap format" so evidently you cannot use + 24bpp for the vncviewers to work on that X display. + + Note, however, that the Unix viewer in the Enhanced TightVNC Viewer + (SSVNC) project can handle 24bpp X displays. It does this by + requesting a 16bpp pixel format (or 8bpp if the -bgr233 option has + been supplied) from the VNC server, and translates that to 24bpp + locally. + [Xterminals] + + Q-29: Can I use x11vnc to view and interact with an Xterminal (e.g. + NCD) that is not running UNIX and so x11vnc cannot be run on it + directly? + + You can, but it will likely be very wasteful of network bandwidth + since you will be polling the X display over the network as opposed to + over the local hardware. To do this, run x11vnc on a UNIX machine as + close as possible network-wise (e.g. same switch) to the Xterminal + machine. Use the -display option to point the display to that of the + Xterminal (you'll of course need basic X11 permission to do that) and + finally supply the -noshm option (this enables the polling over the + network.) + + If the Xterminal's X display is open to the network for connections, + you might use something like "-display xterm123:0". If you are trying + to do this via an SSH tunnel (assuming you can actually ssh into the + Xterminal) it will be a little tricky (either use the ssh "-R" option + or consider ssh-ing in the other direction.) In all cases the X11 + permissions need to allow the connection. + + The response will likely be sluggish (maybe only one "frame" per + second.) This mode is not recommended except for "quick checks" of + hard to get to X servers. Use something like "-wait 150" to cut down + on the polling rate. You may also need -flipbyteorder if the colors + get messed up due to endian byte order differences. + + Q-30: How do I get my X permissions (MIT-MAGIC-COOKIE file) correct + for a Unix/Linux machine acting as an Xterminal? + + If the X display machine is a traditional Xterminal (where the X + server process runs on the Xterminal box, but all of the X client + applications (firefox, etc) run on a central server (aka "terminal + server")), you will need to log into the Xterminal machine (i.e. get a + shell running there) and then start the x11vnc program. If the + Xterminal Linux/Unix machine is stripped down (e.g. no users besides + root) that may be difficult. + + The next problem is the login Display Manager (e.g. gdm, kdm), and + hence the MIT-MAGIC-COOKIE auth files, are on the central server and + not on the Xterminal box where the X server and x11vnc processes are. + + So unless X permissions are completely turned off (e.g. "xhost +"), to + run the x11vnc process on the Xterminal box the MIT-MAGIC-COOKIE auth + file data (XAUTHORITY or $HOME/.Xauthority) must be accessible by or + copied to the Xterminal. If $HOME/.Xauthority is exported via NFS + (this is insecure of course, but has been going on for decades), then + x11vnc can simply pick it up via NFS (you may need to use the -auth + option to point to the correct file.) Other options include copying + the auth file using scp, or something like: + central-server> xauth nextract - xterm123:0 | ssh xterm123 xauth nmerge - + + and then, say, ssh from central-server to xterm123 to start x11vnc. + Here "xterm123" refers to the computer acting as the Xterminal and + "central-server" is the terminal server. You can use "xauth -f + /path/to/cookie-file list" to examine the contents of the cookie(s) in + a file "/path/to/cookie-file". See the xauth(1) manpage for more + details. + + If the display name in the cookie file needs to be changed between the + two hosts, see this note on the "xauth add ..." command. + + A less secure option is to run something like "xhost +127.0.0.1" while + sitting at the Xterminal box to allow cookie-free local access for + x11vnc. You can run "xhost -127.0.0.1" after x11vnc connects if you + want to go back to the original permissions. + + If the Xterminal is really stripped down and doesn't have any user + accounts, NFS, etc. you'll need to contact your system administrator + to set something up. It can be done!!! Some Xterminal projects have + actually enabled "run locally" facilities for the running of an + occasional app more efficiently locally on the Xterminal box (e.g. + realplayer.) + + Not recommended, but as a last resort, you could have x11vnc poll the + Xterminal Display over the network. For this you would run a "x11vnc + -noshm ..." process on the central-server (and hope the network admin + doesn't get angry...) + + Note: use of Display Manager (gdm, kdm, ...) auth cookie files (i.e. + from /var/..., /tmp/..., or elsewhere) may require modification via + xauth(1) to correctly include the display x11vnc refers to (e.g. + "xauth -f cookie-file add :0 . 45be51ae2ce9dfbacd882ab3ef8e96b1", + where the "45be51..." cookie value was found from an "xauth -f + /path/to/original/cookie-file list") or other reasons. See xauth(1) + manpage for full details on how to transfer an MIT-MAGIC-COOKIE + between machines and displays. + + VNCviewer performance on Xterminals: This isn't related to x11vnc on + Xterminals, but we mention it here anyway because of the similar + issues. If you are on an Xterminal and want to use vncviewer to + connect to a VNC server somewhere, then performance would be best if + you ran the viewer on the Xterminal box. Otherwise, (i.e. running the + viewer process on the central-server) all of the vncviewer screen + drawing is done more inefficiently over the network. Something to + consider, especially on a busy network. (BTW, this has all of the + above permission, etc, problems: both vncviewer and x11vnc are X + client apps desired to be run on the Xterminal box.) + + [Sun Rays] + + Q-31: I'm having trouble using x11vnc with my Sun Ray session. + + The Sun Ray technology is a bit like "VNC done in hardware" (the Sun + Ray terminal device, DTU, playing the role of the vncviewer.) + Completely independent of that, the SunRay user's session is still an + X server that speaks the X11 protocol and so x11vnc simply talks to + the X server part to export the SunRay desktop to any place in the + world (i.e. not only to a Sun Ray terminal device), creating a sort of + "Soft Ray". Please see this discussion of Sun Ray issues for solutions + to problems. + + Also see the Sun Ray Remote Control Toolkit that uses x11vnc. + + [Remote Control] + + Q-32: How do I stop x11vnc once it is running in the background? + + As of Dec/2004 there is a remote control feature. It can change a huge + number of parameters on the fly: see the -remote and -query options. + To shut down the running x11vnc server just type "x11vnc -R stop". To + disconnect all clients do "x11vnc -R disconnect:all", etc. + + If the -forever option has not been supplied, x11vnc will + automatically exit after the first client disconnects. In general if + you cannot use the remote control, then you will have to kill the + x11vnc process This can be done via: "kill NNNNN" (where NNNNN is the + x11vnc process id number found from ps(1)), or "pkill x11vnc", or + "killall x11vnc" (Linux only.) + + If you have not put x11vnc in the background via the -bg option or + shell & operator, then simply press Ctrl-C in the shell where x11vnc + is running to stop it. + + Potential Gotcha: If somehow your Keypress of Ctrl-C went through + x11vnc to the Xserver that then delivered it to x11vnc it is possible + one or both of the Ctrl or C keys will be left stuck in the pressed + down state in the Xserver. Tapping the stuck key (either via a new + x11vnc or at the physical console) will release it from the stuck + state. If the keyboard seems to be acting strangely it is often fixed + by tapping Ctrl, Shift, and Alt. Alternatively, the -clear_mods option + and -clear_keys option can be used to release pressed keys at startup + and exit. The option -clear_all will also try to unset Caps_Lock, + Num_Lock, etc. + + + Q-33: Can I change settings in x11vnc without having to restart it? + Can I remote control it? + + Look at the -remote (an alias is -R) and -query (an alias is -Q) + options added in Dec/2004. They allow nearly everything to be changed + dynamically and settings to be queried. Examples: "x11vnc -R shared", + "x11vnc -R forever", "x11vnc -R scale:3/4", "x11vnc -Q modtweak", + "x11vnc -R stop", "x11vnc -R disconnect:all", etc.. + + These commands do not start a x11vnc server, but rather communicate + with one that is already running. The X display (X11VNC_REMOTE + property) is used as the communication channel, so the X permissions + and DISPLAY must be set up correctly for communication to be possible. + + There is also a simple Tcl/Tk gui based on this remote control + mechanism. See the -gui option for more info. You will need to have + Tcl/Tk (i.e. /usr/bin/wish) installed for it to work. It can also run + in the system tray: "-gui tray" or as a standalone small icon window: + "-gui icon". Use "-gui tray=setpass" for a naive user "Share My + Desktop" mode. + + [Security and Permissions] + + Q-34: How do I create a VNC password for use with x11vnc? + + You may already have one in $HOME/.vnc/passwd if you have used, say, + the vncserver program from the regular RealVNC or TightVNC packages + (i.e. launching the Xvnc server.) Otherwise, you could use the + vncpasswd(1) program from those packages. + + As of Jun/2004 x11vnc supports the -storepasswd "pass" "file" option, + which is the same functionality of storepasswd. Be sure to quote the + "pass" if it contains shell meta characters, spaces, etc. Example: + x11vnc -storepasswd 'sword*fish' $HOME/myvncpasswd + + You then use the password via the x11vnc option: "-rfbauth + $HOME/myvncpasswd" + + As of Jan/2006 if you do not supply any arguments: + x11vnc -storepasswd + + you will be prompted for a password to save to ~/.vnc/passwd (your + keystrokes when entering the password will not be echoed to the + screen.) If you supply one argument, e.g. "x11vnc -storepasswd + ~/.mypass", the password you are prompted for will be stored in that + file. + + x11vnc also has the -passwdfile and -passwd/-viewpasswd plain text + (i.e. not obscured like the -rfbauth VNC passwords) password options. + + You can use the -usepw option to automatically use any password file + you have in ~/.vnc/passwd or ~/.vnc/passwdfile (the latter is used + with the -passwdfile option.) + + x11vnc -usepw -display :0 ... + + If neither file exists you are prompted to store a password in + ~/.vnc/passwd. If a password file cannot be found or created x11vnc + exits immediately. An admin may want to set it up this way for users + who do not know better. + + + Q-35: Can I make it so -storepasswd doesn't show my password on the + screen? + + You can use the vncpasswd program from RealVNC or TightVNC mentioned + above. As of Jan/2006 the -storepasswd option without any arguments + will not echo your password as you type it and save the file to + ~/.vnc/passwd: + # x11vnc -storepasswd + Enter VNC password: + Verify password: + Write password to /home/myname/.vnc/passwd? [y]/n + Password written to: /home/myname/.vnc/passwd + + You can also give it an alternate filename, e.g. "x11vnc -storepasswd + ~/.mypass" + + + Q-36: Can I have two passwords for VNC viewers, one for full access + and the other for view-only access to the display? + + Yes, as of May/2004 there is the -viewpasswd option to supply the + view-only password. Note the full-access password option -passwd must + be supplied at the same time. E.g.: -passwd sword -viewpasswd fish. + + To avoid specifying the passwords on the command line (where they + could be observed via the ps(1) command by any user) you can use the + -passwdfile option to specify a file containing plain text passwords. + Presumably this file is readable only by you, and ideally it is + located on the machine x11vnc is run on (to avoid being snooped on + over the network.) The first line of this file is the full-access + password. If there is a second line in the file and it is non-blank, + it is taken as the view-only password. (use "__EMPTY__" to supply an + empty one.) + + View-only passwords currently do not work for the -rfbauth password + option (standard VNC password storing mechanism.) FWIW, note that + although the output (usually placed in $HOME/.vnc/passwd) by the + vncpasswd or storepasswd programs (or from x11vnc -storepasswd) looks + encrypted they are really just obscured to avoid "casual" password + stealing. It takes almost no skill to figure out how to extract the + plain text passwords from $HOME/.vnc/passwd since it is very + straight-forward to work out what to do from the VNC source code. + + + Q-37: Can I have as many full-access and view-only passwords as I + like? + + Yes, as of Jan/2006 in the libvncserver CVS the -passwdfile option has + been extended to handle as many passwords as you like. You put the + view-only passwords after a line __BEGIN_VIEWONLY__. + + You can also easily annotate and comment out passwords in the file. + You can have x11vnc re-read the file dynamically when it is modified. + + + Q-38: Does x11vnc support Unix usernames and passwords? Can I further + limit the set of Unix usernames who can connect to the VNC desktop? + Update: as of Feb/2006 x11vnc has the -unixpw option that does this + outside of the VNC protocol and libvncserver. The standard su(1) + program is used to validate the user's password. A familiar "login:" + and "Password:" dialog is presented to the user on a black screen + inside the vncviewer. The connection is dropped if the user fails to + supply the correct password in 3 tries or does not send one before a + 25 second timeout. Existing clients are view-only during this period. + A list of allowed Unix usernames may also be supplied along with + per-user settings. + + There is also the -unixpw_nis option for non-shadow-password + (typically NIS environments, hence the name) systems where the + traditional getpwnam() and crypt() functions are used instead of + su(1). The encrypted user passwords must be accessible to the user + running x11vnc in -unixpw_nis mode, otherwise the logins will always + fail even when the correct password is supplied. See ypcat(1) and + shadow(5). + + Two settings are enforced in the -unixpw and -unixpw_nis modes to + provide extra security: the 1) -localhost and 2) -stunnel or -ssl + options. Without these one might send the Unix username and password + data in clear text over the network which is a very bad idea. They can + be relaxed if you want to provide encryption other than stunnel or + -ssl (the constraint is automatically relaxed if SSH_CONNECTION is set + and indicates you have ssh-ed in, however the -localhost requirement + is still enforced.) + + The two -unixpw modes have been tested on Linux, Solaris, Mac OS X, + HP-UX, AIX, Tru64, FreeBSD, OpenBSD, and NetBSD. Additional testing is + appreciated. For the last 4 it appears that su(1) will not prompt for + a password if su-ing to oneself. Since x11vnc requires a password + prompt from su, x11vnc forces those logins to fail even when the + correct password is supplied. On *BSD it appears this can be corrected + by removing the pam_self.so entry in /etc/pam.d/su. + + + Previous older discussion (prior to the -unixpw option): + + Until the VNC protocol and libvncserver support this things will be + approximate at best. + + One approximate method involves starting x11vnc with the -localhost + option. This basically requires the viewer user to log into the + workstation where x11vnc is running via their Unix username and + password, and then somehow set up a port redirection of his vncviewer + connection to make it appear to emanate from the local machine. As + discussed above, ssh is useful for this: "ssh -L 5900:localhost:5900 + user@hostname ..." See the ssh wrapper scripts mentioned elsewhere on + this page. stunnel does this as well. + + Of course a malicious user could allow other users to get in through + his channel, but that is a problem with every method. Another thing to + watch out for is a malicious user on the viewer side (where ssh is + running) trying to sneak in through the ssh port redirection there. + + Regarding limiting the set of Unix usernames who can connect, the + traditional way would be to further require a VNC password to supplied + (-rfbauth, -passwd, etc) and only tell the people allowed in what the + VNC password is. A scheme that avoids a second password involves using + the -accept option that runs a program to examine the connection + information to determine which user is connecting from the local + machine. That may be difficult to do, but, for example, the program + could use the ident service on the local machine (normally ident + should not be trusted over the network, but on the local machine it + should be accurate: otherwise root has been compromised and so there + are more serious problems! Unfortunately recent Linux distros seem to + provide a random string (MD5 hash?) instead of the username.) An + example script passed in via -accept scriptname that deduces the Unix + username and limits who can be accepted might look something like + this: +#!/bin/sh +if [ "$RFB_CLIENT_IP" != "127.0.0.1" -o "$RFB_SERVER_IP" != "127.0.0.1" ]; then + exit 1 # something fishy... reject it. +fi +user=`echo "$RFB_CLIENT_PORT, $RFB_SERVER_PORT" | nc -w 1 $RFB_CLIENT_IP 113 \ + | grep 'USERID.*UNIX' | head -1 | sed -e 's/[\r ]//g' | awk -F: '{print + $4}'` + +for okuser in fred barney wilma betty +do + if [ "X$user" = "X$okuser" ]; then + exit 0 # accept it + fi +done +exit 1 # reject it + + For this to work with ssh port redirection, the ssh option + UsePrivilegeSeparation must be enabled otherwise the userid will + always be "root". + + + Q-39: Can I supply an external program to provide my own custom login + method (e.g. Dynamic/One-time passwords or non-Unix (LDAP) usernames + and passwords)? + Yes, there are several possibilities. For background see the FAQ on + the -accept where an external program may be run to decide if a VNC + client should be allowed to try to connect and log in. If the program + (or local user prompted by a popup) answers "yes", then -accept + proceeds to the normal VNC and x11vnc authentication methods, + otherwise the connection is dropped. + + To provide more direct coupling to the VNC client's username and/or + supplied password the following options were added in Sep/2006: + * -unixpw_cmd command + * -passwdfile cmd:command + * -passwdfile custom:command + + In each case "command" is an external command run by x11vnc. You + supply it. For example, it may couple to your LDAP system or other + servers you set up. + + For -unixpw_cmd the normal -unixpw Login: and Password: prompts are + supplied to the VNC viewer and the strings the client returns are then + piped into "command" as the first two lines of its standard input. If + the command returns success, i.e. exit(0), the VNC client is accepted, + otherwise it is rejected. + + For "-passwdfile cmd:command" the command is run and it returns a + password list (like a password file, see the -passwdfile read:filename + mode.) Perhaps a dynamic, one-time password is retrieved from a server + this way. + + For "-passwdfile custom:command" one gets complete control over the + VNC challenge-response dialog with the VNC client. x11vnc sends out a + string of random bytes (16 by the VNC spec) and the client returns the + same number of bytes in a way the server can verify only the + authorized user could have created. The VNC protocol specifies DES + encryption with a password. If you are willing to modify the VNC + viewers, you can have it be anything you want, perhaps a less + crackable MD5 hash scheme or one-time pad. Your program will read from + its standard input the size of the challenge-response followed by a + newline, then the challenge bytes followed by the response bytes. If + your command then returns success, i.e. exit(0), the VNC client is + accepted, otherwise it is rejected. + + In all cases the "RFB_*" environment variables are set as under + -accept. These variables can provide useful information for the + externally supplied program to use. + + + Q-40: Why does x11vnc exit as soon as the VNC viewer disconnects? And + why doesn't it allow more than one VNC viewer to connect at the same + time? + + These defaults are simple safety measures to avoid someone unknowingly + leaving his X11 desktop exposed (to the internet, say) for long + periods of time. Use the -forever option (aka -many) to have x11vnc + wait for more connections after the first client disconnects. Use the + -shared option to have x11vnc allow multiple clients to connect + simultaneously. + + Recommended additional safety measures include using ssh (see above), + stunnel, -ssl, or a VPN to authenticate and encrypt the viewer + connections or to at least use the -rfbauth passwd-file option to use + VNC password protection (or -passwdfile) It is up to YOU to apply + these security measures, they will not be done for you automatically. + + + Q-41: Can I limit which machines incoming VNC clients can connect + from? + + Yes, look at the -allow and -localhost options to limit connections by + hostname or IP address. E.g. + x11vnc -allow 192.168.0.1,192.168.0.2 + + for those two hosts or + x11vnc -allow 192.168.0. + + for a subnet. For individual hosts you can use the hostname instead of + the IP number, e.g.: "-allow snoopy", and "-allow darkstar,wombat". + Note that -localhost achieves the same thing as "-allow 127.0.0.1" + + For more control, build libvncserver with libwrap support + (tcp_wrappers) and then use /etc/hosts.allow See hosts_access(5) for + complete details. + + + Q-42: How do I build x11vnc/libvncserver with libwrap (tcp_wrappers) + support? + + Here is one way to pass this information to the configure script: + env CPPFLAGS=-DUSE_LIBWRAP LDFLAGS=-lwrap ./configure + + then run make as usual. This requires libwrap and its development + package (tcpd.h) to be installed on the build machine. If additional + CPPFLAGS or LDFLAGS options are needed supply them as well using + quotes. + + The resulting x11vnc then uses libwrap/tcp_wrappers for connections. + The service name you will use in /etc/hosts.allow and /etc/hosts.deny + is "vnc", e.g.: + vnc: 192.168.100.3 .example.com + + Note that if you run x11vnc out of inetd you do not need to build + x11vnc with libwrap support because the /usr/sbin/tcpd reference in + /etc/inetd.conf handles the tcp_wrappers stuff. + + + Q-43: Can I have x11vnc only listen on one network interface (e.g. + internal LAN) rather than having it listen on all network interfaces + and relying on -allow to filter unwanted connections out? + + As of Mar/2005 there is the "-listen ipaddr" option that enables this. + For ipaddr either supply the desired network interface's IP address + (or use a hostname that resolves to it) or use the string "localhost". + For additional filtering simultaneously use the "-allow host1,..." + option to allow only specific hosts in. + + This option is useful if you want to insure that no one can even begin + a dialog with x11vnc from untrusted network interfaces (e.g. ppp0.) + The option -localhost now implies "-listen localhost" since that is + what most people expect it to do. + + + Q-44: Now that -localhost implies listening only on the loopback + interface, how I can occasionally allow in a non-localhost via the -R + allowonce remote control command? + + To do this specify "-allow localhost". Unlike -localhost this will + leave x11vnc listening on all interfaces (but of course only allowing + in local connections, e.g. ssh redirs.) Then you can later run "x11vnc + -R allowonce:somehost" or use to gui to permit a one-shot connection + from a remote host. + + + Q-45: Can I fine tune what types of user input are allowed? E.g. have + some users just be able to move the mouse, but not click or type + anything? + + As of Feb/2005, the -input option allows you to do this. "K", "M", + "B", "C", and "F" stand for Keystroke, Mouse-motion, Button-clicks, + Clipboard, and File-Transfer, respectively. The setting: "-input M" + makes attached viewers only able to move the mouse. "-input KMBC,M" + lets normal clients do everything and enables view-only clients to + move the mouse. + + These settings can also be applied on a per-viewer basis via the + remote control mechanism or the GUI. E.g. x11vnc -R input:hostname:M + + + Q-46: Can I prompt the user at the local X display whether the + incoming VNC client should be accepted or not? Can I decide to make + some clients view-only? How about running an arbitrary program to make + the decisions? + + Yes, look at the "-accept command" option, it allows you to specify an + external command that is run for each new client. (use quotes around + the command if it contains spaces, etc.) If the external command + returns 0 (success) the client is accepted, otherwise with any other + return code the client is rejected. See below how to also accept + clients view-only. + + The external command will have the RFB_CLIENT_IP environment variable + set to the client's numerical IP address, RFB_CLIENT_PORT its port + number. Similarly for RFB_SERVER_IP and RFB_SERVER_PORT to allow + identification of the tcp virtual circuit. DISPLAY will be set to that + of the X11 display being polled. Also, RFB_X11VNC_PID is set to the + x11vnc process id (e.g. in case you decided to kill it), RFB_CLIENT_ID + will be an id number, and RFB_CLIENT_COUNT the number of other clients + currently connected. RFB_MODE will be "accept". + + Built-in Popup Window: As a special case, "-accept popup" will + instruct x11vnc to create its own simple popup window. To accept the + client press "y" or click mouse on the "Yes" button. To reject the + client press "n" or click mouse on the "No" button. To accept the + client View-only, press "v" or click mouse on the "View" button. If + the -viewonly option has been supplied, the "View" action will not be + present: the whole display is view only in that case. + + The popup window times out after 120 seconds, to change this behavior + use "-accept popup:N" where N is the number of seconds (use 0 for no + timeout.) More tricks: "-accept popupmouse" will only take mouse click + responses, while "-accept popupkey" will only take keystroke responses + (popup takes both.) After any of the 3 popup keywords you can supply a + position of the window: +N+M, (the default is to center the window) + e.g. -accept popupmouse+10+10. + + Also as a special case "-accept xmessage" will run the xmessage(1) + program to prompt the user whether the client should be accepted or + not. This requires that you have xmessage installed and available via + PATH. In case it is not already on your system, the xmessage program + is available at ftp://ftp.x.org/ + (End of Built-in Popup Window:) + + To include view-only decisions for the external commands, prefix the + command something like this: "yes:0,no:*,view:3 mycommand ..." This + associates the three actions: yes(accept), no(reject), and + view(accept-view-only), with the numerical return (i.e. exit()) codes. + Use "*" instead of a number to set the default action (e.g. in case + the external command returns an unexpected return code.) + + Here is an example -accept script called accept_or_lock. It uses + xmessage and xlock (replace with your screen lock command, maybe it is + "xscreensaver-command -lock", or kdesktop_lock, or "dtaction + LockDisplay".) It will prompt the user at the X display whether to + accept, reject, or accept view-only the client, but if the prompt + times out after 60 seconds the screen is locked and the VNC client is + accepted. This allows the remote access when no one is at the display. +#!/bin/sh +# +# accept_or_lock: prompt user at X display whether to accept an incoming +# VNC connection. If timeout expires, screen is locked +# and the VNC viewer is accepted (allows remote access +# when no one is sitting at the display.) +# +# usage: x11vnc ... -forever -accept 'yes:0,no:*,view:4 accept_or_lock' +# +xmessage -buttons yes:2,no:3,view-only:4 -center \ + -timeout 60 "x11vnc: accept connection from $RFB_CLIENT_IP?" +rc=$? +if [ $rc = 0 ]; then + xlock & # or "xlock -mode blank" for no animations. + sleep 5 + exit 0 +elif [ $rc = 2 ]; then + exit 0 +elif [ $rc = 4 ]; then + exit 4 +fi +exit 1 + + Stefan Radman has written a nice dtksh script dtVncPopup for use in + CDE environments to do the same sort of thing. Information on how to + use it is found at the top of the file. He encourages you to provide + feedback to him to help improve the script. + + Note that in all cases x11vnc will block while the external command or + popup is being run, so attached clients will not receive screen + updates, etc during this period. + + To run a command when a client disconnects, use the "-gone command" + option. This is for the user's convenience only: the return code of + the command is not interpreted by x11vnc. The same environment + variables are set as in "-accept command" (except that RFB_MODE will + be "gone".) + + As of Jan/2006 the "-afteraccept command" option will run the command + only after the VNC client has been accepted and authenticated. Like + -gone the return code is not interpreted. RFB_MODE will be + "afteraccept".) + + + Q-47: I start x11vnc as root because it is launched via inetd(8) or a + display manager like gdm(1). Can I have x11vnc later switch to a + different user? + + As of Feb/2005 x11vnc has the -users option that allows things like + this. Please read the documentation on it (also in the x11vnc -help + output) carefully for features and caveats. It's use can often + decrease security unless care is taken. + + BTW, a nice use of it is "-users +nobody" that switches to the Unix + user nobody right after connections to the X display are established. + + In any event, while running x11vnc as root, remember it comes with no + warranty ;-). + + + Q-48: I use a screen-lock when I leave my workstation (e.g. + xscreensaver or xlock.) When I remotely access my workstation desktop + via x11vnc I can unlock the desktop fine, but I am worried people will + see my activities on the physical monitor. What can I do to prevent + this, or at least make it more difficult? + + Probably most work environments would respect your privacy if you + powered off the monitor. Also remember if people have physical access + to your workstation they basically can do anything they want with it + (e.g. install a backdoor for later use, etc.) + + In any event, as of Jun/2004 there is an experimental utility to make + it more difficult for nosey people to see your x11vnc activities. The + source for it is blockdpy.c The idea behind it is simple (but + obviously not bulletproof): when a VNC client attaches to x11vnc put + the display monitor in the DPMS "off" state, if the DPMS state ever + changes immediately start up the screen-lock program. The x11vnc user + will notice something is happening and think about what to do next + (while the screen is in a locked state.) + + This works (or at least has a chance of working) because if the + intruder moves the mouse or presses a key on the keyboard, the monitor + wakes up out of the DPMS off state, and this induces the screen lock + program to activate as soon as possible. Of course there are cracks in + this, the eavesdropper could detach your monitor and insert a non-DPMS + one, and there are race conditions. As mentioned above this is not + bulletproof. A really robust solution would likely require X server + and perhaps even video hardware support. + + The blockdpy utility is launched by the -accept option and told to + exit via the -gone option (the vnc client user should obviously + re-lock the screen before disconnecting!) Instructions can be found in + the source code for the utility at the above link. Roughly it is + something like this: + x11vnc ... -accept "blockdpy -bg -f $HOME/.bdpy" -gone "touch $HOME/.bdpy" + + but please read the top of the file. + + Update: As of Feb/2007 there is some builtin support for this: + -forcedpms and -clientdpms however, they are probably less robust than + the above blockdpy.c scheme, since if the person floods the physical + machine with mouse or pointer input he can usually see flashes of the + screen before the monitor is powered off again. See also the -grabkbd, + -grabptr, and -grabalways options. + + + Q-49: Can I have x11vnc automatically lock the screen when I + disconnect the VNC viewer? + + Yes, a user mentions he uses the -gone option under CDE to run a + screen lock program: + x11vnc -display :0 -forever -gone 'dtaction LockDisplay' + + Other possibilities are: + x11vnc -display :0 -forever -gone 'xscreensaver-command -lock' + x11vnc -display :0 -forever -gone 'kdesktop_lock' + x11vnc -display :0 -forever -gone 'xlock &' + x11vnc -display :0 -forever -gone 'xlock -mode blank &' + + Here is a scheme using the -afteraccept option (in version 0.8) to + unlock the screen after the first valid VNC login and to lock the + screen after the last valid VNC login disconnects: + x11vnc -display :0 -forever -shared -afteraccept ./myxlocker -gone ./myxlocke +r + + Where the script ./myxlocker is: +#!/bin/sh + +#/usr/bin/env | grep RFB_ | sort # for viewing RFB_* settings. + +if [ "X$RFB_MODE" = "Xafteraccept" ]; then + if [ "X$RFB_STATE" = "XNORMAL" ]; then # require valid login + if [ "X$RFB_CLIENT_COUNT" = "X1" ]; then + killall xlock # Linux only. + fi + fi +elif [ "X$RFB_MODE" = "Xgone" ]; then + if [ "X$RFB_STATE" = "XNORMAL" ]; then # require valid login + if [ "X$RFB_CLIENT_COUNT" = "X0" ]; then + xlock -mode blank & + fi + fi +fi + + Note the xlock option "-mode blank" to avoid animations. + + There is a problem if you have x11vnc running this way in -forever + mode and you hit Ctrl-C to stop it. The xlock (or other program) will + get killed too. To work around this make a little script called + setpgrp that looks like: +#!/usr/bin/perl +setpgrp(0, 0); +exec @ARGV; + + then use -gone "setpgrp xlock &", etc. + [Encrypted Connections] + + Q-50: How can I tunnel my connection to x11vnc via an encrypted SSH + channel between two Unix machines? + + See the description earlier on this page on how to tunnel VNC via SSH + from Unix to Unix. A number of ways are described along with some + issues you may encounter. + + Other secure encrypted methods exists, e.g. stunnel, IPSEC, various + VPNs, etc. + + See also the Enhanced TightVNC Viewer (SSVNC) page where much of this + is now automated. + + + Q-51: How can I tunnel my connection to x11vnc via an encrypted SSH + channel from Windows using an SSH client like Putty? + + Above we described how to tunnel VNC via SSH from Unix to Unix, you + may want to review it. To do this from Windows using Putty it would go + something like this: + * In the Putty dialog window under 'Session' enter the hostname or + IP number of the Unix machine with display to be viewed. + * Make sure the SSH protocol is selected and the server port is + correct. + * Under 'Connections/SSH/Tunnels' Add a Local connection with + 'Source port: 5900' and 'Destination: localhost:5900' + * Log into the remote machine by pressing 'Open' and supplying + username, password, etc. + * In that SSH shell, start up x11vnc by typing the command: x11vnc + -display :0 plus any other desired options (e.g. -localhost.) + * Finally, start up your VNC Viewer in Windows and enter + 'localhost:0' as the VNC server. + + You can keep all of the settings in a Putty 'Saved Session'. Also, + once everything is working, you can consider putting x11vnc -display + :0 (plus other cmdline options) in the 'Remote command' Putty setting + under 'Connections/SSH'. + + See also the Enhanced TightVNC Viewer (SSVNC) page where much of this + is now automated via the Putty plink utility. + + For extra protection feel free to run x11vnc with the -localhost and + -rfbauth/-passwdfile options. + + If the machine you SSH into via Putty is not the same machine with the + X display you wish to view (e.g. your company provides incoming SSH + access to a gateway machine), then you need to change the above Putty + dialog setting to: 'Destination: otherhost:5900', Once logged in, + you'll need to do a second login (ssh or rsh) to the workstation + machine 'otherhost' and then start up x11vnc on it. This can also be + automated by Chaining SSH's. + + As discussed above another option is to first start the VNC viewer in + "listen" mode, and then launch x11vnc with the "-connect localhost" + option to establish the reverse connection. In this case a Remote port + redirection (not Local) is needed for port 5500 instead of 5900 (i.e. + 'Source port: 5500' and 'Destination: localhost:5500' for a Remote + connection.) + + + Q-52: How can I tunnel my connection to x11vnc via an encrypted SSL + channel using an external tool like stunnel? + + It is possible to use a "lighter weight" encryption setup than SSH or + IPSEC. SSL tunnels such as stunnel (also stunnel.org) provide an + encrypted channel without the need for Unix users, passwords, and key + passphrases required for ssh (and at the other extreme SSL can also + provide a complete signed certificate chain of trust.) On the other + hand, since SSH is usually installed everywhere and firewalls often + let its port through, ssh is frequently the path of least resistance + (it also nicely manages public keys for you.) + + Update: As of Feb/2006 x11vnc has the options -ssl, -stunnel, and + -sslverify to provide integrated SSL schemes. They are discussed in + the Next FAQ (you probably want to skip to it now.) + + We include these non-built-in method descriptions below for historical + reference. They are handy because can be used to create SSL tunnels to + any VNC (or other type of) server. + + + Here are some basic examples using stunnel but the general idea for + any SSL tunnel utility is the same: + * Start up x11vnc and constrain it to listen on localhost. + * Then start up the SSL tunnel running on the same machine to + forward incoming connections to that x11vnc. + * Set up and run a similar SSL tunnel for the outgoing connection on + the VNC viewer machine pointing it to the SSL/x11vnc server. + * Optionally, set up server (or even client) public/private keys for + use in authenticating one side to the other. + * Finally, start the VNC Viewer and tell it to connect to the local + port (e.g. a vnc display localhost:0) where its outgoing SSL + tunnel is listening. + + We'll first use the stunnel version 3 syntax since it is the most + concise and Unixy. + + Start up x11vnc listening on port 5900: + x11vnc -display :0 -rfbport 5900 -localhost -bg -passwdfile ~/mypass + + Then start stunnel (version 3, not 4) with this command: + stunnel -d 5901 -r 5900 -p /path/to/stunnel.pem + + The above two commands are run on host "far-away.east". The + stunnel.pem is the self-signed PEM file certificate created when + stunnel is built. One can also create certificates signed by + Certificate Authorities or self-signed if desired using the x11vnc + utilities described there. + + SSL Viewers: Next, on the VNC viewer side we need an SSL tunnel to + encrypt the outgoing connection. The nice thing is any SSL tunnel can + be used because the protocol is a standard. For this example we'll + also use stunnel on the viewer side on Unix. First start up the + client-side stunnel (version 3, not 4): + stunnel -c -d localhost:5902 -r far-away.east:5901 + + Then point the viewer to the local tunnel on port 5902: + vncviewer -encodings "copyrect tight zrle hextile" localhost:2 + + That's it. Note that the ss_vncviewer script can automate this + easily, and so can the Enhanced TightVNC Viewer (SSVNC) package. + + Be sure to use a VNC password because unlike ssh by default the + encrypted SSL channel provides no authentication (only privacy.) With + some extra configuration one could also set up certificates to provide + authentication of either or both sides as well (and hence avoid + man-in-the-middle attacks.) See the stunnel and openssl documentation + and also the key management section for details. + + stunnel has also been ported to Windows, and there are likely others + to choose from for that OS. Much info for using it on Windows can be + found at the stunnel site and in this article The article also shows + the detailed steps to set up all the authentication certificates. (for + both server and clients, see also the x11vnc utilities that do this.) + The default Windows client setup (no certs) is simpler and only 4 + files are needed in a folder: stunnel.exe, stunnel.conf, libssl32.dll, + libeay32.dll. We used an stunnel.conf containing: +# stunnel.conf: +client = yes +options = ALL +[myvncssl] +accept = localhost:5902 +connect = far-away.east:5901 + + then double click on the stunnel.exe icon to launch it (followed by + pointing the VNC viewer to localhost:2). + + + stunnel inetd-like mode: + + As an aside, if you don't like the little "gap" of unencrypted TCP + traffic (and a localhost listening socket) on the local machine + between stunnel and x11vnc it can actually be closed by having stunnel + start up x11vnc in -inetd mode: + stunnel -p /path/to/stunnel.pem -P none -d 5900 -l ./x11vnc_sh + + Where the script x11vnc_sh starts up x11vnc: +#!/bin/sh +x11vnc -q -inetd -display :0 -passwdfile ~/mypass + + Note that this creates a separate x11vnc process for each incoming + connection (as any inetd x11vnc usage would), but for the case of + normally just one viewer at a time it should not be a big problem. + + + stunnel 4 syntax: + + Somewhat sadly, the stunnel version 4 syntax is not so amenable to the + command line or scripts. You need to create a config file with the + parameters. E.g.: + stunnel x11vnc.cfg + + Where the file x11vnc.cfg contains: +foreground = yes +pid = +cert = /path/to/stunnel.pem +[x11vnc_stunnel] +accept = 5901 +connect = 5900 + + One nice thing about version 4 is often the PEM file does not need to + be specified because stunnel finds it in its installed area. One other + gotcha the PEM file is usually only readable by root (it has the + private key afterall), so you'll need to relax the permissions or make + a copy that the user running x11vnc/stunnel can read. + + + SSL VNC Viewers: + + Regarding VNC viewers that "natively" do SSL unfortunately there do + not seem to be many. The SingleClick UltraVNC Java Viewer is SSL and + is compatible with x11vnc's -ssl option and stunnel.) Commercial + versions of VNC seem to have some SSL-like encryption built in, but we + haven't tried those either and they probably wouldn't work since their + (proprietary) SSL-like negotiation is likely embedded in the VNC + protocol unlike our case where it is external. + + Note: as of Mar/2006 libvncserver/x11vnc provides a SSL-enabled Java + applet that can be served up via the -httpdir or -http options when + -ssl is enabled. It will also be served via HTTPS via either the VNC + port (e.g. https://host:5900/) or a 2nd port via the -https option. + + In general current SSL VNC solutions are not particularly "seemless". + But it can be done, and with a wrapper script on the viewer side and + the -stunnel or -ssl option on the server side it works well and is + convenient. Here is a simple script ss_vncviewer that automates + running stunnel on the VNC viewer side on Unix a little more carefully + than the commands printed above. (One could probably do a similar + thing with a .BAT file on Windows in the stunnel folder.) + + Update Jul/2006: we now provide an Enhanced TightVNC Viewer (SSVNC) + package that starts up STUNNEL automatically along with some other + features. All binaries (stunnel, vncviewer, and some utilities) are + provided in the package. It works on Unix, Mac OS X, and Windows. + + + Q-53: Does x11vnc have built-in SSL tunneling? + + You can read about non-built-in methods in the Previous FAQ for + background. + + SSL tunnels provide an encrypted channel without the need for Unix + users, passwords, and key passphrases required for ssh (and at the + other extreme SSL can also provide a complete signed certificate chain + of trust.) On the other hand, since SSH is usually installed + everywhere and firewalls often let its port through, ssh is frequently + the path of least resistance. + + Built-in SSL x11vnc options: + + As of Feb/2006 the x11vnc -ssl option automates the SSL tunnel + creation on the x11vnc server side. An SSL-enabled Java Viewer applet + is also provided that can be served via HTTP or HTTPS to automate SSL + on the client side. + + The -ssl mode uses the www.openssl.org library if available at build + time. + + The mode requires an SSL certificate and key (i.e. .pem file.) These + are usually created via the openssl(1) program (in fact in for "-ssl" + (same as "-ssl SAVE") it will run openssl for you automatically.) So + the SSL is not completely "built-in" since this external tool needs to + be installed, but at least x11vnc runs it for you automatically. + + An -ssl example: + x11vnc -display :0 -ssl -passwdfile ~/mypass + + You'll get output like this: + 09/04/2006 19:27:35 Creating a self-signed PEM certificate... + 09/04/2006 19:27:35 + ... + + The SSL VNC desktop is: far-away.east:0 + PORT=5900 + SSLPORT=5900 + + In this case openssl(1) was used to create a PEM automatically. It + will prompt you if you want to protect it with with a passphrase. Use + "-ssl SAVE_NOPROMPT" to not be prompted. Use "-ssl TMP" to create a + temporary self-signed cert that will be discarded when x11vnc exits. + + Update: As of Nov/2008 x11vnc also supports the VeNCrypt SSL/TLS + tunnel extension to the VNC protocol. The older ANONTLS method (vino) + is also supported. This support is on by default when the -ssl option + is in use and can be fine-tuned using these options: -vencrypt, + -anontls, and -sslonly. + + The normal x11vnc -ssl operation is somewhat like a URL method + vncs://hostname if vnc://hostname indicates a standard unencrypted VNC + connection. Just as https://hostname is an SSL encrypted version of + http://hostname. The entire VNC session goes through the SSL tunnel. + VeNCrypt, on the other hand, switches to SSL/TLS early in the VNC + protocol handshake. x11vnc 0.9.6 supports both simultaneously when + -ssl is active. + + + SSL VNC Viewers:. Viewer-side will need to use SSL as well. See the + next FAQ and here for SSL enabled VNC Viewers, including SSVNC, to + connect to the above x11vnc via SSL. + + + As seen above, the PEM (privacy enhanced mail) file does not need to + be supplied if the openssl(1) command is available in PATH, in that + case a self-signed, certificate good the current and subsequent x11vnc + sessions is created (this may take a while on very slow machines.) + + In general, the PEM file contains both the Certificate (i.e. public + key) and the Private Key. Because of the latter, the file should be + protected from being read by untrusted users. The best way to do this + is to encrypt the key with a passphrase (note however this requires + supplying the passphrase each time x11vnc is started up.) + + See the discussion on x11vnc Key Management for some utilities + provided for creating and managing certificates and keys and even for + creating your own Certificate Authority (CA) for signing VNC server + and client certificates. This may be done by importing the certificate + into Web Browser or Java plugin keystores, or pointing stunnel to it. + The wrapper script ss_vncviewer provides an example on unix (see the + -verify option.) + + Here are some notes on the simpler default (non-CA) operation. To have + x11vnc save the generated certificate and key, use the "SAVE" keyword + like this: + x11vnc -ssl SAVE -display :0 ... + + (this is the same as the default: "-ssl".) This way it will be saved + in the default directory ~/.vnc/certs/ as server.crt (the certificate + only) and server.pem (both certificate and private key.) This opens up + the possibility of copying the server.crt to machines where the VNC + Viewer will be run to enable authenticating the x11vnc SSL VNC server + to the clients. When authentication takes place this way (or via the + more sophisticated CA signing described here), then + Man-In-The-Middle-Attacks are prevented. Otherwise, the SSL encryption + only provides protection against passive network traffic "sniffing" + (i.e. you are not protected against M-I-T-M attacks.) Nowadays, most + people seem mostly concerned mainly about passive sniffing (and the + default x11vnc SSL mode protects against it.) Note that there are + hacker tools like dsniff/webmitm and cain that implement SSL + Man-In-The-Middle attacks. They rely on the client not bothering to + check the cert. + + + One can test to some degree that SSL is working after starting x11vnc + with the -stunnel or -ssl option. From another machine one can use the + openssl command something like this: + openssl s_client -debug -msg -showcerts -connect far-away.east:5900 + + After all of the debugging output and informational messages you'll + see the string "RFB 003.008" that came from x11vnc. Pointing a web + browser connecting to: https://far-away.east:5900/ and then viewing + the SSL certificate information about the connection in the panels + will also work. + + Note: If you serve up the SSL enabled Java VNC Viewer via something + like: + x11vnc -ssl -httpdir /usr/local/share/x11vnc/classes/ssl + + (or just the -http option), you can test it out completely using that, + including using https to download it into the browser and connect to + x11vnc. + + + The older -stunnel option: Before the -ssl option there was a + convenience option -stunnel that would start an external SSL tunnel + for you using stunnel. The -ssl method is the preferred way, but for + historical reference we keep the -stunnel info here. + + The -stunnel mode requires the stunnel.mirt.net command stunnel(8) to + be installed on the system. + + Some -stunnel examples: + x11vnc -display :0 -stunnel /path/to/stunnel.pem -passwdfile ~/mypass + + x11vnc -display :0 -stunnel SAVE ... + + You'll get output like this: + The VNC desktop is: localhost:50 + The SSL VNC desktop is: far-away.east:0 + PORT=5950 + SSLPORT=5900 + + That indicates stunnel is listening on port 5900 for incoming + SSL-wrapped VNC connections from viewers. x11vnc is listening for + local connections on port 5950 in this case (remote viewers cannot + connect to it directly.) For -stunnel to work the stunnel command must + be installed on the machine and available in PATH (note stunnel is + often installed in sbin directories rather than bin.) Note that the + default "-stunnel" by itself creates a temporary cert (as in "-ssl + TMP".) + + + Q-54: How do I use VNC Viewers with built-in SSL tunneling? + + Notes on using "native" VNC Viewers with SSL: + + There aren't any native VNC Viewers that do SSL (ask your VNC viewer + developer to add the feature.) So a tunnel must be setup that you + point the VNC Viewer to. This is often STUNNEL. You can do this + manually, or use the ss_vncviewer script on Unix, or our Enhanced + TightVNC Viewer (SSVNC) package on Unix, Windows, or MacOSX. See the + next section for Java Web browser SSL VNC Viewers (you only need a + Java-enabled Web browser for it to work.) + + Notes on the SSL enabled Java VNC Viewer provided in x11vnc + classes/ssl/VncViewer.jar: + + A Java applet VNC Viewer allows you to connect to a VNC Server from a + Java-enabled Web browser. + + The SSL enabled Java VNC Viewer (VncViewer.jar) in the x11vnc package + supports only SSL based connections by default. As mentioned above the + -httpdir can be used to specify the path to .../classes/ssl. A typical + location might be /usr/local/share/x11vnc/classes/ssl. Or -http can be + used to try to have it find the directory automatically. + + Also note that the SingleClick UltraVNC Java Viewer is compatible with + x11vnc's -ssl SSL mode. (We tested it this way: "java -cp + ./VncViewer.jar VncViewer HOST far-away.east PORT 5900 USESSL 1 + TRUSTALL 1") + + The Java viewer uses SSL to communicate securely with x11vnc. Note + that the applet can optionally also be downloaded into your web + browser via HTTPS (which is HTTP over SSL.) This way the HTML page and + the Java applet itself are also delivered securely with SSL (as + opposed to only the VNC traffic being encrypted with SSL.) + + For this case the output will be something like this: + x11vnc -ssl SAVE -http + ... + The SSL VNC desktop is: far-away.east:0 + Java SSL viewer URL: https://far-away.east:5900/ + Java SSL viewer URL: http://far-away.east:5800/ + PORT=5900 + SSLPORT=5900 + + Indicating the two URLs (the first one encrypted, the second not) one + could point the web browser at to get the VNC viewer applet. E.g. put + this + http://far-away.east:5800/ + + or: + https://far-away.east:5900/ + + into your Java-enabled Web browser. + + Note that KDE's Konqueror web browser seems to have problems with + https Java applets, so you'll have to use the http/5800 with it (if + you get https/5900 working let us know how you did it.) + + If you are using a router/firewall with port-redirection, and you are + redirecting ports other than the default ones (5800, 5900) listed + above see here. + + The https service provided thru the actual VNC port (5900 in the above + example) can occasionally be slow or unreliable (it has to read some + input and try to guess if the connection is VNC or HTTP.) If it is + unreliable for you and you still want to serve the Java applet via + https, use the -https option to get an additional port dedicated to + https (its URL will also be printed in the output.) + + Another possibility is to add the GET applet parameter: + https://far-away.east:5900/?GET=1 + + This will have the VNC Viewer send a special HTTP GET string "GET + /request.https.vnc.connection HTTP/1.0" that x11vnc will notice more + quickly as a request for a VNC connection. Otherwise it must wait for + a timeout to expire before it assumes a VNC connection. + + You may also use "urlPrefix=somestring" to have /somestring prepended + to /request.https.vnc.connection". Perhaps you are using a web server + proxy scheme to enter a firewall or otherwise have rules applied to + the URL. If you need to have any slashes "/" in "somestring" use + "_2F_" (a deficiency in libvncserver prevents using the more natural + "%2F".) + + You apply multiple applet parameters in the regular URL way, e.g.: + https://far-away.east:5900/?GET=1&urlPrefix=mysubdir&... + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + + Tips on Getting the SSL Java Applet Working the First Time: + Unfortunately, it can be a little tricky getting the SSL VNC Java + Viewer working with x11vnc. Here are some tips to getting working the + first time (afterwards you can incrementally customize with more + complex settings.) + * First try it on the LAN: Do NOT try to have it work the first time + going through firewalls, Web proxies, home router port + redirections, or Apache portal. Just try a direct connection over + your LAN first (if you only have 1 machine and no LAN, just do a + direct connection to the same machine: localhost.) If the LAN + machine you run x11vnc on has its own host-level firewall (most + linux machine come with that on by default), disable it or at + least let tcp ports 5800-6000 through. + * First try HTTP to download the Java Applet: x11vnc can serve both + the Java Applet jar file and VNC out of the same port (both + tunneled through SSL, see below.) But it can lead to timing and + other problems. So first try HTTP instead of HTTPS to download the + Applet jar file (VncViewer.jar.) That is to say try + http://hostname:5800 in your web browser first before trying + https://hostname:5900. x11vnc will print out the ports and URLs it + is using, so use the HTTP one it prints out. + * Always Restart the Browser: If you are having failures and have to + repeatedly retry things ALWAYS restart the browser (i.e. + completely exit it and then start a new browser process) each + time. Otherwise as you are changing things the browser may + "remember" failed applet downloads, etc. and just add to the + confusion and irreproducibility. If you see it trying to download + VncViewer.class (instead of VncViewer.jar) you know it is really + confused and needs to be restarted. + * Step Lively: If you get Browser or Java VM or VNC Viewer applet + dialog boxes saying things like "Do you want to trust this + certificate?" or "The hostname does not match the one on the + certificate", etc. just go through them as quickly as possible. + x11vnc cannot wait forever for each SSL connection, and so if you + dawdle too long inspecting the certs, etc it can lead to problems. + Get it working first before taking your time to read the details + in the dialogs, etc. + * No inetd, Please: Even if you intend to deploy via inetd or xinetd + eventually, get that working later (and remember do not use + something like "-ssl TMP" that creates a new temporary SSL + certificate for every new socket connection.) + * Nothing Fancy: Do not try fancy stuff like -svc, -create, -unixpw, + "-users unixpw=", "-users sslpeer=", -sslverify, etc. Just get the + simplest connection working first and then incrementally add what + you need. + + So the recommended test command lines are: + x11vnc -ssl SAVE -http + x11vnc -ssl SAVE -httpdir /path/to/x11vnc/classes/ssl + + Use the latter if x11vnc cannot automatically find the classes/ssl + directory (this what the -http option instructs it to do.) Then point + your browser to the HTTP (not HTTPS) URL it prints out. + + Following the above guidelines, did it work? If so, Congratulations!! + you created an SSL encrypted connection between the SSL Java applet + running in your web browser and x11vnc. The fact that you used HTTP + instead of HTTPS to download the applet is not the end of the world + (some users do it this way), the main thing is that the VNC traffic is + encrypted with SSL. If you are having trouble even with the above + baseline test case feel free to contact me (please send the Full + x11vnc output, not just part of it; the complete x11vnc command line; + the URL(s) entered in the browser; the full Java Console output; and + anything else you can think of.) + + Next, you can add the features you want one by one testing it still + works each time. I suggest first turning on the HTTPS applet download + (https://hostname:5900) if that is what you intend to use. That one + gives the most trouble because of the ambiguity of passing two + different protocols (HTTP and VNC) through the same SSL service port. + + Next, turn on inetd if you intend to use that (this can be tricky too, + be sure to use -oa logfile and inspect it carefully if there are + problems.) If you are going to use non-standard ports (e.g. "-rfbport + 443" as root), work on that next. Then enable the firewall, router + port redirection channel (you will somehow need to be outside to do + that, maybe test that through another VNC session.) + + Then, if you plan to use them, enable "fancy stuff" like "-svc" or + "-unixpw", etc, etc. Be sure to add a password either "-rfbauth" or + "-unixpw" or both. If you need to have the web browser use a corporate + Web Proxy (i.e. it cannot connect directly) work on that last. Ditto + for the Apache portal. + + + Router/Firewall port redirs: If you are doing port redirection at + your router to an internal machine running x11vnc AND the internet + facing port is different from the internal machine's VNC port, you + will need to apply the PORT applet parameter to indicate to the applet + the Internet facing port number (otherwise by default the internal + machine's port, say 5900, is sent and that of course is rejected at + the firewall/router.) For example: + https://far-away.east:443/?GET=1&PORT=443 + + So in this example the user configures his router to redirect + connections to port 443 on his Internet side to, say, port 5900 on the + internal machine running x11vnc. See also the -httpsredir option that + will try to automate this for you. + + To configure your router to do port redirection, see its instructions. + Typically, from the inside you point a web browser to a special URL + (e.g. http://192.168.1.1) and you get a web interface to configure it. + Look for something like "Port Redirection" or "Port Forwarding", + probably under "Advanced" or something like that. If you have a Linux + or Unix system acting as your firewall/router, see its firewall + configuration. + + You can also use x11vnc options -rfbport NNNNN and -httpport NNNNN to + match the ports that your firewall will be redirecting to the machine + where x11vnc is run. + + + Tedious Dialogs: If you do serve the SSL enabled Java viewer via https + be prepared for quite a number of "are you sure you trust this site?" + dialogs: + * First from the Web browser that cannot verify the self-signed + certificate when it downloads index.vnc. + * From the Web browser again noting that the common name on the + certificate does not match the hostname of the remote machine. + * Next from the Java VM that cannot verify the self-signed + certificate when it downloads VncViewer.jar. + * And also from the Java VM again noting that the common name on the + certificate does not match the hostname of the remote machine. + * Finally from the Java VncViewer applet itself saying it cannot + verify the certificate! (or a popup asking you if you want to see + the certificate.) + + Note that sometimes if you pause too long at one of the above dialogs + then x11vnc may exceed a timeout and assume the current socket + connection is VNC instead of the HTTPS it actually is (but since you + have paused too long at the dialog the GET request comes too late.) + Often hitting Reload and going through the dialogs more quickly will + let you connect. The Java VM dialogs are the most important ones to + NOT linger at. If you see in the x11vnc output a request for + VncViewer.class instead of VncViewer.jar it is too late... you will + need to completely restart the Web browser to get it to try for the + jar again. You can use the -https option if you want a dedicated port + for HTTPS connections instead of sharing the VNC port. + + To see example x11vnc output for a successful https://host:5900/ + connection with the Java Applet see This Page. And here is a newer + example including the Java Console output. + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + + Notes on the VNC Viewer ss_vncviewer wrapper script: + + If you want to use a native VNC Viewer with the SSL enabled x11vnc you + will need to run an external SSL tunnel on the Viewer side. There do + not seem to be any native SSL VNC Viewers outside of our x11vnc and + SSVNC packages. The basic ideas of doing this were discussed for + external tunnel utilities here. + + The ss_vncviewer script provided with x11vnc and SSVNC can set up the + stunnel tunnel automatically on unix as long as the stunnel command is + installed on the Viewer machine and available in PATH (and vncviewer + too of course.) Note that on a Debian based system you will need to + install the package stunnel4 not stunnel. You can set the environment + variables STUNNEL and VNCVIEWERCMD to point to the correct programs if + you want to override the defaults. + + Here are some examples: + 1) ss_vncviewer far-away.east:0 + + 2) ss_vncviewer far-away.east:0 -encodings "copyrect tight zrle hextile" + + 3) ss_vncviewer -verify ./server.crt far-away.east:0 + + 4) ss_vncviewer -mycert ./client.pem far-away.east:0 + + 5) ss_vncviewer -proxy far-away.east:8080 myworkstation:0 + + The first one is the default mode and accepts the x11vnc certificate + without question. The second one is as the first, but adds the + -encodings options to the vncviewer command line. + + The third one requires that the x11vnc server authenticate itself to + the client against the certificate in the file ./server.crt (e.g. one + created by "x11vnc -ssl SAVE" and safely copied to the VNC viewer + machine.) + + The fourth one is for VNC Viewer authentication, it uses ./client.pem + to authenticate itself to x11vnc. One can supply both -verify and + -mycert simultaneously. + + The fifth one shows that Web proxies can be used if that is the only + way to get out of the firewall. If the "double proxy" situation arises + separate the two by commas. See this page for more information on how + Web proxies come into play. + + If one uses a Certificate Authority (CA) scheme described here, the + wrapper script would use the CA cert instead of the server cert: + 3') ss_vncviewer -verify ./cacert.crt far-away.east:0 + + Update Jul/2006: we now provide an Enhanced TightVNC Viewer (SSVNC) + package that starts up STUNNEL automatically along with some other + features. All binaries (stunnel, vncviewer, and some utilities) are + provided in the package. It works on Unix, Mac OS X, and Windows. + + + Q-55: How do I use the Java applet VNC Viewer with built-in SSL + tunneling when going through a Web Proxy? + The SSL enabled Java VNC Viewer and firewall Proxies: + + SSL and HTTPS aside, there is a general problem with Firewall Proxies + and Java Applets that open sockets. The applet is downloaded + successfully (through the browser) using HTTP and the proxy, but when + the applet tries to reconnect to the originating host (the only one + allowed by security) it does not use the proxy channel. So it cannot + reconnect to the server the applet came from! + + We have found a convenient workaround: in the directory where + VncViewer.jar resides there is a digitally signed version of the same + applet called SignedVncViewer.jar. Since the applet is digitally + signed, there will be an additional dialog from the Java VM plugin + asking you if you want to trust the applet fully. + + You should say "Yes". If you do, the applet will be run in a mode + where it can try to determine the firewall proxy host name and port + (it will ask you for them if it cannot find them.) This way it can + connect directly to the Proxy and then request the CONNECT method to + be redirected to the originating host (the x11vnc VNC Server.) SSL is + then layered over this socket. + + To do this you should use the proxy.vnc HTML file like via this URL in + your browser: + https://yourmachine.com:5900/proxy.vnc + + (instead of the unsigned one in https://yourmachine.com:5900/ that + gives the default index.vnc) + + Proxies that limit CONNECT to ports 443 and 563: + + Things become trickier if the Web proxy restricts which CONNECT ports + can be redirected to. For security, some (most?) proxies only allow + port 443 (HTTPS) and 563 (SNEWS) by default. In this case, the only + thing to do is run x11vnc on that low port, e.g. "-rfbport 443", (or + use a port redirection on, say, a firewall or router port 443 to the + internal machine.) + + If you do such a redirection to an internal machine and x11vnc is not + listening on port 443, you will probably need to edit proxy.vnc. + Suppose the SSL x11vnc server was listening on port 5901. You should + change the line in proxy.vnc from: + + + to: + + + Since otherwise $PORT will be expanded to 5901 by x11vnc and the + viewer applet will fail to connect to that port on the firewall. + + Another way to achieve the same thing is to use the applet PORT + parameter: + https://yourmachine.com/proxy.vnc?PORT=443 + + this is cleaner because it avoids editing the file, but requires more + parameters in the URL. See also the -httpsredir x11vnc option that + will try to automate this for you. To use the GET trick discussed + above, do: + https://yourmachine.com/proxy.vnc?GET=1&PORT=443 + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + Here is an example of Java Console and x11vnc output for the Web proxy + case. + + + Note that both the ss_vncviewer stunnel Unix wrapper script and + Enhanced TightVNC Viewer (SSVNC) can use Web proxies as well even + though they do not involve a Web browser. + + + Q-56: Can Apache web server act as a gateway for users to connect via + SSL from the Internet with a Web browser to x11vnc running on their + workstations behind a firewall? + Yes. You will need to configure apache to forward these connections. + It is discussed here. This SSL VNC portal provides a clean alternative + to the traditional method where the user uses SSH to log in through + the gateway to create the encrypted port redirection to x11vnc running + on her desktop. + + Also see the desktop.cgi CGI script method that achieves much of what + this Apache VNC SSL portal method does (as long as desktop.cgi's 'port + redirection' mode is enabled.) + + + Q-57: Can I create and use my own SSL Certificate Authority (CA) with + x11vnc? + Yes, see this page for how to do this and the utility commands x11vnc + provides to create and manage many types of certificates and private + keys. + + + + [Display Managers and Services] + + Q-58: How can I run x11vnc as a "service" that is always available? + + There are a number of ways to do this. The primary thing you need to + decide is whether you want x11vnc to connect to the X session on the + machine 1) regardless of who (or if anyone) has the X session, or 2) + only if a certain user has the X session. Because X sessions are + protected by X permissions (MIT-MAGIC-COOKIE files XAUTHORITY and + $HOME/.Xauthority) the automatically started x11vnc will of course + need to have sufficient permissions to connect to the X display. + + Here are some ideas: + * Use the description under "Continuously" in the FAQ on x11vnc and + Display Managers + * Use the description in the FAQ on x11vnc and inetd(8) + * Use the description in the FAQ on Unix user logins and inetd(8) + * Start x11vnc from your $HOME/.xsession (or $HOME/.xinitrc or + autostart script or ...) + * Although less reliable, see the x11vnc_loop rc.local hack below. + + The display manager scheme will not be specific to which user has the + X session unless a test is specifically put into the display startup + script (often named Xsetup.) The inetd(8) scheme may or may not be + specific to which user has the X session (and it may not be able to do + all users via the XAUTHORITY permission issues.) + + The .xsession/.xinitrc scheme is obviously is specific to a particular + user and only when they are logged into X. If you do not know what a + $HOME/.xsession script is or how to use one, perhaps your desktop has + a "session startup commands" configuration option. The command to be + run in the .xsession or .xinitrc file may look like this: +x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg + + plus any other options you desire. + + Depending on your desktop and/or OS/distribution the automatically run + X startup scripts (traditionally .xsession/.xinitrc) may have to be in + a different directory or have a different basename. One user + recommends the description under 'Running Scripts Automatically' at + this link. + + Firewalls: note all methods will require the host-level firewall to be + configured to allow connections in on a port. E.g. 5900 (default VNC + port) or 22 (default SSH port for tunnelling VNC.) Most systems these + days have firewalls turned on by default, so you will actively have to + do something to poke a hole in the firewall at the desired port + number. See your system administration tool for Firewall settings + (Yast, Firestarter, etc.) + + + Q-59: How can I use x11vnc to connect to an X login screen like xdm, + GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into an X + session yet.) + + We describe two scenarios here. The first is called 'One time only' + meaning you just need to do it quickly once and don't want to repeat; + and the second is called 'Continuously' meaning you want the access to + be available after every reboot and after every desktop logout. + _________________________________________________________________ + + One time only: If the X login screen is running and you just want to + connect to it once (i.e. a one-shot): + + It is usually possible to do this by just adjusting the XAUTHORITY + environment variable to point to the correct MIT-COOKIE auth file + while running x11vnc as root, e.g. for the gnome display manager, GDM: + x11vnc -auth /var/gdm/:0.Xauth -display :0 + + (the -auth option sets the XAUTHORITY variable for you.) + + There will be a similar thing to do for xdm using however a different + auth directory path (perhaps something like + /var/lib/xdm/authdir/authfiles/A:0-XQvaJk) for the xdm greeter or + /var/lib/kdm/A:0-crWk72 (or /var/run/xauth/A:0-qQPftr, etc. etc) for + the kdm greeter. Of course, the random characters in the file basename + will vary and you will need to use the actual filename on your system. + Read your system docs to find out where the display manager cookie + files are kept. + + Trick: sometimes ps(1) can reveal the X server process -auth argument + (e.g. "ps wwaux | grep auth") and hence the path to the auth file. + + x11vnc must be run as root for this because the /var/gdm/:0.Xauth, + /var/lib/kdm/A:0-crWk72, etc. auth files are only readable by root. If + you do not want to run x11vnc as root, you can copy (as root or sudo) + the auth file to some location and make it readable by your userid. + Then run x11vnc as your userid with -auth pointed to the copied file. + + Update Dec/2009: use "-auth guess" to have x11vnc try to guess the + location of the auth file for you. + + You next connect to x11vnc with a VNC viewer, give your username and + password to the X login prompt to start your session. + + Note: GDM: gdm seems to have an annoying setting that causes x11vnc + (and any other X clients) to be killed after the user logs in. Setting + KillInitClients=false in the [daemon] section of /etc/X11/gdm/gdm.conf + (or /etc/gdm/gdm.conf, etc.) avoids this. Otherwise, just restart + x11vnc and then reconnect your viewer. Other display managers (kdm, + etc) may also have a similar problem. One user reports having to alter + "gdm.conf-custom" as well. + + Note: Solaris: For dtlogin in addition to the above sort of trick + (BTW, the auth file should be in /var/dt), you'll also need to add + something like Dtlogin*grabServer:False to the Xconfig file + (/etc/dt/config/Xconfig or /usr/dt/config/Xconfig on Solaris, see the + example at the end of this FAQ.) Then restart dtlogin, e.g.: + /etc/init.d/dtlogin stop; /etc/init.d/dtlogin start or reboot. + + Update Nov/2008: Regarding GDM KillInitClients: see the -reopen option + for another possible workaround. + + Update Oct/2009: Regarding GDM KillInitClients: starting with x11vnc + 0.9.9 it will try to apply heuristics to detect if a window manager is + not running (i.e. whether the Display Manager Greeter Login panel is + still up.) If it thinks the display manager login is still up it will + delay creating windows or using XFIXES. The former is what GDM uses to + kill the initial clients, use of the latter can cause a different + problem: an Xorg server crash. So with 0.9.9 and later it should all + work without needing to set KillInitClients=false (which is a good + because recent GDM, v2.24, has removed this option) or use -noxfixes. + To disable the heuristics and delaying set X11VNC_AVOID_WINDOWS=never; + to set the delay time explicitly use, e.g., X11VNC_AVOID_WINDOWS=120 + (delays for 120 seconds after the VNC connection; you have that long + to log in.) + _________________________________________________________________ + + Continuously: Have x11vnc reattach each time the X server is + restarted (i.e. after each logout and reboot): + + To make x11vnc always attached to the X server including the login + screen you will need to add a command to a display manager startup + script. + + Please consider the security implications of this! The VNC display for + the X session always accessible (but hopefully password protected.) + Add -localhost if you only plan to access via a SSH tunnel. + + The name of the display manager startup script file depends on desktop + used and seem to be: + GDM (GNOME) /etc/X11/gdm/Init/Default + /etc/gdm/Init/Default + KDM (KDE) /etc/kde*/kdm/Xsetup + XDM /etc/X11/xdm/Xsetup (or sometimes xdm/Xsetup_0) + CDE /etc/dt/config/Xsetup + + although the exact location can be operating system, distribution, and + time dependent. See the documentation for your display manager: + gdm(1), kdm(1), xdm(1), dtlogin(1) for additional details. There may + also be display number specific scripts: e.g. Xsetup_0 vs. Xsetup, you + need to watch out for. + + Note: You should read and understand all of the Note's and Update's + in the 'One time only' section above. All of the GDM topics apply here + as well: + + Note: GDM: The above (in 'One time only') gdm setting of + KillInitClients=false in /etc/X11/gdm/gdm.conf (or /etc/gdm/gdm.conf, + etc.) for GDM is needed here as well. Other display managers (KDM, + etc) may also have a similar problem. + + Also see the Update Oct/2009 above where x11vnc 0.9.9 and later + automatically avoids being killed. + + Note: DtLogin: The above (in 'One time only') + Dtlogin*grabServer:False step for Solaris will be needed for dtlogin + here as well. + + In any event, the line you will add to the display manager script + (Xsetup, Default, or whatever) will look something like: + /usr/local/bin/x11vnc -rfbauth /path/to/the/vnc/passwd -o /var/log/x11vnc.log + -forever -bg + + where you should customize the exact command to your needs (e.g. + -localhost for SSH tunnel-only access; -ssl SAVE for SSL access; etc.) + + Happy, happy, joy, joy: Note that we do not need to specify -display + or -auth because happily they are already set for us in the DISPLAY + and XAUTHORITY environment variables for the Xsetup script!!! + + You may also want to force the VNC port with something like "-rfbport + 5900" (or -N) to avoid autoselecting one if 5900 is already taken. + _________________________________________________________________ + + Fedora/gdm: Here is an example of what we did on a vanilla install of + Fedora-C3 (seems to use gdm by default.) Add a line like this to + /etc/X11/gdm/Init/:0 + /usr/local/bin/x11vnc -rfbauth /etc/x11vnc.passwd -forever -bg -o /var/log/x1 +1vnc.log + + And then add this line to /etc/X11/gdm/gdm.conf (or /etc/gdm/gdm.conf, + etc.) in the [daemon] section: + KillInitClients=false + + Then restart: /usr/sbin/gdm-restart (or reboot.) The + KillInitClients=false setting is important: without it x11vnc will be + killed immediately after the user logs in. Here are full details on + how to configure gdm + _________________________________________________________________ + + Solaris/dtlogin: Here is an example of what we did on a vanilla + install of Solaris: + Make the directory /etc/dt/config: + mkdir -p /etc/dt/config + + Copy over the Xconfig file for customization: + cp /usr/dt/config/Xconfig /etc/dt/config/Xconfig + + Edit /etc/dt/config/Xconfig and uncomment the line: + Dtlogin*grabServer: False + + Next, copy over Xsetup for customization: + cp /usr/dt/config/Xsetup /etc/dt/config/Xsetup + + Edit /etc/dt/config/Xsetup and at the bottom put a line like: + /usr/local/bin/x11vnc -forever -o /var/log/x11vnc.log -bg + + (tweaked to your local setup and preferences, a password via -rfbauth, + etc. would be a very good idea.) + + Restart the X server and dtlogin: + /etc/init.d/dtlogin stop + /etc/init.d/dtlogin start + + (or reboot or maybe just restart the X session.) + _________________________________________________________________ + + KDM: One user running the kdm display manager reports putting this + line: + x11vnc -forever -rfbauth /home/xyz/.vnc/passwd -bg -o /var/log/x11vnc.log + + in /etc/kde/kdm/Xsetup. After rebooting the system it all seemed to + work fine. + _________________________________________________________________ + + + If you do not want to deal with any display manager startup scripts, + here is a kludgey script that can be run manually or out of a boot + file like rc.local: x11vnc_loop It will need some local customization + before running. Because the XAUTHORITY auth file must be guessed by + this script, use of the display manager script method described above + is greatly preferred. There is also the -loop option that does + something similar. + + If the machine is a traditional Xterminal you may want to read this + FAQ. + + Firewalls: note all methods will require the host-level firewall to be + configured to allow connections in on a port. E.g. 5900 (default VNC + port) or 22 (default SSH port for tunnelling VNC.) Most systems these + days have firewalls turned on by default, so you will actively have to + do something to poke a hole in the firewall at the desired port + number. See your system administration tool for Firewall settings + (Yast, Firestarter, etc.) + + + Q-60: Can I run x11vnc out of inetd(8)? How about xinetd(8)? + + Yes, perhaps a line something like this in /etc/inetd.conf will do it + for you: + + 5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc_sh + + where the shell script /usr/local/bin/x11vnc_sh uses the -inetd option + and looks something like (you'll need to customize to your settings.) +#!/bin/sh +/usr/local/bin/x11vnc -inetd -display :0 -auth /home/fred/.Xauthority \ + -rfbauth /home/fred/.vnc/passwd -o /var/log/x11vnc_sh.log + + Important: Note that you must redirect the standard error output to a + log file (e.g. -o logfile) or "2>/dev/null" for proper operation via + inetd (otherwise the standard error also goes to the VNC vncviewer, + and that confuses it greatly, causing it to abort.) If you do not use + a wrapper script as above but rather call x11vnc directly in + /etc/inetd.conf and do not redirect stderr to a file, then you must + specify the -q (aka -quiet) option: "/usr/local/bin/x11vnc -q -inetd + ...". When you supply both -q and -inet and no "-o logfile" then + stderr will automatically be closed (to prevent, e.g. library stderr + messages leaking out to the viewer.) The recommended practice is to + use "-o logfile" to collect the output in a file or wrapper script + with "2>logfile" redirection because the errors and warnings printed + out are very useful in troubleshooting problems. + + Note also the need to set XAUTHORITY via -auth to point to the + MIT-COOKIE auth file to get permission to connect to the X display + (setting and exporting the XAUTHORITY variable accomplishes the same + thing.) See the x11vnc_loop file in the previous question for more + ideas on what that auth file may be, etc. The scheme described in the + FAQ on Unix user logins and inetd(8) works around the XAUTHORITY issue + nicely. + + Note: On Solaris you cannot have the bare number 5900 in + /etc/inetd.conf, you'll need to replace it with a word like x11vnc an + then put something like "x11vnc 5900/tcp" in /etc/services. + + Since the process runs as root, it might be a bad idea to have the + logfile in a world-writable area like /tmp if there are untrustworthy + users on the machine. Perhaps /var/log is a better place. + + Be sure to look at your /etc/hosts.allow and /etc/hosts.deny settings + to limit the machines that can connect to this service (your desktop!) + For the above example with /etc/hosts.allow: + x11vnc_sh : 123.45.67.89 + + A really safe way to do things is to limit the above inetd to + localhost only (via /etc/hosts.allow) and use ssh to tunnel the + incoming connection. Using inetd for this prevents there being a tiny + window of opportunity between x11vnc starting up and your vncviewer + connecting to it. Always use a VNC password to further protect against + unwanted access. + + For xinetd(8), one user reports he created the file + /etc/xinetd.d/x11vncservice containing the following: +# default: off +# description: +service x11vncservice +{ + flags = REUSE NAMEINARGS + port = 5900 + type = UNLISTED + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/sbin/tcpd + server_args = /usr/local/bin/x11vnc_sh + disable = no +} + + With the contents of /usr/local/bin/x11vnc_sh similar to the example + given above. One user reports this works with avoiding the wrapper + script: +service x11vncservice +{ + port = 5900 + type = UNLISTED + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/local/bin/x11vnc + server_args = -inetd -q -display :0 -auth /var/gdm/:0.Xauth + disable = no +} + + (or one can replace the -q with say "-o /var/log/x11vnc.log" to + capture a log) + + The above works nicely for GDM because the -auth file is a fixed name. + For KDM or XDM the filename varies. Here is one idea for a x11vnc_sh + wrapper to try to guess the name: +#!/bin/sh +COLUMNS=256 +export COLUMNS +authfile=`ps wwaux | grep '/X.*-auth' | grep -v grep | sed -e 's/^.*-auth *//' +-e 's/ .*$//' | head -n 1` + +if [ -r "$authfile" ]; then + exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -display :0 -a +uth "$authfile" +fi +exit 1 + + Starting with x11vnc 0.9.3 this can be automated by: +#!/bin/sh +exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -find -env FD_XDM=1 + + + Q-61: Can I have x11vnc advertise its VNC service and port via mDNS / + Zeroconf (e.g. Avahi) so VNC viewers on the local network can detect + it automatically? + + Yes, as of Feb/2007 x11vnc supports mDNS / Zeroconf advertising of its + service via the Avahi client library. Use the option -avahi (same as + -mdns or -zeroconf) to enable it. Depending on your setup you may need + to install Avahi (including the development/build packages), enable + the server: avahi-daemon and avahi-dnsconfd, and possibly open up UDP + port 5353 on your firewall. + + If the Avahi client library or build environment is not available at + build-time, then at run-time x11vnc will try to look for external + helper programs, avahi-browse(1) or dns-sd(1), to do the work. + + The service was tested with Chicken of the VNC ("Use Bonjour" + selected) on a Mac on the same network and the service was noted and + listed in the servers list. Clicking on it and then "Connect" + connected automatically w/o having to enter any hostnames or port + numbers. + + It appears SuSE 10.1 comes with avahi (or you can add packages, e.g. + avahi-0.6.5-27) but not the development package (you can use the + OpenSuSE avahi-devel rpm.) Unfortunately, you may need to disable + another Zeroconf daemon "/etc/init.d/mdnsd stop", before doing + "/etc/init.d/avahi-daemon start" and "/etc/init.d/avahi-dnsconfd + start". We also had to comment out the browse-domains line in + /etc/avahi/avahi-daemon.conf. Hopefully there is "LessConf" to do on + other distros/OS's... + + + Q-62: Can I have x11vnc allow a user to log in with her UNIX username + and password and then have it find her X session display on that + machine and then attach to it? How about starting an X session if one + cannot be found? + + The easiest way to do this is via inetd(8) using the -unixpw and + -display WAIT options. The reason inetd(8) makes this easier is that + it starts a new x11vnc process for each new user connection. Otherwise + a wrapper would have to listen for connections and spawn new x11vnc's + (see this example and also the -loopbg option.) inetd(8) is not + required for this, but it makes some aspects more general. + + Also with inetd(8) users always connect to a fixed VNC display, say + hostname:0, and do not need to memorize a special VNC display number + just for their personal use, etc. + + Update: Use the -find, -create, -svc, and -xdmsvc options that are + shorthand for common FINDCREATEDISPLAY usage modes (e.g. terminal + services) described below. (i.e. simply use "-svc" instead of the + cumbersome "-display WAIT:cmd=FINDCREATEDISPLAY-Xvfb -unixpw -users + unixpw= -ssl SAVE") + + The -display WAIT option makes x11vnc wait until a VNC viewer is + connected before attaching to the X display. + + Additionally it can be used to run an external command that returns + the DISPLAY and XAUTHORITY data. We provide some useful builtin ones + (FINDDISPLAY and FINDCREATEDISPLAY below), but in principle one could + supply his own script: "-display WAIT:cmd=/path/to/find_display" where + the script find_display might look something like this. + + A default script somewhat like the above is used under "-display + WAIT:cmd=FINDDISPLAY" (same as -find) The format for any such command + is that it returns DISPLAY=:disp as the first line and any remaining + lines are either XAUTHORITY=file or raw xauth data (the above example + does the latter.) If applicable (-unixpw mode), the program is run as + the Unix user name who logged in. + + On Linux if the virtual terminal is known the program appends ",VT=n" + to the DISPLAY line; a chvt n will be attempted automatically. Or if + only the X server process ID is known it appends ",XPID=n" (a chvt + will be attempted by x11vnc.) + + Tip: Note that the -find option is an alias for "-display + WAIT:cmd=FINDDISPLAY". Use it! + + The -unixpw option allows UNIX password logins. It conveniently knows + the Unix username whose X display should be found. Here are a couple + /etc/inetd.conf examples of this usage: +5900 stream tcp nowait nobody /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd +-unixpw \ + -find -o /var/log/x11vnc.log -ssl SAVE -ssldir /usr/local/certs +5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd +-unixpw \ + -find -o /var/log/x11vnc.log -ssl SAVE -users unixpw= + + Note we have used the -find alias and the very long lines have been + split. An alternative is to use a wrapper script, e.g. + /usr/local/bin/x11vnc.sh that has all of the options. (see also the + -svc alias.) + + In the first inetd line x11vnc is run as user "nobody" and stays user + nobody during the whole session. The permissions of the log files and + certs directory will need to be set up to allow "nobody" to use them. + + In the second one x11vnc is run as root and switches to the user that + logs in due to the "-users unixpw=" option. + + Note that SSL is required for this mode because otherwise the Unix + password would be passed in clear text over the network. In general + -unixpw is not required for this sort of scheme, but it is convenient + because it determines exactly who the Unix user is whose display + should be sought. Otherwise the find_display script would have to use + some method to work out DISPLAY, XAUTHORITY, etc (perhaps you use + multiple inetd ports and hardwire usernames for different ports.) + + If you really want to disable the SSL or SSH -localhost constraints + (this is not recommended unless you really know what you are doing: + Unix passwords sent in clear text is a very bad idea...) read the + -unixpw documentation. + + A inetd(8) scheme for a fixed user that doesn't use SSL or unix + passwds could be: + /usr/local/bin/x11vnc -inetd -users =fred -find -rfbauth /home/fred/.vnc/pass +wd -o /var/log/x11vnc.log + + The "-users =fred" option will cause x11vnc to switch to user fred and + then find his X display. The VNC password (-rfbauth) as opposed to + Unix password (-unixpw) is used to authenticate the VNC client. + + Similar looking commands to the above examples can be run directly and + do not use inetd (just remove the -inetd option and run from the + cmdline, etc.) + + + X Session Creation: An added (Nov/2006) extension to FINDDISPLAY is + FINDCREATEDISPLAY where if it does not find an X display via the + FINDDISPLAY method it will create an X server session for the user + (i.e. desktop/terminal server.) This is the only time x11vnc actually + tries to start up an X server (normally it just attaches to an + existing one.) + + For virtual sessions you will need to install the Xvfb program (e.g. + apt-get install xvfb) or our Xdummy program (see below.) + + By default it will only try to start up virtual (non-hardware) X + servers: first Xvfb and if that is not available then Xdummy (included + in the x11vnc source code.) Note that Xdummy only works on Linux + whereas Xvfb works just about everywhere (and in some situations + Xdummy must be run as root.) An advantage of Xdummy over Xvfb is that + Xdummy supports RANDR dynamic screen resizing, which can be handy if + the user accesses the desktop from different sized screens (e.g. + workstation and laptop.) + + So an inetd(8) example might look like: +5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd \ + -o /var/log/x11vnc.log -http -prog /usr/local/bin/x11vnc \ + -ssl SAVE -unixpw -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY + + Where the very long lines have been split. See below where that long + and cumbersome last line is replaced by the -svc alias. + + The above mode will allow direct SSL (e.g. ss_vncviewer or SSVNC) + access and also Java Web browers access via: https://hostname:5900/. + + Tip: Note that the -create option is an alias for "-display + WAIT:cmd=FINDCREATEDISPLAY-Xvfb". + + Tip: Note that -svc is a short hand for the long "-ssl SAVE -unixpw + -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY" part. Unlike + -create, this alias also sets up SSL encryption and Unix password + login. + + The above inetd example then simplifies to: +5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd \ + -o /var/log/x11vnc.log -http -prog /usr/local/bin/x11vnc \ + -svc + + Tip: In addition to the usual unixpw parameters, inside the VNC viewer + the user can specify after his username (following a ":" see -display + WAIT for details) for FINDCREATEDISPLAY they can add "geom=WxH" or + "geom=WxHxD" to specify the width, height, and optionally the color + depth. E.g. "fred:geom=800x600" at the login: prompt. Also if the env. + var X11VNC_CREATE_GEOM is set to the desired WxH or WxHxD that will be + used by x11vnc. + + You can set the env. var X11VNC_SKIP_DISPLAY to a comma separated list + of displays to ignore in the FINDDISPLAY process (to force creation of + new displays in some cases.) The user logging in via the vncviewer can + also set this via username:nodisplay=...) + + If you do not plan on using the Java Web browser applet you can remove + the -http (and -prog) option since this will speed up logging-in by a + few seconds (x11vnc will not have to wait to see if a connection is + HTTPS or VNC.) + + For reference, xinetd format in the file, say, /etc/xinetd.d/x11vnc: +service x11vnc +{ + type = UNLISTED + port = 5900 + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/local/bin/x11vnc + server_args = -inetd -o /var/log/x11vnc.log -http -prog /usr/local/ +bin/x11vnc -svc + disable = no +} + + To print out the script in this case use "-display + WAIT:cmd=FINDCREATEDISPLAY-print". To change the preference of + Xservers and which to try list them, e.g.: "-display + WAIT:cmd=FINDCREATEDISPLAY-X,Xvfb,Xdummy" or use "-create_xsrv + X,Xvfb,Xdummy". The "X" one means to try to start up a real, hardware + X server, e.g. startx(1) (if there is already a real X server running + this may only work on Linux and the chvt program may need to be run to + switch to the correct Linux virtual terminal.) x11vnc will try to run + chvt automatically if it can determine which VT should be switched to. + + XDM/GDM/KDM Login Greeter Panel: If you want to present the user with + a xdm/gdm/kdm display manager "greeter" login you can use Xvfb.xdmcp + instead of Xvfb, etc in the above list. However, you need to configure + xdm/gdm/kdm to accept localhost XDMCP messages, this can be done by + (from -help output): + If you want the FINDCREATEDISPLAY session to contact an XDMCP login + manager (xdm/gdm/kdm) on the same machine, then use "Xvfb.xdmcp" + instead of "Xvfb", etc. The user will have to supply his username + and password one more time (but he gets to select his desktop + type so that can be useful.) For this to work, you will need to + enable localhost XDMCP (udp port 177) for the display manager. + This seems to be: + + for gdm in gdm.conf: Enable=true in section [xdmcp] + for kdm in kdmrc: Enable=true in section [Xdmcp] + for xdm in xdm-config: DisplayManager.requestPort: 177 + + Unless you are also providing XDMCP service to xterminals or other + machines, make sure that the host access list only allows local + connections (the name of this file is often Xaccess and it is usually + setup by default to do just that.) Nowadays, host level firewalling + will also typically block UDP (port 177 for XDMCP) by default + effectively limiting the UDP connections to localhost. + + Tip: Note that -xdmsvc is a short hand alias for the long "-ssl SAVE + -unixpw -users unixpw= -display + WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp". So we simply use: +service x11vnc +{ + type = UNLISTED + port = 5900 + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/local/bin/x11vnc + server_args = -inetd -o /var/log/x11vnc.log -xdmsvc + disable = no +} + + (Note: use "-svc" instead of "-xdmsvc" for no XDMCP login greeter.) + + + Local access (VNC Server and VNC Viewer on the same machine): To + access your virtual X display session locally (i.e. while sitting at + the same machine it is running on) one can perhaps have something like + this in their $HOME/.xinitrc +#!/bin/sh +x11vnc -create -rfbport 5905 -env WAITBG=1 +vncviewer -geometry +0+0 -encodings raw -passwd $HOME/.vnc/passwd localhost:5 + + You may not need the -passwd. Recent RealVNC viewers might be this: +#!/bin/sh +x11vnc -create -rfbport 5905 -env WAITBG=1 +vncviewer -FullScreen -PreferredEncoding raw -passwd $HOME/.vnc/passwd localhos +t:5 + + This way a bare X server is run with no window manager or desktop; it + simply runs only the VNC Viewer on the real X server. The Viewer then + draws the virtual X session on to the real one. On your system it + might not be $HOME/.xinitrc, but rather .xsession, .Xclients, or + something else. You will need to figure out what it is for your system + and configuration. + + There may be a problem if the resolution (WxH) of the virtual X + display does not match that of the physical X display. + + If you do not want to or cannot figure out the X startup script name + (.xinitrc, etc) you could save the above commands to a shell script, + say "vnclocal", and the log in via the normal KDM or GDM greeter + program using the "Failsafe" option. Then in the lone xterm that comes + up type "vnclocal" to connect to your virtual X display via x11vnc and + vncviewer. + + _________________________________________________________________ + + Summary: The "-display WAIT:cmd=FINDCREATEDISPLAY" scheme can be used + to provide a "desktop service" (i.e. terminal service) on the server + machine: you always get some desktop there, either a real hardware X + server or a virtual one (depending on how you set things up.) + + So it provides simple "terminal services" based on Unix username and + password. The created X server sessions (virtual or real hardware) + will remain running after you disconnect the VNC viewer and will be + found again on reconnecting via VNC and logging in. To terminate them + use the normal way to Exit/LogOut from inside your X session. The user + does not have to memorize which VNC display number is his. They all go + the same one (e.g. hostname:0) and it switches based on username. + + + Q-63: Can I have x11vnc restart itself after it terminates? + + One could do this in a shell script, but now there is an option -loop + that makes it easier. Of course when x11vnc restarts it needs to have + permissions to connect to the (potentially new) X display. This mode + could be useful if the X server restarts often. Use e.g. "-loop5000" + to sleep 5000 ms between restarts. Also "-loop2000,5" to sleep 2000 ms + and only restart 5 times. + + One can also use the -loopbg to emulate inetd(8) to some degree, where + each connected process runs in the background. It could be combined, + say, with the -svc option to provide simple terminal services without + using inetd(8). + + + Q-64: How do I make x11vnc work with the Java VNC viewer applet in a + web browser? + + To have x11vnc serve up a Java VNC viewer applet to any web browsers + that connect to it, run x11vnc with this option: + -httpdir /path/to/the/java/classes/dir + + (this directory will contain the files index.vnc and, for example, + VncViewer.jar) Note that libvncserver contains the TightVNC Java + classes jar file for your convenience. (it is the file + classes/VncViewer.jar in the source tree.) + + You will see output something like this: + 14/05/2004 11:13:56 Autoprobing selected port 5900 + 14/05/2004 11:13:56 Listening for HTTP connections on TCP port 5800 + 14/05/2004 11:13:56 URL http://walnut:5800 + 14/05/2004 11:13:56 screen setup finished. + 14/05/2004 11:13:56 The VNC desktop is walnut:0 + PORT=5900 + + then you can connect to that URL with any Java enabled browser. Feel + free to customize the default index.vnc file in the classes directory. + + As of May/2005 the -http option will try to guess where the Java + classes jar file is by looking in expected locations and ones relative + to the x11vnc binary. + + Also note that if you wanted to, you could also start the Java viewer + entirely from the viewer-side by having the jar file there and using + either the java or appletviewer commands to run the program. + java -cp ./VncViewer.jar VncViewer HOST far-away.east PORT 5900 + + Proxies: See the discussion here if the web browser must use a web + proxy to connect to the internet. It is tricky to get Java applets to + work in this case: a signed applet must be used so it can connect to + the proxy and ask for the redirection to the VNC server. One way to do + this is to use the signed SSL one referred to in classes/ssl/proxy.vnc + and set disableSSL=yes (note that this has no encryption; please use + SSL or SSH as discuss elsewhere on this page) in the URL or the file. + + + Q-65: Are reverse connections (i.e. the VNC server connecting to the + VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? + + As of Mar/2004 x11vnc supports reverse connections. On Unix one starts + the VNC viewer in listen mode: "vncviewer -listen" (see your + documentation for Windows, etc), and then starts up x11vnc with the + -connect option. To connect immediately at x11vnc startup time use the + "-connect host:port" option (use commas for a list of hosts to connect + to.) The ":port" is optional (default is VNC listening port is 5500.) + + If a file is specified instead: -connect /path/to/some/file then that + file is checked periodically (about once a second) for new hosts to + connect to. + + The -remote control option (aka -R) can also be used to do this during + an active x11vnc session, e.g.: +x11vnc -display :0 -R connect:hostname.domain + + Use the "-connect_or_exit" option to have x11vnc exit if the reverse + connection fails. Also, note the "-rfbport 0" option disables TCP + listening for connections (potentially useful for reverse connection + mode, assuming you do not want any "forward" connections.) + + Note that as of Mar/2006 x11vnc requires password authentication for + reverse connections as well as for forward ones (assuming password + auth has been enabled, e.g. via -rfbauth, -passwdfile, etc.) Many VNC + servers do not require any password for reverse connections. To regain + the old behavior supply this option "-env + X11VNC_REVERSE_CONNECTION_NO_AUTH=1" to x11vnc. + + Vncconnect command: To use the vncconnect(1) program (from the core + VNC package at www.realvnc.com) specify the -vncconnect option to + x11vnc (Note: as of Dec/2004 -vncconnect is now the default.) + vncconnect(1) must be pointed to the same X11 DISPLAY as x11vnc (since + it uses X properties to communicate with x11vnc.) If you do not have + or do not want to get the vncconnect(1) program, the following script + (named "Vncconnect") may work if your xprop(1) supports the -set + option: +#!/bin/sh +# usage: Vncconnect +# Vncconnect +# note: not all xprop(1) support -set. +# +xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" + + + Q-66: Can reverse connections be made to go through a Web or SOCKS + proxy or SSH? + + Yes, as of Oct/2007 x11vnc supports reverse connections through + proxies: use the "-proxy host:port" option. The default is to assume + the proxy is a Web proxy. Note that most Web proxies only allow proxy + destination connections to ports 443 (HTTPS) and 563 (SNEWS) and so + this might not be too useful unless the proxy has been modified + (AllowCONNECT apache setting) or the VNC viewer listens on one of + those ports (or the router does a port redir.) A web proxy may also be + specified via "-proxy http://host:port" + + For SOCKS4 and SOCKS4a proxies use this format "-proxy + socks://host:port". If the reverse connection hostname is a numerical + IP or "localhost" then SOCKS4 (no host lookup) is used, otherwise + SOCKS4a will be used. For SOCKS5 (proxy will do lookup and many other + things) use "-proxy socks5://host:port". Note that the SSH builtin + SOCKS proxy "ssh -D port" only does SOCKS4 or SOCKS5, so use socks5:// + for a ssh -D proxy. + + The proxying works for both SSL encrypted and normal reverse + connections. + + An experimental mode is "-proxy http://host:port/..." where the URL + (e.g. a CGI script) is retrieved via the GET method. See -proxy for + more info. + + Another experimental mode is "-proxy ssh://user@host" in which case a + SSH tunnel is used for the proxying. See -proxy for more info. + + Up to 3 proxies may be chained together by listing them by commas + e.g.: "-proxy http://host1:port1,socks5://host2:port2" in case one + needs to ricochet off of several machines to ultimately reach the + listening viewer. + + + Q-67: Can x11vnc provide a multi-user desktop web login service as an + Apache CGI or PHP script? + Yes. See the example script desktop.cgi for ideas. It is in the source + tree in the directory x11vnc/misc. It serves x11vnc's SSL enabled Java + Applet to the web browser with the correct connection information for + the user's virtual desktop (an Xvfb session via -create; be sure to + add the Xvfb package.) HTTPS/SSL enabled Apache should be used to + serve the script to avoid unix and vnc passwords from being sent in + cleartext and sniffed. + + By default it uses a separate VNC port for each user desktop (either + by autoprobing in a range of ports or using a port based on the userid + number.) The web server's firewall must allow incoming connections to + these ports. + + It is somewhat difficult to do all of this with x11vnc listening on a + single port, however there is also a 'fixed port' scheme described in + the script based on -loopbg that works fairly well (but more + experience is needed to see what problems contention for the same port + causes; however at worst one user may need to re-login.) + + There is also an optional 'port redirection' mode for desktop.cgi that + allows redirection to other machines inside the firewall already + running SSL enabled VNC servers. This provides much of the + functionality as the SSL Portal and is easier to set up. + + + Q-68: Can I use x11vnc as a replacement for Xvnc? (i.e. not for a real + display, but for a virtual one I keep around.) + + You can, but you would not be doing this for performance reasons (for + virtual X sessions via VNC, Xvnc should give the fastest response.) + You may want to do this because Xvnc is buggy and crashes, does not + support an X server extension you desire, or you want to take + advantage of one of x11vnc's unending number of options and features. + + One way to achieve this is to have a Xvfb(1) virtual framebuffer X + server running in the background and have x11vnc attached to it. + Another method, faster and more accurate, is to use the "dummy" Device + Driver in XFree86/Xorg (see below.) + + For these virtual sessions you will need to install the Xvfb program + (e.g. apt-get install xvfb) or our Xdummy program (see below.) + + In either case, one can view this desktop both remotely and also + locally using vncviewer. Make sure vncviewer's "-encodings raw" is in + effect for local viewing (compression seems to slow things down + locally.) For local viewing you set up a "bare" window manager that + just starts up vncviewer and nothing else (See how below.) + + Here is one way to start up Xvfb: + xinit -- /usr/bin/Xvfb :1 -cc 4 -screen 0 1024x768x16 + + This starts up a 16bpp virtual display. To export it via VNC use + x11vnc -display :1 ... + + Then have the remote vncviewer attach to x11vnc's VNC display (e.g. :0 + which is port 5900.) + + The "-cc 4" Xvfb option is to force it to use a TrueColor visual + instead of DirectColor (this works around a recent bug in the Xorg + Xvfb server.) + + One good thing about Xvfb is that the virtual framebuffer exists in + main memory (rather than in the video hardware), and so x11vnc can + "screen scrape" it very efficiently (more than, say, 100X faster than + normal video hardware.) + + Update Nov/2006: See the FINDCREATEDISPLAY discussion of the "-display + WAIT:cmd=FINDDISPLAY" option where virtual (Xvfb or Xdummy, or even + real ones by changing an option) X servers are started automatically + for new users connecting. This provides a "desktop service" for the + machine. You either get your real X session or your virtual + (Xvfb/Xdummy) one whenever you connect to the machine (inetd(8) is a + nice way to provide this service.) The -find, -create, -svc, and + -xdmsvc aliases can also come in handy here. + + There are some annoyances WRT Xvfb however. The default keyboard + mapping seems to be very poor. One should run x11vnc with -add_keysyms + option to have keysyms added automatically. Also, to add the Shift_R + and Control_R modifiers something like this is needed: +#!/bin/sh +xmodmap -e "keycode any = Shift_R" +xmodmap -e "add Shift = Shift_L Shift_R" +xmodmap -e "keycode any = Control_R" +xmodmap -e "add Control = Control_L Control_R" +xmodmap -e "keycode any = Alt_L" +xmodmap -e "keycode any = Alt_R" +xmodmap -e "keycode any = Meta_L" +xmodmap -e "add Mod1 = Alt_L Alt_R Meta_L" + + (note: these are applied automatically in the FINDCREATEDISPLAY mode + of x11vnc.) Perhaps the Xvfb options -xkbdb or -xkbmap could be used + to get a better default keyboard mapping... + + Dummy Driver: A user points out a faster and more accurate method is + to use the "dummy" Device Driver of XFree86/Xorg instead of Xvfb. He + uses this to create a persistent and resizable desktop accessible from + anywhere. In the Device Section of the config file set Driver "dummy". + You may also need to set VideoRam NNN to be large enough to hold the + framebuffer. The framebuffer is kept in main memory like Xvfb except + that the server code is closely correlated with the real XFree86/Xorg + Xserver unlike Xvfb. + + The main drawback to this method (besides requiring extra + configuration and possibly root permission) is that it also does the + Linux Virtual Console/Terminal (VC/VT) switching even though it does + not need to (since it doesn't use a real framebuffer.) There are some + "dual headed" (actually multi-headed/multi-user) patches to the X + server that turn off the VT usage in the X server. Update: As of + Jul/2005 we have an LD_PRELOAD script Xdummy that allows you to use a + stock (i.e. unpatched) Xorg or XFree86 server with the "dummy" driver + and not have any VT switching problems! An advantage of Xdummy over + Xvfb is that Xdummy supports RANDR dynamic screen resizing. + + The standard way to start the "dummy" driver would be: +startx -- :1 -config /etc/X11/xorg.conf.dummy + + where the file /etc/X11/xorg.conf.dummy has its Device Section + modified as described above. To use the LD_PRELOAD wrapper script: +startx -- /path/to/Xdummy :1 + + An xdm(1) example is also provided. + + In general, one can use these sorts of schemes to use x11vnc to export + other virtual X sessions, say Xnest or even Xvnc itself (useful for + testing x11vnc.) + + Local access (VNC Server and VNC Viewer on the same machine): You use + a VNC viewer to access the display remotely; to access your virtual X + display locally (i.e. while sitting at the same machine it is running + on) one can perhaps have something like this in their $HOME/.xinitrc +#!/bin/sh +x11vnc -display :5 -rfbport 5905 -bg +vncviewer -geometry +0+0 -encodings raw -passwd $HOME/.vnc/passwd localhost:5 + + The display numbers (VNC and X) will likely be different (you could + also try -find), and you may not need the -passwd. Recent RealVNC + viewers might be this: +#!/bin/sh +x11vnc -display :5 -rfbport 5905 -bg +vncviewer -FullScreen -PreferredEncoding raw -passwd $HOME/.vnc/passwd localhos +t:5 + + This way a bare X server is run with no window manager or desktop; it + simply runs only the VNC Viewer on the real X server. The Viewer then + draws the virtual X session on to the real one. On your system it + might not be $HOME/.xinitrc, but rather .xsession, .Xclients, or + something else. You will need to figure out what it is for your system + and configuration. + + + XDM/GDM/KDM One-Shot X sessions: For the general replacement of Xvnc + by Xvfb+x11vnc, one user describes a similar setup he created where + the X sessions are one-shot's (destroyed after the vncviewer + disconnects) and it uses the XDM/GDM/KDM login greeter here. + + + Q-69: How can I use x11vnc on "headless" machines? Why might I want + to? + + An interesting application of x11vnc is to let it export displays of + "headless" machines. For example, you may have some lab or server + machines with no keyboard, mouse, or monitor, but each one still has a + video card. One can use x11vnc to provide a simple "desktop service" + from these server machines. + + An X server can be started on the headless machine (sometimes this + requires configuring the X server to not fail if it cannot detect a + keyboard or mouse, see the next paragraph.) Then you can export that X + display via x11vnc (e.g. see this FAQ) and access it from anywhere on + the network via a VNC viewer. + + Some tips on getting X servers to start on machines without keyboard + or mouse: For XFree86/Xorg the Option "AllowMouseOpenFail" "true" + "ServerFlags" config file option is useful. On Solaris Xsun the + +nkeyboard and +nmouse options are useful (put them in the server + command line args in /etc/dt/config/Xservers.) There are patches + available for Xsun at lease back to Solaris 8 that support this. See + Xserver(1) for more info. + + Although this usage may sound strange it can be quite useful for a GUI + (or other) testing or QA setups: the engineers do not need to walk to + lab machines running different hardware, OS's, versions, etc (or have + many different machines in their office.) They just connect to the + various test machines over the network via VNC. The advantage to + testing this way instead of using Xvnc or even Xvfb is that the test + is done using the real X server, fonts, video hardware, etc. that will + be used in the field. + + One can imagine a single server machine crammed with as many video + cards as it can hold to provide multiple simultaneous access or + testing on different kinds of video hardware. + + See also the FINDCREATEDISPLAY discussion of the "-display + WAIT:cmd=FINDDISPLAY" option where virtual Xvfb or Xdummy, or real X + servers are started automatically for new users connecting. The -find, + -create, -svc, and -xdmsvc aliases can also come in handy here. + + [Resource Usage and Performance] + + Q-70: I have lots of memory, but why does x11vnc fail with shmget: + No space left on device or Minor opcode of failed request: 1 + (X_ShmAttach)? + + It is not a matter of free memory, but rather free shared memory (shm) + slots, also known as shm segments. This often occurs on a public + Solaris machine using the default of only 100 slots. You (or the owner + or root) can clean them out with ipcrm(1). x11vnc tries hard to + release its slots, but it, and other programs, are not always able to + (e.g. if kill -9'd.) + + Sometimes x11vnc will notice the problem with shm segments and tries + to get by with fewer, only giving a warning like this: + 19/03/2004 10:10:58 shmat(tile_row) failed. + shmat: Too many open files + 19/03/2004 10:10:58 error creating tile-row shm for len=4 + 19/03/2004 10:10:58 reverting to single_copytile mode + + Here is a shell script shm_clear to list and prompt for removal of + your unattached shm segments (attached ones are skipped.) I use it + while debugging x11vnc (I use "shm_clear -y" to assume "yes" for each + prompt.) If x11vnc is regularly not cleaning up its shm segments, + please contact me so we can work to improve the situation. + + Longer term, on Solaris you can put something like this in + /etc/system: + set shmsys:shminfo_shmmax = 0x2000000 + set shmsys:shminfo_shmmni = 0x1000 + + to sweep the problem under the rug (4096 slots.) On Linux, examine + /proc/sys/kernel/shmmni; you can modify the value by writing to that + file. + + Things are even more tight on Solaris 8 and earlier, there is a + default maximum number of shm segments per process of 6. The error is + the X server (not x11vnc) being unable to attach to the segments, and + looks something like this: + 30/04/2004 14:04:26 Got connection from client 192.168.1.23 + 30/04/2004 14:04:26 other clients: + X Error of failed request: BadAccess (attempt to access private resource den +ied) + Major opcode of failed request: 131 (MIT-SHM) + Minor opcode of failed request: 1 (X_ShmAttach) + Serial number of failed request: 14 + Current serial number in output stream: 17 + + This tight limit on Solaris 8 can be increased via: + set shmsys:shminfo_shmseg = 100 + + in /etc/system. See the next paragraph for more workarounds. + + To minimize the number of shm segments used by x11vnc try using the + -onetile option (corresponds to only 3 shm segments used, and adding + -fs 1.0 knocks it down to 2.) If you are having much trouble with shm + segments, consider disabling shm completely via the -noshm option. + Performance will be somewhat degraded but when done over local machine + sockets it should be acceptable (see an earlier question discussing + -noshm.) + + + Q-71: How can I make x11vnc use less system resources? + + The -nap (now on by default; use -nonap to disable) and "-wait n" + (where n is the sleep between polls in milliseconds, the default is 30 + or so) option are good places to start. In addition, something like + "-sb 15" will cause x11vnc to go into a deep-sleep mode after 15 + seconds of no activity (instead of the default 60.) + + Reducing the X server bits per pixel depth (e.g. to 16bpp or even + 8bpp) will further decrease memory I/O and network I/O. The ShadowFB X + server setting will make x11vnc's screen polling less severe. Using + the -onetile option will use less memory and use fewer shared memory + slots (add -fs 1.0 for one less slot.) + + + Q-72: How can I make x11vnc use MORE system resources? + + You can try -threads (note this mode can be unstable and/or crash; and + as of May/2008 is strongly discouraged, see the option description) or + dial down the wait time (e.g. -wait 1) and possibly dial down -defer + as well. Note that if you try to increase the "frame rate" too much + you can bog down the server end with the extra work it needs to do + compressing the framebuffer data, etc. + + That said, it is possible to "stream" video via x11vnc if the video + window is small enough. E.g. a 256x192 xawtv TV capture window (using + the x11vnc -id option) can be streamed over a LAN or wireless at a + reasonable frame rate. If the graphics card's framebuffer read rate is + faster than normal then the video window size and frame rate can be + much higher. The use of TurboVNC and/or TurboJPEG can make the frame + rate somewhat higher still (but most of this hinges on the graphics + card's read rate.) + + + Q-73: I use x11vnc over a slow link with high latency (e.g. dialup + modem or broadband), is there anything I can do to speed things up? + + Some things you might want to experiment with (many of which will help + performance on faster links as well): + + X server/session parameters: + * Configure the X server bits per pixel to be 16bpp or even 8bpp. + (reduces amount of data needed to be polled, compressed, and sent) + * Use a smaller desktop size (e.g. 1024x768 instead of 1280x1024) + * Make sure the desktop background is a solid color (the background + is resent every time it is re-exposed.) Consider using the -solid + [color] option to try to do this automatically. + * Configure your window manager or desktop "theme" to not use fancy + images, shading, and gradients for the window decorations, etc. + Disable window animations, etc. Maybe your desktop has a "low + bandwidth" theme you can easily switch into and out of. Also in + Firefox disable eye-candy, e.g.: Edit -> Preferences -> Advanced + -> Use Smooth Scrolling (deselect it.) + * Avoid small scrolls of large windows using the Arrow keys or + scrollbar. Try to use PageUp/PageDown instead. (not so much of a + problem in x11vnc 0.7.2 if -scrollcopyrect is active and detecting + scrolls for the application.) + * If the -wireframe option is not available (earlier than x11vnc + 0.7.2 or you have disabled it via -nowireframe) then Disable + Opaque Moves and Resizes in the window manager/desktop. + * However if -wireframe is active (on by default in x11vnc 0.7.2) + then you should Enable Opaque Moves and Resizes in the window + manager! This seems counter-intuitive, but because x11vnc detects + the move/resize events early there is a huge speedup over a slow + link when Opaque Moves and Resizes are enabled. (e.g. CopyRect + encoding will be used.) + * Turn off Anti-aliased fonts on your system, web browser, terminal + windows, etc. AA fonts do not compress as well as traditional + fonts (sometimes 10X less.) + * On Firefox/Mozilla (and anything else) turn off "Smooth Scroll" + animations. In Firefox put in the URL "about:config" and set + general.smoothScroll to false. + * On XFree86 turn on the Shadow Framebuffer to speed up reading. + (Option "ShadowFB" "true" in the Device section of + /etc/X11/XF86Config) This disables 2D acceleration on the physical + display and so may not be worth it, but could be of use in some + situations. If the link is very slow, this speedup may not be + noticed. + + VNC viewer parameters: + * Use a TightVNC enabled viewer! (Actually, RealVNC 4.x viewer with + ZRLE encoding is not too bad either; some claim it is faster.) + * Make sure the tight (or zrle) encoding is being used (look at + vncviewer and x11vnc outputs) + * Request 8 bits per pixel using -bgr233 (up to 4X speedup over + depth 24 TrueColor (32bpp), but colors will be off) + * RealVNC 4.x viewer has some extremely low color modes (only 64 and + even 8 colors.) SSVNC does too. The colors are poor, but it is + usually noticeably faster than bgr233 (256 colors.) + * Try increasing the TightVNC -compresslevel (compresses more on + server side before sending, but uses more CPU) + * Try reducing the TightVNC -quality (increases JPEG compression, + but is lossy with painting artifacts) + * Try other VNC encodings via -encodings (tight may be the fastest, + but you should compare it to zrle and maybe some of the others) + * On the machine where vncviewer is run, make sure Backing Store is + enabled (XFree86/Xorg disables it by default causing re-exposures + of vncviewer to be very slow) Option "backingstore" in config + file. + + x11vnc parameters: + * Make sure the -wireframe option is active (it should be on by + default) and you have Opaque Moves/Resizes Enabled in the window + manager. + * Make sure the -scrollcopyrect option is active (it should be on by + default.) This detects scrolls in many (but not all) applications + an applies the CopyRect encoding for a big speedup. + * Enforce a solid background when VNC viewers are connected via + -solid + * Try x11vnc's client-side caching client-side caching scheme: + -ncache + * Specify -speeds modem to force the wireframe and scrollcopyrect + heuristic parameters (and any future ones) to those of a dialup + modem connection (or supply the rd,bw,lat numerical values that + characterize your link.) + * If wireframe and scrollcopyrect aren't working, try using the more + drastic -nodragging (no screen updates when dragging mouse, but + sometimes you miss visual feedback) + * Set -fs 1.0 (disables fullscreen updates) + * Try increasing -wait or -defer (reduces the maximum "frame rate", + but won't help much for large screen changes) + * Try the -progressive pixelheight mode with the block pixelheight + 100 or so (delays sending vertical blocks since they may change + while viewer is receiving earlier ones) + * If you just want to watch one (simple) window use -id or -appshare + (cuts down extraneous polling and updates, but can be buggy or + insufficient) + * Set -nosel (disables all clipboard selection exchange) + * Use -nocursor and -nocursorpos (repainting the remote cursor + position and shape takes resources and round trips) + * On very slow links (e.g. <= 28.8) you may need to increase the + -readtimeout n setting if it sometimes takes more than 20sec to + paint the full screen, etc. + * Do not use -fixscreen to automatically refresh the whole screen, + tap three Alt_L's then the screen has painting errors (rare + problem.) + + + Example for the KDE desktop: + + Launch the "KDE Control Center" utility. Sometimes this is called + "Personal Settings". + + Select "Desktop". + + Then Select "Window Behavior". In the "Moving" Tab set these: + * YES - Display content in moving windows + * YES - Display content in resizing windows + * NO - Display window geometry when moving or resizing + * NO - Animate minimize and restore + + In the "Translucency" Tab set: + * NO - Use translucency/shadows + + Next hit "Back" and then select "Panels". + + In the "Appearance" Tab set: + * NO - Enable icon mouseover effects + * NO - Enable transparency + + Now go all the way back up to the top and Select "Appearance & + Themes". + + Select "Background" and set: + * YES - No picture + * Colors: Single Color + + Select "Fonts" and disable anti-aliased fonts if you are bold enough. + + Select "Launch Feedback" and set: + * Busy Cursor: No Busy Cursor + * NO - Enable taskbar notification + + Select "Screen Saver" and set: + * Screen Saver: Blank Screen + + Select "Style" and in the "Effects" Tab set: + * NO - Enable GUI effects + + + Example for the GNOME desktop: + * TBD. + + + Q-74: Does x11vnc support the X DAMAGE Xserver extension to find + modified regions of the screen quickly and efficiently? + + Yes, as of Mar/2005 x11vnc will use the X DAMAGE extension by default + if it is available on the display. This requires libXdamage to be + available in the build environment as well (recent Linux distros and + Solaris 10 have it.) + + The DAMAGE extension enables the X server to report changed regions of + the screen back to x11vnc. So x11vnc doesn't have to guess where the + changes are (by polling every pixel of the entire screen every 2-4 + seconds.) The use of X DAMAGE dramatically reduces the load when the + screen is not changing very much (i.e. most of the time.) It also + noticeably improves updates, especially for very small changed areas + (e.g. clock ticking, cursor flashing, typing, etc.) + + Note that the DAMAGE extension does not speed up the actual reading of + pixels from the video card framebuffer memory, by, say, mirroring them + in main memory. So reading the fb is still painfully slow (e.g. + 5MB/sec), and so even using X DAMAGE when large changes occur on the + screen the bulk of the time is still spent retrieving them. Not ideal, + but use of the ShadowFB XFree86/Xorg option speeds up the reading + considerably (at the cost of h/w acceleration.) + + Unfortunately the current Xorg DAMAGE extension implementation can at + times be overly conservative and report very large rectangles as + "damaged" even though only a small portion of the pixels have actually + been modified. This behavior is often the fault of the window manager + (e.g. it redraws the entire, unseen, frame window underneath the + application window when it gains focus), or the application itself + (e.g. does large, unnecessary repaints.) + + To work around this deficiency, x11vnc currently only trusts small + DAMAGE rectangles to contain real damage. The larger rectangles are + only used as hints to focus the traditional scanline polling (i.e. if + a scanline doesn't intersect a recent DAMAGE rectangle, the scan is + skipped.) You can use the "-xd_area A" option to adjust the size of + the trusted DAMAGE rectangles. The default is 20000 pixels (e.g. a + 140x140 square, etc.) Use "-xd_area 0" to disable the cutoff and trust + all DAMAGE rectangles. + + The option "-xd_mem f" may also be of use in tuning the algorithm. To + disable using DAMAGE entirely use "-noxdamage". + + + Q-75: My OpenGL application shows no screen updates unless I supply + the -noxdamage option to x11vnc. + One user reports in his environment (MythTV using the NVIDIA OpenGL + drivers) he gets no updates after the initial screen is drawn unless + he uses the "-noxdamage" option. + + This seems to be a bug in the X DAMAGE implementation of that driver. + You may have to use -noxdamage as well. A way to autodetect this will + be tried, probably the best it will do is automatically stop using X + DAMAGE. + + A developer for MiniMyth reports that the 'alphapulse' tag of the + theme G.A.N.T. can also cause problems, and should be avoided when + using VNC. + + Update: see this FAQ too. + + + Q-76: When I drag windows around with the mouse or scroll up and down + things really bog down (unless I do the drag in a single, quick + motion.) Is there anything to do to improve things? + + This problem is primarily due to slow hardware read rates from video + cards: as you scroll or move a large window around the screen changes + are much too rapid for x11vnc to keep up them (it can usually only + read the video card at about 5-10 MB/sec, so it can take a good + fraction of a second to read the changes induce from moving a large + window, if this to be done a number of times in succession the window + or scroll appears to "lurch" forward.) See the description in the + -pointer_mode option for more info. The next bottleneck is compressing + all of these changes and sending them out to connected viewers, + however the VNC protocol is pretty much self-adapting with respect to + that (updates are only packaged and sent when viewers ask for them.) + + As of Jan/2004 there are some improvements to libvncserver. The + default should now be much better than before and dragging small + windows around should no longer be a huge pain. If for some reason + these changes make matters worse, you can go back to the old way via + the "-pointer_mode 1" option. + + Also added was the -nodragging option that disables all screen updates + while dragging with the mouse (i.e. mouse motion with a button held + down.) This gives the snappiest response, but might be undesired in + some circumstances when you want to see the visual feedback while + dragging (e.g. menu traversal or text selection.) + + As of Dec/2004 the -pointer_mode n option was introduced. n=1 is the + original mode, n=2 an improvement, etc.. See the -pointer_mode n help + for more info. + + Also, in some circumstances the -threads option can improve response + considerably. Be forewarned that if more than one vncviewer is + connected at the same time then libvncserver may not be thread safe + (try to get the viewers to use different VNC encodings, e.g. tight and + ZRLE.) This option can be unstable and so as of Feb/2008 it is + disabled by default. Set env. X11VNC_THREADED=1 to re-enable. + + As of Apr/2005 two new options (see the wireframe FAQ and + scrollcopyrect FAQ below) provide schemes to sweep this problem under + the rug for window moves or resizes and for some (but not all) window + scrolls. These are the preferred way of avoiding the "lurching" + problem, contact me if they are not working. Note on SuSE and some + other distros the RECORD X extension used by scrollcopyrect is not + enabled by default, turn it on in xorg.conf: +Section "Module" + ... + Load "record" + ... +EndSection + + + Q-77: Why not do something like wireframe animations to avoid the + windows "lurching" when being moved or resized? + + Nice idea for a hack! As of Apr/2005 x11vnc by default will apply + heuristics to try to guess if a window is being (opaquely) moved or + resized. If such a change is detected framebuffer polling and updates + will be suspended and only an animated "wireframe" (a rectangle + outline drawn where the moved/resized window would be) is shown. When + the window move/resize stops, it returns to normal processing: you + should only see the window appear in the new position. This spares you + from interacting with a "lurching" window between all of the + intermediate steps. BTW the lurching is due to slow video card read + rates (see here too.) A displacement, even a small one, of a large + window requires a non-negligible amount of time, a good fraction of a + second, to read in from the hardware framebuffer. + + Note that Opaque Moves/Resizes must be Enabled by your window manager + for -wireframe to do any good. + + The mode is currently on by default because most people are afflicted + with the problem. It can be disabled with the -nowireframe option (aka + -nowf.) Why might one want to turn off the wireframing? Since x11vnc + is merely guessing when windows are being moved/resized, it may guess + poorly for your window-manager or desktop, or even for the way you + move the pointer. If your window-manager or desktop already does its + own wireframing then this mode is a waste of time and could do the + wrong thing occasionally. There may be other reasons the new mode + feels unnatural. If you have very expensive video hardware (SGI, well + now even proprietary Xorg drivers are fast at reading) or are using an + in-RAM video framebuffer (SunRay, ShadowFB, Xvfb), the read rate from + that framebuffer may be very fast (100's of MB/sec) and so you don't + really see much lurching (at least over a fast LAN): opaque moves look + smooth in x11vnc. Note: ShadowFB is often turned on when you are using + the vesafb or fbdev XFree86 video driver instead of a native one so + you might be using it already and not know. + + The heuristics used to guess window motion or resizing are simple, but + are not fool proof: x11vnc is sometimes tricked and so you'll + occasionally see the lurching opaque move and rarely something even + worse. + + First it assumes that the move/resize will occur with a mouse button + pressed, held down and dragged (of course this is only mostly true.) + Next it will only consider a window for wireframing if the mouse + pointer is initially "close enough" to the edges of the window frame, + e.g. you have grabbed the title bar or a resizer edge (this + requirement can be disabled and it also not applied if a modifier key, + e.g. Alt, is pressed.) If these are true, it will wait an amount of + time to see if the window starts moving or resizing. If it does, it + starts drawing the wireframe "outline" of where the window would be. + When the mouse button is released, or a timeout occurs, it goes back + to the standard mode to allow the actual framebuffer changes to + propagate to the viewers. + + These parameters can be tweaked: + * Color/Shade of the wireframe. + * Linewidth of the outline frame. + * Cutoff size of windows to not apply wireframing to. + * Cutoffs for closeness to Top, Bottom, Left, and Right edges of + window. + * Modifier keys to enable interior window grabbing. + * Maximum time to wait for dragging pointer events. + * Maximum time to wait for the window to start moving/resizing. + * Maximum time to show a wireframe animation. + * Minimum time between sending wireframe outlines. + + See the "-wireframe tweaks" option for more details. On a slow link, + e.g. dialup modem, the parameters may be automatically adjusted for + better response. + + + CopyRect encoding: In addition to the above there is the + "-wirecopyrect mode" option. It is also on by default. This instructs + x11vnc to not only show the wireframe animation, but to also instruct + all connected VNC viewers to locally translate the window image data + from the original position to the new position on the screen when the + animation is done. This speedup is the VNC CopyRect encoding: the + framebuffer update doesn't need to send the actual new image data. + This is nice in general, and very convenient over a slow link, but + since it is based on heuristics you may need to disable it with the + -nowirecopyrect option (aka -nowcr) if it works incorrectly or + unnaturally for you. + + The -wirecopyrect modes are: "never" (same as -nowirecopyrect); "top", + only apply the CopyRect if the window is appears to be on the top of + the window stack and is not obstructed by other windows; and "always" + to always try to apply the CopyRect (obstructed regions are usually + clipped off and not translated.) + + Note that some desktops (KDE and xfce) appear to mess with the window + stacking in ways that are not yet clear. In these cases x11vnc works + around the problem by applying the CopyRect even if obscuring windows' + data is translated! Use -nowirecopyrect if this yields undesirable + effects for your desktop. + + Also, the CopyRect encoding may give incorrect results under -scale + (depending on the scale factor the CopyRect operation is often only + approximate: the correctly scaled framebuffer will be slightly + different from the translated one.) x11vnc will try to push a + "cleanup" update after the CopyRect if -scale is in effect. Use + -nowirecopyrect if this or other painting errors are unacceptable. + + + Q-78: Can x11vnc try to apply heuristics to detect when a window is + scrolling its contents and use the CopyRect encoding for a speedup? + + Another nice idea for a hack! As of May/2005 x11vnc will by default + apply heuristics to try to detect if the window that has the input + focus is scrolling its contents (but only when x11vnc is feeding user + input, keystroke or pointer, to the X server.) So, when detected, + scrolls induced by dragging on a scrollbar or by typing (e.g. Up or + Down arrows, hitting Return in a terminal window, etc), will show up + much more quickly than via the standard x11vnc screen polling update + mechanism. + + There will be a speedup for both slow and fast links to viewers. For + slow links the speedup is mostly due to the CopyRect encoding not + requiring the image data to be transmitted over the network. For fast + links the speedup is primarily due to x11vnc not having to read the + scrolled framebuffer data from the X server (recall that reading from + the hardware framebuffer is slow.) + + To do this x11vnc uses the RECORD X extension to snoop the X11 + protocol between the X client with the focus window and the X server. + This extension is usually present on most X servers (but SuSE disables + it for some reason.) On XFree86/Xorg it can be enabled via Load + "record" in the Module section of the config file if it isn't already: +Section "Module" + ... + Load "record" + ... +EndSection + + Currently the RECORD extension is used as little as possible so as to + not slow down regular use. Only simple heuristics are applied to + detect XCopyArea and XConfigureWindow calls from the application. + These catch a lot of scrolls, e.g. in mozilla/firefox and in terminal + windows like gnome-terminal and xterm. Unfortunately the toolkits KDE + applications use make scroll detection less effective (only rarely are + they detected: i.e. Konqueror and Konsole don't work.) An interesting + project, that may be the direction x11vnc takes, is to record all of + the X11 protocol from all clients and try to "tee" the stream into a + modified Xvfb watching for CopyRect and other VNC speedups. A + potential issue is the RECORD stream is delayed from actual view on + the X server display: if one falls too far behind it could become a + mess... + + The initial implementation of -scrollcopyrect option is useful in that + it detects many scrolls and thus gives a much nicer working + environment (especially when combined with the -wireframe + -wirecopyrect options, which are also on by default; and if you are + willing to enable the ShadowFB things are very fast.) The fact that + there aren't long delays or lurches during scrolling is the primary + improvement. + + But there are some drawbacks: + * Not all scrolls are detected. Some apps scroll windows in ways + that cannot currently be detected, and other times x11vnc "misses" + the scroll due to timeouts, etc. Sometimes it is more distracting + that a speedup occasionally doesn't work as opposed to being + consistently slow! + * For rapid scrolling (i.e. sequence of many scrolls over a short + period) there can be painting errors (tearing, bunching up, etc.) + during the scroll. These will repair themselves after the scroll + is over, but when they are severe it can be distracting. Try to + think of the approximate window contents as a quicker and more + useful "animation" compared to the slower polling scheme... + * Scrolling inside shells in terminal windows (gnome-terminal, + xterm), can lead to odd painting errors. This is because x11vnc + did not have time to detect a screen change just before the scroll + (most common is the terminal undraws the block cursor before + scrolling the text up: in the viewer you temporarily see multiple + block cursors.) Another issue is with things like more(1): scroll + detection for 5-6 lines happens nicely, but then it can't keep up + and so there is a long pause for the standard polling method to + deliver the remaining updates. + * More rarely sometimes painting errors are not repaired after the + scroll is over. This may be a bug in x11vnc or libvncserver, or it + may be an inescapable fact of the CopyRect encoding and the delay + between RECORD callbacks and what is actually on the X display. + One can tap the Alt_L key (Left "Alt" key) 3 times in a row to + signal x11vnc to refresh the screen to all viewers. Your + VNC-viewer may have its own screen refresh hot-key or button. See + also: -fixscreen + * Some applications, notably OpenOffice, do XCopyArea scrolls in + weird ways that assume ancestor window clipping is taking place. + See the -scr_skip option for ways to tweak this on a + per-application basis. + * Selecting text while dragging the mouse may be slower, especially + if the Button-down event happens near the window's edge. This is + because the scrollcopyrect scheme is watching for scrolls via + RECORD and has to wait for a timeout to occur before it does the + update. + * For reasons not yet understood the RECORD extension can stop + responding (and hence scrolls are missed.) As a workaround x11vnc + attempts to reset the RECORD connection every 60 seconds or so. + Another workaround is to type 4 Super_L (Left Super/Windows-Flag + key) in a row to reset RECORD. Work is in progress to try to fix + this bug. + * Sometimes you need to "retrain" x11vnc for a certain window + because it fails to detect scrolls in it. Sometimes clicking + inside the application window or selecting some text in it to + force the focus helps. + * When using the -scale option there will be a quick CopyRect + scroll, but it needs to be followed by a slower "cleanup" update. + This is because for a fixed finite screen resolution (e.g. 75 dpi) + scaling and copyrect-ing are not exactly independent. Scaling + involves a blending of nearby pixels and if you translate a pixel + the neighbor pixel weighting may be different. So you have to wait + a bit for the cleanup update to finish. On slow links x11vnc may + automatically decide to not detect scrolls when -scale is in + effect. In general it will also try to defer the cleanup update if + possible. + + If you find the -scrollcopyrect behavior too approximate or + distracting you can go back to the standard polling-only update method + with the -noscrollcopyrect (or -noscr for short.) If you find some + extremely bad and repeatable behavior for -scrollcopyrect please + report a bug. + + Alternatively, as with -wireframe, there are many tuning parameters to + try to improve the situation. You can also access these parameters + inside the gui under "Tuning". These parameters can be tweaked: + * The minimum pixel area of a rectangle to be watched for scrolls. + * A list if application names to skip scroll detection. + * Which keystrokes should trigger scroll detection. + * Which applications should have a "terminal" tweak applied to them. + * When repeating keys (e.g. Up arrow) should be discarded to + preserve a scroll. + * Cutoffs for closeness to Top, Bottom, Left, and Right edges of + window for mouse induced scrolls. + * Set timeout parameters for keystroke induced scrolls. + * Set timeout parameters for mouse pointer induced scrolls. + * Have the full screen be periodically refreshed to fix painting + errors. + + + Q-79: Can x11vnc do client-side caching of pixel data? I.e. so when + that pixel data is needed again it does not have to be retransmitted + over the network. + + As of Dec/2006 in the 0.9 development tarball there is an experimental + client-side caching implementation enabled by the "-ncache n" option. + In fact, during the test period it was on by default with n set to 10. + To disable it use "-noncache". + + It is a simple scheme where a (very large) lower portion of the + framebuffer (i.e. starting just below the user's actual desktop + display) is used for storing pixel data. CopyRect; a fast, essentially + local viewer-side VNC encoding; is used to swap the pixel data in and + out of the actual display area. It gives an excellent speedup for + iconifying/deiconifying and moving windows and re-posting of menus + (often it doesn't feel like VNC at all: there is no delay waiting for + the pixel data to fill in.) + + This scheme is nice because it does all of this within the existing + VNC protocol, and so it works with all VNC viewers. + + A challenge to doing more sophisticated (e.g. compressed and/or + shared) client-side caching is that one needs to extend the VNC + protocol, modify a viewer and then also convince users to adopt your + modified VNC Viewer (or get the new features to be folded into the + main VNC viewers, patches accepted, etc... likely takes years before + they might be deployed in the field) + + A drawback of the "-ncache n" method is that in the VNC Viewer you can + scroll down and actually see the cached pixel data. So it looks like + there is a bug: you can scroll down in your viewer and see a strange + "history" of windows on your desktop. This is working as intended. One + will need to try to adjust the size of his VNC Viewer window so the + cache area cannot be seen. SSVNC (see below) can do this + automatically. + + At some point LibVNCServer may implement a "rfbFBCrop" pseudoencoding + that viewers can use to learn which portion of the framebuffer to + actually show to the users (with the hidden part used for caching, or + perhaps something else, maybe double buffering or other offscreen + rendering...) + + The Enhanced TightVNC Viewer (SSVNC) Unix viewer has a nice -ycrop + option to help hide the pixel cache area from view. It will turn on + automatically if the framebuffer appears to be very tall (height more + than twice the width), or you can supply the actual value for the + height. If the screen is resized by scaling, etc, the ycrop value is + scaled as well. In fullscreen mode you cannot scroll past the end of + the actual screen, and in non-fullscreen mode the window manager frame + is adjusted to fit the actual display (so you don't see the pixel + cache region) and the scrollbars are very thin to avoid distraction + and trouble fitting inside your display. Use the "-sbwidth n" viewer + option to make the scrollbars thicker if you like. + + Another drawback of the scheme is that it is VERY memory intensive, + the n in "-ncache n" is the factor of increase over the base + framebuffer size to use for caching. It is an even integer and should + be fairly large, 6-12, to achieve good response. This usually requires + about 50-100MB of additional RAM on both the client and server sides. + For example with n=6 a 1280x1024 display will use a framebuffer that + is 1280x7168: everything below row 1024 is the pixel buffer cache. If + you are running on low memory machines or memory is tight because of + other running applications you should not use -ncache. + + The reason for so much memory is because the pixel data is not + compressed and so the whole window to be saved must be stored + "offscreen". E.g. for a large web browser window this can be nearly 1 + million pixels, and that is only for a single window! One typically + wants to cycle between 5-10 large active windows. Also because both + backing-store (the window's actual contents) and save-unders (the + pixels covered up by the window) are cached offscreen that introduces + an additional factor of 2 in memory use. + + However, even in the smallest usage mode with n equal 2 and + -ncache_no_rootpixmap set (this requires only 2X additional + framebuffer memory) there is still a noticable improvement for many + activities, although it is not as dramatic as with, say n equal 12 and + rootpixmap (desktop background) caching enabled. + + The large memory consumption of the current implementation can be + thought of as a tradeoff to providing caching and being compatible + with all VNC viewers and also ease of implementing. Hopefully it can + be tuned to use less, or the VNC community will extend the protocol to + allow caching and replaying of compressed blobs of data. + + Another option to experiment with is "-ncache_cr". By specifying it, + x11vnc will try to do smooth opaque window moves instead of its + wireframe. This can give a very nice effect (note: on Unix the realvnc + viewer seems to be smoother than the tightvnc viewer), but can lead to + some painting problems, and can be jerky in some circumstances. + + Surprisingly, for very slow connections, e.g. modem, the -ncache_cr + option can actually improve window drags. This is probably because no + pixel data (only CopyRect instructions) are sent when dragging a + window. Normally, the wireframe must be sent and this involves + compressing and sending the lines that give rise to the moving box + effect (note that real framebuffer data is sent to "erase" the white + lines of the box.) + + If you experience painting errors you can can tap the Alt_L key (Left + "Alt" key) 3 times in a row to signal x11vnc to refresh the screen to + all viewers. You may also need to iconify and then deiconify any + damaged windows to correct their cache data as well. Note that if you + change color viewer depth (e.g. 8bpp to full color) dynamically that + will usually lead to the entire extended framebuffer being resent + which can take a long time over very slow links: it may be better to + reconnect and reset the format right after doing so. x11vnc will try + to detect the format change and clear (make completely black) the + cache region. + + Gotcha for older Unix VNC Viewers: The older Unix VNC viewers (e.g. + current TightVNC Unix Viewer) require X server backingstore to keep + off-viewer screen data local. If the viewer-side X server has + backingstore disabled (sadly, currently the default on Linux, etc), + then to get the offscreen pixels the viewer has to ask for a refresh + over the network, thereby defeating the caching. Use something like + this in your viewer-side /etc/X11/xorg.conf file (or otherwise get + your viewer-side system to do it) +Section "Device" + ... + Option "backingstore" + ... +EndSection + + No problems like this have been observed with Windows VNC Viewers: + they all seem to keep their entire framebuffer in local memory. Gotcha + for KDE krdc VNC Viewer: One user found that KDE's krdc viewer has + some sort of hardwired limit on the maximum size of the framebuffer + (64MB?). It fails quickly saying "The connection to the host has been + interrupted." The workaround for his 1280x1024 x11vnc-side display was + to run with "-ncache 10", i.e. a smaller value to be under the krdc + threshold. + + Although this scheme is not as quick (nor as compressed) as + nx/nomachine, say, it does provide a good step in the direction of + improving VNC performance by client side caching. + + + Q-80: Does x11vnc support TurboVNC? + + As of Feb/2009 (development tarball) there is an experimental kludge + to let you build x11vnc using TurboVNC's modified TightVNC encoding. + TurboVNC is part of the VirtualGL project. It does two main things to + speed up the TightVNC encoding: + * It eliminates bottlenecks, overheads, wait-times in the TightVNC + encoding implementation and instead only worries about sending + very well (and quickly) compressed JPEG data. + * A fast proprietary JPEG implemention is used (Intel IPP on x86) + instead of the usual libjpeg implementation. TurboJPEG is an + interface library, libturbojpeg, provided by the project that + achieves this. + + TurboVNC works very well over LAN and evidently fast Broadband too. + When using it with x11vnc in such a situation you may want to dial + down the delays, e.g. "-wait 5" and "-defer 5" (or even a smaller + setting) to poll and pump things out more quickly. + + See the instructions in "x11vnc/misc/turbovnc/README" for how to build + x11vnc with TurboVNC support. You will also need to download the + TurboJPEG software. + + In brief, the steps look like this: + cd x11vnc-x.y.z/x11vnc/misc/turbovnc + ./apply_turbovnc + cd ../../.. + env LDFLAGS='-L/DIR -Xlinker --rpath=/DIR' ./configure + make AM_LDFLAGS='-lturbojpeg' + + where you replace "/DIR" with the directory containing libturbojpeg.so + you downloaded separately. If it works out well enough TurboVNC + support will be integrated into x11vnc and more of its tuning features + will be implemented. Support for TurboVNC in SSVNC viewer has been + added as an experiment as well. If you try either one, let us know how + it went. + + There also may be some Linux.i686 and Darwin.i386 x11vnc binaries with + TurboVNC support in the misc. bins directory. For other platforms you + will need to compile yourself. + + On relatively cheap and old hardware (Althon64 X2 5000+ / GeForce + 6200) x11vnc and SSVNC, both TurboVNC enabled, were able to sustain + 13.5 frames/sec (fps) and 15 Megapixels/sec using the VirtualGL + supplied OpenGL benchmark program glxspheres. VirtualGL on higher-end + hardware can sustain 20-30 fps with the glxspheres benchmark. + + Potential Slowdown: As we describe elsewhere, unless you use x11vnc + with an X server using, say, NVidia proprietary drivers (or a virtual + X server like Xvfb or Xdummy, or in ShadowFB mode), then the read rate + from the graphics card can be rather slow (e.g. 10 MB/sec) and becomes + the bottleneck when using x11vnc over fast networks. Note that all of + Xorg's drivers currently (2009) have slow read rates (only proprietary + drivers appear to have optimized reads.) + + So under these (more or less typical) conditions, the speed + improvement provided by TurboVNC may only be marginal. Look for this + output to see your read rate: + 28/02/2009 11:11:07 Autoprobing TCP port + 28/02/2009 11:11:07 Autoprobing selected port 5900 + 28/02/2009 11:11:08 fb read rate: 10 MB/sec + 28/02/2009 11:11:08 screen setup finished. + + A rate of 10 MB/sec means a 1280x1024x24 screen takes 0.5 seconds to + read in. TurboVNC compresses that to JPEG in a much shorter time. On + the other hand, an NVidia driver may have a read rate of 250 MB/sec + and so only takes 0.02 seconds to read the entire screen in. + + + + [Mouse Cursor Shapes] + + Q-81: Why isn't the mouse cursor shape (the little icon shape where + the mouse pointer is) correct as I move from window to window? + + On X servers supporting XFIXES or Solaris/IRIX Overlay extensions it + is possible for x11vnc to do this correctly. See a few paragraphs down + for the answer. + + Historically, the X11 mouse cursor shape (i.e. little picture: an + arrow, X, I-beam, resizer, etc) is one of the few WRITE-only objects + in X11. That is, an application can tell the X server what the cursor + shape should be when the pointer is in a given window, but a program + (like x11vnc) unfortunately cannot read this information. I believe + this is because the cursor shape is often downloaded to the graphics + hardware (video card), but I could be mistaken. + + A simple kludge is provided by the "-cursor X" option that changes the + cursor when the mouse is on the root background (or any window has the + same cursor as the root background.) Note that desktops like GNOME or + KDE often cover up the root background, so this won't work for those + cases. Also see the "-cursor some" option for additional kludges. + + Note that as of Aug/2004 on Solaris using the SUN_OVL overlay + extension and IRIX, x11vnc can show the correct mouse cursor when the + -overlay option is supplied. See this FAQ for more info. + + Also as of Dec/2004 XFIXES X extension support has been added to allow + exact extraction of the mouse cursor shape. XFIXES fixes the problem + of the cursor-shape being write-only: x11vnc can now query the X + server for the current shape and send it back to the connected + viewers. XFIXES is available on recent Linux Xorg based distros and + Solaris 10. + + The only XFIXES issue is the handling of alpha channel transparency in + cursors. If a cursor has any translucency then in general it must be + approximated to opaque RGB values for use in VNC. There are some + situations where the cursor transparency can also handled exactly: + when the VNC Viewer requires the cursor shape be drawn into the VNC + framebuffer or if you apply a patch to your VNC Viewer to extract + hidden alpha channel data under 32bpp. Details can be found here. + + + Q-82: When using XFIXES cursorshape mode, some of the cursors look + really bad with extra black borders around the cursor and other cruft. + How can I improve their appearance? + + This happens for cursors with transparency ("alpha channel"); regular + X cursors (bitmaps) should be correct. Unfortunately x11vnc 0.7 was + released with a very poor algorithm for approximating the + transparency, which led to the ugly black borders. + + The problem is as follows: XFIXES allows x11vnc to retrieve the + current X server cursor shape, including the alpha channel for + transparency. For traditional bitmap cursors the alpha value will be 0 + for completely transparent pixels and 255 for completely opaque + pixels; whereas for modern, eye-candy cursors an alpha value between 0 + and 255 means to blend in the background colors to that degree with + the cursor colors. The pixel color blending formula is something like + this: Red = Red_cursor * a + Red_background * (1 - a), (where here 0 + =< a =< 1), with similar for Green and Blue. The VNC protocol does not + currently support an alpha channel in cursors: it only supports + regular X bitmap cursors and Rich Cursors that have RGB (Red, Green, + Blue) color data, but no "A" = alpha data. So in general x11vnc has to + approximate a cursor with transparency to create a Rich Cursor. This + is easier said than done: some cursor themes have cursors with + complicated drop shadows and other forms of translucency. + + Anyway, for the x11vnc 0.7.1 release the algorithm for approximating + transparency is much improved and hopefully gives decent cursor shapes + for most cursor themes and you don't have to worry about it. + + In case it still looks bad for your cursor theme, there are (of + course!) some tunable parameters. The "-alphacut n" option lets you + set the threshold "n" (between 0 and 255): cursor pixels with alpha + values below n will be considered completely transparent while values + equal to or above n will be completely opaque. The default is 240. The + "-alphafrac f" option tries to correct individual cursors that did not + fare well with the default -alphacut value: if a cursor has less than + fraction f (between 0.0 and 1.0) of its pixels selected by the default + -alphacut, the threshold is lowered until f of its pixels are + selected. The default fraction is 0.33. + + Finally, there is an option -alpharemove that is useful for themes + where many cursors are light colored (e.g. "whiteglass".) XFIXES + returns the cursor data with the RGB values pre-multiplied by the + alpha value. If the white cursors look too grey, specify -alpharemove + to brighten them by having x11vnc divide out the alpha value. + + One user played with these parameters and reported back: + Of the cursor themes present on my system: + + gentoo and gentoo-blue: alphacut:192 - noalpharemove + + gentoo-silver: alphacut:127 and alpharemove + + whiteglass and redglass (presumably also handhelds, which is based + heavily on redglass) look fine with the apparent default of alphacut:255. + + + Q-83: In XFIXES mode, are there any hacks to handle cursor + transparency ("alpha channel") exactly? + + As of Jan/2005 libvncserver has been modified to allow an alpha + channel (i.e. RGBA data) for Rich Cursors. So x11vnc can now send the + alpha channel data to libvncserver. However, this data will only be + used for VNC clients that do not support the CursorShapeUpdates VNC + extension (or have disabled it.) It can be disabled for all clients + with the -nocursorshape x11vnc option. In this case the cursor is + drawn, correctly blended with the background, into the VNC framebuffer + before being sent out to the client. So the alpha blending is done on + the x11vnc side. Use the -noalphablend option to disable this behavior + (always approximate transparent cursors with opaque RGB values.) + + The CursorShapeUpdates VNC extension complicates matters because the + cursor shape is sent to the VNC viewers supporting it, and the viewers + draw the cursor locally. This improves response over slow links. Alpha + channel data for these locally drawn cursors is not supported by the + VNC protocol. + + However, in the libvncserver CVS there is a patch to the TightVNC + viewer to make this work for CursorShapeUpdates under some + circumstances. This hack is outside of the VNC protocol. It requires + the screens on both sides to be depth 24 at 32bpp (it uses the extra 8 + bits to secretly hide the cursor alpha channel data.) Not only does it + require depth 24 at 32bpp, but it also currently requires the client + and server to be of the same endianness (otherwise the hidden alpha + data gets reset to zero by a libvncserver translation function; we can + fix this at some point if there is interest.) The patch is for the + TightVNC 1.3dev5 Unix vncviewer and it enables the TightVNC viewer to + do the cursor alpha blending locally. The patch code should give an + example on how to change the Windows TightVNC viewer to achieve the + same thing (send me the patch if you get that working.) + + This patch is applied to the Enhanced TightVNC Viewer (SSVNC) package + we provide. + + [Mouse Pointer] + + Q-84: Why does the mouse arrow just stay in one corner in my + vncviewer, whereas my cursor (that does move) is just a dot? + + This default takes advantage of a tightvnc extension + (CursorShapeUpdates) that allows specifying a cursor image shape for + the local VNC viewer. You may disable it with the -nocursor option to + x11vnc if your viewer does not have this extension. + + Note: as of Aug/2004 this should be fixed: the default for + non-tightvnc viewers (or ones that do not support CursorShapeUpdates) + will be to draw the moving cursor into the x11vnc framebuffer. This + can also be disabled via -nocursor. + + + Q-85: Can I take advantage of the TightVNC extension to the VNC + protocol where Cursor Positions Updates are sent back to all connected + clients (i.e. passive viewers can see the mouse cursor being moved + around by another viewer)? + + Use the -cursorpos option when starting x11vnc. A VNC viewer must + support the Cursor Positions Updates for the user to see the mouse + motions (the TightVNC viewers support this.) As of Aug/2004 -cursorpos + is the default. See also -nocursorpos and -nocursorshape. + + + Q-86: Is it possible to swap the mouse buttons (e.g. left-handed + operation), or arbitrarily remap them? How about mapping button clicks + to keystrokes, e.g. to partially emulate Mouse wheel scrolling? + + You can remap the mouse buttons via something like: -buttonmap 13-31 + (or perhaps 12-21.) Also, note that xmodmap(1) lets you directly + adjust the X server's button mappings, but in some circumstances it + might be more desirable to have x11vnc do it. + + One user had an X server with only one mouse button(!) and was able to + map all of the VNC client mouse buttons to it via: -buttonmap 123-111. + + Note that the -debug_pointer option prints out much info for every + mouse/pointer event and is handy in solving problems. + + To map mouse button clicks to keystrokes you can use the alternate + format where the keystrokes are enclosed between colons like this + :: in place of the mouse button digit. For a sequence of + keysyms separate them with "+" signs. Look in the include file + , or use xev(1), or -debug_keyboard to find the + keysym names. Button clicks can also be included in the sequence via + the fake keysyms Button1, etc. + + As an example, suppose the VNC viewer machine has a mouse wheel (these + generate button 4 and 5 events), but the machine that x11vnc is run on + only has the 3 regular buttons. In normal operation x11vnc will + discard the button 4 and 5 events. However, either of the following + button maps could possibly be of use emulating the mouse wheel events + in this case: + -buttonmap 12345-123:Prior::Next: + -buttonmap 12345-123:Up+Up+Up::Down+Down+Down: + + Exactly what keystroke "scrolling" events they should be bound to + depends on one's taste. If this method is too approximate, one could + consider not using -buttonmap but rather configuring the X server to + think it has a mouse with 5 buttons even though the physical mouse + does not. (e.g. 'Option "ZAxisMapping" "4 5"'.) + + Note that when a keysym-mapped mouse button is clicked down this + immediately generates the key-press and key-release events (for each + keysym in turn if the mapping has a sequence of keysyms.) When the + mouse button goes back up nothing is generated. + + If you include modifier keys like Shift_L instead of key-press + immediately followed by key-release the state of the modifier key is + toggled (however the initial state of the modifier key is ignored.) So + to map the right button to type my name 'Karl Runge' I could use this: + -buttonmap 3-:Shift_L+k+Shift_L+a+r+l+space+Shift_L+r+Shift_L+u+n+g+e: + + (yes, this is getting a little silly.) + + BTW, Coming the other way around, if the machine you are sitting at + does not have a mouse wheel, but the remote machine does (or at least + has 5 buttons configured), this key remapping can be useful: + -remap Super_R-Button4,Menu-Button5 + + you just tap those two keys to get the mouse wheel scrolls (this is + more useful than the Up and Down arrow keys because a mouse wheel + "click" usually gives a multi-line scroll.) + [Keyboard Issues] + + Q-87: How can I get my AltGr and Shift modifiers to work between + keyboards for different languages? + + The option -modtweak should help here. It is a mode that monitors the + state of the Shift and AltGr Modifiers and tries to deduce the correct + keycode to send, possibly by sending fake modifier key presses and + releases in addition to the actual keystroke. + + Update: As of Jul/2004 -modtweak is now the default (use -nomodtweak + to get the old behavior.) This was done because it was noticed on + newer XFree86 setups even on bland "us" keyboards like "pc104 us" + XFree86 included a "ghost" key with both "<" and ">" it. This key does + not exist on the keyboard (see this FAQ for more info.) Without + -modtweak there was then an ambiguity in the reverse map keysym => + keycode, making it so the "<" symbol could not be typed. + + Also see the FAQ about the -xkb option for a more powerful method of + modifier tweaking for use on X servers with the XKEYBOARD extension. + + When trying to resolve keyboard mapping problems, note that the + -debug_keyboard option prints out much info for every keystroke and so + can be useful debugging things. + + Note that one user had a strange setup and none of the above helped. + His solution was to disable all of the above and use -nomodtweak. This + is the simplest form of keystroke insertion and it actually solved the + problem. Try it if the other options don't help. + + + Q-88: When I try to type a "<" (i.e. less than) instead I get ">" + (i.e. greater than)! Strangely, typing ">" works OK!! + + Does your keyboard have a single key with both "<" and ">" on it? Even + if it doesn't, your X server may think your keyboard has such a key + (e.g. pc105 in the XF86Config file when it should be something else, + say pc104.) + + Short Cut: Try the -xkb or -sloppy_keys options and see if that helps + the situation. The discussion below is a bit outdated (e.g. -modtweak + is now the default) but it is useful reference for various tricks and + so is kept. + + + The problem here is that on the Xserver where x11vnc is run there are + two keycodes that correspond to the "<" keysym. Run something like + this to see: + + xmodmap -pk | egrep -i 'KeyCode|less|greater' + There are 4 KeySyms per KeyCode; KeyCodes range from 8 to 255. + KeyCode Keysym (Keysym) ... + 59 0x002c (comma) 0x003c (less) + 60 0x002e (period) 0x003e (greater) + 94 0x003c (less) 0x003e (greater) + + That keycode 94 is the special key with both "<" and ">". When x11vnc + receives the "<" keysym over the wire from the remote VNC client, it + unfortunately maps it to keycode 94 instead of 59, and sends 94 to the + X server. Since Shift is down (i.e. you are Shifting the comma key), + the X server interprets this as Shifted-94, which is ">". + + A workaround in the X server configuration is to "deaden" that special + key: + + xmodmap -e "keycode 94 = " + + However, one user said he had to do this: + + xmodmap -e "keycode 94 = 0x002c 0x003c" + + (If the numerical values are different for your setup, substitute the + ones that correspond to your display. The above xmodmap scheme can + often be used to work around other ambiguous keysym to keycode + mappings.) + + Alternatively, here are some x11vnc options to try to work around the + problem: + -modtweak + + and + -remap less-comma + + These are convenient in that they do not modify the actual X server + settings. The former (-modtweak) is a mode that monitors the state of + the Shift and AltGr modifiers and tries to deduce the correct keycode + sequence to send. Since Jul/2004 -modtweak is now the default. The + latter (-remap less-comma) is an immediate remapping of the keysym + less to the keysym comma when it comes in from a client (so when Shift + is down the comma press will yield "<".) + + See also the FAQ about the -xkb option as a possible workaround using + the XKEYBOARD extension. + + Note that the -debug_keyboard option prints out much info for every + keystroke to aid debugging keyboard problems. + + + Q-89: Extra Character Inserted, E.g.: When I try to type a "<" (i.e. + less than) instead I get "<," (i.e. an extra comma.) + + This is likely because you press "Shift" then "<" but then released + the Shift key before releasing the "<". Because of a keymapping + ambiguity the last event "< up" is interpreted as "," because that key + unshifted is the comma. + + This extra character insertion will happen for other combinations of + characters: in general it can happen whenever the Shift key is + released early. + + This should not happen in -xkb mode, because it works hard to resolve + the ambiguities. If you do not want to use -xkb, try the option + -sloppy_keys to attempt a similar type of algorithm. + + One user had this problem for Italian and German keyboards with the + key containing ":" and "." When he typed ":" he would get an extra "." + inserted after the ":". The solution was -sloppy_keys. + + + Q-90: I'm using an "international" keyboard (e.g. German "de", or + Danish "dk") and the -modtweak mode works well if the VNC viewer is + run on a Unix/Linux machine with a similar keyboard. But if I run + the VNC viewer on Unix/Linux with a different keyboard (e.g. "us") or + Windows with any keyboard, I can't type some keys like: "@", "$", + "<", ">", etc. How can I fix this? + + The problem with Windows is it does not seem to handle AltGr well. It + seems to fake it up by sending Control_L+Alt_R to applications. The + Windows VNC viewer sends those two down keystrokes out on the wire to + the VNC server, but when the user types the next key to get, e.g., "@" + the Windows VNC viewer sends events bringing the up the + Control_L+Alt_R keys, and then sends the "@" keysym by itself. + + The Unix/Linux VNC viewer on a "us" keyboard does a similar thing + since "@" is the Shift of the "2" key. The keysyms Shift and "@" are + sent to the VNC server. + + In both cases no AltGr is sent to the VNC server, but we know AltGr is + needed on the physical international keyboard to type a "@". + + This all worked fine with x11vnc running with the -modtweak option (it + figures out how to adjust the Modifier keys (Shift or AltGr) to get + the "@".) However it fails under recent versions of XFree86 (and the + X.org fork.) These run the XKEYBOARD extension by default and make + heavy use of it to handle international keyboards. + + To make a long story short, on these newer XFree86 setups the + traditional X keymap lookup x11vnc uses is no longer accurate. x11vnc + can't find the keysym "@" anywhere in the keymapping! (even though it + is in the XKEYBOARD extended keymapping.) + + How to Solve: As of Jul/2004 x11vnc has two changes: + * -modtweak (tweak Modifier keys) is now the default (use + -nomodtweak to go back to the old way) + * there is a new option -xkb to use the XKEYBOARD extension API to + do the Modifier key tweaking. + + The -xkb option seems to fix all of the missing keys: "@", "<", ">", + etc.: it is recommended that you try it if you have this sort of + problem. Let us know if there are any remaining problems (see the next + paragraph for some known problems.) If you specify the -debug_keyboard + (aka -dk) option twice you will get a huge amount of keystroke + debugging output (send it along with any problems you report.) + + Update: as of Jun/2005 x11vnc will try to automatically enable -xkb if + it appears that would be beneficial (e.g. if it sees any of "@", "<", + ">", "[" and similar keys are mapped in a way that needs the -xkb to + access them.) To disable this automatic check use -noxkb. + + Known problems: + * One user had to disable a "ghost" Mode_switch key that was causing + problems under -xkb. His physical AltGr key was bound to + ISO_Level3_Shift (which seems to be the XKEYBOARD way of doing + things), while there was a ghost key Mode_switch (which seems to + be obsolete) in the mapping as well. Both of these keysyms were + bound to Mod5 and x11vnc was unfortunately choosing Mode_switch. + From the x11vnc -xkb -dk -dk output it was noted that Mode_switch + was attached to keycode 93 (no physical key generates this + keycode) while ISO_Level3_Shift was attached to keycode 113. The + keycode skipping option was used to disable the ghost key: + -skip_keycodes 93 + * In implementing -xkb we noticed that some characters were still + not getting through, e.g. "~" and "^". This is not really an + XKEYBOARD problem. What was happening was the VNC viewer was + sending the keysyms asciitilde and asciicircum to x11vnc, but on + the X server with the international keyboard those keysyms were + not mapped to any keys. So x11vnc had to skip them (Note: as of + May/2005 they are added by default see -add_keysyms below.) + The way these characters are typically entered on international + keyboards is by "dead" (aka "mute") keys. E.g. to enter "~" at the + physical display the keysym dead_tilde is pressed and released + (this usually involves holding AltGr down while another key is + pressed) and then space is pressed. (this can also be used get + characters with the "~" symbol on top, e.g. "ã" by typing "a" + instead of space.) + What to do? In general the VNC protocol has not really solved this + problem: what should be done if the VNC viewer sends a keysym not + recognized by the VNC server side? Workarounds can possibly be + created using the -remap x11vnc option: + -remap asciitilde-dead_tilde,asciicircum-dead_circumflex + etc. Use -remap filename if the list is long. Please send us your + workarounds for this problem on your keyboard. Perhaps we can have + x11vnc adjust automatically at some point. Also see the + -add_keysyms option in the next paragraph. + Update: for convenience "-remap DEAD" does many of these mappings + at once. + * To complement the above workaround using the -remap, an option + -add_keysyms was added. This option instructs x11vnc to bind any + unknown Keysyms coming in from VNC viewers to unused Keycodes in + the X server. This modifies the global state of the X server. When + x11vnc exits it removes the extra keymappings it created. Note + that the -remap mappings are applied first, right when the Keysym + is received from a VNC viewer, and only after that would + -add_keysyms, or anything else, come into play. + Update: -add_keysyms is now on by default. Use -noadd_keysyms to + disable. + + + Q-91: When typing I sometimes get double, triple, or more of my + keystrokes repeated. I'm sure I only typed them once, what can I do? + + This may be due to an interplay between your X server's key autorepeat + delay and the extra time delays caused by x11vnc processing. + + Short answer: disable key autorepeating by running the command "xset r + off" on the Xserver where x11vnc is run (restore via "xset r on") or + use the new (Jul/2004) -norepeat x11vnc option. You will still have + autorepeating because that is taken care of on your VNC viewer side. + + Update: as of Dec/2004 -norepeat is now the default. Use -repeat to + disable it. + + Details: + suppose you press a key DOWN and it generates changes in large regions + of the screen. The CPU and I/O work x11vnc does for the large screen + change could be longer than your X server's key autorepeat delay. + x11vnc may not get to processing the key UP event until after the + screen work is completed. The X server believes the key has been held + down all this time, and applies its autorepeat rules. + + Even without inducing changes in large regions of the screen, this + problem could arise when accessing x11vnc via a dialup modem or + otherwise high latency link (e.g. > 250 ms latency.) + + Look at the output of "xset q" for the "auto repeat delay" setting. Is + it low (e.g. < 300 ms)? If you turn off autorepeat completely: "xset r + off", does the problem go away? + + The workaround is to manually apply "xset r off" and "xset r on" as + needed, or to use the -norepeat (which has since Dec/2004 been made + the default.) Note that with X server autorepeat turned off the VNC + viewer side of the connection will (nearly always) do its own + autorepeating so there is no big loss here, unless someone is also + working at the physical display and misses his autorepeating. + + + Q-92: The x11vnc -norepeat mode is in effect, but I still get repeated + keystrokes!! + + Are you using x11vnc to log in to an X session via display manager? + (as described in this FAQ) If so, x11vnc is starting before your + session and it disables autorepeat when you connect, but then after + you log in your session startup (GNOME, KDE, ...) could be resetting + the autorepeat to be on. Or it could be something inside your desktop + trying to be helpful that decides to turn it back on. + + x11vnc in -norepeat mode will by default reset autorepeat to off 2 + times (to help get thru the session startup problem), but it will not + continue to battle with things turning autorepeat back on. It will + also turn autorepeat off whenever it goes from a state of zero clients + to one client. You can adjust the number of resets via "-norepeat N", + or use "-norepeat -1" to have it keep resetting it whenever autorepeat + gets turned back on when clients are connected. + + In general you can manually turn autorepeating off by typing "xset r + off", or a using desktop utility/menu, or "x11vnc -R norepeat". If + something in your desktop is automatically turning it back on you + should figure out how to disable that somehow. + + + Q-93: After using x11vnc for a while, I find that I cannot type some + (or any) characters or my mouse clicks and drags no longer have any + effect, or they lead to strange effects. What happened? + + Probably a modifier key, e.g. Control or Alt is "stuck" in a pressed + down state. + + This happens for VNC in general by the following mechanism. Suppose on + the Viewer side desktop there is some hot-key to switch + desktops/rooms/spaces, etc. E.g. suppose Alt+LeftArrow moves to the + left desktop/room/space. Or suppose an Alt+hotkey combination + iconifies a window. This can leave the Alt key pressed down on the + remote side. + + Consider the sequence that happens. The Alt_L key and then the + LeftArrow key go down. Since you are inside the viewer the Alt_L key + press is sent to the other side (x11vnc) and so it is pressed down in + the remote desktop as well. (by "Alt_L" we mean the Alt key on the + left-hand side of the keyboard.) Your local desktop (where the VNC + Viewer is running) then warps to the new desktop/room/space: Leaving + the Alt_L key still pressed down in the remote desktop. + + If someone is sitting at the desktop, or when you return in the viewer + it may be very confusing because the Alt_L is still pressed down but + you (or the person sitting at the desktop) do not realize this. + Depending on which remote desktop (x11vnc side) is used, it can act + very strangely. + + A quick workaround when you notice this is to press and release all of + the Alt, Shift, Control, Windows-Flag, modifier keys to free the + pressed one. You need to do this for both the left and right Shift, + Alt, Control, etc. keys to be sure. + + Note that many VNC Viewers try to guard against this when they are + notified by the window system that the viewer app has "lost focus". + When it receives the "lost focus" event, the viewer sends VNC + Key-Release events for all modifier keys that are currently pressed + down. This does not always work, however, since it depends on how the + desktop manages these "warps". If the viewer is not notified it cannot + know it needs to release the modifiers. + + You can also use the -clear_mods option to try to clear all of the + modifier keys at x11vnc startup. You will still have to be careful + that you do not leave the modifier key pressed down during your + session. It is difficult to prevent this problem from occurring (short + of using -remap to prevent sending all of the problem modifier keys, + which would make the destkop pretty unusable.) + + During a session these x11vnc remote control commands can also help: + x11vnc -R clear_mods + x11vnc -R clear_keys + x11vnc -R clear_locks + x11vnc -R clear_all + + A similar problem can occur if you accidentally press the Caps_Lock or + Num_Lock down. When these are locked on the remote side it can + sometimes lead to strange desktop behavior (e.g. cannot drag or click + on windows.) As above you may not notice this because the lock isn't + down on the local (Viewer) side. See this FAQ on lock keys problem. + These options may help avoid the problem: -skip_lockkeys and + -capslock. See also -clear_all. + + + Q-94: The machine where I run x11vnc has an AltGr key, but the local + machine where I run the VNC viewer does not. Is there a way I can map + a local unused key to send an AltGr? How about a Compose key as well? + + Something like "-remap Super_R-Mode_switch" x11vnc option may work. + Note that Super_R is the "Right Windoze(tm) Flaggie" key; you may want + to choose another. The -debug_keyboard option comes in handy in + finding keysym names (so does xev(1).) + + For Compose how about "-remap Menu-Multi_key" (note that Multi_key is + the official name for Compose.) To do both at the same time: "-remap + Super_R-Mode_switch,Menu-Multi_key" or use "-remap filename" to + specify remappings from a file. + + + Q-95: I have a Sun machine I run x11vnc on. Its Sun keyboard has just + one Alt key labelled "Alt" and two Meta keys labelled with little + diamonds. The machine where I run the VNC viewer only has Alt keys. + How can I send a Meta keypress? (e.g. emacs needs this) + + Here are a couple ideas. The first one is to simply use xmodmap(1) to + adjust the Sun X server. Perhaps xmodmap -e "keysym Alt_L = Meta_L + Alt_L" will do the trick. (there are other ways to do it, one user + used: xmodmap -e "keycode 26 = Meta_L" for his setup.) + + Since xmodmap(1) modifies the X server mappings you may not want to do + this (because it affects local work on that machine.) Something like + the -remap Alt_L-Meta_L to x11vnc may be sufficient for ones needs, + and does not modify the X server environment. Note that you cannot + send Alt_L in this case, maybe -remap Super_L-Meta_L would be a better + choice if the Super_L key is typically unused in Unix. + + + Q-96: Running x11vnc on HP-UX I cannot type "#" I just get a "3" + instead. + + One user reports this problem on HP-UX Rel_B.11.23. The problem was + traced to a strange keyboard mapping for the machine (e.g. xmodmap -pk + output) that looked like: + ... + 039 2 at at at + ... + 047 3 numbersign numbersign numbersign + + and similar triple mappings (with two in the AltGr/Mode_switch group) + of a keysum to a single keycode. + + Use the -nomodtweak option as a workaround. You can also use xmodmap + to correct these mappings in the server, e.g.: + xmodmap -e "keycode 47 = 3 numbersign" + + Also, as of Feb/2007, set the environment variable MODTWEAK_LOWEST=1 + (either in your shell or via "-env MODTWEAK_LOWEST=1" option) to + handle these mappings better. + + + Q-97: Can I map a keystroke to a mouse button click on the remote + machine? + + This can be done directly in some X servers using AccessX and + Pointer_EnableKeys, but is a bit awkward. It may be more convenient to + have x11vnc do the remapping. This can be done via the -remap option + using the fake "keysyms" Button1, Button2, etc. as the "to" keys (i.e. + the ones after the "-") + + As an example, consider a laptop where the VNC viewer is run that has + a touchpad with only two buttons. It is difficult to do a middle + button "paste" because (using XFree86/Xorg Emulate3Buttons) you have + to click both buttons on the touch pad at the same time. This + remapping: + -remap Super_R-Button2 + + maps the Super_R "flag" key press to the Button2 click, thereby making + X pasting a bit easier. + + Note that once the key goes down, the button down and button up events + are generated immediately on the x11vnc side. When the key is released + (i.e. goes up) no events are generated. + + Q-98: How can I get Caps_Lock to work between my VNC viewer and + x11vnc? + + This is a little tricky because it is possible to get the Caps_Lock + state out of sync between your viewer-side machine and the x11vnc-side + X server. For best results, we recommend not ever letting the + Caps_Lock keypresses be processed by x11vnc. That way when you press + Caps_Lock in the viewer your local machine goes into the Caps_Lock on + state and sends keysym "A" say when you press "a". x11vnc will then + fake things up so that Shift is held down to generate "A". The + -skip_lockkeys option should help to accomplish this. For finer grain + control use something like: "-remap Caps_Lock-None". + + Also try the -nomodtweak and -capslock options. + + Another useful option that turns off any Lock keys on the remote side + at startup and end is the -clear_all option. During a session you can + run these remote control commands to modify the Lock keys: + x11vnc -R clear_locks + x11vnc -R clear_all + + the former will try to unset any Lock keys, the latter will do same + and also try to make it so no key is pressed down (e.g. "stuck" Alt_L, + etc.) + [Screen Related Issues and Features] + + Q-99: The remote display is larger (in number of pixels) than the + local display I am running the vncviewer on. I don't like the + vncviewer scrollbars, what I can do? + + vncviewer has a option (usually accessible via F8 key or -fullscreen + option) for vncviewer to run in full screen, where it will + automatically scroll when the mouse is near the edge of the current + view. For quick scrolling, also make sure Backing Store is enabled on + the machine vncviewer is run on. (XFree86/Xorg disables it by default + for some reason, add Option "backingstore" to XF86Config on the + vncviewer side.) + + BTW, contact me if you are having problems with vncviewer in + fullscreen mode with your window manager (i.e. no keyboard response.) + I have a workaround for vncviewer using XGrabServer(). + + There may also be scaling viewers out there (e.g. TightVNC or UltraVNC + on Windows) that automatically shrink or expand the remote framebuffer + to fit the local display. Especially for hand-held devices. See also + the next FAQ on x11vnc scaling. + + + Q-100: Does x11vnc support server-side framebuffer scaling? (E.g. to + make the desktop smaller.) + + As of Jun/2004 x11vnc provides basic server-side scaling. It is a + global scaling of the desktop, not a per-client setting. To enable it + use the "-scale fraction" option. "fraction" can either be a floating + point number (e.g. -scale 0.75) or the alternative m/n fraction + notation (e.g. -scale 3/4.) Note that if fraction is greater than one + the display is magnified. + + Extra resources (CPU, memory I/O, and memory) are required to do the + scaling. If the machine is slow where x11vnc is run with scaling + enabled, the interactive response can be unacceptable. OTOH, if run + with scaling on a fast machine the performance degradation is usually + not a big issue or even noticeable. + + It may help to compile x11vnc with compiler option -O3 or -O4 to speed + up the scaling code. Set the CFLAGS env. var. before running + configure. + + Also, if you just want a quick, rough "thumbnail" of the display you + can append ":nb" to the fraction to turn on "no blending" mode. E.g.: + "-scale 1/3:nb" Fonts will be difficult to read, but the larger + features will be recognizable. BTW, "no blending" mode is forced on + when scaling 8bpp PseudoColor displays (because blending an indexed + colormap is a bad idea and leads to random colors, use :fb to force it + on.) + + One can also use the ":nb" with an integer scale factor (say "-scale + 2:nb") to use x11vnc as a screen magnifier for vision impaired + applications. Since with integer scale factors the framebuffers become + huge and scaling operations time consuming, be sure to use ":nb" for + the fastest response. + + In general for a scaled display if you are using a TightVNC viewer you + may want to turn off jpeg encoding (e.g. vncviewer -nojpeg host:0.) + There appears to be a noise enhancement effect, especially for regions + containing font/text: the scaling can introduce some pixel artifacts + that evidently causes the tight encoding algorithm to incorrectly + detect the regions as image data and thereby introduce additional + pixel artifacts due to the lossiness of the jpeg compression + algorithm. Experiment to see if -nojpeg vncviewer option improves the + readability of text when using -scale to shrink the display size. Also + note that scaling may actually slow down the transfer of text regions + because after being scaled they do not compress as well. (this can + often be a significant slowdown, e.g. 10X.) + + Another issue is that it appears VNC viewers require the screen width + to be a multiple of 4. When scaling x11vnc will round the width to the + nearest multiple of 4. To disable this use the ":n4" sub option (like + ":nb" in the previous paragraph; to specify both use a comma: + ":nb,n4", etc.) + + If one desires per-client scaling for something like 1:1 from a + workstation and 1:2 from a smaller device (e.g. handheld), currently + the only option is to run two (or more) x11vnc processes with + different scalings listening on separate ports (-rfbport option, etc.) + + Update: As of May/2006 x11vnc also supports the UltraVNC server-side + scaling. This is a per-client scaling by factors 1/2, 1/3, ... and so + may be useful for PDA's ("-scale 1/2", etc. will give similar results + except that it applies to all clients.) You may need to supply + "-rfbversion 3.6" for this to be recognized by UltraVNC viewers. + + BTW, whenever you run two or more x11vnc's on the same X display and + use the GUI, then to avoid all of the x11vnc's simultaneously + answering the gui you will need to use something like "-connect file1 + -gui ..." with different connect files for each x11vnc you want to + control via the gui (or remote-control.) The "-connect file1" usage + gives separate communication channels between a x11vnc process and the + gui process. Otherwise they all share the same X property channels: + VNC_CONNECT and X11VNC_REMOTE. + + Update: As of Mar/2005 x11vnc now scales the mouse cursor with the + same scale factor as the screen. If you don't want that, use the + "-scale_cursor frac" option to set the cursor scaling to a different + factor (e.g. use "-scale_cursor 1" to keep the cursor at its natural + unscaled size.) + + + Q-101: Does x11vnc work with Xinerama? (i.e. multiple monitors joined + together to form one big, single screen.) + + Yes, it should generally work because it simply polls the big + effective screen. + + If the viewing-end monitor is not as big as the remote Xinerama + display, then the vncviewer scrollbars, etc, will have to be used to + pan across the large area. However one user started two x11vnc's, one + with "-clip 1280x1024+0+0" and the other with "-clip 1280x1024+1280+0" + to split the big screen into two and used two VNC viewers to access + them. + + As of Jun/2008: Use "-clip xinerama0" to clip to the first xinerama + sub-screen (if xinerama is active.) xinerama1 for the 2nd sub-screen, + etc. This way you don't need to figure out the WxH+X+Y of the desired + xinerama sub-screen. screens are sorted in increasing distance from + the (0,0) origin (I.e. not the Xserver's order.) + + There are a couple potential issues with Xinerama however. If the + screen is not rectangular (e.g. 1280x1024 and 1024x768 monitors joined + together), then there will be "non-existent" areas on the screen. The + X server will return "garbage" image data for these areas and so they + may be distracting to the viewer. The -blackout x11vnc option allows + you to blacken-out rectangles by manually specifying their WxH+X+Y + geometries. If your system has the libXinerama library, the -xinerama + x11vnc option can be used to have it automatically determine the + rectangles to be blackened out. (Note on 8bpp PseudoColor displays the + fill color may not be black.) Update: -xinerama is now on by default. + + Some users have reported that the mouse does not behave properly for + their Xinerama display: i.e. the mouse cannot be moved to all regions + of the large display. If this happens try using the -xwarppointer + option. This instructs x11vnc to fake mouse pointer motions using the + XWarpPointer function instead of the XTestFakeMotionEvent XTEST + function. (This may be due to a bug in the X server for XTEST when + Xinerama is enabled.) Update: As of Dec/2006 -xwarppointer will be + applied automatically if Xinerama is detected. To disable use: + -noxwarppointer + + + Q-102: Can I use x11vnc on a multi-headed display that is not Xinerama + (i.e. separate screens :0.0, :0.1, ... for each monitor)? + + You can, but it is a little bit awkward: you must start separate + x11vnc processes for each screen, and on the viewing end start up + separate VNC viewer processes connecting to them. e.g. on the remote + end: + x11vnc -display :0.0 -bg -q -rfbport 5900 + x11vnc -display :0.1 -bg -q -rfbport 5901 + + (this could be automated in the display manager Xsetup for example) + and then on the local machine where you are sitting: + vncviewer somehost:0 & + vncviewer somehost:1 & + + Note: if you are running on Solaris 8 or earlier you can easily hit up + against the maximum of 6 shm segments per process (for Xsun in this + case) from running multiple x11vnc processes. You should modify + /etc/system as mentioned in another FAQ to increase the limit. It is + probably also a good idea to run with the -onetile option in this case + (to limit each x11vnc to 3 shm segments), or even -noshm to use no shm + segments. + + + Q-103: Can x11vnc show only a portion of the display? (E.g. for a + special purpose application or a very large screen.) + + As of Mar/2005 x11vnc has the "-clip WxH+X+Y" option to select a + rectangle of width W, height H and offset (X, Y). Thus the VNC screen + will be the clipped sub-region of the display and be only WxH in size. + One user used -clip to split up a large Xinerama screen into two more + managable smaller screens. + + This also works to view a sub-region of a single application window if + the -id or -sid options are used. The offset is measured from the + upper left corner of the selected window. + + + Q-104: Does x11vnc support the XRANDR (X Resize, Rotate and + Reflection) extension? Whenever I rotate or resize the screen x11vnc + just seems to crash. + + As of Dec/2004 x11vnc supports XRANDR. You enable it with the -xrandr + option to make x11vnc monitor XRANDR events and also trap X server + errors if the screen change occurred in the middle of an X call like + XGetImage. Once it traps the screen change it will create a new + framebuffer using the new screen. + + If the connected vnc viewers support the NewFBSize VNC extension + (Windows TightVNC viewer and RealVNC 4.0 windows and Unix viewers do) + then the viewer will automatically resize. Otherwise, the new + framebuffer is fit as best as possible into the original viewer size + (portions of the screen may be clipped, unused, etc.) For these + viewers you can try the -padgeom option to make the region big enough + to hold all resizes and rotations. We have fixed this problem for the + TightVNC Viewer on Unix: SSVNC + + If you specify "-xrandr newfbsize" then vnc viewers that do not + support NewFBSize will be disconnected before the resize. If you + specify "-xrandr exit" then all will be disconnected and x11vnc will + terminate. + + + Q-105: Independent of any XRANDR, can I have x11vnc rotate and/or + reflect the screen that the VNC viewers see? (e.g. for a handheld + whose screen is rotated 90 degrees.) + + As of Jul/2006 there is the -rotate option allow this. E.g's: "-rotate + +90", "-rotate -90", "-rotate x", etc. + + + Q-106: Why is the view in my VNC viewer completely black? Or why is + everything flashing around randomly? + + See the next FAQ for a possible explanation. + + + Q-107: I use Linux Virtual Terminals (VT's) to implement 'Fast User + Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, + Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those + keystrokes to switch between their sessions.) How come the view in a + VNC viewer connecting to x11vnc is either completely black or + otherwise all messed up unless the X session x11vnc is attached to is + in the active VT? + + This seems to have to do with how applications (the X server processes + in this case) must "play nicely" if they are not on the active VT + (sometimes called VC for virtual console.) That is, they should not + read from the keyboard or mouse or manage the video display unless + they have the active VT. Given that it appears the XGetImage() call + must ultimately retrieve the framebuffer data from the video hardware + itself, it would make sense x11vnc's polling wouldn't work unless the + X session had active control of the VT. + + There does not seem to be an easy way to work around this. Even xwd(1) + doesn't work in this case (try it.) Something would need to be done at + a lower level, say in the XFree86/Xorg X server. Also, using the + Shadow Framebuffer (a copy of the video framebuffer is kept in main + memory) does not appear to fix the problem. + + If no one is sitting at the workstation and you just want to remotely + switch the VT over to the one associated with your X session (so + x11vnc can poll it correctly), one can use the chvt(1) command, e.g. + "chvt 7" for VT #7. + + + Q-108: I am using x11vnc where my local machine has "popup/hidden + taskbars" and the remote display where x11vnc runs also has + "popup/hidden taskbars" and they interfere and fight with each other. + What can I do? + + When you move the mouse to the edge of the screen where the popups + happen, the taskbars interfere with each other in strange ways. This + sometimes happens where the local machine is GNOME or Mac OS X and the + remote machine is GNOME. Is there a way to temporarily disable one or + both of these magic desktop taskbars? + + One x11vnc user suggests: it should be straightforward to right mouse + click on the task bar panel, and uncheck "enable auto-hide" from the + panel properties dialog box. This will make the panel always visible. + + Q-109: Help! x11vnc and my KDE screensaver keep switching each other + on and off every few seconds. + + This is a new (Jul/2006) problem seen, say, on the version of KDE that + is shipped with SuSE 10.1. It is not yet clear what is causing this... + If you move the mouse through x11vnc the screensaver shuts off like it + should but then a second or two after you stop moving the mouse the + screensaver snaps back on. + + This may be a bug in kdesktop_lock. For now the only workaround is to + disable the screensaver. You can try using another one such as + straight xscreensaver (see the instructions here for how to disable + kdesktop_lock.) If you have more info on this or see it outside of KDE + please let us know. + + Update: It appears this is due to kdesktop_lock enabling the screen + saver when the Monitor is in DPMS low-power state (e.g. standby, + suspend, or off.) In Nov/2006 the x11vnc -nodpms option was added as a + workaround. Normally it is a good thing that the monitor powers down + (since x11vnc can still poll the framebuffer in this state), but if + you experience the kdesktop_lock problem you can specify the "-nodpms" + option to keep the Monitor out of low power state while VNC clients + are connected. This is basically the same as typing "xset dpms force + on" periodically. (if you don't want to do these things just disable + the screensaver.) Feel free to file a bug against kdesktop_lock with + KDE. + + Q-110: I am running the beryl 3D window manager (or compiz, MythTv, + Google Earth, or some other OpenGL app) and I do not get screen + updates in x11vnc. + + This appears to be because the 3D OpenGL/GLX hardware screen updates + do not get reported via the XDAMAGE mechanism. So this is a bug in + beryl/compiz or XDAMAGE/Xorg or the (possibly 3rd party) video card + driver. + + As a workaround apply the -noxdamage option. As of Feb/2007 x11vnc + will try to autodetect the problem and disable XDAMAGE if is appears + to be missing a lot of updates. But if you know you are using beryl + you might as well always supply -noxdamage. Thanks to this user who + reported the problem and discovered the workaround. + + A developer for MiniMyth reports that the 'alphapulse' tag of the + theme G.A.N.T. can also cause problems, and should be avoided when + using VNC. + + Please report a bug or complaint to Beryl/Compiz and/or Xorg about + this: running x11vnc with -noxdamage disables a nice improvement in + responsiveness (especially for typing) and also leads to unnecessary + CPU and memory I/O load due to the extra polling. + + Q-111: Can I use x11vnc to view my VMWare session remotely? + + Yes, since VMWare usually runs as an X application you can view it via + x11vnc in the normal way. + + Note that VMWare has several viewing modes: + * Normal X application window (with window manager frame) + * Quick-Switch mode (with no window manager frame) + * Fullscreen mode + + The way VMWare does Fullscreen mode on Linux is to display the Guest + desktop in a separate Virtual Terminal (e.g. VT 8) (see this FAQ on + VT's for background.) Unfortunately, this Fullscreen VT is not an X + server. So x11vnc cannot access it (however, see this discussion of + -rawfb for a possible workaround.) x11vnc works fine with "Normal X + application window" and "Quick-Switch mode" because these use X. + + Update: It appears the in VMWare 5.x the Fullscreen mode is X, so + x11vnc access does work. + + One user reports he left his machine with VMWare in the Fullscreen + mode, and even though his X session wasn't in the active VT, he could + still connect x11vnc to the X session and pass the keystrokes Ctrl-Alt + (typing "blind") to the VMWare X app. This induced VMWare to switch + out of Fullscreen into Normal X mode and he could continue working in + the Guest desktop remotely. + + + Aside: Sometimes it is convenient (for performance, etc.) to start + VMWare in its own X session using startx(1). This can be used to have + a minimal window manger (e.g. twm or even no window manager), to + improve response. One can also cut the display depth (e.g. to 16bpp) + in this 2nd X session to improve video performance. This 2nd X session + emulates Fullscreen mode to some degree and can be viewed via x11vnc + as long as the VMWare X session is in the active VT. + + Also note that with a little bit of playing with "xwininfo -all + -children" output one can extract the (non-toplevel) window-id of the + of the Guest desktop only when VMWare is running as a normal X + application. Then one can export just the guest desktop (i.e. without + the VMWare menu buttons) by use of the -id windowid option. The + caveats are the X session VMWare is in must be in the active VT and + the window must be fully visible, so this mode is not terribly + convenient, but could be useful in some circumstances (e.g. running + VMWare on a very powerful server machine in a server room that happens + to have a video card, (but need not have a monitor, Keyboard or + mouse).) + + + + [Exporting non-X11 devices via VNC] + + Q-112: Can non-X devices (e.g. a raw framebuffer) be viewed (and even + controlled) via VNC with x11vnc? + + As of Apr/2005 there is support for this. Two options were added: + "-rawfb string" (to indicate the raw frame buffer device, file, etc. + and its parameters) and "-pipeinput command" (to provide an external + program that will inject or otherwise process mouse and keystroke + input.) Some useful -pipeinput schemes, VID, CONSOLE, and UINPUT, have + since been built into x11vnc for convenience. + + This non-X mode for x11vnc is somewhat experimental because it is so + removed in scope from the intended usage of the tool. Incomplete + attempt is made to make all of the other options consistent with non-X + framebuffer polling. So all of the X-related options (e.g. + -add_keysyms, -xkb) are just ignored or may cause an error if used. Be + careful applying such an option via remote control. + + The format for the -rawfb string is: + -rawfb :@xx[-][://][+] + + There are also some useful aliases (e.g. "console".) Some examples: + -rawfb shm:210337933@800x600x32:ff/ff00/ff0000 + + -rawfb map:/dev/fb0@1024x768x16 + + -rawfb map:/tmp/Xvfb_screen0@640x480x8+3232 + + -rawfb file:/tmp/my.pnm@250x200x24+37 + + -rawfb file:/dev/urandom@128x128x8 + + -rawfb snap:/dev/video0@320x240x24 -24to32 + + -rawfb console + + -rawfb vt2 + + -rawfb video + + -rawfb setup:mycmd.sh + + So the type can be "shm" for shared memory objects, and "map" or + "file" for file objects. "map" uses mmap(2) to map the file into + memory and is preferred over "file" (that uses the slower lseek(2) + access method.) Only use file if map isn't working. BTW, "mmap" is an + alias for "map" and if you do not supply a type and the file exists, + map is assumed (see the -help output and below for some exceptions to + this.) The "snap:" setting applies the -snapfb option with "file:" + type reading (this is useful for exporting webcams or TV tuner video; + see the next FAQ for more info.) + + Also, if the string is of the form "setup:cmd" then cmd is run and the + first line of its output retrieved and used as the rawfb string. This + allows initializing the device, determining WxHxB, etc. + + The object will be the numerical shared memory id for the case of shm. + The idea here is some other program has created this shared memory + segment and periodically updates it with new framebuffer data. x11vnc + polls the area for changes. See shmat(2) and ipcs(8) for more info. + The ipcs command will list current shared memory segments on the + system. Sometimes you can snoop on a program's framebuffer it did not + expect you would be polling! + + The object will be the path to the regular or character special file + for the cases of map and file. The idea here is that in the case of a + regular file some other program is writing/updating framebuffer image + data to it. In the case of a character special (e.g. /dev/fb0) it is + the kernel that is "updating" the framebuffer data. + + In most cases x11vnc needs to be told the width, height, and number of + bits per pixel (bpp) of the framebuffer. This is the @WxHxB field. For + the case of the Linux framebuffer device, /dev/fb0, the fbset(8) may + be of use (but may not always be accurate for what is currently + viewable.) In general some guessing may be required, especially for + the bpp. Update: in "-rawfb console" mode x11vnc will use the linuxfb + API to try to guess (it is still not always accurate.) Also try + "-rawfb vtN" (on x11vnc 0.9.7 and later) for the N-th Linux text + console (aka virtual terminal.) If the number of Bytes Per Line is not + WxHxB/8 (i.e. the framebuffer lines are padded) you can specify this + information after WxHxB via "-BPL", e.g. @800x600x16-2048 + + Based on the bpp x11vnc will try to guess the red, green, and blue + masks (these indicate which bits correspond to each color.) It if gets + it wrong you can specify them manually via the optional ":R/G/B" + field. E.g. ":0xff0000/0x00ff00/0x0000ff" (this is the default for + 32bpp.) + + Finally, the framebuffer may not begin at the beginning of the memory + object, so use the optional "+offset" parameter to indicate where the + framebuffer information starts. So as an example, the Xvfb virtual + framebuffer has options -shmem and -fbdir for exporting its virtual + screen to either shm or a mapped file. The format of these is XWD and + so the initial header should be skipped. BTW, since XWD is not + strictly RGB the view will only be approximate, but usable. Of course + for the case of Xvfb x11vnc can poll it much better via the X API, but + you get the idea. + + By default in -rawfb mode x11vnc will actually close any X display it + happened to open. This is basically to shake out bugs (e.g it will + crash rather than mysteriously interacting with the X display.) If you + want x11vnc to keep the X display open while polling the raw + framebuffer prefix a "+" sign at the beginning of the string (e.g. + +file:/dev/urandom@64x64x8) This could be convenient for keeping the + remote control channel active (it uses X properties.) The "-connect + /path/to/file" mechanism could also be used for remote control to + avoid the X property channel. Rare usage, but if you also supply + -noviewonly in this "+" mode then the mouse and keyboard input are + still sent to the X display, presumably for doing something amusing + with /dev/fb... + + Interesting Devices:. Here are some aliases for interesting device + files that can be polled via -rawfb: + -rawfb console /dev/fb0 Linux Console + -rawfb vt2 /dev/vcsa2 Linux Console (e.g. virtual ter +minal #2) + -rawfb video /dev/video0 Video4Linux Capture device + -rawfb rand /dev/urandom Random Bytes + -rawfb null /dev/zero Zero Bytes (black screen) + + The Linux console, /dev/fb0, etc needs to have its driver enabled in + the kernel. Some of the drivers are video card specific and + accelerated. The console is either the Text consoles (usually + tty1-tty6), or X graphical display (usually starting at tty7.) In + addition to the text console other graphical ones may be viewed and + interacted with as well, e.g. DirectFB or SVGAlib apps, VMWare non-X + fullscreen, or Qt-embedded apps (PDAs/Handhelds.) By default the + pipeinput mechanisms UINPUT and CONSOLE (keystrokes only) are + automatically attempted in this mode under "-rawfb console". + + The Video4Linux Capture device, /dev/video0, etc is either a Webcam or + a TV capture device and needs to have its driver enabled in the + kernel. See this FAQ for details. If specified via "-rawfb Video" then + the pipeinput method "VID" is applied (it lets you change video + parameters dynamically via keystrokes.) + + The last two, /dev/urandom and /dev/zero are just for fun, but are + also useful in testing. + + + All of the above -rawfb options are just for viewing the raw + framebuffer (although some of the aliases do imply keystroke and mouse + pipeinput methods.) That may be enough for certain applications of + this feature (e.g. suppose a video camera mapped its framebuffer into + memory and you just wanted to look at it via VNC.) + To handle the pointer and keyboard input from the viewer users the + "-pipeinput cmd" option was added to indicate a helper program to + process the user input. The input is streamed to it and looks + something like this: + Pointer 1 205 257 0 None + Pointer 1 198 253 0 None + Pointer 1 198 253 1 ButtonPress-1 + Pointer 1 198 253 0 ButtonRelease-1 + Pointer 1 198 252 0 None + Keysym 1 1 119 w KeyPress + Keysym 1 0 119 w KeyRelease + Keysym 1 1 65288 BackSpace KeyPress + Keysym 1 0 65288 BackSpace KeyRelease + Keysym 1 1 112 p KeyPress + Keysym 1 0 112 p KeyRelease + + Run "-pipeinput tee:/bin/cat" to get a description of the format. Note + that the -pipeinput option is independent of -rawfb mode and so may + have some other interesting uses. The "tee:" prefix means x11vnc will + both process the user input and pipe it to the command. The default is + to just pipe it to the -pipeinput command. + + Note the -pipeinput helper program could actually control the raw + framebuffer. In the libvncserver CVS a simple example program + x11vnc/misc/slide.pl is provided that demonstrates a simple jpeg + "slideshow" application. Also the builtin "-pipeinput VID" mode does + this for webcams and TV capture devices (/dev/video0.) + + The -pipeinput program is run with these environment variables set: + X11VNC_PID, X11VNC_PROG, X11VNC_CMDLINE, X11VNC_RAWFB_STR to aid its + knowing what is up. + + Another example provided in libvncserver CVS is a script to inject + keystrokes into the Linux console (e.g. the virtual consoles: + /dev/tty1, /dev/tty2, etc) in x11vnc/misc/vcinject.pl. It is based on + the vncterm/LinuxVNC.c program also in the libvncserver CVS. So to + view and interact with VT #2 (assuming it is the active VT) one can + run something like: + x11vnc -rawfb map:/dev/fb0@1024x768x16 -pipeinput './vcinject.pl 2' + + This assumes your Linux framebuffer device (/dev/fb0) is properly + configured. See fbset(8) and other documentation. Try + "file:/dev/fb0@WxHxB" as a last resort. Starting with x11vnc 0.8.1, + the above VT injection is built in, as well as WxHxB determination. + Just use something like: + x11vnc -rawfb console + + this will try to guess the active virtual console (via /dev/tty0) and + also the /dev/fb0 WxHxB and rgb masks automatically. Use, e.g., + "-rawfb console3" to force the VT number. This input method can be + used generally via "-pipeinput CONSOLE". Also starting with x11vnc + 0.8.2 the "-pipeinput UINPUT" mode is tried first (it does both + keyboard and mouse input) and then falls back to CONSOLE mode if it is + not available. Here is the -help output for this mode: + + If the rawfb string begins with "console" the framebuffer device + /dev/fb0 is opened (this requires the appropriate kernel modules to + be installed) and so is /dev/tty0. The latter is used to inject + keystrokes (not all are supported, but the basic ones are.) You + will need to be root to inject keystrokes. /dev/tty0 refers to the + active VT, to indicate one explicitly, use "console2", etc. using + the VT number. + + If the Linux version seems to be 2.6 or later and the "uinput" + module appears to be present, then the uinput method will be used + instead of /dev/ttyN. uinput allows insertion of BOTH keystrokes + and mouse input and so it preferred when accessing graphical (e.g. + Qt-embedded) linux console apps. See -pipeinput UINPUT below for + more information on this mode (you may want to also use the + -nodragging and -cursor none options.) Use "console0", etc or + -pipeinput CONSOLE to force the /dev/ttyN method. + + Note you can change VT remotely using the chvt(1) command. + Sometimes switching out and back corrects the framebuffer state. + + To skip input injecting entirely use "consolex". + + The string "/dev/fb0" (1, etc) can be used instead of "console". + This can be used to specify a different framebuffer device, e.g. + /dev/fb1. As a shortcut the "/dev/" can be dropped. If the name is + something nonstandard, use "console:/dev/foofb" + + If you do not want x11vnc to guess the framebuffer's WxHxB and + masks automatically (sometimes the kernel gives inaccurate + information), specify them with a @WxHxB at the end of the string. + + The above is just an example of what can be done. Note that if you + really want to view and interact with the Linux Text console it is + better to use the more accurate and faster LinuxVNC program. The + advantage x11vnc -rawfb might have is that it can allow interaction + with a non-text application, e.g. one based on SVGAlib or Qt-embedded + Also, for example the VMWare Fullscreen mode is actually viewable + under -rawfb and can be interacted with if uinput is enabled. + + If the Linux uinput driver is available then full keystroke and mouse + input into the Linux console can be performed. You may be able to + enable uinput via commands like these: + modprobe uinput + mknod /dev/input/uinput c 10 223 + + The -rawfb and -pipeinput features are intended to help one creatively + "get out of a jam" (say on a legacy or embedded device) where X is + absent or doesn't work properly. Feedback and bug reports are welcome. + For more control and less overhead use libvncserver in your own C + program that passes the framebuffer to libvncserver. + + + Q-113: Can I export the Linux Console (Virtual Terminals) via VNC + using x11vnc? + + Yes, you may need to be root to access the devices that make up the + linux console. + + To access the active Linux console via the computer's framebuffer try + something like: + x11vnc -rawfb console + x11vnc -rawfb console2 + + These will try to access the framebuffer through /dev/fb (or /dev/fb0, + etc.) and if it succeeds it will show any text or graphics that is + currently displayed. Keystrokes will be injected via the device + /dev/tty0 (to force an explicit virtual terminal append a number, e.g. + "console2" to select /dev/tty2.) + + If your Linux system does not have a framebuffer device (/dev/fb) you + can get one by adding, e.g., vga=0x31B boot parameter. This enables + the VGA framebuffer device at 1280x1024x24. 0x317 gives 1024x768x16, + etc. You can also enable a Linux framebuffer device by modprobing a + framebuffer driver specific to your video card. + + Note that this "-rawfb console" mode shows the contents of the + hardware framebuffer, and so will show whatever is on the screen. It + has no concept of Virtual Terminals WRT what there is to view, it + always shows the active virtual terminal. + + Another mode is specific to the Linux text Virtual Terminals, it shows + their text and colors (but no graphics) regardless of whether it is + the active VT or not. It is available on x11vnc 0.9.7 and later. + Enable this mode like this: + x11vnc -rawfb vt + x11vnc -rawfb vt2 + + The former will select the active one, the latter the 2nd VT. x11vnc + implements this mode by opening the current console text file + "/dev/vcsa2" instead of "/dev/fb". In this way it provides the basic + functionality of the LibVNCServer LinuxVNC program. + + The vt mode can be a useful way to try to get a machine's X server + working remotely, e.g. you edit /etc/X11/xorg.conf and then type + startx (or similar, e.g. gdm) in the virtual terminal. A 2nd x11vnc + could be used to see if the X server is now working correctly. + + Q-114: Can I export via VNC a Webcam or TV tuner framebuffer using + x11vnc? + + Yes, this is possible to some degree with the -rawfb option. There is + no X11 involved: snapshots from the video capture device are used for + the screen image data. See the previous FAQ on -rawfb for background. + For best results, use x11vnc version 0.8.1 or later. + + Roughly, one would do something like this: + x11vnc -rawfb snap:/dev/video@320x240x32 + + This requires that the system allows simple read(2) access to the + video device. This is true for video4Linux on Linux kernel 2.6 and + later (it won't work for 2.4, you'll need a separate program to + snapshot to a file that you point -rawfb to; ask me if it is not clear + what to do.) + + The "snap:" enforces -snapfb mode which appears to be necessary. The + read pointer for video capture devices cannot be repositioned (which + would be needed for scanline polling), but you can read a full frame + of data from the device. + + On Linux, if the Video4Linux API is present or the v4l-info(1) program + (related to xawtv) exists in in PATH, then x11vnc can be instructed to + try it to determine the -rawfb WxHxB parameters for you automatically. + In this case one would just type: + x11vnc -rawfb video + + or "-rawfb video1" for the 2nd video device, etc. + + x11vnc has also been extended to use the Video4Linux API over v4l-info + if it is available at build time. This enables setting parameters + (e.g. size and brightness) via x11vnc. See the description below. + Without Video4Linux you will need to initialize the settings of the + video device using something like xawtv or spcaview (and then hope the + settings persist until x11vnc reopens the device.) + + Many video4linux drivers tend to set the framebuffer to be 24bpp (as + opposed to 32bpp.) Since this can cause problems with VNC viewers, + etc, the -24to32 option will be automatically imposed when in 24bpp. + + Note that by its very nature, video capture involves rapid change in + the framebuffer. This is especially true for cameras where slight + wavering in brightness is always happening. This can lead to much + network bandwidth consumption for the VNC traffic and also local CPU + and I/O resource usage. You may want to experiment with "dialing down" + the framerate via the -wait, -slow_fb, or -defer options. Decreasing + the window size and bpp also helps. + + + Setting Camera/Tuner parameters via x11vnc: + + There is also some support for setting parameters of the capture + device. This is done via "-rawfb video:". This could be + useful for unattended startup at boottime, etc. Here is the -help + description: + + A more sophisticated video device scheme allows initializing the + device's settings using: + + -rawfb video: + + The prefix could also be, as above, e.g. "video1:" to specify the + device file. The v4l API must be available for this to work. + Otherwise, you will need to try to initialize the device with an + external program, e.g. xawtv, spcaview, and hope they persist when + x11vnc re-opens the device. + + is a comma separated list of key=value pairs. The + device's brightness, color, contrast, and hue can be set to + percentages, e.g. br=80,co=50,cn=44,hu=60. + + The device filename can be set too if needed (if it does not start + with "video"), e.g. fn=/dev/qcam. + + The width, height and bpp of the framebuffer can be set via, e.g., + w=160,h=120,bpp=16. + + Related to the bpp above, the pixel format can be set via the + fmt=XXX, where XXX can be one of: GREY, HI240, RGB555, RGB565, + RGB24, and RGB32 (with bpp 8, 8, 16, 16, 24, and 32 respectively.) + See http://www.linuxtv.org for more info (V4L api.) + + For TV/rf tuner cards one can set the tuning mode via tun=XXX where + XXX can be one of PAL, NTSC, SECAM, or AUTO. + + One can switch the input channel by the inp=XXX setting, where XXX + is the name of the input channel (Television, Composite1, S-Video, + etc.) Use the name that is in the information about the device that + is printed at startup. + + For input channels with tuners (e.g. Television) one can change + which station is selected by the sta=XXX setting. XXX is the + station number. Currently only the ntsc-cable-us (US cable) + channels are built into x11vnc. See the -freqtab option below to + supply one from xawtv. If XXX is greater than 500, then it is + interpreted as a raw frequency in KHz. + + Example: + + -rawfb video:br=80,w=320,h=240,fmt=RGB32,tun=NTSC,sta=47 + + one might need to add inp=Television too for the input channel to + be TV if the card doesn't come up by default in that one. + + Note that not all video capture devices will support all of the + above settings. + + See the -pipeinput VID option below for a way to control the + settings through the VNC Viewer via keystrokes. + + As above, if you specify a "@WxHxB..." after the string + they are used verbatim: the device is not queried for the current + values. Otherwise the device will be queried. + + Also, if you supply the "-pipeinput VID" (or use "-rawfb Video") + option you can control the settings to some degree via keystroke + mappings, e.g. B to increase the brightness or Up arrow to change the + TV station: + + For "-pipeinput VID" and you are using the -rawfb for a video + capture device, then an internal list of keyboard mappings is used + to set parameters of the video. The mappings are: + + "B" and "b" adjust the brightness up and down. + "H" and "h" adjust the hue. + "C" and "c" adjust the colour. + "N" and "n" adjust the contrast. + "S" and "s" adjust the size of the capture screen. + "I" and "i" cycle through input channels. + Up and Down arrows adjust the station (if a tuner) + F1, F2, ..., F6 will switch the video capture pixel + format to HI240, RGB565, RGB24, RGB32, RGB555, and + GREY respectively. See -rawfb video for details. + + See also the -freqtab option to supply your own xawtv channel to + frequency mappings for your country (only ntsc-cable-us is built into + x11vnc.) + + + Q-115: Can I connect via VNC to a Qt-embedded/Qtopia application + running on my handheld or PC using the Linux console framebuffer (i.e. + not X11)? + + Yes, the basic method for this is the -rawfb scheme where the Linux + console framebuffer (usually /dev/fb0) is polled and the uinput driver + is used to inject keystrokes and mouse input. Often you will just have + to type: + x11vnc -rawfb console + + (you may need to enable the uinput driver on the system via "modprobe + uinput; mknod /dev/input/uinput c 10 223") If this does not find the + correct frame buffer properties figure them out or guess them and use + something like: + x11vnc -rawfb /dev/fb0@640x480x16 + + Also, to force usage of the uinput injection method use "-pipeinput + UINPUT". See the -pipeinput description for tunable parameters, etc. + + One problem with the x11vnc uinput scheme is that it cannot guess the + mouse motion "acceleration" used by the windowing application (e.g. + QWS or X11.) For X11 and Qt-embedded the acceleration is usually 2 + (i.e. a dx of 1 from the mouse yields a 2 pixel displacement of the + mouse cursor.) The default x11vnc uses is 2, since that is often used. + However for one Qt-embedded system we needed to do: + x11vnc -rawfb console -pipeinput UINPUT:accel=4.0 + + to get reasonable positioning of the mouse. + + Even with the correct acceleration setting there is still some drift + (probably because of the mouse threshold where the acceleration kicks + in) and so x11vnc needs to reposition the cursor from 0,0 about 5 + times a second. See the -pipeinput UINPUT option for tuning parameters + that can be set (there are some experimental thresh=N tuning + parameters as well) + + Currently, one can expect mouse input to be a little flakey. All in + all, the Linux framebuffer input mechanism for Qt-embedded framebuffer + apps is not perfect, but it is usable. + + If you need to create a smaller x11vnc binary for a handheld + environment be sure to run strip(1) on it and also consider + configuring with, e.g. "env CPPFLAGS='-DSMALL_FOOTPRINT=1' ./configure + ..." to remove rarely used features and large texts (use 2 or 3 + instead of 1 to remove more.) Currently (Jul/2006) this can lower the + size of the x11vnc from 1.1MB to 0.6-0.7MB. + + The x11vnc uinput method applies to nearly anything on the Linux + framebuffer console, not just Qt-embedded/Qtopia. DirectFB, SDL using + fbcon driver, SVGAlib applications can also be viewed and interacted + with. Even a Linux X session can be viewed and interacted with without + using X11 (and x11vnc does not have to terminate when the X server + restarts!) The Linux Text consoles (F1-F6) also work. + + Note that Qt-embedded supplies its own VNC graphics driver, but it + cannot do both the Linux console framebuffer and VNC at the same time, + which is often what is desired from VNC. + + Update: We are finding some setups like Qtopia on the IPAQ do not + allow mouse input via uinput. Please help us debug this problem by + trying x11vnc on your device and letting us know what does and does + not work. + + + Q-116: Now that non-X11 devices can be exported via VNC using x11vnc, + can I build it with no dependencies on X11 header files and libraries? + + Yes, as of Jul/2006 x11vnc enables building for -rawfb only support. + Just do something like when building: + ./configure --without-x (plus any other flags) + make + + You can then test via "ldd x11vnc" that the binary does not depend on + libX11.so, etc. See the previous FAQ's for non-X11 framebuffer usage. + If you use this for an interesting non-X11 application please let us + know what you did. + + + Q-117: Does x11vnc support Mac OS X Aqua/Quartz displays natively + (i.e. no X11 involved)? + + Yes, since Nov/2006 in the development tree (x11vnc-0.8.4 tarball) + there is support for native Mac OS X Aqua/Quartz displays using the + -rawfb mechanism described above. The mouse and keyboard input is + achieved via Mac OS X API's. + + So you can use x11vnc as an alternative to OSXvnc (aka Vine Server), + or Apple Remote Desktop (ARD). Perhaps there is some x11vnc feature + you'd like to use on Mac OS X, etc. For a number of activities (e.g. + window drags) it seems to be faster than OSXvnc. + + Notes: + + X11: x11vnc will also work (as it has for years) with a X11 server + (XDarwin) running on Mac OS X (people often install this software to + display remote X11 apps on their Mac OS X system, or use some old + favorites locally such as xterm.) However in this case x11vnc will + only work reasonably in single window -id windowid mode (and the + window may need to have mouse focus.) + + If you do not have the DISPLAY env. variable set, x11vnc will assume + native Aqua/Quartz on Mac OS X, however if DISPLAY is set it will + assume an X11 connection. Use "-rawfb console" to force the native + display (or unset DISPLAY.) + + Update: Leopard sets DISPLAY by default in all sessions. Since it + starts with the string "/tmp/" x11vnc will use that to know if it + should ignore it. Use "-display :0.0" to force it. + + Building: If you don't have the X11 build and runtime packages + installed you will need to build it like this: + (cd to the e.g. x11vnc-0.9, source directory) + ./configure --without-x + make + + Win2VNC/x2vnc: One handy use is to use the -nofb mode to redirect + mouse and keyboard input to a nearby Mac (i.e. one to the side of your + desk) via x2vnc or Win2VNC. See this FAQ for more info. + + Options: Here are the Mac OS X specific x11vnc options: + -macnodim For the native Mac OS X server, disable dimming. + -macnosleep For the native Mac OS X server, disable display sleep +. + -macnosaver For the native Mac OS X server, disable screensaver. + -macnowait For the native Mac OS X server, do not wait for the + user to switch back to his display. + -macwheel n For the native Mac OS X server, set the mouse wheel + speed to n (default 5.) + -macnoswap For the native Mac OS X server, do not swap mouse + buttons 2 and 3. + -macnoresize For the native Mac OS X server, do not resize or rese +t + the framebuffer even if it is detected that the scree +n + resolution or depth has changed. + -maciconanim n For the native Mac OS X server, set n to the number + of milliseconds that the window iconify/deiconify + animation takes. In -ncache mode this value will be + used to skip the animation if possible. (default 400) + -macmenu For the native Mac OS X server, in -ncache client-sid +e + caching mode, try to cache pull down menus (not perfe +ct + because they have animated fades, etc.) + + PasteBoard/Clipboard: There is a bug that the Clipboard (called + PasteBoard on Mac it appears) exchange will not take place unless + x11vnc was started from inside the Aqua display (e.g. started inside a + Terminal app window.) Otherwise it cannot connect to the PasteBoard + server. So Clipboard exchange won't work for our standard "ssh in" + startup scheme. + + Hopefully this deficiency can be removed, but until then for Clipboard + exchange to work you will need to start x11vnc inside the desktop + session (i.e. either start it running before you leave, or start up a + 2nd x11vnc inside from a 1st one started outside, or use the apple + script below) + + Here also is a osascript trick that seems to work (it opens the + Terminal app and instructs it to start x11vnc): + +#!/bin/sh +# +# start_x11vnc: start x11vnc in a Terminal window +# (this will allow Clipboard/Pasteboard exchange to work) + +tmp=/tmp/start_x11vnc.$$ + +cat > $tmp < vncviewer -listen + client2> vncviewer -listen + client3> vncviewer -listen + ... + client64> vncviewer -listen + + (e.g. client1> is the cmdline prompt on machine client1 ... etc) and + all the repeaters R are started like this: + repeater1> x11vnc -reflect listen -connect client1,client2,...client8 + repeater2> x11vnc -reflect listen -connect client9,client10,...client16 + ... + repeater8> x11vnc -reflect listen -connect client57,client58,...client64 + + and finally the main server is started to kick the whole thing into + motion: + vncserver> x11vnc -display :0 -connect repeater1,repeater2,...repeater8 + + (or instruct a non-x11vnc VNC server to reverse connect to the + repeaters.) For a classroom broadcasting setup one might have the + first two sets of commands start automatically at bootup or when + someone logs in, and then start everything up with the S server. One + may even be able to script the forward connection bootstrap case, let + us know what you did. A really nice thing would be some sort of + auto-discovery of your repeater, etc... + + Q-119: Can x11vnc be used during a Linux, Solaris, etc. system + Installation so the Installation can be done remotely? + + This can be done, but it doesn't always work because it depends on how + the OS does its install. We have to "sneak in" somehow. Note that some + OS's have a remote install (ssh etc.) built in and so you might want + to use that instead. + + Usually the OS install will have to be a network-install in order to + have networking up during the install. Otherwise, you may have a + (slim) chance to configure the networking manually (ifconfig(8) and + route(8).) + + To avoid library dependencies problems in the typical minimal (e.g. + busybox) installation OS it is a good idea to build a statically + linked x11vnc binary. A way that often works is to do a normal build + and then paste the final x11vnc link line into a shell script. Then + change the "gcc" to "gcc -static" and run the shell script. You may + need to disable features (e.g. "--without-xfixes") if there is not a + static library for the feature available. You may also need to add + extra link options (e.g. "-lXrender") to complete library dependencies + manually. + + Let's call the binary x11vnc.static. Place it on a webserver + somewhere. It may be possible to retrieve it via scp(1) too. + + During the install you need to get a shell to retreive x11vnc.static + and run it. + + If the Solaris install is an older X-based one, there will be a menu + for you to get a terminal window. From that window you might be able + to retrieve x11vnc.static via wget, scp, or ftp. Remember to do "chmod + 755 ./x11vnc.static" and then find the -auth file as in this FAQ. + + If it is a Linux install that uses an X server (e.g. SuSE and probably + Fedora), then you can often get a shell by pressing Ctrl-Alt-F2 or + similar. Then get the x11vnc binary via something like this: + cd /tmp + wget http://192.168.0.22/x11vnc.static + chmod 755 ./x11vnc.static + + Find the name of the auth file as in this FAQ. (maybe run "ps wwaux | + grep auth".) Then run it like this: + ./x11vnc.static -forever -nopw -display :0 -auth /tmp/wherever/the/authfile + + then press Alt-F7 to go back to the X install. You should now be able + to connect via a vnc viewer and continue the install. Watch out for + the display being :1, etc. + + If there is a firewall blocking incoming connections during the + install, use the "-connect hostname" option option for a reverse + connection to the hostname running the VNC viewer in listen mode. + + Debian based installs are either console-text or console-framebuffer + based. These are install (or expert) and installgui (or expertgui) + boot lines, respectively. For the console-text based installs you + probably need to add a boot cmd line option like vga=0x314 (which is + 800x600x16) to get the console-text to use the linux framebuffer + device properly. + + For a Debian console-text based install after the network is + configured press Ctrl-Alt-F2 to get a shell. Retrieve the binary via + wget as above and chmod 755 it. Then run it something like this: + sleep 10; ./x11vnc.static -forever -nopw -rawfb console + + then before the sleep is over press Alt-F1 to get back to the install + virtual console. You should be able to connect via a VNC viewer and + continue with the install. + + For a recent (2009) Debian install we booted with "expert vga=0x301" + and "expert vga=0x311" to get console text based installs at 640x480x8 + and 640x480x16, respectively (replace "expert" with "install" if you + like.) Otherwise it was giving a 16 color 640x480x4 (4 bit per pixel) + display which x11vnc could not handle. + + For Debian console-framebuffer GUI based installs (installgui or + expertgui) we have not be able to enter keystrokes or mouse motions. + This may be resolved if the install had the Linux kernel module + uinput, but it doesn't; one can wget uinput.ko and then run insmod on + it, but the module must match the installation kernel. So, failing + that, you can only do the GUI view-only, which can be handy to watch a + long network install from your desk instead of in front of the machine + being installed. For these, after the network is configured press + Ctrl-Alt-F2 to get a shell. Retrieve the binary via wget as above and + chmod 755 it. Then run it something like this: + sleep 10; ./x11vnc.static -forever -nopw -rawfb console + + then before the sleep is over press Alt-F5 to get back to the GUI + install console. You should be able to connect via a VNC viewer and + watch the install. + [Misc: Clipboard, File Transfer/Sharing, Printing, Sound, Beeps, + Thanks, etc.] + + Q-120: Does the Clipboard/Selection get transferred between the + vncviewer and the X display? + + As of Jan/2004 x11vnc supports the "CutText" part of the RFB (aka VNC) + protocol. When text is selected/copied in the X session that x11vnc is + polling it will be sent to connected VNC viewers. And when CutText is + received from a VNC viewer then x11vnc will set the X11 selections + PRIMARY, CLIPBOARD, and CUTBUFFER0 to it. x11vnc is able to hold the + PRIMARY and CLIPBOARD selections (Xvnc does not seem to do this.) + + The X11 selections can be confusing, especially to those coming from + Windows or MacOSX where there is just a single 'Clipboard'. The X11 + CLIPBOARD selection is a lot like that of Windows and MacOSX, e.g. + highlighted text is sent to the clipboard when the user activates + "Edit -> Copy" or presses "Control+C" (and pasting it via "Edit -> + Paste" or "Control+V".) The X11 PRIMARY selection has been described + as 'for power users' or 'an Easter Egg'. As soon as text is + highlighted it is set to the PRIMARY selection and so it is + immediately ready for pasting, usually via the Middle Mouse Button or + "Shift+Insert". See this jwz link for more information. + + x11vnc's default behavior is to watch both CLIPBOARD and PRIMARY and + whenever one of them changes, it sends the new text to connected + viewers. Note that since the RFB protocol only has a single "CutText" + then both selections are "merged" to some degree (and this can lead to + confusing results.) One user was confused why x11vnc was "forgetting" + his CLIPBOARD selection and the reason was he also changed PRIMARY + some time after he copied text to the clipboard. Usually an app will + set PRIMARY as soon as any text is highlighted so it easy to see how + CLIPBOARD was forgotten. Use the -noprimary described below as a + workaround. Similarly, by default when x11vnc receives CutText it sets + both CLIPBOARD and PRIMARY to it (this is probably less confusing, but + could possibly lead to some failure modes as well.) + + You may not like these defaults. Here are ways to change the behavior: + * If you don't want the Clipboard/Selection exchanged at all use the + -nosel option. + * If you want changes in PRIMARY to be ignored use the -noprimary + option. + * If you want changes in CLIPBOARD to be ignored use the + -noclipboard option. + * If you don't want x11vnc to set PRIMARY to the "CutText" received + from viewers use the -nosetprimary option. + * If you don't want x11vnc to set CLIPBOARD to the "CutText" + received from viewers use the -nosetclipboard option. + + You can also fine-tune it a bit with the -seldir dir option and also + -input. + + You may need to watch out for desktop utilities such as KDE's + "Klipper" that do odd things with the selection, clipboard, and + cutbuffers. + + + Q-121: Can I use x11vnc to record a Shock Wave Flash (or other format) + video of my desktop, e.g. to record a tutorial or demo? + + Yes, it is possible with a number of tools that record VNC and + transform it to swf format or others. One such popular tool is + pyvnc2swf. There are a number of tutorials (broken link?) on how to do + this. Another option is to use the vnc2mpg that comes in the + LibVNCServer package. + An important thing to remember when doing this is that tuning + parameters should be applied to x11vnc to speed up its polling for + this sort of application, e.g. "-wait 10 -defer 10". + + Q-122: Can I transfer files back and forth with x11vnc? + + As of Oct/2005 and May/2006 x11vnc enables, respectively, the TightVNC + and UltraVNC file transfer implementations that were added to + libvncserver. This currently works with TightVNC and UltraVNC viewers + (and Windows viewers only support filetransfer it appears... but they + do work to some degree under Wine on Linux.) + + The SSVNC Unix VNC viewer supports UltraVNC file transfer by use of a + Java helper program. + + TightVNC file transfer is off by default, if you want to enable it use + the -tightfilexfer option. + + UltraVNC file transfer is off by default, to enable it use something + like "-rfbversion 3.6 -permitfiletransfer" + options (UltraVNC incorrectly uses the RFB protocol version to + determine if its features are available, so x11vnc has to pretend to + be version 3.6.) As of Sep/2006 "-ultrafilexfer" is an alias for these + two options. Note that running as RFB version 3.6 may confuse other + VNC Viewers. + + Sadly you cannot do both -tightfilexfer and -ultrafilexfer at the same + time because the latter requires setting the version to 3.6 and + tightvnc will not do filetransfer when it sees that version number. + + Also, because of the way the LibVNCServer TightVNC file transfer is + implemented, you cannot do Tightvnc file transfer in -unixpw mode. + However, UltraVNC file transfer does work in -unixpw (but if a client + tries it do a filetransfer during the login process it will be + disconnected.) + + IMPORTANT: please understand if -ultrafilexfer or -tightfilexfer is + specified and you run x11vnc as root for, say, inetd or display + manager (gdm, kdm, ...) access and you do not have it switch users via + the -users option, then VNC Viewers that connect are able to do + filetransfer reads and writes as *root*. + + The UltraVNC and TightVNC settings can be toggled on and off inside + the gui or by -R remote control. However for TightVNC the changed + setting only applies for NEW clients, current clients retain their + TightVNC file transfer ability. For UltraVNC it works better, however + if an UltraVNC client has initiated a file transfer dialog it will + remain in effect until the dialog is closed. If you want to switch + between UltraVNC and TightVNC file transfer in the gui or by remote + control you will probably be foiled by the "-rfbversion 3.6" issue. + + + Q-123: Which UltraVNC extensions are supported? + + Some of them are supported. To get UltraVNC Viewers to attempt to use + these extensions you will need to supply this option to x11vnc: + -rfbversion 3.6 + + Or use -ultrafilexfer which is an alias for the above option and + "-permitfiletransfer". UltraVNC evidently treats any other RFB version + number as non-UltraVNC. + + Here are a list of the UltraVNC extensions supported by x11vnc: + * ServerInput: "Toggle Remote Input and Remote Blank Monitor" + * FileTransfer: "Open File Transfer..." + * SingleWindow: "Select Single Window..." + * TextChat: "Open Chat..." + * 1/n Server Scaling + * rfbEncodingUltra compression encoding + + The SSVNC Unix VNC viewer supports these UltraVNC extensions. + + To disable SingleWindow and ServerInput use -noultraext (the others + are managed by LibVNCServer.) See this option too: -noserverdpms. + + Also, the UltraVNC repeater proxy is supported for use with reverse + connections: "-connect repeater://host:port+ID:NNNN". Use it for both + plaintext and SSL connections. This mode can send any string before + switching to the VNC protocol, and so could be used with other + proxy/gateway tools. Also, a perl repeater implemention is here: + ultravnc_repeater.pl + + + Q-124: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for + Unix? I.e. something very simple for a naive user to initiate a + reverse vnc connection from their Unix desktop to a helpdesk + operator's VNC Viewer. + + Yes, UltraVNC's Single Click (SC) mode can be emulated fairly well on + Unix. + + We use the term "helpdesk" below, but it could be any sort of remote + assistance you want to set up, e.g. something for Unix-using friends + or family to use. This includes Mac OS X. + + Assume you create a helpdesk directory "hd" on your website: + http://www.mysite.com/hd (any website that you can upload files to + should work, although remember the user will be running the programs + you place there.) + + In that "hd" subdirectory copy an x11vnc binary to be run on the Unix + user's machine (e.g. Linux, etc) and also create a file named "vnc" + containing the following: +#!/bin/sh + +webhost="http://www.mysite.com/hd" # Your helpdesk dir URL. + +vnchost="ip.someplace.net" # Your host running 'vncviewer -listen' + # It could also be your IP number. If it is + # a router/firewall, you will need to + # configure it to redirect port 5500 to you +r + # workstation running 'vncviewer -listen' + +dir=/tmp/vnc_helpdesk.$$ # Make a temporary working dir. +mkdir $dir || exit 1 +cd $dir || exit 1 + +trap "cd /tmp; rm -rf $dir" 0 2 15 # Cleans up on exit. + +wget $webhost/x11vnc # Fetch x11vnc binary. If multi- +chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc + # or similar. + +./x11vnc -connect_or_exit $vnchost -rfbport 0 -nopw + + with the hostnames / IP addresses customized to your case. + + On the helpdesk VNC viewer machine (ip.someplace.net in this example) + you have the helpdesk operator running VNC viewer in listen mode: + vncviewer -listen + + or if on Windows, etc. somehow have the VNC viewer be in "listen" + mode. + + Then, when the naive user needs assistance you instruct him to open up + a terminal window on his Unix desktop and paste the following into the + shell: + wget -qO - http://www.mysite.com/hd/vnc | sh - + + and then press Enter. You could have this instruction on a web page or + in an email you send him, etc. This requires that the wget is + installed on the user's Unix machine (he might only have curl or lynx, + see below for more info.) + + + So I guess this is about 3-4 clicks (start a terminal and paste) and + pressing "Enter" instead of "single click"... + + See this page for some variations on this method, e.g. how to add a + password, SSL Certificates, etc. + + + If you don't have a website (there are many free ones) or don't want + to use one you will have to email him all of the ingredients (x11vnc + binary and a launcher script) and tell him how to run it. This could + be easy or challenging depending on the skill of the naive unix + user... + + A bit of obscurity security could be put in with a -passwd, -rfbauth + options, etc. (note that x11vnc will require a password even for + reverse connections.) More info here. + + + Firewalls: If the helpdesk (you) with the vncviewer is behind a + NAT/Firewall/Router the router will have to be configured to redirect + a port (i.e. 5500 or maybe different one if you like) to the vncviewer + machine. If the vncviewer machine also has its own host-level + firewall, you will have to open up the port there as well. + + NAT-2-NAT: There is currently no way to go "NAT-2-NAT", i.e. both User + and Helpdesk workstations behind NAT'ing Firewall/Routers without + configuring a router to do a port redirection (i.e. on your side, the + HelpDesk.) To avoid modifying either firewall/router, one would need + some public (IP address reachable on the internet) redirection/proxy + service. Perhaps such a thing exists. http://sc.uvnc.com provides this + service for their UltraVNC Single Click users. + + Update: It may be possible to do "NAT-2-NAT" with a UDP tunnel such as + http://samy.pl/pwnat/. All that is required is that both NAT firewalls + allow in UDP packets from an IP address to which a UDP packet has + recently been sent to. If you try it out let us know how it went. + + + Very Naive Users: + + If it is beyond the user how to open a terminal window and paste in a + command (you have my condolences...) you would have to somehow setup + his Web browser to download the "vnc" file (or a script containing the + above wget line) and prompt the user if he wants to run it. This may + be tricky to set up (which is probably a good thing to not have the + web browser readily run arbitrary programs downloaded from the + internet...) + + One command-line free way, tested with KDE, is to name the file vnc.sh + and then instruct the user to right-click on the link and do "Save + Link As" to his Desktop. It will appear as an icon, probably one that + looks like a terminal or a command line prompt. He next should + right-click on the icon and select "Properties" and go to the + "Permissions" tab. Then in that dialog select the checkbox "Is + executable". He should then be able to click on the icon to launch it. + Another option is to right-click on the icon and select "Open With -> + Other ..." and for the name of the application type in "/bin/sh". + Unfortunately in both cases the command output is lost and so errors + cannot be debugged as easily. A similar thing appears to work in GNOME + if under "Properties -> Permissions" they click on "Execute" checkbox + for "Owner". Then when they click on the icon, they will get a dialog + where they can select "Run in Terminal". In general for such cases, if + it is feasible, it might be easier to ssh to his machine and set + things up yourself... + + + SSL Encrypted Helpdesk Connections: + + As of Apr/2007 x11vnc supports reverse connections in SSL and so we + can do this. On the Helpdesk side (Viewer) you will need STUNNEL or + better use the Enhanced TightVNC Viewer (SSVNC) package we provide + that automates all of the SSL for you. + + To do this create a file named "vncs" in the website "hd" directory + containing the following: +#!/bin/sh + +webhost="http://www.mysite.com/hd" # Your helpdesk dir URL. + +vnchost="ip.someplace.net" # Your host running 'vncviewer -listen' + # It could also be your IP number. If it is + # a router/firewall, you will need to + # configure it to redirect port 5500 to you +r + # workstation running 'vncviewer -listen' + +dir=/tmp/vnc_helpdesk.$$ # Make a temporary working dir. +mkdir $dir || exit 1 +cd $dir || exit 1 + +trap "cd /tmp; rm -rf $dir" 0 2 15 # Cleans up on exit. + +wget $webhost/x11vnc # Fetch x11vnc binary. If multi- +chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc + # or similar. + +./x11vnc -connect_or_exit $vnchost -rfbport 0 -nopw -ssl # Note -ssl option. + + with the hostnames or IP addresses customized to your case. + + The only change from the "vnc" above is the addition of the -ssl + option to x11vnc. This will create a temporary SSL cert: openssl(1) + will need to be installed on the user's end. A fixed SSL cert file + could be used to avoid this (and provide some authentication; more + info here.) + + The naive user will be doing this: + wget -qO - http://www.mysite.com/hd/vncs | sh - + + (or perhaps even use https:// if available.) + + But before that, the helpdesk operator needs to have "vncviewer + -listen" running as before, however he needs an SSL tunnel at his end. + The easiest way to do this is use Enhanced TightVNC Viewer (SSVNC). + Start it, and select Options -> 'Reverse VNC Connection (-listen)'. + Then UN-select 'Verify All Certs' (this can be enabled later if you + want; you'll need the x11vnc SSL certificate), and click 'Listen'. + + If you don't want to use SSVNC for the viewer, but rather set up + STUNNEL manually instead, make a file "stunnel.cfg" containing: +foreground = yes +pid = + +[vnc] +accept = 5500 +connect = localhost:5501 + + and run: + stunnel ./stunnel.cfg + + and then start the "vncviewer -listen 1" (i.e. 1 to correspond to the + 5501 port.) Note that this assumes the stunnel install created a + Server SSL cert+key, usually /etc/stunnel/stunnel.pem (not all distros + will do this.) Also, that file is by default only readable by root, so + stunnel needs to be run as root. If your system does not have a key + installed or you do not want to run stunnel as root (or change the + permissions on the file), you can use x11vnc to create one for you for + example: + x11vnc -sslGenCert server self:mystunnel + + answer the prompts with whatever you want; you can take the default + for all of them if you like. The openssl(1) package must be installed. + See this link and this one too for more info on SSL certs. This + creates $HOME/.vnc/certs/server-self:mystunnel.pem, then you would + change the "stunnel.cfg" to look something like: +foreground = yes +pid = +cert = /home/myusername/.vnc/certs/server-self:mystunnel.pem + +[vnc] +accept = 5500 +connect = localhost:5501 + + In any event, with stunnel having been setup, the naive user is + instructed to paste in and run: + wget -qO - http://www.mysite.com/hd/vncs | sh - + + to pick up the vncs script this time. + + Of course if a man-in-the-middle can alter what the user downloads + then all bets are off!. + + More SSL variations and info about certificates can be found here. + + + OpenSSL libssl.so.0.9.7 problems: + + If you build your own stunnel or x11vnc for deployment, you may want + to statically link libssl.a and libcrypto.a into it because Linux + distros are currently a bit of a mess regarding which version of + libssl is installed. + + You will find the details here. + + + Q-125: Can I (temporarily) mount my local (viewer-side) Windows/Samba + File share on the machine where x11vnc is running? + + You will have to use an external network redirection for this. + Filesystem mounting is not part of the VNC protocol. + + We show a simple Samba example here. + + First you will need a tunnel to redirect the SMB requests from the + remote machine to the one you sitting at. We use an ssh tunnel: + sitting-here> ssh -C -R 1139:localhost:139 far-away.east + + Or one could combine this with the VNC tunnel at the same time, e.g.: + sitting-here> ssh -C -R 1139:localhost:139 -t -L 5900:localhost:5900 far-away +.east 'x11vnc -localhost -display :0' + + Port 139 is the Windows Service port. For Windows systems instead of + Samba, you may need to use the actual IP address of the Window machine + instead of "localhost" in the -R option (since the Windows service + does not listen on localhost by default.) + + Note that we use 1139 instead of 139 on the remote side because 139 + would require root permission to listen on (and you may have a samba + server running on it already.) + + The ssh -C is to enable compression, which might speed up the data + transfers. + + Depending on the remote system side configuration, it may or may not + be possible to mount the SMB share as a non-root user. Try it first as + a non-root user and if that fails you will have to become root. + + We will assume the user name is "fred" and we will try to mount the + viewer-side Windows SMB share "//haystack/pub" in + /home/fred/smb-haystack-pub. + far-away> mkdir -p /home/fred/smb-haystack-pub + far-away> smbmount //haystack/pub /home/fred/smb-haystack-pub -o username=fre +d,ip=127.0.0.1,port=1139 + + (The 2nd command may need to be run as root.) Then run "df" or "ls -l + /home/fred/smb-haystack-pub" to see if it is mounted properly. Consult + the smbmount(8) and related documentation (it may require some + fiddling to get write permissions correct, etc.) To unmount: + far-away> smbumount /home/fred/smb-haystack-pub + + At some point we hope to fold some automation for SMB ssh redir setup + into the Enhanced TightVNC Viewer (SSVNC) package we provide (as of + Sep 2006 it is there for testing.) + + + Q-126: Can I redirect CUPS print jobs from the remote desktop where + x11vnc is running to a printer on my local (viewer-side) machine? + + You will have to use an external network redirection for this. + Printing is not part of the VNC protocol. + + We show a simple Unix to Unix CUPS example here. Non-CUPS port + redirections (e.g. LPD) should also be possible, but may be a bit more + tricky. If you are viewing on Windows SMB and don't have a local cups + server it may be trickier still (see below.) + + First you will need a tunnel to redirect the print requests from the + remote machine to the one you sitting at. We use an ssh tunnel: + sitting-here> ssh -C -R 6631:localhost:631 far-away.east + + Or one could combine this with the VNC tunnel at the same time, e.g.: + sitting-here> ssh -C -R 6631:localhost:631 -t -L 5900:localhost:5900 far-away +.east 'x11vnc -localhost -display :0' + + Port 631 is the default CUPS port. The above assumes you have a Cups + server running on your viewer machine (localhost:631), if not, use + something like my-cups-srv:631 (the viewer-side Cups server) in the -R + instead. + + Note that we use 6631 instead of 631 on the remote side because 631 + would require root permission to listen on (and you likely have a cups + server running on it already.) + + Now the tricky part: to get applications to notice your cups + server/printer on localhost:6631. + + If you have administrative privilege (i.e. root password) on the + x11vnc side where the desktop is running, it should be easy to add the + printer through some configuration utility (e.g. in KDE: Utilities -> + Printing -> Printing Manager, and then supply admin password, and then + Add Printer/Class, and then fill in the inquisitive wizard. Most + important is the "Remote IPP server" panel where you put in localhost + for Host and 6631 for Port.) The main setting you want to convey is + the host is localhost and the port is non-standard (e.g. 6631.) Some + configuration utilities will take an Internet Printing Protocol (IPP) + URI, e.g. http://localhost:6631/printers/, + ipp://localhost:6631/printers/printer-name, + ipp://localhost:6631/ipp/printer-name, etc. Check your CUPS + documentation and admin interfaces to find what the syntax is and what + the "printer name" is. + + If you do not have root or print admin privileges, but are running a + recent (version 1.2 or greater) of the Cups client software, then an + easy way to temporarily switch Cups servers is to create the directory + and file: $HOME/.cups/client.conf on the remote side with a line like: + ServerName localhost:6631 + + When not using x11vnc for remote access you can comment the above line + out with a '#' (or rename the client.conf file), to have normal cups + operation. + + Unfortunately, running applications may need to be restarted to notice + the new printers (libcups does not track changes in client.conf.) + Depending on circumstances, a running application may actually notice + the new printers without restarting (e.g. no print dialog has taken + place yet, or there are no CUPS printers configured on the remote + side.) + + Cups client software that is older (1.1) does not support appending + the port number, and for newer ones there is a bug preventing it from + always working (fixed in 1.2.3.) Kludges like these at the command + line will work: + far-away> env CUPS_SERVER=localhost IPP_PORT=6631 lpstat -p -d + far-away> env CUPS_SERVER=localhost IPP_PORT=6631 lpr -P myprinter file.ps + far-away> env CUPS_SERVER=localhost IPP_PORT=6631 firefox + + but are somewhat awkward since you have to retroactively set the env. + var IPP_PORT. Its value cannot be broadcast to already running apps + (like the $HOME/.cups/client.conf trick sometimes does.) A common + workaround for an already running app is to somehow get it to "Print + To File", e.g. file.ps and then use something like the lpr example + above. Also, the option "-h host:port" works with CUPS lp(1) and + lpr(1). + + You can also print to Windows shares printers in principle. You may do + this with the smbspool(8) command, or configure the remote CUPS via + lpadmin(8), etc, to use a printer URI something like + smb://machine:port/printer (this may have some name resolution + problems WRT localhost.) Also, as with SMB mounting, the port redir + (-R) to the Windows machine must use the actual IP address instead of + "localhost". + + At some point we hope to fold some automation for CUPS ssh redir setup + into the Enhanced TightVNC Viewer (SSVNC) package we provide (as of + Sep 2006 it is there for testing.) + + + Q-127: How can I hear the sound (audio) from the remote applications + on the desktop I am viewing via x11vnc? + + You will have to use an external network audio mechanism for this. + Audio is not part of the VNC protocol. + + We show a simple Unix to Unix esd example here (artsd should be + possible too, we have also verified the esd Windows port works for the + method described below.) + + First you will need a tunnel to redirect the audio from the remote + machine to the one you sitting at. We use an ssh tunnel: + sitting-here> ssh -C -R 16001:localhost:16001 far-away.east + + Or one could combine this with the VNC tunnel at the same time, e.g.: + sitting-here> ssh -C -R 16001:localhost:16001 -t -L 5900:localhost:5900 far-a +way.east 'x11vnc -localhost -display :0' + + Port 16001 is the default ESD uses. So when an application on the + remote desktop makes a sound it will connect to this tunnel and be + redirected to port 16001 on the local machine (sitting-here in this + example.) The -C option is an attempt to compress the audio a little + bit. + + So we next need a local (sitting-here) esd daemon running that will + receive those requests and play them on the local sound device: + sitting-here> esd -promiscuous -port 16001 -tcp -bind 127.0.0.1 + + See the esd(1) man page for the meaning of the options (the above are + not very secure.) (This method also works with the EsounD windows port + esd.exe) + + To test this sound tunnel, we use the esdplay program to play a simple + .wav file: + far-away> esdplay -s localhost:16001 im_so_happy.wav + + If you hear the sound (Captain Kirk in this example), that means you + are in great shape. + + To run individual audio applications you can use the esddsp(1) + command: + far-away> esddsp -s localhost:16001 xmms + + Then you could try playing some sounds inside xmms. You could also set + the environment variable ESPEAKER=localhost:16001 to not need to + supply the -s option all the time. (for reasons not clear, sometimes + esddsp can figure it out on its own.) All the script esddsp does is to + set ESPEAKER and LD_PRELOAD for you so that when the application opens + the sound device (usually /dev/dsp) its interactions with the device + will be intercepted and sent to the esd daemon running on sitting-here + (that in turn writes them to the real, local /dev/dsp.) + + Redirecting All sound: + + It does not seem to be possible to switch all of the sound of the + remote machine from its sound device to the above esd+ssh tunnel + without some preparation. But it can be done reasonably well if you + prepare (i.e. restart) the desktop with this in mind. + + Here is one way to redirect all sound. The idea is we run the entire + desktop with sound directed to localhost:16001. When we are sitting at + far-away.east we run "esd -promiscuous -port 16001 -tcp -bind + 127.0.0.1" on far-away.east (to be able to hear the sound.) However, + when we are sitting at sitting-here.west we kill that esd process and + run that same esd command on sitting-here.west and start up the above + ssh tunnel. This is a little awkward, but with some scripts one would + probably kill and restart the esd processes automatically when x11vnc + is used. + + So next we have to run the whole desktop pointing toward our esd. Here + is a simple way to test. Log in to the machine via the "FailSafe" + desktop. Then in the lone terminal type something like: + esddsp -s localhost:16001 gnome-session +or: + esddsp -s localhost:16001 startkde + + where the last part is whatever command starts your desktop (even + fvwm2.) This causes the environment variables ESPEAKER and LD_PRELOAD + to be set appropriately and every application (processes with the + desktop as an ancestor) will use them. If this scheme works well you + can make it less klunky by adding the command to your ~/.xsession, + etc. file that starts your default desktop. Or you may be able to + configure your desktop to use localhost:16001, or whatever is needed, + via a gui configuration panel. Some Notes: + * Not all audio applications are compatible with the esd and artsd + mechanisms, but many are. + * The audio is not compressed so you probably need a broadband or + faster connection. Listening to music may not be very pleasant... + (Although we found streaming music from across the US over cable + modem worked OK, but took 200 KB/sec, to use less bandwidth + consider something like "ssh far-away.east 'cat favorite.mp3' | + mpg123 -b 4000 -") + * Linux does not seem to have the concept of LD_PRELOAD_64 so if you + run on a mixed 64- and 32-bit ABI system (e.g. AMD x86_64) some of + the applications will fail to run because LD_PRELOAD will point to + libraries of the wrong wordsize. + * At some point we hope to fold some automation for esd or artsd ssh + redir setup into the Enhanced TightVNC Viewer (SSVNC) package we + provide (as of Sep/2006 it is there for testing.) + + + Q-128: Why don't I hear the "Beeps" in my X session (e.g. when typing + tput bel in an xterm)? + + As of Dec/2003 "Beep" XBell events are tracked by default. The X + server must support the XKEYBOARD extension (this is not on by default + in Solaris, see Xserver(1) for how to turn it on via +kb), and so you + won't hear them if the extension is not present. + + If you don't want to hear the beeps use the -nobell option. If you + want to hear the audio from the remote applications, consider trying a + redirector such as esd. + + + Q-129: Does x11vnc work with IPv6? + + Update: as of Apr/2010 in the 0.9.10 x11vnc development tarball, there + is now built-in support for IPv6 (128 bit internet addresses.) See the + -6 and -connect options for details. + + The remainder of this FAQ entry shows how to do with this with pre + 0.9.10 x11vnc using IPv6 helper tools. + _________________________________________________________________ + + Using an external IPv6 helper: + A way to do this is via a separate helper program such as inetd (or + for encrypted connections: ssh or stunnel.) For example, you configure + x11vnc to be run from inetd or xinetd and instruct it to listen on an + IPv6 address. For xinetd the setting "flags = IPv6" will be needed. + For inetd.conf, an example is: + 5900 stream tcp6 nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc_wrapper.sh + + We also provide a transitional tool in "x11vnc/misc/inet6to4" that + acts as a relay for any IPv4 application to allow connections over + IPv6. For example: + inet6to4 5900 localhost:5900 + + where x11vnc is listening on IPv4 port 5900. + + Also note that not all VNC Viewers are IPv6 enabled, so a redirector + may also be needed for them. The tool "inet6to4 -r ..." can do this as + well. SSVNC (see below) supports IPv6 without need for the helper. + + # ./inet6to4 -help + + inet6to4: Act as an ipv6-to-ipv4 relay for tcp applications that + do not support ipv6. + + Usage: inet6to4 + inet6to4 -r + + Examples: inet6to4 5900 localhost:5900 + inet6to4 8080 web1:80 + inet6to4 -r 5900 fe80::217:f2ff:fee6:6f5a%eth0:5900 + + The -r option reverses the direction of translation (e.g. for ipv4 + clients that need to connect to ipv6 servers.) Reversing is the default + if this script is named 'inet4to6' (e.g. by a symlink.) + + Use Ctrl-C to stop this program. + + You can also set env. vars INET6TO4_LOOP=1 or INET6TO4_LOOP=BG + to have an outer loop restarting this program (BG means do that + in the background), and INET6TO4_LOGFILE for a log file. + Also set INET6TO4_VERBOSE to verbosity level and INET6TO4_WAITTIME + and INET6TO4_PIDFILE (see below.) + + The "INET6TO4_LOOP=BG" and "INET6TO4_LOGFILE=..." env. variables make + the tool run reliably as a daemon for very long periods. Read the top + part of the script for more information. + _________________________________________________________________ + + Encrypted Tunnels with IPv6 Support: + For SSH tunnelled encrypted VNC connections, one can of course use the + IPv6 support in ssh(1). + + For SSL encrypted VNC connections, one possibility is to use the IPv6 + support in stunnel(1). This includes the built-in support via the + -stunnel option. For example: + x11vnc -stunnel SAVE -env STUNNEL_LISTEN=:: -env STUNNEL_DEBUG=1 ... + _________________________________________________________________ + + SSH IPv6 Tricks: + It is interesting to note that ssh(1) can do basically the same thing + as inet6to4 above by: + ssh -g -L 5900:localhost:5901 localhost "printf 'Press Enter to Exit: '; read + x" + + (where we have x11vnc running via "-rfbport 5901" in this case.) + + Note that one can also make a home-brew SOCKS5 ipv4-to-ipv6 gateway + proxy using ssh like this: + ssh -D '*:1080' localhost "printf 'Press Enter to Exit: '; read x" + + then specify a proxy like socks://hostname:1080 where hostname is the + machine running the above ssh command (add -v to ssh for connection + logging info.) + _________________________________________________________________ + + IPv6 SSVNC Viewer: + Our SSVNC VNC Viewer is basically a wrapper for ssh(1) and stunnel(1), + and so it already has good IPv6 support because these two commands do. + On Unix, MacOSX, and Windows nearly all of the the remaining parts of + SSVNC (e.g. the built-in proxying and un-encrypted connections) have + been modified to support IPv6 in SSVNC 1.0.26. + + + + + + + Contributions: + + Q-130: Thanks for your program or for your help! Can I make a + donation? + + Please do (any amount is appreciated; very few have donated) and thank + you for your support! Click on the PayPal button below for more info. + + [x-click-but04.gif]-Submit + +======================================================================= +http://www.karlrunge.com/x11vnc/chainingssh.html: + + + _________________________________________________________________ + + Chaining ssh's: Note that for use of a ssh gateway and -L redirection + to an internal host (e.g. "-L 5900:otherhost:5900") the VNC traffic + inside the firewall is not encrypted and you have to manually log into + otherhost to start x11vnc. Kyle Amon shows a method where you chain + two ssh's together that encrypts all network traffic and also + automatically starts up x11vnc on the internal workstation: +#!/bin/sh +# +gateway="example.com" # or "user@example.com" +host="labyrinth" # or "user@hostname" +user="kyle" + +# Need to sleep long enough for all of the passwords and x11vnc to start up. +# The /dev/null) & + +# Chain the vnc connection thru 2 ssh's, and connect x11vnc to user's display: +# +exec /usr/bin/ssh -t -L 5900:localhost:5900 $gateway \ + /usr/bin/ssh -t -L 5900:localhost:5900 $host \ + sudo /usr/bin/x11vnc -localhost -auth /home/$user/.Xauthority \ + -rfbauth .vnc/passwd -display :0 + + Also note the use of sudo(1) to switch to root so that the different + user's .Xauthority file can be accessed. See the visudo(8) manpage for + details on how to set this up (remove the sudo if you do not want to + do this). One can also chain together ssh's for reverse connections + with vncviewers using the -listen option. For this case -R would + replace the -L (and 5500 the 5900, see the #2 example script above). + If the gateway machine's sshd is configured with GatewayPorts=no (the + default) then the double chaining of "ssh -R ..." will be required for + reverse connections to work. + +======================================================================= +http://www.karlrunge.com/x11vnc/miscbuild.html: + + + _________________________________________________________________ + + Misc. Build problems: We collect here rare build problems some users + have reported and the corresponding workarounds. See also the FAQ's on + building. + _________________________________________________________________ + + ENV parameter: One user had a problem where the build script below was + failing because his work environment had the ENV variable set to a + script that was resetting his PATH so that gcc could no longer be + found. Make sure you do not have any ENV or BASH_ENV in your + environment doing things like that. Typing "unset ENV", etc. before + configuring and building should clear it. + _________________________________________________________________ + + Bash xpg: One user had his bash shell compiled with + --enable-xpg-echo-default that causes some strange behavior with + things like echo "\\1 ..." the configure script executes. In + particular instead of getting "\1" the non-printable character "^A" is + produced, and causes failures at compile time like: + ../rfb/rfbconfig.h:9:22: warning: extra tokens at end of #ifndef directive + + The workaround is to configure like this: + env CONFIG_SHELL=/bin/sh /bin/sh ./configure + + i.e. avoid using the bash with the misbehavior. A bug has been filed + against autoconf to guard against this. + _________________________________________________________________ + + AIX: one user had to add the "X11.adt" package to AIX to get build + header files like XShm.h, etc. + _________________________________________________________________ + + Ubuntu Feisty Fawn 7.04: In May/2007 one user said he needed to add + these packages to compile x11vnc on that Linux distro and version: + apt-get install build-essential make bin86 libjpeg62-dev libssl-dev libxtst-d +ev + + Note that Ubuntu is based on Debian, so perhaps this is the list + needed on Debian (testing?) as well. To build in Avahi (mDNS service + advertising) support it would appear that libavahi-client-dev is + needed as well. + _________________________________________________________________ + + Exceedingly slow compilation: x11vnc has a couple of files which + contain very large "case statements" (over 100 cases) that on some + platforms can take a very long time to compile (in extreme cases over + an hour). However on 32bit Linux with intel/amd processor and gcc + these files usually take less than 10 seconds to compile. For 64bit + systems using gcc the problem appears to be much worse. + + The two files with the large number of cases, remote.c and x11vnc.c, + have no real need to be optimized (the code is used only very + infrequently). So it is fine to supply "-O0" (disables optimization) + to CFLAGS when compiling them. However, it is tricky with + autoconf/automake to do this (especially since both the compiler and + make versions have a big effect). + + So if the compile times are getting too long for you for these two + files you will need to manually change some things. First, run + configure and when it has finished, edit the generated file + x11vnc/Makefile and put these lines at the very top: +x11vnc-x11vnc.o : CFLAGS += -O0 +x11vnc-remote.o : CFLAGS += -O0 + + Those lines assume gnu make (gmake) is being used. If you are using + another make, say Solaris make, insert these instead: +x11vnc-x11vnc.o := CFLAGS += -O0 +x11vnc-remote.o := CFLAGS += -O0 + + You could write a build shell script that modified the Makefile this + way before running make. + + The "-O0" (note it is "capital Oh" followed by "zero") assumes the gcc + compiler. If you are using a different compiler you will need to find + the command line option to disable optimization, or otherwise have the + lines set CFLAGS to the empty string. + _________________________________________________________________ + +======================================================================= +http://www.karlrunge.com/x11vnc/sunray.html: + + + Sun Ray Notes: + + You can run x11vnc on your (connected or disconnected) SunRay session + (Please remember to use settings like -wait 200, -sb 15, and not + running a screensaver animation (blank instead) to avoid being a + resource hog! x11vnc does induce a lot of memory I/O from polling the + X server. It also helps to have a solid background color, e.g. + -solid). + + News: Sun Ray Remote Control Toolkit: See the nice set of tools in the + Sun Ray Remote Control Toolkit that launch x11vnc automatically for + you for certain usage modes. + + You have to know the name of the machine your SunRay session X server + is running on (so you can ssh into it and start x11vnc). You also need + to know the X11 DISPLAY number for the session: on a SunRay it could + be a large number, e.g. :137, since there are many people with X + sessions (Xsun processes) on the same machine. If you don't know it, + you can get it by running who(1) in a shell on the SunRay server and + looking for the dtlocal entry with your username (and if you don't + even know which server machine has your session, you could login to + all possible ones looking at the who output for your username...). + + I put some code in my ~/.dtprofile script that stores $DISPLAY + (including the hostname) in a ~/.sunray_current file at session + startup (and deletes it when the X session ends) to make it easy to + get at the hostname and X11 display number info for my current X + sessions when I ssh in and am about to start x11vnc. + + SunRay Gotcha #1: Note that even though your SunRay X11 DISPLAY is + something like :137, x11vnc still tries for port 5900 as its listening + port if it can get it, in which case the VNC display (i.e. the + information you supply to the VNC viewer) is something like + sunray-server:0 (note the :0 corresponding to port 5900, it is not + :137). If it cannot get 5900, it tries for 5901, and so on. You can + also try to force the port (and thereby the VNC display) using the + -rfbport NNNN option. + + Especially on a busy Sun Ray server it is often difficult to find free + ports for both VNC and the HTTP Java applet server to listen on. This + script, vnc_findports may be of use for doing this automatically. It + suggests x11vnc command line options based on netstat output that + lists the occupied ports. It is even more difficult to start + vncserver/Xvnc on a busy Sun Ray because then 3 ports (HTTP, VNC, and + X11), all separated by 100 are needed! This script, findvncports may + be helpful as well. Both scripts start at VNC display :10 and work + their way up. + + SunRay Gotcha #2: If you get an error like: + shmget(tile) failed. + shmget: No space left on device + + when starting up x11vnc that most likely means all the shared memory + (shm) slots are filled up on your machine. The Solaris default is only + 100, and that can get filled up in a week or so on a SunRay server + with lots of users. If the shm slot is orphaned (e.g. creator process + dies) the slot is not reclaimed. You can view the shm slots with the + "ipcs -mA" command. If there are about 100 then you've probably hit + this problem. They can be cleaned out (by the owner or by root) using + the ipcrm command. I wrote a script shm_clear that finds the orphans + and lists or removes them. Longer term, have your SunRay sysadmin add + something like this to /etc/system: + set shmsys:shminfo_shmmax = 0x2000000 + set shmsys:shminfo_shmmni = 0x1000 + + SunRay Gotcha #3: Some SunRay installations have implemented + suspending certain applications when a SunRay session is in a + disconnected state (e.g. Java Badge pulled out, utdetach, etc). This + is a good thing because it limits hoggy or runaway apps from wasting + the shared CPU resource. Think how much CPU and memory I/O is wasted + by a bunch of Firefox windows running worthless Flash animations while + your session is disconnected! + + So some sites have implemented scripts to suspend (e.g. kill -STOP) + certain apps when your badge is removed from the SunRay terminal. When + you reattach, it kill -CONT them. This causes problems for viewing the + detached SunRay session via x11vnc: those suspended apps will not + respond (their windows will be blank or otherwise inactive). + + What to do? Well, since you are going to be using the application you + might as well unfreeze it rather than starting up a 2nd instance. Here + is one way to do it using the kill -CONT mechanism: + kill -CONT `ps -ealf | grep ' T ' | grep $LOGNAME | awk '{print $4}'` + + If you want to be a good citizen and re-freeze them before you exit + x11vnc this script could be of use: +#!/bin/sh +# +# kill -STOP/-CONT script for x11vnc (or other) SunRay usage ("freezes" +# certain apps from hogging resources when disconnected). +# +# Put here a pattern that matches the apps that are frozen: +# +appmatch="java_vm|jre|netscape-bin|firefox-bin|realplay|acroread|mozilla-bin" + +if [ "X$1" = "Xfreeze" ]; then + pkill -STOP -U $LOGNAME "$appmatch" +elif [ "X$1" = "Xthaw" ]; then + pkill -CONT -U $LOGNAME "$appmatch" + +elif [ "$RFB_MODE" = "afteraccept" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "1" ]; then + # only one client present. + pkill -CONT -U $LOGNAME "$appmatch" + fi +elif [ "$RFB_MODE" = "gone" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "0" ]; then + # last client present has just left. + pkill -STOP -U $LOGNAME "$appmatch" + fi +fi +exit 0 + + If you called the script "goodcitizen" you could type "goodcitizen + thaw" to unfreeze them, and then "goodcitizen freeze" to refreeze + them. One could also use these x11vnc options "-afteraccept + goodcitizen -gone goodcitizen" to do it automatically. + + SunRay Gotcha #4: Recent versions of the Sun Ray Server Software + SRSS (seems to be version 3.0 or 3.1) have a "misfeature" that when + the session is disconnected (i.e. badge/smartcard out) the screen + locker (xscreensaver) will freeze the X server just when the "Enter + Password" dialog box appears. So you cannot unlock the screen remotely + via x11vnc! + + Update: please see Bob Doolittle's detailed description of the this + issue at the bottom of this section. + + Here "freeze" means "stop other X clients from inserting keyboard and + mouse input and from viewing the current contents of the screen". Or + something like that; the upshot is x11vnc can't do its normal thing. + + There are several workarounds for this. + + 1) The easiest one by far is to put these lines in your + $HOME/.dtprofile file: +SUN_SUNRAY_UTXLOCK_PREF="/usr/openwin/bin/xlock -mode blank" +export SUN_SUNRAY_UTXLOCK_PREF + + One might argue that xlock isn't particularly "pretty". (Just IMHO, + but if something like this not being pretty actually gets in the way + of your work I think some introspection may be in order. :-) + + 2) The problem has been traced to the pam_sunray.so PAM module. + Evidently xscreensaver invokes this pam module and it communicates + with utsessiond who in turn instructs the Xsun server to not process + any synthetic mouse/keyboard input or to update the screen + framebuffer. It is not clear if this is by design (security?) or + something else. + + In any event, the problem can be avoided, somewhat drastically, by + commenting out the corresponding line in /etc/pam.conf: +#xscreensaver auth sufficient /opt/SUNWut/lib/pam_sunray.so syncondisplay + + Leave the other xscreensaver pam authentication lines unchanged. The + dtsession-SunRay line may also need to be commented out to avoid the + problem for CDE sessions. N.B. it is possible the application of a + SSRS patch, etc, may re-enable that /etc/pam.conf line. It may be + difficult to convince a sysadmin to make this change. + + 3) A more forceful way is to kill the xscreensaver process from a + shell prompt whenever you connect via x11vnc and the screen is in a + locked state: +pkill -U $LOGNAME '^xscreensaver$' + + And then after you are in be sure to restart it by typing something + like: +xscreensaver & + + You may want to avoid restarting it until you are about to disconnect + your VNC viewer (since if it locks the screen while you are working + you'll be stuck again). + + 3') The above idea can be done a bit more cleanly by having x11vnc do + it. Suppose we called the following script xss_killer: +#!/bin/sh +# +# xss_killer: kill xscreensaver after a valid x11vnc client logs in. +# Restart xscreensaver and lock it when the last client +# disconnects. + +PATH=/usr/openwin/bin:/usr/bin:$PATH +export PATH + +if [ "$RFB_MODE" = "afteraccept" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "1" ]; then + # only one client present. + pkill -U $LOGNAME '^xscreensaver$' + pkill -KILL -U $LOGNAME -f xscreensaver/hacks + fi +elif [ "$RFB_MODE" = "gone" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "0" ]; then + # last client present has just left. + xscreensaver -nosplash & + sleep 1 + xscreensaver-command -lock & + fi +fi + + Then we would run x11vnc with these options: "-afteraccept xss_killer + -gone xss_killer". The -afteraccept option (introduced in version 0.8) + is used to run a command after a vncviewer has successfully logged in + (note that this is a VNC login, not a Unix login, so you may not want + to do this if you are really paranoid...) + + Note if you use the above script and also plan to Ctrl-C (SIGINT) + x11vnc you have to run the xscreensaver in a new process group to + avoid killing it as well. One way to do this is via this kludge: +perl -e 'setpgrp(0,0); exec "xscreensaver -nosplash &"' + + in the above script. + + 4) There appears to be a bug in pam_sunray.so in that it doesn't seem + to honor the convention that, say, DISPLAY=unix:3 means to use Unix + sockets to connect to display 3 on the local machine (this is a bit + faster than TCP sockets). Rather, it thinks the display is a non-local + one to a machine named "unix" (that usually does not resolve to an IP + address). + + Amusingly, this can be used to bypass the pam_sunray.so blocking of + Xsun that prevents one from unlocking the screen remotely via x11vnc. + One could put something like this in $HOME/.dtprofile to kill any + existing xscreensavers and then start up a fresh xscreensaver using + DISPLAY=unix:N +# stop/kill any running xscreensavers (probably not running yet, but to be sure +) +xscreensaver-command -exit +pkill -U $LOGNAME '^xscreensaver$' +env DISPLAY=`echo $DISPLAY | sed -e 's/^.*:/unix:/'` xscreensaver & + + + Important: Note that all of the above workarounds side-step the + pam_sunray.so PAM module in one way or another. You'll need to see if + that is appropriate for your site's SunRay / smartcard usage. Also, + these hacks may break other things and so you may want to test various + scenarios carefully. E.g. check corner cases like XDMCP/dtremote, + NSCM, etc. + + + Update May 2008: Here is a useful description of this issue from Bob + Doolittle who is a developer for Sun Ray at Sun. I don't have the time + to digest and distill it and then adjust the above methods to provide + a clearer description, so I just include below the description he sent + me with the hope that it will help some users: + + In SRSS 4.0 and earlier, the purpose of pam_sunray.so in the "auth" + PAM stack of screensavers is to enable NSCM (and, although this is + much less commonly used, "SC", which is configured when 3rd-party + software is installed to allow smartcards to be used as part of the + authentication process) to work. It should have no effect with + smartcards. Currently, however, it does block the PAM stack for all + sessions, which causes xscreensaver, when it locks a disconnected + session, to not process any mouse or keyboard events as you + describe (unless xscreensaver does an X server grab, however, other + applications should still be able to draw in the session although + xscreensaver may be playing tricks like putting a black window on + top of everything). In both of the NSCM and SC models, + authentication occurs in a separate session before SRSS will + reconnect to the user session, in which case pam_sunray.so causes + xscreensaver to just unlock the screen without prompting the user + to enter their password again. To do this, pam_sunray.so has to + block until the session becomes reconnected, so it can query SRSS + at that time to determine whether the user has already + authenticated or not. In SRSS 4.0 and earlier releases, + pam_sunray.so could have been optimized to not block smartcard + sessions, although since the session is disconnected this typically + isn't important (except in the x11vnc case, as you've observed). + + In SRSS 4.1, however, for increased security the out-of-session + authentication model has been extended to *all* session types, so + pam_sunray.so will be required in all cases unless users are + willing to authenticate twice upon hotdesking (e.g. when their card + is inserted). In future, we may do away with pam_sunray.so, and in + fact with any traditional screen locker in the user session, since + SRSS itself will be providing better security than a screen locker + running entirely within the user's X session is capable of + providing. + + Your trick of setting DISPLAY to unix:DPY will effectively disable + pam_sunray.so (I'm not sure I'd call that a bug - you're going out + of your way to do something that wouldn't occur in the normal + course of events, and really provides no useful value other than to + tickle this behavior in pam_sunray.so). This will mean that, in + SRSS 4.0 and earlier releases, users will be prompted for their + passwords twice when reconnecting to their sessions for NSCM and SC + session types. In 4.1, disabling pam_sunray.so in this way will + cause this double-authentication to occur for *all* sessions, + including simple smartcard sessions. Users may be willing to pay + that price in order to be able to use x11vnc in disconnected + sessions. I like this hack, personally. It's a little less + convenient than some of the other approaches you describe, but it's + lighter-weight and more secure than most of the other approaches, + and provides the value of being able to use x11vnc in locked + sessions. + + Here are some other minor notes: - I wouldn't recommend storing + your display in your .dtprofile, unless you're willing to live with + a single session at a time. Personally, I often find myself using + several sessions, in several FoGs, for short periods of time so + this would certainly break. IMO it's pretty easy to use $DISPLAY to + do what you want on the fly, as needed, so I don't think the price + of breaking multiple-session functionality would be worth the + convenience, to me at least. Here's some ksh/bash syntax to extract + the hostname and display number on the fly which you may find + useful: +HOSTNAME=${DISPLAY%:*} +FULLDPY=${DISPLAY#*:} +DPYNUM=${FULLDPY%.*} + + A final note may give you some insight into other clever hacks in + this area: - Check out utaction. It's a very handy little utility + that can be run as a daemon in the user session which will invoke a + specified command upon session connects and/or disconnects. + Personally, I start one up in my .dtprofile as follows: +utaction -c $HOME/.srconnectrc -d $HOME/.srdisconnectrc & + + This then allows me to construct a .srconnectrc script containing + useful commands I'd like to have run every time I insert my + smartcard, and a .srdisconnectrc script of commands to be run every + time I remove my smartcard (or, connect/disconnect to my session + via NSCM or SC). This can be used for things like notifying a chat + client of away status, as well as some of the hacks you've + described on your page such as freeze/unfreeze, or perhaps to + terminate an xscreensaver and start up a new one with the unix:DPY + $DISPLAY specification as you describe (although it probably makes + most sense to do this at login time, as opposed to every connect or + disconnect event). + +======================================================================= +http://www.karlrunge.com/x11vnc/ssl.html: + + + _________________________________________________________________ + + Notes on x11vnc SSL Certificates and Key Management: + + The simplest scheme ("x11vnc -ssl TMP") is where x11vnc generates a + temporary, self-signed certificate each time (automatically using + openssl(1)) and the VNC viewer client accepts the certificate without + question (e.g. user clicks "Yes" in a dialog box. Perhaps the dialog + allows them to view the certificate too). Also note stunnel's default + is to quietly accept all certificates. + + The encryption this provides protects against all passive sniffing of + the VNC traffic and passwords on the network and so it is quite good, + but it does not prevent a Man-In-The-Middle active attack: e.g. an + attacker intercepts the VNC client stream and sends it his own Public + key for SSL negotiation (pretending to be the server). Then it makes a + connection to SSL x11vnc itself and forwards the data back and forth. + He can see all the traffic and modify it as well. + + Most people don't seem to worry about Man-In-The-Middle attacks these + days; they are more concerned about passive sniffing of passwords, + etc. Perhaps someday that will change if attack tools are used more + widely to perform the attack. NOTE: There are hacker tools like + dsniff/webmitm and cain that implement SSL Man-In-The-Middle attacks. + They all rely on the client not bothering to check that the cert is + valid. + + If you are not worried about Man-In-The-Middle attacks you do not have + to read the techniques described in the rest of this document. + + To prevent Man-In-The-Middle attacks, certificates must somehow be + verified. This requires the VNC client side have some piece of + information that can be used to verify the SSL x11vnc server. + Alternatively, although rarely done, x11vnc can verify VNC Clients' + certificates, see the -sslverify option that is discussed below. + + There are a number of ways to have the client authenticate the SSL + x11vnc server. The quickest way perhaps would be to copy (safely) the + certificate x11vnc prints out: +26/03/2006 21:12:00 Creating a temporary, self-signed PEM certificate... +... +-----BEGIN CERTIFICATE----- +MIIC4TCCAkqgAwIBAgIJAMnwCaOjvEKaMA0GCSqGSIb3DQEBBAUAMIGmMQswCQYD +VQQGEwJBVTEOMAwGA1UEBxMFTGludXgxITAfBgNVBAsTGGFuZ2VsYS0xMTQzNDI1 +NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM +(more lines) ... +-----END CERTIFICATE----- + + to the client machine(s) and have the client's SSL machinery (e.g. + stunnel, Web Browser, or Java plugin) import the certificate. That way + when the connection to x11vnc is made the client can verify that is it + the desired server on the other side of the SSL connection. + + So, for example suppose the user is using the SSL enabled Java VNC + Viewer and has incorporated the x11vnc certificate into his Web + browser on the viewing side. If he gets a dialog that the certificate + is not verified he knows something is wrong. It may be a + Man-In-The-Middle attack, but more likely x11vnc certificate has + changed or expired or his browser was reinstalled and/or lost the + certificate, etc, etc. + + As another example, if the user was using stunnel with his VNC viewer + (this is mentioned in this FAQ), e.g. STUNNEL.EXE on Windows, then he + would have to set the "CAfile = path-to-the-cert" and "verify = 2" + options in the stunnel.conf file before starting up the tunnel. If a + x11vnc certificate cannot be verified, stunnel will drop the + connection (and print a failure message in its log file). + + A third example, using the VNC viewer on Unix with stunnel the wrapper + script can be used this way: "ss_vncviewer -verify ./x11vnc.crt + far-away.east:0" where ./x11vnc.crt is the copied certificate x11vnc + printed out. + + As fourth example, our SSVNC enhanced tightvnc viewer can also use + these certificate files for server authentication. You can load them + via the SSVNC 'Certs...' dialog and set 'ServerCert' to the + certificate file you safely copied there. + + Note that in principle the copying of the certificate to the client + machine(s) itself could be altered by a Man-In-The-Middle attack! You + can't win; it is very difficult to be completely secure. It is + unlikely the attacker could predict how you were going to send it + unless you had, say, done it many times before the same way. SSH is a + very good way to send it (but of course it too depends on public keys + being sent unaltered between the two machines!). + + If you are really paranoid, I'm sure you'll figure out a really good + way to transport the certificates. See the Certificate Authority + scheme below for a way to make this easier (you just have to do it + once). + + _________________________________________________________________ + + Saving SSL certificates and keys: + + Now, it would be very inconvenient to copy the new temporary + certificate every time x11vnc is run in SSL mode. So for convenience + there is the "SAVE" keyword to instruct x11vnc to save the certificate + it creates: + x11vnc -ssl SAVE -display :0 ... + + This behavior is now the default, you must use "TMP" for a temporary + one. It will save the certificate and private key in these files: + ~/.vnc/certs/server.crt + ~/.vnc/certs/server.pem + + The ".crt" file contains only the certificate and should be safely + copied to the VNC Viewer machine(s) that will be authenticating the + x11vnc server. The ".pem" file contains both the certificate and the + private key and should be kept secret. (If you don't like the default + location ~/.vnc/certs, e.g. it is on an NFS share and you are worried + about local network sniffing, use the -ssldir dir option to point to a + different directory.) + + So the next time you run "x11vnc -ssl SAVE ..." it will read the + server.pem file directly instead of creating a new one. + + You can manage multiple SSL x11vnc server keys in this simple way by + using: + x11vnc -ssl SAVE-key2 -display :0 ... + + etc, where you put whatever name you choose for the key after "SAVE-". + E.g. "-ssl SAVE-fred". + + Also, if you want to be prompted to possibly change the made up names, + etc. that x11vnc creates (e.g. "x11vnc-SELF-SIGNED-CERT-7762" for the + CommonName) for the certificates distinguished name (DN), then use + "x11vnc -ssl SAVE_PROMPT ...", "x11vnc -ssl SAVE_PROMPT-fred ..." etc. + when you create the key the first time. + + Tip: when prompting, if you choose the CommonName entry to be the full + internet hostname of the machine the clients will be connecting to + then that will avoid an annoying dialog box in their Web browsers that + warn that the CommonName doesn't match the hostname. + + _________________________________________________________________ + + Passphrases for server keys: + + Well, since now with the "SAVE" keyword the certificate and key will + be longer lived, one can next worry about somebody stealing the + private key and pretending to be the x11vnc server! How to guard + against this? + + The first is that the file is created with perms 600 (i.e. -rw-------) + to make it harder for an untrusted user to copy the file. A better way + is to also encrypt the private key with a passphrase. You are prompted + whether you want to do this or not when the key is first created under + "-ssl SAVE" mode ("Protect key with a passphrase? y/n"). It is + suggested that you use a passphrase. The inconvenience is every time + you run "x11vnc -ssl SAVE ..." you will need to supply the passphrase + to access the private key: + 06/04/2006 11:39:11 using PEM /home/runge/.vnc/certs/server.pem 0.000s + + A passphrase is needed to unlock an OpenSSL private key (PEM file). + Enter passphrase> + + before x11vnc can continue. + + _________________________________________________________________ + + Being your own Certificate Authority: + + A very sophisticated way that scales well if the number of users is + large is to use a Certificate Authority (CA) whose public certificate + is available to all of the VNC clients and whose private key has been + used to digitally sign the x11vnc server certificate(s). + + The idea is as follows: + * A special CA cert and key is generated. + * Its private key is always protected by a good passphrase since it + is only used for signing. + * The CA cert is (safely) distributed to all machines where VNC + clients will run. + * One or more x11vnc server certs and keys are generated. + * The x11vnc server cert is signed with the CA private key. + * x11vnc is run using the server key. (e.g. "-ssl SAVE") + * VNC clients (viewers) can now authenticate the x11vnc server + because they have the CA certificate. + + The advantage is the CA cert only needs to be distributed once to the + various machines, that can be done even before x11vnc server certs are + generated. + + As above, it is important the CA private key and the x11vnc server key + are kept secret, otherwise someone could steal them and pretend to be + the CA or the x11vnc server if they copied the key. It is recommended + that the x11vnc server keys are also protected via a passphrase (see + the previous section). + + Optionally, VNC viewer certs and keys could also be generated to + enable the x11vnc server to authenticate each client. This is not + normally done (usually a simple viewer password scheme is used), but + this can be useful in some situations. These optional steps go like + this: + * One or more VNC client certs and keys are generated. + * These VNC client certs are signed with the CA private key. + * The VNC client certs+keys are safely distributed to the + corresponding client machines. + * x11vnc is told to verify clients by using the CA cert. (e.g. + "-sslverify CA") + * When VNC clients (viewers) connect, they must authenticate + themselves to x11vnc by using their client key. + + Again, it is a good idea if the client private keys are protected with + a passphrase, otherwise if stolen they could be used to gain access to + the x11vnc server. Once distributed to the client machines, there is + no need to keep the client key on the CA machine that generated and + signed it. You can keep the client certs if you like because they are + public. + + _________________________________________________________________ + + How to do the above CA steps with x11vnc: + + Some utility commands are provided to ease the cert+key creation, + signing, and management: -sslGenCA, -sslGenCert, -sslDelCert, + -sslEncKey, -sslCertInfo. They basically run the openssl(1) command + for you to manage the certs/keys. It is required that openssl(1) is + installed on the machine and available in PATH. All commands can be + pointed to an alternate toplevel certificate directory via the -ssldir + option if you don't want to use the default ~/.vnc/certs. + + 1) To generate your Certificate Authority (CA) cert and key run this: + x11vnc -sslGenCA + + Follow the prompts, you can modify any informational strings you care + to. You will also be required to encrypt the CA private key with a + passphrase. This generates these files: + ~/.vnc/certs/CA/cacert.pem (the CA public certificate) + ~/.vnc/certs/CA/private/cakey.pem (the encrypted CA private key) + + If you want to use a different directory use -ssldir It must supplied + with all subsequent SSL utility options to point them to the correct + directory. + + 2) To generate a signed x11vnc server cert and key run this: + x11vnc -sslGenCert server + + As with the CA generation, follow the prompts and you can modify any + informational strings that you care to. This will create the files: + ~/.vnc/certs/server.crt (the server public certificate) + ~/.vnc/certs/server.pem (the server private key + public cert) + + It is recommended to protect the server private key with a passphrase + (you will be prompted whether you want to). You will need to provide + it whenever you start x11vnc using this key. + + 3) Start up x11vnc using this server key: + x11vnc -ssl SAVE -display :0 ... + + (SAVE corresponds to server.pem, see -sslGenCert server somename info + on creating additional server keys, server-somename.crt ...) + + 4) Next, safely copy the CA certificate to the VNC viewer (client) + machine(s). Perhaps: + scp ~/.vnc/CA/cacert.pem clientmachine:. + + 5) Then the tricky part, make it so the SSL VNC Viewer uses this + certificate! There are a number of ways this might be done, it depends + on what your client and/or SSL tunnel is. Some examples: + + For the SSL Java VNC viewer supplied with x11vnc in + classes/ssl/VncViewer.jar or classes/ssl/SignedVncViewer.jar: + * Import the cacert.pem cert into your Web Browser (e.g. Edit -> + Preferences -> Privacy & Security -> Manage Certificates -> + WebSites -> Import) + * Or Import the cacert.pem cert into your Java Plugin (e.g. run + ControlPanel, then Security -> Certificates -> Secure Site -> + Import) + + When importing, one would give the browser/java-plugin the path to the + copied cacert.pem file in some dialog. Note that the Web browser or + Java plugin is used for the server authentication. If the user gets a + "Site not verified" message while connecting he should investigate + further. + + For the use of stunnel (e.g. on Windows) one would add this to the + stunnel.conf: + # stunnel.conf: + client = yes + options = ALL + CAfile = /path/to/cacert.pem # or maybe C:\path\to\cacert.pem + [myvncssl] + accept = 5901 + connect = far-away.east:5900 + + (then point the VNC viewer to localhost:1). + + Here is an example for the Unix stunnel wrapper script ss_vncviewer in + our SSVNC package: + ss_vncviewer -verify ./cacert.pem far-away.east:0 + + Our SSVNC enhanced tightvnc viewer GUI can also use the certificate + file for server authentication. You can load it via the SSVNC + 'Certs...' dialog and set 'ServerCert' to the cacert.pem file you + safely copied there. + + _________________________________________________________________ + + Tricks for server keys: + + To create additional x11vnc server keys do something like this: + x11vnc -sslGenCert server myotherkey + + and use it this way: + x11vnc -ssl SAVE-myotherkey ... + + The files will be ~/.vnc/certs/server-myotherkey.{crt,pem} + + You can also create a self-signed server key: + x11vnc -sslGenCert server self:third_key + + and use it this way: + x11vnc -ssl SAVE-self:third_key ... + + This key is not signed by your CA. This can be handy to have a key set + separate from your CA when you do not want to create a 2nd CA + cert+key. + + _________________________________________________________________ + + Using external CA's: + + You don't have to use your own CA cert+key, you can use a third + party's instead. Perhaps you have a company-wide CA or you can even + have your x11vnc certificate signed by a professional CA (e.g. + www.thawte.com or www.verisign.com or perhaps the free certificate + service www.startcom.org or www.cacert.org). + + The advantage to doing this is that the VNC client machines will + already have the CA certificates installed and you don't have to + install it on each machine. + + To generate an x11vnc server cert+key this way you should generate a + "request" for a certicate signing something like this (we use the name + "external" in this example, it could be anything you want): + x11vnc -sslGenCert server req:external + + This will create the request file: + ~/.vnc/certs/server-req:external.req + + Which you should send to the external CA. When you get the signed + certificate back from them, save it in the file: + ~/.vnc/certs/server-req:external.crt + + and create the .pem this way: + mv ~/.vnc/certs/server-req:external.key ~/.vnc/certs/server-req:external. +pem + chmod 600 ~/.vnc/certs/server-req:external.pem + cat ~/.vnc/certs/server-req:external.crt >> ~/.vnc/certs/server-req:external. +pem + + You also rename the two files (.crt and .pem) to have a shorter + basename if you like. E.g.: + mv ~/.vnc/certs/server-req:external.pem ~/.vnc/certs/server-ext.pem + mv ~/.vnc/certs/server-req:external.crt ~/.vnc/certs/server-ext.crt + + and the use via "x11vnc -ssl SAVE-ext ...", etc. + + On the viewer side make sure the external CA's certificate is + installed an available for the VNC viewer software you plan to use. + + _________________________________________________________________ + + Using Client Keys for Authentication: + + You can optionally create certs+keys for your VNC client machines as + well. After distributing them to the client machines you can have + x11vnc verify the clients using SSL. Here is how to do this: + + x11vnc -sslGenCert client dilbert + x11vnc -sslGenCert client wally + x11vnc -sslGenCert client alice + ... + + As usual, follow the prompts if you want to change any of the info + field values. As always, it is a good idea (although inconvenient) to + protect the private keys with a passphrase. These files are created: + ~/.vnc/certs/clients/dilbert.crt + ~/.vnc/certs/clients/dilbert.pem + ... + + Note that these are kept in a clients subdirectory. + + Next, safely copy the .pem files to each corresponding client machine + and incorporate them into the VNC viewer / SSL software (see the ideas + mentioned above for the CA and server keys). The only difference is + these certificates might be referred to as "My Certificates" or + "Client Certificates". They are used for client authentication (which + is relatively rare for SSL). + + After copying them you can delete the clients/*.pem files for extra + safety because the private keys are not needed by the x11vnc server. + You don't really need the clients/*.crt files either (because they + have been signed by the CA). But they could come in handy for tracking + or troubleshooting, etc. + + Now start up x11vnc and instruct it to verify connecting clients via + SSL and the CA cert: + x11vnc -ssl SAVE -sslverify CA + + The "CA" special token instructs x11vnc to use its CA signed certs for + verification. + + For arbitrary self-signed client certificates (no CA) it might be + something like this: + x11vnc -ssl SAVE -sslverify path/to/client.crt + x11vnc -ssl SAVE -sslverify path/to/client-hash-dir + x11vnc -ssl SAVE -sslverify path/to/certs.txt + + Where client.crt would be an individual client certificate; + client-hash-dir a directory of file names based on md5 hashes of the + certs (see -sslverify); and certs.txt signifies a single file full of + client certificates. + + Finally, connect with your VNC viewer using the key. Here is an + example for the Unix stunnel wrapper script ss_vncviewer: using client + authentication (and the standard server authentication with the CA + cert): + ss_vncviewer -mycert ./dilbert.pem -verify ./cacert.pem far-away.east:0 + + Our SSVNC enhanced tightvnc viewer can also use these openssl .pem + files (you can load them via Certs... -> MyCert dialog). + + It is also possible to use -sslverify on a per-client key basis, and + also using self-signed client keys (x11vnc -sslGenCert client + self:dilbert) + + Now a tricky part is to get Web browsers or Java Runtime to import and + use the openssl .pem cert+key files. See the next paragraph on how to + convert them to pkcs12 format. If you find a robust way to import them + and and get them to use the cert please let us know! + + Here is how to convert our openssl crt/pem files to pkcs12 format + (contains both the client certificate and key) that can be read by Web + browsers and Java for use in client authentication: + openssl pkcs12 -export -in mycert.crt -inkey mycert.pem -out mycert.p12 + + it will ask for a passphrase to protect mycert.p12. Some software + (e.g. Java ControlPanel) may require a non-empty passphrase. Actually, + since our .pem contains both the certificate and private key, you + could just supply it for the -in and remove the -inkey option. It + appears that for certificates only importing, our .crt file is + sufficient and can be read by Mozilla/Firefox and Java... + + If you have trouble getting your Java Runtime to import and use the + cert+key, there is a workaround for the SSL-enabled Java applet. On + the Web browser URL that retrieves the VNC applet, simply add a + "/?oneTimeKey=..." applet parameter (see ssl-portal for more details + on applet parameters; you don't need to do the full portal setup + though). The value of the oneTimeKey will be the very long string that + is output of the onetimekey program found in the classes/ssl x11vnc + directory. Or you can set oneTimeKey=PROMPT in which case the applet + will ask you to paste in the long string. These scheme is pretty ugly, + but it works. A nice application of it is to make one time keys for + users that have already logged into a secure HTTPS site via password. + A cgi program then makes a one time key for the logged in user to use: + it is passed back over HTTPS as the applet parameter in the URL and so + cannot be sniffed. x11vnc is run to use that key via -sslverify. + + Update: as of Apr 2007 in the 0.9.1 x11vnc tarball there is a new + option setting "-users sslpeer=" that will do a switch user much like + -unixpw does, but this time using the emailAddress field of the + Certificate subject of the verified Client. This mode requires + -sslverify turned on to verify the clients via SSL. This mode can be + useful in situations using -create or -svc where a new X server needs + to be started up as the authenticated user (but unlike in -unixpw + mode, the unix username is not obviously known). + + _________________________________________________________________ + + Revoking Certificates: + + A large, scaled-up installation may benefit from being able to revoke + certificates (e.g. suppose a user's laptop with a vnc client or server + key is compromised.) You can use this option with x11vnc: -sslCRL. See + the info at that link for a guide on what openssl(1) commands you will + need to run to revoke a certificate. + + _________________________________________________________________ + + Additional utlities: + + You can get information about your keys via -sslCertInfo. These lists + all your keys: + x11vnc -sslCertInfo list + x11vnc -sslCertInfo ll + + (the latter is long format). + + These print long output, including the public certificate, for + individual keys: + x11vnc -sslCertInfo server + x11vnc -sslCertInfo dilbert + x11vnc -sslCertInfo all (every key, very long) + + If you want to add a protecting passphrase to a key originally created + without one: + x11vnc -sslEncKey SAVE + x11vnc -sslEncKey SAVE-fred + + To delete a cert+key: + x11vnc -sslDelCert SAVE + x11vnc -sslDelCert SAVE-fred + x11vnc -sslDelCert wally + + (but rm(1) will be just as effective). + + _________________________________________________________________ + + Chained Certificates: + + There is increasing interest in using chained CA's instead of a single + CA. The merits of using chained CA's are not described here besides to + say its use may make some things easier when a certificate needs to be + revoked. + + x11vnc supports chained CA certificates. We describe a basic use case + here. + + Background: Of course the most straight forward way to use SSL with + x11vnc is to use no CA at all (see above): a self-signed certificate + and key is used and its certificate needs to be safely copied to the + client side. This is basically the same as the SSH style of managing + keys. Next level up, one can use a single CA to sign server keys: then + only the CA's certificate needs to be safely copied to the client + side, this can happen even before any server certs are created (again, + see all of the discussion above.) + + With a certificate chain there are two or more CA's involved. Perhaps + it looks like this: + root_CA ---> intermediate_CA ---> server_cert + + Where the arrow basically means "signs". + + In this usage mode the client (viewer-side) will have root_CA's + certificate available for verifying (and nothing else.) If the viewer + only received server_cert's certificate, it would not have enough info + to verify the server. The client needs to have intermediate_CA's cert + as well. The way to do this with x11vnc (i.e. an OpenSSL using app) is + to concatenate the server_cert's pem and the intermediate_CA's + certificate together. + + For example, suppose the file intermediate_CA.crt had + intermediate_CA's certificate. And suppose the file server_cert.pem + had the server's certificate and private key pair as described above + on this page. We need to do this: + cat intermediate_CA.crt >> server_cert.pem + + (Note: the order of the items inside the file matters; intermediate_CA + must be after the server key and cert) and then we run x11vnc like + this: + x11vnc -ssl ./server_cert.pem ... + + Then, on the VNC viewer client side, the viewer authenticates the + x11vnc server by using root_CA's certificate. Suppose that is in a + file named root_CA.crt, then using the SSVNC wrapper script + ss_vncviewer (which is also included in the SSVNC package) as our + example, we have: + ss_vncviewer -verify ./root_CA.crt hostname:0 + + (where "hostname" is the machine where x11vnc is running.) One could + also use the SSVNC GUI setting Certs -> ServerCert to the root_CA.crt + file. Any other SSL enabled VNC viewer would use root_CA.crt in a + similar way. + _________________________________________________________________ + + Creating Chained Certificates: + + Here is a fun example using VeriSign's "Trial Certificate" program. + Note that VeriSign has a Root CA and also an Intermediate CA and uses + the latter to sign customers certificates. So this provides an easy + way to test out the chained certificates mechanism with x11vnc. + + First we created a test x11vnc server key: + openssl genrsa -out V1.key 1024 + + then we created a certificate signing request (CSR) for it: + openssl req -new -key V1.key -out V1.csr + + (we followed the prompts and supplied information for the various + fields.) + + Then we went to VeriSign's page http://www.verisign.com/ssl/index.html + and clicked on "FREE TRIAL" (the certificate is good for 14 days.) We + filled in the forms and got to the point where it asked for the CSR + and so we pasted in the contents of the above V1.csr file. Then, after + a few more steps, VeriSign signed and emailed us our certificate. + + The VeriSign Trial certificates were found here: + http://www.verisign.com/support/verisign-intermediate-ca/Trial_Secure_Server_ +Root/index.html + http://www.verisign.com/support/verisign-intermediate-ca/trial-secure-server- +intermediate/index.html + + The former was pasted into a file V-Root.crt and the latter was pasted + into V-Intermediate.crt + + We pasted our Trial certificate that VeriSign signed and emailed to us + into a file named V1.crt and then we typed: + cat V1.key V1.crt > V1.pem + cat V1.pem V-Intermediate.crt > V1-combined.pem + chmod 600 V1.pem V1-combined.pem + + So now the file V1-combined.pem has our private key and (VeriSign + signed) certificate and VeriSign's Trial Intermediate certificate. + + Next, we start x11vnc: + x11vnc -ssl ./V1-combined.pem ... + + and finally, on the viewer side (SSVNC wrapper script example): + ss_vncviewer -verify ./V-Root.crt hostname:0 + + One will find that only that combination of certs and keys will work, + i.e. allow the SSL connection to be established. Every other + combination we tried failed (note that ss_vncviewer uses the external + stunnel command to handle the SSL so we are really testing stunnel's + SSL implementation on the viewer side); and so the system works as + expected. + _________________________________________________________________ + + VNC Client Authentication using Certificate Chains: + + Now, going the other way around with the client authenticating himself + via this chain of SSL certificates, x11vnc is run this way: + x11vnc -ssl SAVE -sslverify ./V-Root.crt ... + + (note since the server must always supply a cert, we use its normal + self-signed, etc., one via "-ssl SAVE" and use the VeriSign root cert + for client authentication via -sslverify. The viewer must now supply + the combined certificates, e.g.: + ss_vncviewer -mycert ./V1-combined.pem hostname:0 + _________________________________________________________________ + + Using OpenSSL and x11vnc to create Certificate Chains: + + Although the x11vnc CA mechanism (-sslGenCA and -sslGenCert; see + above) was designed to only handle a single root CA (to sign server + and/or client certs) it can be coerced into creating a certificate + chain by way of an extra openssl(1) command. + + We will first create two CA's via -sslGenCA; then use one of these CA + to sign the other; create a new (non-CA) server cert; and append the + intermediate CA's cert to the server cert to have everything needed in + the one file. + + Here are the commands we ran to do what the previous paragraph + outlines. + + First we create the two CA's, called CA_root and CA_Intermediate here, + in separate directories via x11vnc: + x11vnc -ssldir ~/CA_Root -sslGenCA + (follow the prompts, we included "CA_Root", e.g. Common Name, to aid ident +ifying it) + + x11vnc -ssldir ~/CA_Intermediate -sslGenCA + (follow the prompts, we included "CA_Intermediate", e.g. Common Name, to a +id identifying it) + + Next backup CA_Intermediate's cert and then sign it with CA_Root: + mv ~/CA_Intermediate/CA/cacert.pem ~/CA_Intermediate/CA/cacert.pem.ORIG + cd ~/CA_Root + openssl ca -config ./CA/ssl.cnf -policy policy_anything -extensions v3_ca -no +text -ss_cert ~/CA_Intermediate/CA/cacert.pem.ORIG -out ~/CA_Intermediate/CA/ca +cert.pem + + Note that it is required to cd to the ~/CA_Root directory and run the + openssl command from there. + + You can print out info about the cert you just modified by: + openssl x509 -noout -text -in ~/CA_Intermediate/CA/cacert.pem + + Now we create an x11vnc server cert named "test_chain" that is signed + by CA_Intermediate: + x11vnc -ssldir ~/CA_Intermediate -sslGenCert server test_chain + (follow the prompts) + + You can print out information about this server cert just created via + this command: + x11vnc -ssldir ~/CA_Intermediate -sslCertInfo SAVE-test_chain + + This will tell you the full path to the server certificate, which is + needed because we need to manually append the CA_Intermediate cert for + the chain to work: + cat ~/CA_Intermediate/CA/cacert.pem >> ~/CA_Intermediate/server-test_chain.pe +m + + Now we are finally ready to use it. We can run x11vnc using this + server cert+key by either this command: + x11vnc -ssldir ~/CA_Intermediate -ssl SAVE-test_chain ... + + or this command: + x11vnc -ssl ~/CA_Intermediate/server-test_chain.pem ... + + since they are equivalent (both load the same pem file.) + + Finally we connect via VNC viewer that uses CA_Root to verify the + server. As before we use ss_vncviewer: + ss_vncviewer -verify ~/CA_Root/CA/cacert.pem hostname:0 + + Client Certificates (see above) work in a similar manner. + + So although it is a little awkward with the extra steps (e.g. + appending the CA_Intermediate cert) it is possible. If you want to do + this entirely with openssl(1) you will have to learn the openssl + commands corresponding to -genCA and -genCert. You may be able to find + guides on the Internet to do this. Starting with x11vnc 0.9.10, you + can have it print out the wrapper scripts it uses via: -sslScripts + (you will still need to fill in a few pieces of information; ask if it + is not clear from the source code.) + + _________________________________________________________________ + + More info: + + See also this article for some some general info and examples using + stunnel and openssl on Windows with VNC. Also + http://www.stunnel.org/faq/certs.html is a very good source of + information on SSL certificate creation and management. + +======================================================================= +http://www.karlrunge.com/x11vnc/ssl-portal.html: + + + _________________________________________________________________ + + Using Apache as an SSL Gateway to multiple x11vnc servers inside a + firewall: + + Background: + + The typical way to allow access to x11vnc (or any other VNC server) + running on multiple workstations inside a firewall is via SSH. The + user somewhere out on the Internet logs in to the SSH gateway machine + and uses port forwarding (e.g. ssh -t -L 5900:myworkstation:5900 + user@gateway) to set up the encrypted channel that VNC is then + tunneled through. Next he starts up the VNC viewer on the machine + where he is sitting directed to the local tunnel port (e.g. + localhost:0). + + The SSH scheme is nice because it is a widely used and well tested + login technique for users connecting to machines inside their company + or home firewall. For VNC access it is a bit awkward, however, because + SSH needs to be installed on the Viewer machine and the user usually + has to rig up his own port redirection plumbing (however, see our + other tool). + + Also, some users have restrictive work environments where SSH and + similar applications are prohibited (i.e. only outgoing connections to + standard WWW ports from a browser are allowed, perhaps mediated by a + proxy server). These users have successfully used the method described + here for remote access. + + With the SSL support in x11vnc and the SSL enabled Java VNC viewer + applet, a convenient and secure alternative exists that uses the + Apache webserver as a gateway. The idea is that the company or home + internet connection is already running apache as a web server (either + SSL or non-SSL) and we add to it the ability to act as a gateway for + SSL VNC connections. The only thing needed on the Viewer side is a + Java enabled Web Browser: the user simply enters a URL that starts the + entire VNC connection process. No VNC or SSH specific software needs + to be installed on the viewer side machine. + + The stunnel VNC viewer stunnel wrapper script provided (ss_vncviewer) + can also take advantage of the method described here with its -proxy + option. + + _________________________________________________________________ + + Simpler Solutions: This apache SSL VNC portal solution may be too much + for you. It is mainly intended for automatically redirecting to + MULTIPLE workstations inside the firewall. If you only have one or two + inside machines that you want to access, the method described here is + overly complicated! See below for some simpler (and still non-SSH) + encrypted setups. + + Also see the recent (Mar/2010) desktop.cgi x11vnc desktop web login + CGI script that achieves much of what the method describes here + (especially if its 'port redirection' feature is enabled.) + _________________________________________________________________ + + + + There are numerous ways to achieve this with Apache. We present one of + the simplest ones here. + + Important: these sorts of schemes allow incoming connections from + anywhere on the Internet to fixed ports on machines inside the + firewall. Care must be taken to implement and test thoroughly. If one + is paranoid one can (and should) add extra layers of protection. (e.g. + extra passwords, packet filtering, SSL certificate verification, etc). + + Also, it is easy to miss the point that unless precautions are taken + to verify SSL Certificates, then the VNC Viewer is vulnerable to + man-in-the-middle attacks (but not to the more common passive sniffing + attacks). Note that there are hacker tools like dsniff/webmitm and + cain that implement SSL Man-In-The-Middle attacks. They rely on the + client not bothering to check the cert. + _________________________________________________________________ + + The Holy Grail: a single https port (443) + + Before we discuss the self-contained apache examples here, we want to + mention that many x11vnc users who read this page and implement the + apache SSL VNC portal ask for something that (so far) seems difficult + or impossible to do entirely inside apache: + * A single port, 443 (the default https:// port), is open to the + Internet + * It is HTTPS/SSL encrypted + * It handles both VNC traffic and Java VNC Applet downloads. + * And the server can also serve normal HTTPS webpages, CGI, etc. + + It is the last item that makes it tricky (otherwise the method + described on this page will work). If you are interested in such a + solution and are willing to run a separate helper program + (connect_switch) look here. Also, see this apache patch. + _________________________________________________________________ + + Example: + + The scheme described here sets up apache on the firewall/gateway as a + regular Web proxy into the intranet and allows connections to a single + fixed port on a limited set of machines. + + The configuration described in this section does not use the mod_ssl + apache module (the optional configuration described in the section + "Downloading the Java applet to the browser via HTTPS" does take + advantage of mod_ssl) + + In this example suppose the gateway machine running apache is named + "www.gateway.east" (e.g. it may also provide normal web service). We + also choose the Internet-facing port for this VNC service to be port + 563. One could choose any port, including the default HTTP port 80. + + Detail: We choose 563 because it is the rarely used SNEWS port that is + often allowed by Web proxies for the CONNECT method. The idea is the + user may be coming out of another firewall using a proxy (not the one + we describe here, that is, the case when two proxies are involved, + e.g. one at work and another Apache (described here) at home + redirecting into our firewall; the "double proxy" or "double firewall" + problem). Using port 563 simplifies things because CONNECT's to it are + usually allowed by default. + + We also assume all of the x11vnc servers on the internal machines are + all listening on port 5915 ("-rfbport 5915") instead of the default + 5900. This is to limit any unintended proxy redirections to a lesser + used port, and also to stay out of the way of normal VNC servers on + the same machines. One could obviously implement a scheme that handles + different ports, but we just discuss this simple setup here. + + So we basically assume x11vnc has been started this way on all of the + workstations to be granted VNC access: + x11vnc -ssl SAVE -http -display :0 -forever -rfbauth ~/.vnc/passwd -rfbport 5 +915 + + i.e. we force SSL VNC connections, port 5915, serve the Java VNC + viewer applet, and require a VNC password (another option would be + -unixpw). The above command could also be run out of inetd(8). It can + also be used to autodetect the user's display and Xauthority data. + + + These sections are added to the httpd.conf apache configuration file + on www.gateway.east: + +# In the global section you need to enable these modules. +# Note that the ORDER MATTERS! mod_rewrite must be before mod_proxy +# (so that we can check the allowed host list via rewrite) +# +LoadModule rewrite_module modules/mod_rewrite.so +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_connect_module modules/mod_proxy_connect.so +LoadModule proxy_ftp_module modules/mod_proxy_ftp.so +LoadModule proxy_http_module modules/mod_proxy_http.so + +LoadModule ssl_module modules/mod_ssl.so + + + +# Near the bottom of httpd.conf you put the port 563 virtual host: + +Listen 563 + + + + # Allow proxy CONNECT requests *only* to port 5915. + # If the machines use different ports, e.g. 5916 list them here as well: + # + ProxyRequests On + AllowCONNECT 5915 + + RewriteEngine On + + # Convenience rules to expand applet parameters. These do not have a traili +ng "/" + # + # /vnc for http jar file downloading: + # + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1 [R,NE,L] + RewriteRule /vnc/trust/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&trustAllVncCerts=yes [R,NE,L] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,NE,L] + RewriteRule /vnc/trust/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes&trustAllVncCerts=yes [R,NE,L] + + # Read in the allowed host to vnc display mapping file. It looks like: + # + # host1 15 + # host2 15 + # ... + # + # the display "15" means 5815 for http applet download, 5915 for SSL vnc. + # + RewriteMap vnchosts txt:/dist/apache/conf/vnc.hosts + + # Proxy: check for the CONNECT hostname and port being in the vnc.hosts list +. + # + RewriteCond %{THE_REQUEST} ^CONNECT [NC] + RewriteCond %{REQUEST_URI} ^(.*):(.*)$ + RewriteCond ${vnchosts:%1|NOTFOUND} NOTFOUND + RewriteRule ^.*$ /VNCFAIL [F,L] + + RewriteCond %{THE_REQUEST} ^CONNECT [NC] + RewriteCond %{REQUEST_URI} ^(.*):(.*)$ + RewriteCond 59${vnchosts:%1}=%2 !^(.*)=(\1)$ + RewriteRule ^.*$ /VNCFAIL [F,L] + + + # Remap /vnc to the proxy http download (e.g. http://host:5815) + # + # First, fail if it starts with the string /vnc0: + # + RewriteRule ^/vnc0.* /VNCFAIL [F,L] + # + # Next, map the prefix to /vnc0/host:protocol:port + # + RewriteRule ^/vnc/([^/]+)/(.*) /vnc0/$1:http:58${vnchosts:$1|NOTFOUND}/$2 +[NE] + # + # Drop any not found: + # + RewriteRule ^/vnc0.*NOTFOUND.* /VNCFAIL [F,L] + + # Construct the proxy URL and retrieve it: + # + RewriteRule ^/vnc0/([^/]+):([^/]+):([^/]+)/(.*) $2://$1:$3/$4 [P,NE,L] + + + + Then restart apache (perhaps: "apachectl stop; apachectl start"). + + Note that the listing of allowed internal workstations is done in an + external file (/dist/apache/conf/vnc.hosts in the example above), the + format is like this: +# allowed vnc hosts file: +hostname1 15 +hostname2 15 +... + + You list the hostname and the VNC display (always 15 in our example). + Only to these hosts will the external VNC viewers be able to connect + to (via the HTTP CONNECT method). + + The above setup requires mod_rewrite and mod_proxy be enabled in the + apache web server. In this example they are loaded as modules (and + note that mod_rewrite must be listed before mod_proxy); + + The user at the Java enabled Web browser would simply enter this URL + into the browser: + http://www.gateway.east:563/vnc/host2 + + to connect to internal workstation host2, etc. + + Important: do not put a trailing "/" on the URL, since that will + defeat the RewriteRules that look for the hostname at the very end. + + There will be a number of SSL certificate, etc, dialogs he will have + to respond to in addition to any passwords he is required to provide + (this depends on how you set up user authentication for x11vnc). + + If a second Web proxy is involved (i.e. the user's browser is inside + another firewall and policy requires using a Web proxy server) then + use this URL: + http://www.gateway.east:563/vnc/proxy/host2 + + This will involve downloading a signed java viewer applet jar file + that is able to interact with the internal proxy for the VNC + connection. See this FAQ for more info on how this works. Note: + sometimes with the Proxy case if you see 'Bad Gateway' error you will + have to wait 10 or so seconds and then hit reload. This seems to be + due to having to wait for a Connection Keepalive to terminate... + + For completeness, the "trust" cases that skip a VNC certificate dialog + (discussed below) would be entered as: + http://www.gateway.east:563/vnc/trust/host2 + http://www.gateway.east:563/vnc/trust/proxy/host2 + + You can of course choose shorter or more easy to remember URL formats. + Just change the Convenience RewriteRules in httpd.conf. + + _________________________________________________________________ + + Port Variations: + + Note that you can run this on the default HTTP port 80 instead of port + 563. If you do not expect to have a browser connecting from inside a + proxying firewall (where sometimes only connections to ports 443 and + 563 are allowed) this should be fine. Use "80" instead of "563" in the + httpd.conf config file (you may need to merge it with other default + port 80 things you have there). + + Then the URL's will be a bit simpler: + http://www.gateway.east/vnc/host2 + http://www.gateway.east/vnc/trust/host2 + + etc. + + Besides 80 one could use any other random port number (since there are + so many port scans on 80, a little obscurity might be useful). + + One option is to use port "443" (the default https:// port) instead of + "563". In this case Apache is not configured for mod_ssl; we just + happen to use port "443" in the way any random port would be used. + This could be handy if the Viewer side environment is restrictive in + that it only allows outgoing connections to ports 80 and 443 (and, + say, you didn't want to use port 80, or you wanted to use 80 for + something else). Another reason for using 443 would be some web proxy + environments only allow the CONNECT method to go to port 443 (and not + even the case 563 we use above). + + _________________________________________________________________ + + Details: + + Let's go through the httpd.conf additions in detail from the top. + + The LoadModules directives load the necessary apache modules. Note + that mod_rewrite must be listed first. If you are compiling from + scratch something like this worked for us: + ./configure --enable-proxy=shared --enable-proxy-connect=shared --enable-ssl= +shared --enable-rewrite=shared --prefix=/dist/apache + + Then the VirtualHost *:563 virtual host section starts. + + The "ProxyRequests On" and "AllowCONNECT 5915" enable the web server + to forward proxy requests to port 5915 (and only this port) INSIDE the + firewall. Think about the implications of this thoroughly and test it + carefully. + + The RewriteRule's are for convenience only so that the URL entered + into the Web browser does not need the various extra parameters, e.g.: + http://www.gateway.east:563/vnc/host2/index.vnc?CONNECT=host2+5915&PORT=563, +blah,blah... + + (or otherwise make direct edits to index.vnc to set these parameters). + The forceProxy=yes parameter is passed to the applet to force the use + of a outgoing proxy socket connection. Use it only if the Web browser + is inside a separate Web proxying environment (i.e. large corporation) + + The rewrites with parameter urlPrefix are described under Tricks for + Better Response. The "trust" ones (also described under Tricks) with + trustAllVncCerts tell the Java VNC applet to skip a dialog asking + about the VNC Certificate. They are a bit faster and more reliable + than the original method. In the best situation they lead to being + logged in 20 seconds or less (without them the time to login can be + much longer since a number of connections must timeout). + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + The external file /dist/apache/conf/vnc.hosts containing the allowed + VNC server hostnames is read in. Its 2nd column contains the VNC + display of the host (always 15 in our example; if you make it vary you + will need to adjust some lines in the httpd.conf accordingly, e.g. + AllowCONNECT). This list is used to constrain both the Jar file + download URL and the proxy CONNECT the VNC viewer makes to only the + intended VNC servers. + + Limiting the proxy CONNECT is done with the two sets of RewriteCond + conditions. + + Limiting the Jar file download URL is done in the remaining 4 + RewriteRule's. + + Note that these index.vnc and VncViewer.jar downloads to the browser + are not encrypted via SSL, and so in principle could be tampered with + by a really bad guy. The subsequent VNC connection, however, is + encrypted through a single SSL connection (it makes a CONNECT straight + to x11vnc). See below for how to have these initial downloads + encrypted as well (if the apache web server has SSL/mod_ssl, i.e. + https, enabled and configured). + + Unfortunately the Java VNC viewer applet currently is not able to save + its own list of Certificates (e.g. the user says trust this VNC + certificate 'always'). This is because an applet it cannot open local + files, etc. Sadly, the applet cannot even remember certificates in the + same browser session because it is completely reinitialized for each + connection (see below). + + _________________________________________________________________ + + Too Much? + + If these apache rules are a little too much for you, there is a little + bit simpler scheme where you have to list each of the individual + machines in the httpd.conf and ssl.conf files. It may be a little more + typing to maintain, but perhaps being more straight forward (less + RewriteRule's) is desirable. + + _________________________________________________________________ + + Problems? + + To see example x11vnc output for a successful https://host:5900/ + connection with the Java Applet see This Page. + + _________________________________________________________________ + + Some Ideas for adding extra authentication, etc. for the paranoid: + * VNC passwords: -rfbauth, -passwdfile, or -usepw. Even adding a + simple company-wide VNC password helps block unwanted access. + * Unix passwords: -unixpw + * SSL Client certificates: -sslverify + * Apache AuthUserFile directive: .htaccess, etc. + * Filter connections based on IP address or hostname. + * Use Port-knocking on your firewall as described in: Enhanced + TightVNC Viewer (ssvnc). + * Add proxy password authentication (requires Viewer changes?) + * Run a separate instance of Apache that provides this VNC service + so it can be brought up and down independently of the normal web + server. + * How secure is the Client side? Public machines in internet cafes, + etc, are often hacked, with backdoors and VNC servers of their + own. Prefer using your own firewalled laptop to a public machine. + + + _________________________________________________________________ + + Using non-Java viewers with this scheme: + + The ss_vncviewer stunnel wrapper script for VNC viewers has the -proxy + option that can take advantage of this method. + ss_vncviewer -proxy www.gateway.east:563 host1:15 + + For the case of the "double proxy" situation (see below) supply both + separated by a comma. + ss_vncviewer -proxy proxy1.foobar.com:8080,www.gateway.east:563 host1:15 + + For the Enhanced TightVNC Viewer (ssvnc) GUI (it uses ss_vncviewer on + Unix) put 'host1:15' into the 'VNC Server' entry box, and here are + possible Proxy/Gateway entries + Proxy/Gateway: www.gateway.east:563 + Proxy/Gateway: proxy1.foobar.com:8080,www.gateway.east:563 + + then click on the 'Connect' button. + + _________________________________________________________________ + + Downloading the Java applet to the browser via HTTPS: + + To have the Java applet downloaded to the user's Web Browser via an + encrypted (and evidently safer) SSL connection the Apache webserver + should be configured for SSL via mod_ssl. + + It is actually possible to use the x11vnc Key Management utility + "-sslGenCert" to generate your Apache/SSL .crt and .key files. (In + brief, run something like "x11vnc -sslGenCert server self:apache" then + copy the resulting self:apache.crt file to conf/ssl.crt/server.crt and + extract the private key part from self:apache.pem and paste it into + conf/ssl.key/server.key). Setting the env var REQ_ARGS='-days 1095' + before running x11vnc will bump up the expiration date (3 years in + this case). + + Or you can use the standard methods described in the Apache mod_ssl + documentation to create your keys. Then restart Apache, usually + something like "apachectl stop" followed by "apachectl startssl" + + In addition to the above sections in httpd.conf one should add the + following to ssl.conf: + SSLProxyEngine On + + RewriteEngine On + + # Convenience rules to expand applet parameters. These do not have a traili +ng "/" + # + # /vnc http jar file downloading: + # + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1 [R,NE,L] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,N +E,L] + # + # (we skipped the "trust" ones above, put them in if you like) + # + # /vncs https jar file downloading: + # + RewriteRule /vncs/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1 [R,NE,L] + RewriteRule /vncs/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes [R, +NE,l] + RewriteRule /vncs/trust/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&trustAllVncCerts=y +es [R,NE,L] + RewriteRule /vncs/trust/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes&tru +stAllVncCerts=yes [R,NE,L] + + # Convenience rules used for the connect_switch helper (requires Listen 127. +0.0.1:443 above): + # + RewriteRule /vnc443/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1 [R,NE,L] + RewriteRule /vnc443/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes [R, +NE,L] + RewriteRule /vnc443/trust/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&trustAllVncCerts=y +es [R,NE,L] + RewriteRule /vnc443/trust/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes&tru +stAllVncCerts=yes [R,NE,L] + + # Read in the allowed host to vnc display mapping file. It looks like: + # + # host1 15 + # host2 15 + # ... + # + # the display "15" means 5915 for SSL VNC and 5815 for http applet download. + # + RewriteMap vnchosts txt:/dist/apache/conf/vnc.hosts + + + # Remap /vnc and /vncs to the proxy http download (e.g. https://host:5915) + # + # First, fail if it starts with the string /vnc0: + # + RewriteRule ^/vnc0.* /VNCFAIL [F,L] + # + # Next, map the prefix to /vnc0:host:protocol:port + # + RewriteRule ^/vnc/([^/]+)/(.*) /vnc0/$1:http:58${vnchosts:$1|NOTFOUND}/$2 +[NE] + RewriteRule ^/vncs/([^/]+)/(.*) /vnc0/$1:https:59${vnchosts:$1|NOTFOUND}/$2 +[NE] + # + # Drop any not found: + # + RewriteRule ^/vnc0.*NOTFOUND.* /VNCFAIL [F,L] + + # Construct the proxy URL and retrieve it: + # + RewriteRule ^/vnc0/([^/]+):([^/]+):([^/]+)/(.*) $2://$1:$3/$4 [P,NE,L] + + This is all in the "" section of ssl.conf. + + The user could then point the Web Browser to: + https://www.gateway.east/vnc/host2 + + or + https://www.gateway.east/vnc/proxy/host2 + + for the "double proxy" case. (Important: do not put a trailing "/" on + the URL, since that will defeat the RewriteRules.) + + As with the httpd.conf case, the external file + (/dist/apache/conf/vnc.hosts in the above example) contains the + hostnames of the allowed VNC servers. + + Note that inside the firewall the Java applet download traffic is not + encrypted (only over the Internet is SSL used) for these cases: + https://www.gateway.east/vnc/host2 + https://www.gateway.east/vnc/proxy/host2 + + However for the special "vncs" rules above: + https://www.gateway.east/vncs/host2 + + the Java applet download is encrypted via SSL for both legs. Note that + the two legs are two separate SSL sessions. So the data is decrypted + inside an apache process and reencrypted by the apache process for the + 2nd SSL session inside the same apache process (a very small gap one + might overlook). + + The "vncs/trust" ones are like the "trust" ones described earlier + https://www.gateway.east/vncs/trust/mach2 + + and similarly for the httpsPort ones. See Tricks for Better Response. + + In all of the above cases the VNC traffic from Viewer to x11vnc is + encrypted end-to-end in a single SSL session, even for the "double + proxy" case because the CONNECT method is used (there are actually two + CONNECT's for the "double proxy" case). This part (the VNC traffic) is + the most important part to have encrypted. + + Note that the Certificate dialogs the user has in his web browser will + be for the Apache Certificate, while for the Java applet it will be + the x11vnc certificate. + + Note also that you can have Apache serve up the Jar file VncViewer.jar + and/or index.vnc/proxy.vnc instead of each x11vnc if you want to. + + The rules in ssl.conf are similar to the ones in httpd.conf and so are + not discussed in detail. The only really new thing is the /vncs + handling to download the applet jar via HTTPS on port 5915. + + The special entries "/vnc443" are only used for the special helper + program (connect_switch) for the https port 443 only mode discussed + here. + + _________________________________________________________________ + + INETD automation: + + The "single-port" (i.e. 5915) HTTPS applet download and VNC connection + aspect shown here is convenient and also enables having x11vnc run out + of inetd. That way x11vnc is run on demand instead of being run all + the time (the user does not have to remember to start it). The first + connections to inetd download index.vnc and the Jar file (via https) + and the the last connection to inetd establishes the SSL VNC + connection. Since x11vnc is restarted for each connection, this will + be a bit slower than the normal process. + + For example, the /etc/inetd.conf line could be: + 5915 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc_ssl.sh + + where the script x11vnc_ssl.sh looks something like this: +#!/bin/sh + +/usr/local/bin/x11vnc -inetd -oa /var/log/x11vnc-15.log \ + -ssl SAVE -http -unixpw -localhost \ + -display :0 -auth /home/THE_USER/.Xauthority + + where, as usual, the inetd launching needs to know which user is + typically using the display on that machine. One could imagine giving + different users different ports, 5915, 5916, etc. to distinguish (then + the script would need to be passed the username). mod_rewrite could be + used to automatically map username in the URL to his port number. + + A better way is to use the "-display WAIT:cmd=FINDDISPLAY" feature to + autodetect the user and Xauthority data: +#!/bin/sh + +/usr/local/bin/x11vnc -inetd -oa /var/log/x11vnc-15.log \ + -ssl SAVE -http -unixpw -localhost -users unixpw= \ + -find + + (we have used the alias -find for "-display WAIT:cmd=FINDDISPLAY".) + This way the user must supply his Unix username and password and then + his display and Xauthority data on that machine will be located and + returned to x11vnc to allow it to attach. If he doesn't have a display + running on that machine or he fails to log in correctly, the + connection will be dropped. + + The variant "-display WAIT:cmd=FINDCREATEDISPLAY" (aliased by + "-create") will actually create a (virtual or real) X server session + for the user if one doesn't already exist. See here for details. + + To enable inetd operation for the non-HTTPS Java viewer download (port + 5815 in the above httpd.conf example) you will need to run x11vnc in + HTTPONCE mode on port 5815: For example, the /etc/inetd.conf line + could be: + 5815 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc \ + -inetd -prog /usr/local/bin/x11vnc -oa /var/log/x11vnc-15.log \ + -http_ssl -display WAIT:cmd=HTTPONCE + + where the long inetd.conf line has been split. Note how the -http_ssl + tries to automatically find the .../classes/ssl subdirectory. This + requires the -prog option available in x11vnc 0.8.4 (a shell script + wrapper, e.g. /usr/local/bin/x11vnc_http.sh can be used to work around + this). + + Also note the use of "-ssl SAVE" above. This way a saved server.pem is + used for each inetd invocation (rather generating a new one each time + as happens for "-ssl TMP"). Note that it cannot have a protecting + passphrase because inetd will not be able to supply it. + + Another option is: + 5815 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc \ + -inetd -httpdir /usr/local/share/x11vnc/classes/ssl \ + -oa /var/log/x11vnc-15.log -display WAIT:cmd=HTTPONCE + + (this also requires a feature found in x11vnc 0.8.4). + _________________________________________________________________ + + Other Ideas: + + - The above schemes work, but they are a bit complicated with all of + the rigging. There should be more elegant ways to configure Apache to + do these, but we have not found them (please let us know if you + discover something nice). However, once this scheme has been set up + and is working it is easy to maintain and add/delete workstations, + etc. + + - In general Apache is not required, but it makes things convenient. + The firewall itself could do the port redirection via its firewall + rules. Evidently different Internet-facing ports would be required for + each workstation. This could be set up using iptables rules for + example. If there were just one or two machines this would be the + easiest method. For example: + iptables -t nat -A PREROUTING -p tcp -d 24.35.46.57 --dport 5901 -j DNAT --to +-destination 192.168.1.2:5915 + iptables -t nat -A PREROUTING -p tcp -d 24.35.46.57 --dport 5902 -j DNAT --to +-destination 192.168.1.3:5915 + + Where 24.35.46.57 is the internet IP address of the gateway. In this + example 24.35.46.57:5901 is redirected to the internal machine + 192.168.1.2:5915 and 24.35.46.57:5902 is redirected to another + internal machine 192.168.1.3:5915, both running x11vnc -ssl ... in SSL + mode. For this example, the user would point the web browser to, e.g.: + https://24.35.46.57:5901/?PORT=5901 + + or using the stunnel wrapper script: + ss_vncviewer 24.35.46.57:1 + + One can achieve similar things with dedicated firewall/routers (e.g. + Linksys) using the device's web or other interface to configure the + firewall. + + If the user may be coming out of a firewall using a proxy it may be + better to redirect ports 443 and 563 (instead of 5901 and 5902) to the + internal machines so that the user's proxy will allow CONNECTing to + them. + + - The redirection could also be done at the application level using a + TCP redirect program (e.g. ip_relay or fancier ones). Evidently more + careful internal hostname checking, etc., could be performed by the + special purpose application to add security. See connect_switch which + is somewhat related. + + - One might imagine the ProxyPass could be done for the VNC traffic as + well (for the ssl.conf case) to avoid the CONNECT proxying completely + (which would be nice to avoid). Unfortunately we were not able to get + this to work. Since HTTP is a request-response protocol (as opposed to + a full bidirectional link required by VNC that CONNECT provides) this + makes it difficult to do. It may be possible, but we haven't found out + how yet. + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + _________________________________________________________________ + + Tricks for Better Response and reliability: + + The "original scheme" using httpd.conf and ssl.conf rewrites without + urlPrefix and trustAllVncCerts above should work OK, but may lead to + slow and/or unreliable loading of the applet and final connection to + x11vnc. The following are what I do now to get better response and + reliability. YMMV. + + The problem with the "original scheme" is that there is a point where + the VNC Viewer applet can try up to 3 times to retrieve the x11vnc + certificate, since it needs to get it to show it to you and ask you if + you accept it. This can add about 45 seconds to the whole process + (which takes 1 to 1.5 minutes with all the dialogs) since a couple of + those connections must time out. The "trust" items in the config add a + parameter trustAllVncCerts=yes similar to the forceProxy=yes + parameter. This can cut the total time to the VNC password prompt down + to 15 seconds which is pretty good. (Note by ignoring the certificate + this does not protect against man-in-the-middle attacks which are + rare, but maybe the won't be so rare in the future... see + dsniff/webmitm and cain) + + First make sure the x11vnc SSL certificate+key is the same as + Apache's. (otherwise you may get one extra dialog and/or one extra + connection that has to time out). + + The following RewriteRule's are the same now advocated in the + instructions above. + + The httpsPort and urlPrefix= parameters give hints to the applet to + improve connecting: This is what goes in httpd.conf: + RewriteEngine On + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1 [R,NE] + RewriteRule /vnc/trust/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&trustAllVncCerts=yes [R,NE] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,NE] + RewriteRule /vnc/trust/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes&trustAllVncCerts=yes [R,NE] + + The httpsPort and urlPrefix provide useful hints to the VNC Viewer + applet when it connects to x11vnc to glean information about Proxies, + certificates, etc. + + This is what goes into ssl.conf: + RewriteEngine On + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1 [R,NE] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,NE] + RewriteRule /vncs/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1 [R,NE] + RewriteRule /vncs/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes [R,NE] + RewriteRule /vncs/trust/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&trustAllVncCerts=yes [R,NE +] + RewriteRule /vncs/trust/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes&trustAllVnc +Certs=yes [R,NE] + + The rest is the same. + + The httpsPort and urlPrefix and GET provide useful hints to the VNC + Viewer applet when it connects to x11vnc to glean information about + Proxies, certificates, etc, and also for the ultimate VNC connection + (GET speeds this up by sending a special HTTP GET to cause x11vnc to + immediately switch to the VNC protocol). + + To turn these into URLs, as was done above, take the string in the + RewriteRule, e.g. /vncs and turn it into + https://gateway/vncs/machinename Similarly for non-https: + http://gateway:563/vnc/machinename + + If you use the 'trust' ones, you are performing NO checks, visual or + otherwise, on the VNC SSL certificate. It is trusted without question. + This speeds things up because it avoids a dialog about certificates, + but of course has some risk WRT Man in the Middle attacks. I don't + recommend them. It is better to use /vnc or /vncs and the first time + you connect carefully check the Certificate and then tell your Browser + and Java Virtual Machine to trust the certificate 'Always'. Then if + you later get an unexpected dialog, you know something is wrong. + Nearly always it is just a changed or expired certificate, but better + safe than sorry... + +======================================================================= +http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html: + + + _________________________________________________________________ + +Enhanced TightVNC Viewer (SSVNC: SSL/SSH VNC viewer) + + (To Downloads) (To Quick Start) + + [ssvnc.gif] [ssvnc_windows.gif] [ssvnc_macosx.gif] . . + + + The Enhanced TightVNC Viewer, SSVNC, adds encryption security to VNC + connections. + + The package provides a GUI for Windows, Mac OS X, and Unix that + automatically starts up an STUNNEL SSL tunnel for SSL or ssh/plink for + SSH connections to any VNC server, such as x11vnc, and then launches + the VNC Viewer to use the encrypted tunnel. + + The x11vnc server has built-in SSL support, however SSVNC can make SSL + encrypted VNC connections to any VNC Server if they are running an SSL + tunnel, such as STUNNEL or socat, at their end. SSVNC's SSH tunnel + will work to any VNC Server host running sshd that you can log into. + + The Enhanced TightVNC Viewer package started as a project to add some + patches to the long neglected Unix TightVNC Viewer. However, now the + front-end GUI, encryption, and wrapper scripts features possibly + outweigh the Unix TightVNC Viewer improvements (see the lists below to + compare). + + The SSVNC Unix vncviewer can also be run without the SSVNC encryption + GUI as an enhanced replacement for the xvncviewer, xtightvncviewer, + etc., viewers. + + In addition to normal SSL, SSVNC also supports the VeNCrypt SSL/TLS + and Vino/ANONTLS encryption extensions to VNC on Unix, Mac OS X, and + Windows. Via the provided SSVNC VeNCrypt bridge, VeNCrypt and ANONTLS + encryption also works with any third party VNC Viewer (e.g. RealVNC, + TightVNC, UltraVNC, etc...) you select via 'Change VNC Viewer'. + + The short name for this project is "ssvnc" for SSL/SSH VNC Viewer. + This is the name of the command to start it. + + There is a simplified SSH-Only mode (sshvnc). And an even more + simplified Terminal-Services mode (tsvnc) for use with x11vnc on the + remote side. + + It is also possible (although not recommended) to disable encryption: + -noenc cmdline option; Ctrl-E toggle; or Vnc:// host prefix; see the + online Help for details. + + The tool has many additional features; see the descriptions below. + + It is a self-contained bundle, you could carry it around on, say, a + USB memory stick / flash drive for secure VNC viewing from almost any + machine, Unix, Mac OS X, and Windows (and if you create a directory + named "Home" in the toplevel ssvnc directory on the drive your VNC + profiles and certs will be kept there as well). For Unix, there is + also a conventional source tarball to build and install in the normal + way and not use a pre-built bundle. + + _________________________________________________________________ + + Announcements: + + Important: If you created any SSL certificates with SSVNC (or anything + else) on a Debian or Ubuntu system from Sept. 2006 through May 2008, + then those keys are likely extremely weak and can be easily cracked. + The certificate files should be deleted and recreated on a non-Debian + system or an updated one. See + http://www.debian.org/security/2008/dsa-1571 for details. The same + applies to SSH keys. + + Please read this information on using SSVNC on workstations with + Untrusted Local Users. + + _________________________________________________________________ + + Feature List: + + Wrapper scripts and a tcl/tk GUI were written to create these features + for Unix, Mac OS X, and Windows: + * SSL support for connections using the bundled stunnel program. + * Automatic SSH connections from the GUI (system ssh is used on Unix + and MacOS X; bundled plink is used on Windows) + * Ability to Save and Load VNC profiles for different hosts. + * You can also use your own VNC Viewer, e.g. UltraVNC or RealVNC, + with the SSVNC encryption GUI front-end if you prefer. + * Create or Import SSL Certificates and Private Keys. + * Reverse (viewer listening) VNC connections via SSL and SSH. + * VeNCrypt SSL/TLS VNC encryption support (used by VeNCrypt, QEMU, + ggi, libvirt/virt-manager/xen, vinagre/gvncviewer/gtk-vnc) + * ANONTLS SSL/TLS VNC encryption support (used by Vino) + * VeNCrypt and ANONTLS are also enabled for any 3rd party VNC Viewer + (e.g. RealVNC, TightVNC, UltraVNC ...) on Unix, MacOSX, and + Windows via the provided SSVNC VeNCrypt Viewer Bridge tool (use + 'Change VNC Viewer' to select the one you want.) + * Support for Web Proxies, SOCKS Proxies, and the UltraVNC repeater + proxy (e.g. repeater://host:port+ID:1234). Multiple proxies may be + chained together (3 max). + * Support for SSH Gateway connections and non-standard SSH ports. + * Automatic Service tunnelling via SSH for CUPS and SMB Printing, + ESD/ARTSD Audio, and SMB (Windows/Samba) filesystem mounting. + * Sets up any additional SSH port redirections that you want. + * Zeroconf (aka Bonjour) is used on Unix and Mac OS X to find VNC + servers on your local network if the avahi-browse or dns-sd + program is available and in your PATH. + * Port Knocking for "closed port" SSH/SSL connections. In addition + to a simple fixed port sequence and one-time-pad implementation, a + hook is also provided to run any port knocking client before + connecting. + * Support for native MacOS X usage with bundled Chicken of the VNC + viewer (the Unix X11 viewer is also provided for MacOS X, and is + better IMHO. It is now the default on MacOS X.) + * Dynamic VNC Server Port determination and redirection (using ssh's + builtin SOCKS proxy, ssh -D) for servers like x11vnc that print + out PORT= at startup. + * Unix Username and Password entry for use with "x11vnc -unixpw" + type login dialogs. + * Simplified mode launched by command "sshvnc" that is SSH Only. + * Simplified mode launched by command "tsvnc" that provides a VNC + "Terminal Services" mode (uses x11vnc on the remote side). + * IPv6 support for all connection modes on Unix, MacOSX, and + Windows. + + Patches to TightVNC 1.3.9 vnc_unixsrc tree were created for Unix + TightVNC Viewer improvements (these only apply to the Unix VNC viewer, + including MacOSX XQuartz): + * rfbNewFBSize VNC support (dynamic screen resizing) + * Client-side Scaling of the Desktop in the viewer. + * ZRLE VNC encoding support (RealVNC's encoding) + * Support for the ZYWRLE encoding, a wavelet based extension to ZRLE + to improve compression of motion video and photo regions. + * TurboVNC support (VirtualGL's modified TightVNC encoding; requires + TurboJPEG library) + * Pipelined Updates of the framebuffer as in TurboVNC (asks for the + next update before the current one has finished downloading; this + gives some speedup on high latency connections.) + * Cursor alphablending with x11vnc at 32bpp (-alpha option) + * Option "-unixpw ..." for use with "x11vnc -unixpw" type login + dialogs. + * Support for UltraVNC extensions: 1/n Server side scaling, Text + Chat, Single Window, Disable Server-side Input. Both UltraVNC and + x11vnc servers support these extensions. + * UltraVNC File Transfer via an auxiliary Java helper program (java + must be in $PATH). Note that the x11vnc server also supports + UltraVNC file transfer. + * Connection support for the UltraVNC repeater proxy (-repeater + option). + * Support for UltraVNC Single Click operation. (both unencrypted: SC + I, and SSL encrypted: SC III) + * Support for UltraVNC DSM Encryption Plugin symmetric encryption + mode. (ARC4, AESV2, MSRC4, and SecureVNC) + * Support for UltraVNC MS-Logon authentication (NOTE: the UltraVNC + MS-Logon key exchange implementation is very weak; an eavesdropper + on the network can recover your Windows password easily in a few + seconds; you need to use an additional encrypted tunnel with + MS-Logon.) + * Support for symmetric encryption (including blowfish and 3des + ciphers) to Non-UltraVNC Servers. Any server using the same + encryption method will work, e.g.: x11vnc -enc blowfish:./my.key + * Instead of hostname:display one can also supply "exec=command + args..." to connect the viewer to the stdio of an external command + (e.g. stunnel or socat) rather than using a TCP/IP socket. Unix + domain sockets, e.g. /path/to/unix/socket, and a previously opened + file descriptor fd=0, work too. + * Local Port Protections for STUNNEL and SSH: avoid having for long + periods of time a listening port on the the local (VNC viewer) + side that redirects to the remote side. + * Reverse (viewer listening) VNC connections can show a Popup dialog + asking whether to accept the connection or not (-acceptpopup.) The + extra info provided by UltraVNC Single Click reverse connections + is also supported (-acceptpopupsc) + * Extremely low color modes: 64 and 8 colors in 8bpp + (-use64/-bgr222, -use8/-bgr111) + * Medium color mode: 16bpp mode on a 32bpp Viewer display + (-16bpp/-bgr565) + * For use with x11vnc's client-side caching -ncache method use the + cropping option -ycrop n. This will "hide" the large pixel buffer + cache below the actual display. Set to the actual height or use -1 + for autodetection (also, tall screens, H > 2*W, are autodetected + by default). + * Escape Keys: specify a set of modifier keys so that when they are + all pressed down you can invoke Popup menu actions via keystrokes. + I.e., a set of 'Hot Keys'. One can also pan (move) the desktop + inside the viewport via Arrow keys or a mouse drag. + * Scrollbar width setting: -sbwidth n, the default is very thin, 2 + pixels, for less distracting -ycrop usage. + * Selection text sending and receiving can be fine-tuned with the + -sendclipboard, -sendalways, and -recvtext options. + * TightVNC compression and quality levels are automatically set + based on observed network latency (n.b. not bandwidth.) + * Improvements to the Popup menu, all of these can now be changed + dynamically via the menu: ViewOnly, Toggle Bell, CursorShape + updates, X11 Cursor, Cursor Alphablending, Toggle Tight/ZRLE, + Toggle JPEG, FullColor/16bpp/8bpp (256/64/8 colors), Greyscale for + low color modes, Scaling the Viewer resolution, Escape Keys, + Pipeline Updates, and others, including UltraVNC extensions. + * Maintains its own BackingStore if the X server does not. + * The default for localhost:0 connections is not raw encoding since + same-machine connections are pretty rare. Default assumes you are + using a SSL or SSH tunnel. Use -rawlocal to revert. + * XGrabServer support for fullscreen mode, for old window managers + (-grab/-graball option). + * Fix for Popup menu positioning for old window managers (-popupfix + option). + * The VNC Viewer ssvncviewer supports IPv6 natively (no helpers + needed.) + + The list of 3rd party software bundled in the archive files: + * TightVNC Viewer (windows, unix, macosx) + * Chicken of the VNC Viewer (macosx) + * Stunnel (windows, unix, macosx) + * Putty/Plink/Pageant (windows) + * OpenSSL (windows) + * esound (windows) + + These are all self-contained in the bundle directory: they will not be + installed on your system. Just un-zip or un-tar the file you + downloaded and run the frontend ssvnc straight from its directory. + Alternatively, on Unix you can use the conventional source tarball. + + _________________________________________________________________ + + Here is the Quick Start info from the README for how to setup and use + SSVNC: +Quick Start: +----------- + +Unix and Mac OS X: + + Inside a Terminal do something like the following. + + Unpack the archive: + + % gzip -dc ssvnc-1.0.28.tar.gz | tar xvf - + + Run the GUI: + + % ./ssvnc/Unix/ssvnc (for Unix) + + % ./ssvnc/MacOSX/ssvnc (for Mac OS X) + + The smaller file "ssvnc_no_windows-1.0.28.tar.gz" + could have been used as well. + + On MacOSX you could also click on the SSVNC app icon in the Finder. + + On MacOSX if you don't like the Chicken of the VNC (e.g. no local + cursors, no screen size rescaling, and no password prompting), and you + have the XDarwin X server installed, you can set DISPLAY before starting + ssvnc (or type DISPLAY=... in Host:Disp and hit Return). Then our + enhanced TightVNC viewer will be used instead of COTVNC. + Update: there is now a 'Use X11 vncviewer on MacOSX' under Options ... + + + If you want a SSH-only tool (without the distractions of SSL) run + the command: + + sshvnc + + instead of "ssvnc". Or click "SSH-Only Mode" under Options. + Control-h will toggle between the two modes. + + + If you want a simple VNC Terminal Services only mode (requires x11vnc + on the remote server) run the command: + + tsvnc + + instead of "ssvnc". Or click "Terminal Services" under Options. + Control-t will toggle between the two modes. + + "tsvnc profile-name" and "tsvnc user@hostname" work too. + + +Unix/MacOSX Install: + + There is no standard install for the bundles, but you can make + symlinks like so: + + cd /a/directory/in/PATH + ln -s /path/to/ssvnc/bin/{s,t}* . + + Or put /path/to/ssvnc/bin, /path/to/ssvnc/Unix, or /path/to/ssvnc/MacOSX + in your PATH. + + For the conventional source tarball it will compile and install, e.g.: + + gzip -dc ssvnc-1.0.28.src.tar.gz | tar xvf - + cd ssvnc-1.0.28 + make config + make all + make PREFIX=/my/install/dir install + + then have /my/install/dir/bin in your PATH. + + + +Windows: + + Unzip, using WinZip or a similar utility, the zip file: + + ssvnc-1.0.28.zip + + Run the GUI, e.g.: + + Start -> Run -> Browse + + and then navigate to + + .../ssvnc/Windows/ssvnc.exe + + select Open, and then OK to launch it. + + The smaller file "ssvnc_windows_only-1.0.28.zip" + could have been used as well. + + You can make a Windows shortcut to this program if you want to. + + See the Windows/README.txt for more info. + + + If you want a SSH-only tool (without the distractions of SSL) run + the command: + + sshvnc.bat + + Or click "SSH-Only Mode" under Options. + + + If you want a simple VNC Terminal Services only mode (requires x11vnc + on the remote server) run the command: + + tsvnc.bat + + Or click "Terminal Services" under Options. Control-t will toggle + between the two modes. "tsvnc profile-name" and "tsvnc user@hostname" + work too. + + _________________________________________________________________ + + You can read all of the SSVNC GUI's Online Help Text here. + _________________________________________________________________ + + The bundle unpacks a directory/folder named: ssvnc. It contains these + programs to launch the GUI: + Windows/ssvnc.exe for Windows + MacOSX/ssvnc for Mac OS X + Unix/ssvnc for Unix + + (the Mac OS X and Unix launchers are simply links to the bin + directory). See the README for more information. + + The SSH-Only mode launcher program has name sshvnc. The Terminal + Services mode launcher program (assumes x11vnc 0.8.4 or later and Xvfb + installed on the server machine) has name tsvnc. + + The Viewer SSL support is done via a wrapper script (bin/ssvnc_cmd + that calls bin/util/ss_vncviewer) that starts up the STUNNEL tunnel + first and then starts the TightVNC viewer pointed at that tunnel. The + bin/ssvnc program is a GUI front-end to that script. See this FAQ for + more details on SSL tunnelling. In SSH connection mode, the wrappers + start up SSH appropriately. + + + Memory Stick Usage: If you create a directory named "Home" in that + toplevel ssvnc directory then that will be used as the base for + storing VNC profiles and certificates. Also, for convenience, if you + first run the command with "." as an argument (e.g. "ssvnc .") it will + automatically create the "Home" directory for you. This is handy if + you want to place SSVNC on a USB flash drive that you carry around for + mobile use and you want the profiles you create to stay with the drive + (otherwise you'd have to browse to the drive directory each time you + load or save). + + One user on Windows created a BAT file to launch SSVNC and needed to + do this to get the Home directory correct: +cd \ssvnc\Windows +start \ssvnc\Windows\ssvnc.exe + + (an optional profile name can be supplied to the ssvnc.exe line) + + WARNING: if you use ssvnc from an "Internet Cafe", i.e. some untrusted + computer, please be aware that someone may have set up that machine to + be capturing your keystrokes, etc. + + + SSH-Only version: The command "sshvnc" can be run instead of "ssvnc" + to get an SSH-only version of the tool: + + [sshvnc.gif] + + These also work: "sshvnc myprofile" and "sshvnc user@hostname". To + switch from the regular SSVNC mode, click "SSH-Only Mode" under + Options. This mode is less distracting if you never plan to use SSL, + manage certificates, etc. + + + Terminal Services Only: The command "tsvnc" can be run instead of + "ssvnc" to get a "Terminal Services" only version of the tool: + + [tsvnc.gif] + + These also work: "tsvnc myprofile" and "tsvnc user@hostname". To + switch from the regular SSVNC mode, click "Terminal Services" under + Options. + + This mode requires x11vnc (0.9.3 or later) installed on the remote + machine to find, create, and manage the user sessions. SSH is used to + create the encrypted and authenticated tunnel. The Xvfb (virtual + framebuffer X server) program must also be installed on the remote + system. However tsvnc will also connect to a real X session (i.e. on + the physical hardware) if you are already logged into the X session; + this is a useful access mode and does not require Xvfb on the remote + system. + + This mode should be very easy for beginner users to understand and + use. On the remote end you only need to have x11vnc and Xvfb available + in $PATH, and on the local end you just run something like: + tsvnc myname@myhost.com + + (or start up the tsvnc GUI first and then enter myname@myhost.com and + press "Connect"). + + Normally the Terminal Services sessions created are virtual (RAM-only) + ones (e.g. Xvfb, Xdummy, or Xvnc), however a nice feature is if you + have a regular X session (i.e displaying on the physical hardware) on + the remote machine that you are ALREADY logged into, then the x11vnc + run from tsvnc will find it for you as well. + + Also, there is setting "X Login" under Advanced Options that allows + you to attach to a real X server with no one logged in yet (i.e. + XDM/GDM/KDM Login Greeter screen) as long as you have sudo(1) + permission on the remote machine. + + Nice features to soon to be added to the tsvnc mode are easy CUPS + printing (working fairly well) and Sound redirection (needs much work) + of the Terminal Services Desktop session. It is easier in tsvnc mode + because the entire desktop session can be started with the correct + environment. ssvnc tries to handle the general case of an already + started desktop and that is more difficult. + + + Proxies: Web proxies, SOCKS proxies, and the UltraVNC repeater proxy + are supported to allow the SSVNC connection to go through the proxy to + the otherwise unreachable VNC Server. SSH gateway machines can be used + in the same way. Read more about SSVNC proxy support here. + + + Dynamic VNC Server Port determination: If you are running SSVNC on + Unix and are using SSH to start the remote VNC server and the VNC + server prints out the line "PORT=NNNN" to indicate which dynamic port + it is using (x11vnc does this), then if you prefix the SSH command + with "PORT=" SSVNC will watch for the PORT=NNNN line and uses ssh's + built in SOCKS proxy (ssh -D ...) to connect to the dynamic VNC server + port through the SSH tunnel. For example: + VNC Host:Display user@somehost.com + Remote SSH Command: PORT= x11vnc -find + + or "PORT= x11vnc -display :0 -localhost", etc. Or use "P= x11vnc ..." + + There is also code to detect the display of the regular Unix + vncserver(1). It extracts the display (and hence port) from the lines + "New 'X' desktop is hostname:4" and also "VNC server is already + running as :4". So you can use something like: + PORT= vncserver; sleep 15 +or: PORT= vncserver :4; sleep 15 + + the latter is preferred because when you reconnect with it will find + the already running one. The former one will keep creating new X + sessions if called repeatedly. + + If you use PORT= on Windows, a large random port is selected instead + and the -rfbport option is passed to x11vnc (it does not work with + vncserver). + + + + Patches for Unix Tightvnc viewer: + + The rfbNewFBSize support allows the enhanced TightVNC Unix viewer to + resize when the server does (e.g. "x11vnc -R scale=3/4" remote control + command). + + The cursor alphablending is described here. + + The RealVNC ZRLE encoding is supported, in addition to some low colors + modes (16bpp and 8bpp at 256, 64, and even 8 colors, for use on very + slow connections). Greyscales are also enabled for the low color + modes. + + The Popup menu (F8) is enhanced with the ability to change many things + on the fly. F9 is added as a shortcut to toggle FullScreen mode. + + Client Side Caching: The x11vnc client-side caching is handled nicely + by this viewer. The very large pixel cache below the actual display in + this caching method is distracting. Our Unix VNC viewer will + automatically try to autodetect the actual display height if the + framebuffer is very tall (more than twice as high as it is wide). One + can also set the height to the known value via -ycrop n, or use -ycrop + -1 to force autodection. In fullscreen mode one is not possible to + scroll down to the pixel cache region. In non-fullscreen mode the + window manager frame is "shrink-wrapped" around the actual screen + display. You can still scroll down to the pixel cache region. The + scrollbars are set to be very thin (2 pixels) to be less distracting. + Use the -sbwidth n to make them wider. + + Probably nobody is interested in the grabserver patch for old window + managers when the viewer is in fullscreen mode... This and some other + unfixed bugs have been fixed in our patches (fullscreen toggle works + with KDE, -x11cursor has been fixed, and the dot cursor has been made + smaller). + + From the -help output: +SSVNC Viewer (based on TightVNC viewer version 1.3.9) + +Usage: vncviewer [] [][:] + vncviewer [] [][::] + vncviewer [] exec=[CMD ARGS...] + vncviewer [] fd=n + vncviewer [] /path/to/unix/socket + vncviewer [] -listen [] + vncviewer -help + + are standard Xt options, or: + -via + -shared (set by default) + -noshared + -viewonly + -fullscreen + -noraiseonbeep + -passwd (standard VNC authentication) + -user (Unix login authentication) + -encodings (e.g. "tight,copyrect") + -bgr233 + -owncmap + -truecolour + -depth + -compresslevel (0..9: 0-fast, 9-best) + -quality (0..9: 0-low, 9-high) + -nojpeg + -nocursorshape + -x11cursor + -autopass + +Option names may be abbreviated, e.g. -bgr instead of -bgr233. +See the manual page for more information. + + +Enhanced TightVNC viewer (SSVNC) options: + + URL http://www.karlrunge.com/x11vnc/ssvnc.html + + Note: ZRLE and ZYWRLE encodings are now supported. + + Note: F9 is shortcut to Toggle FullScreen mode. + + Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1 + to allow more than one incoming VNC server at a time. + This is the same as -multilisten described below. Set + SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than "n" + simultaneous reverse connections. + + Note: If the host:port is specified as "exec=command args..." + then instead of making a TCP/IP socket connection to the + remote VNC server, "command args..." is executed and the + viewer is attached to its stdio. This enables tunnelling + established via an external command, e.g. an stunnel(8) + that does not involve a listening socket. This mode does + not work for -listen reverse connections. + + If the host:port is specified as "fd=n" then it is assumed + n is an already opened file descriptor to the socket. (i.e + the parent did fork+exec) + + If the host:port contains a '/' it is interpreted as a + unix-domain socket (AF_LOCAL insead of AF_INET) + + -multilisten As in -listen (reverse connection listening) except + allow more than one incoming VNC server to be connected + at a time. The default for -listen of only one at a + time tries to play it safe by not allowing anyone on + the network to put (many) desktops on your screen over + a long window of time. Use -multilisten for no limit. + + -acceptpopup In -listen (reverse connection listening) mode when + a reverse VNC connection comes in show a popup asking + whether to Accept or Reject the connection. The IP + address of the connecting host is shown. Same as + setting the env. var. SSVNC_ACCEPT_POPUP=1. + + -acceptpopupsc As in -acceptpopup except assume UltraVNC Single + Click (SC) server. Retrieve User and ComputerName + info from UltraVNC Server and display in the Popup. + + -use64 In -bgr233 mode, use 64 colors instead of 256. + -bgr222 Same as -use64. + + -use8 In -bgr233 mode, use 8 colors instead of 256. + -bgr111 Same as -use8. + + -16bpp If the vnc viewer X display is depth 24 at 32bpp + request a 16bpp format from the VNC server to cut + network traffic by up to 2X, then tranlate the + pixels to 32bpp locally. + -bgr565 Same as -16bpp. + + -grey Use a grey scale for the 16- and 8-bpp modes. + + -alpha Use alphablending transparency for local cursors + requires: x11vnc server, both client and server + must be 32bpp and same endianness. + + -scale str Scale the desktop locally. The string "str" can + a floating point ratio, e.g. "0.9", or a fraction, + e.g. "3/4", or WxH, e.g. 1280x1024. Use "fit" + to fit in the current screen size. Use "auto" to + fit in the window size. "str" can also be set by + the env. var. SSVNC_SCALE. + + If you observe mouse trail painting errors, enable + X11 Cursor mode (either via Popup or -x11cursor.) + + Note that scaling is done in software and so can be + slow and requires more memory. Some speedup Tips: + + ZRLE is faster than Tight in this mode. When + scaling is first detected, the encoding will + be automatically switched to ZRLE. Use the + Popup menu if you want to go back to Tight. + Set SSVNC_PRESERVE_ENCODING=1 to disable this. + + Use a solid background on the remote side. + (e.g. manually or via x11vnc -solid ...) + + If the remote server is x11vnc, try client + side caching: x11vnc -ncache 10 ... + + -ycrop n Only show the top n rows of the framebuffer. For + use with x11vnc -ncache client caching option + to help "hide" the pixel cache region. + Use a negative value (e.g. -1) for autodetection. + Autodetection will always take place if the remote + fb height is more than 2 times the width. + + -sbwidth n Scrollbar width for x11vnc -ncache mode (-ycrop), + default is very narrow: 2 pixels, it is narrow to + avoid distraction in -ycrop mode. + + -nobell Disable bell. + + -rawlocal Prefer raw encoding for localhost, default is + no, i.e. assumes you have a SSH tunnel instead. + + -notty Try to avoid using the terminal for interactive + responses: use windows for messages and prompting + instead. Messages will also be printed to terminal. + + -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C, + Ctrl+V) instead of the X PRIMARY selection (mouse + select and middle button paste.) + + -sendalways Whenever the mouse enters the VNC viewer main + window, send the selection to the VNC server even if + it has not changed. This is like the Xt resource + translation SelectionToVNC(always) + + -recvtext str When cut text is received from the VNC server, + ssvncviewer will set both the X PRIMARY and the + X CLIPBOARD local selections. To control which + is set, specify 'str' as 'primary', 'clipboard', + or 'both' (the default.) + + -graball Grab the entire X server when in fullscreen mode, + needed by some old window managers like fvwm2. + + -popupfix Warp the popup back to the pointer position, + needed by some old window managers like fvwm2. + -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C, + Ctrl+V) instead of the X PRIMARY selection (mouse + select and middle button paste.) + + -sendalways Whenever the mouse enters the VNC viewer main + window, send the selection to the VNC server even if + it has not changed. This is like the Xt resource + translation SelectionToVNC(always) + + -recvtext str When cut text is received from the VNC server, + ssvncviewer will set both the X PRIMARY and the + X CLIPBOARD local selections. To control which + is set, specify 'str' as 'primary', 'clipboard', + or 'both' (the default.) + + -graball Grab the entire X server when in fullscreen mode, + needed by some old window managers like fvwm2. + + -popupfix Warp the popup back to the pointer position, + needed by some old window managers like fvwm2. + + -grabkbd Grab the X keyboard when in fullscreen mode, + needed by some window managers. Same as -grabkeyboard. + -grabkbd is the default, use -nograbkbd to disable. + + -bs, -nobs Whether or not to use X server Backingstore for the + main viewer window. The default is to not, mainly + because most Linux, etc, systems X servers disable + *all* Backingstore by default. To re-enable it put + + Option "Backingstore" + + in the Device section of /etc/X11/xorg.conf. + In -bs mode with no X server backingstore, whenever an + area of the screen is re-exposed it must go out to the + VNC server to retrieve the pixels. This is too slow. + + In -nobs mode, memory is allocated by the viewer to + provide its own backing of the main viewer window. This + actually makes some activities faster (changes in large + regions) but can appear to "flash" too much. + + -noshm Disable use of MIT shared memory extension (not recommended +) + + -termchat Do the UltraVNC chat in the terminal vncviewer is in + instead of in an independent window. + + -unixpw str Useful for logging into x11vnc in -unixpw mode. "str" is a + string that allows many ways to enter the Unix Username + and Unix Password. These characters: username, newline, + password, newline are sent to the VNC server after any VNC + authentication has taken place. Under x11vnc they are + used for the -unixpw login. Other VNC servers could do + something similar. + + You can also indicate "str" via the environment + variable SSVNC_UNIXPW. + + Note that the Escape key is actually sent first to tell + x11vnc to not echo the Unix Username back to the VNC + viewer. Set SSVNC_UNIXPW_NOESC=1 to override this. + + If str is ".", then you are prompted at the command line + for the username and password in the normal way. If str is + "-" the stdin is read via getpass(3) for username@password. + Otherwise if str is a file, it is opened and the first line + read is taken as the Unix username and the 2nd as the + password. If str prefixed by "rm:" the file is removed + after reading. Otherwise, if str has a "@" character, + it is taken as username@password. Otherwise, the program + exits with an error. Got all that? + + -repeater str This is for use with UltraVNC repeater proxy described + here: http://www.uvnc.com/addons/repeater.html. The "str" + is the ID string to be sent to the repeater. E.g. ID:1234 + It can also be the hostname and port or display of the VNC + server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when + using -repeater, the host:dpy on the cmdline is the repeate +r + server, NOT the VNC server. The repeater will connect you. + + Example: vncviewer ... -repeater ID:3333 repeat.host:5900 + Example: vncviewer ... -repeater vhost:0 repeat.host:5900 + + Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a + Single Click III (SSL) repeater (repeater_SSL.exe) and you + are passing the SSL part of the connection through stunnel, + socat, etc. This way the magic UltraVNC string 'testB' + needed to work with the repeater is sent to it. + + -rfbversion str Set the advertised RFB version. E.g.: -rfbversion 3.6 + For some servers, e.g. UltraVNC this needs to be done. + + -ultradsm UltraVNC has symmetric private key encryption DSM plugins: + http://www.uvnc.com/features/encryption.html. It is assumed + you are using a unix program (e.g. our ultravnc_dsm_helper) + to encrypt and decrypt the UltraVNC DSM stream. IN ADDITION + TO THAT supply -ultradsm to tell THIS viewer to modify the + RFB data sent so as to work with the UltraVNC Server. For + some reason, each RFB msg type must be sent twice under DSM +. + + -mslogon user Use Windows MS Logon to an UltraVNC server. Supply the + username or "1" to be prompted. The default is to + autodetect the UltraVNC MS Logon server and prompt for + the username and password. + + IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman + exchange is very weak and can be brute forced to recover + your username and password in a few seconds of CPU time. + To be safe, be sure to use an additional encrypted tunnel + (e.g. SSL or SSH) for the entire VNC session. + + -chatonly Try to be a client that only does UltraVNC text chat. This + mode is used by x11vnc to present a chat window on the + physical X11 console (i.e. chat with the person at the + display). + + -env VAR=VALUE To save writing a shell script to set environment variables +, + specify as many as you need on the command line. For + example, -env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi + + -noipv6 Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1. + + -noipv4 Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1. + + -printres Print out the Ssvnc X resources (appdefaults) and then exit + You can save them to a file and customize them (e.g. the + keybindings and Popup menu) Then point to the file via + XENVIRONMENT or XAPPLRESDIR. + + -pipeline Like TurboVNC, request the next framebuffer update as soon + as possible instead of waiting until the end of the current + framebuffer update coming in. Helps 'pipeline' the updates +. + This is currently the default, use -nopipeline to disable. + + -appshare Enable features for use with x11vnc's -appshare mode where + instead of sharing the full desktop only the application's + windows are shared. Viewer multilisten mode is used to + create the multiple windows: -multilisten is implied. + See 'x11vnc -appshare -help' more information on the mode. + + Features enabled in the viewer under -appshare are: + Minimum extra text in the title, auto -ycrop is disabled, + x11vnc -remote_prefix X11VNC_APPSHARE_CMD: message channel, + x11vnc initial window position hints. See also Escape Keys + below for additional key and mouse bindings. + + -escape str This sets the 'Escape Keys' modifier sequence and enables + escape keys mode. When the modifier keys escape sequence + is held down, the next keystroke is interpreted locally + to perform a special action instead of being sent to the + remote VNC server. + + Use '-escape default' for the default modifier sequence. + (Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L) + + Here are the 'Escape Keys: Help+Set' instructions from the Popup Menu: + + Escape Keys: Enter a comma separated list of modifier keys to be the + 'escape sequence'. When these keys are held down, the next keystroke is + interpreted locally to invoke a special action instead of being sent to + the remote VNC server. In other words, a set of 'Hot Keys'. + + To enable or disable this, click on 'Escape Keys: Toggle' in the Popup. + + Here is the list of hot-key mappings to special actions: + + r: refresh desktop b: toggle bell c: toggle full-color + f: file transfer x: x11cursor z: toggle Tight/ZRLE + l: full screen g: graball e: escape keys dialog + s: scale dialog +: scale up (=) -: scale down (_) + t: text chat a: alphablend cursor + V: toggle viewonly Q: quit viewer 1 2 3 4 5 6: UltraVNC scale 1/n + + Arrow keys: pan the viewport about 10% for each keypress. + PageUp / PageDown: pan the viewport by a screenful vertically. + Home / End: pan the viewport by a screenful horizontally. + KeyPad Arrow keys: pan the viewport by 1 pixel for each keypress. + Dragging the Mouse with Button1 pressed also pans the viewport. + Clicking Mouse Button3 brings up the Popup Menu. + + The above mappings are *always* active in ViewOnly mode, unless you set the + Escape Keys value to 'never'. + + If the Escape Keys value below is set to 'default' then a default list of + of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it + is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag + on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side + of the keyboard. + + On Unix the default is Alt and Windows keys on Left side of keyboard. + On MacOSX the default is Control and Command keys on Left side of keyboard. + + Example: Press and hold the Alt and Windows keys on the LEFT side of the + keyboard and then press 'c' to toggle the full-color state. Or press 't' + to toggle the ultravnc Text Chat window, etc. + + To use something besides the default, supply a comma separated list (or a + single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L + Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. + + + New Popup actions: + + ViewOnly: ~ -viewonly + Disable Bell: ~ -nobell + Cursor Shape: ~ -nocursorshape + X11 Cursor: ~ -x11cursor + Cursor Alphablend: ~ -alpha + Toggle Tight/Hextile: ~ -encodings hextile... + Toggle Tight/ZRLE: ~ -encodings zrle... + Toggle ZRLE/ZYWRLE: ~ -encodings zywrle... + Quality Level ~ -quality (both Tight and ZYWRLE) + Compress Level ~ -compresslevel + Disable JPEG: ~ -nojpeg (Tight) + Pipeline Updates ~ -pipeline + + Full Color as many colors as local screen allows. + Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. + 16 bit color (BGR565) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. + 64 colors ~ -bgr222 / -use64 + 8 colors ~ -bgr111 / -use8 + Scale Viewer ~ -scale + Escape Keys: Toggle ~ -escape + Escape Keys: Help+Set ~ -escape + Set Y Crop (y-max) ~ -ycrop + Set Scrollbar Width ~ -sbwidth + XGrabServer ~ -graball + + UltraVNC Extensions: + + Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. + Text Chat Ultravnc ext. Do Text Chat. + File Transfer Ultravnc ext. File xfer via Java helper. + Single Window Ultravnc ext. Grab and view a single window. + (select then click on the window you want). + Disable Remote Input Ultravnc ext. Try to prevent input and + viewing of monitor at physical display. + + Note: the Ultravnc extensions only apply to servers that support + them. x11vnc/libvncserver supports some of them. + + Send Clipboard not Primary ~ -sendclipboard + Send Selection Every time ~ -sendalways + + Nearly all of these can be changed dynamically in the Popup menu + (press F8 for it): + + [viewer_menu.gif] [unixviewer.jpg] + + _________________________________________________________________ + + Windows: + + For Windows, SSL Viewer support is provided by a GUI Windows/ssvnc.exe + that prompts for the VNC display and then starts up STUNNEL followed + by the Stock TightVNC Windows Viewer. Both are bundled in the package + for your convenience. The GUI has other useful features. When the + connection is finished, you will be asked if you want to terminate the + STUNNEL program. For SSH connections from Windows the GUI will use + PLINK instead of STUNNEL. + + Unix and Mac OS X: + + Run the GUI (ssvnc, see above) and let me know how it goes. + _________________________________________________________________ + + Hopefully this tool will make it convenient for people to help test + and use the built-in SSL support in x11vnc. Extra testing of this + feature is much appreciated!! Thanks. + + Please Help Test the newly added features: + * Automatic Service tunnelling via SSH for CUPS and SMB Printing + * ESD/ARTSD Audio + * SMB (Windows/Samba) filesystem mounting + + These allow you to print from the remote (VNC Server) machine to local + printers, listen to sounds (with some limitations) from the remote VNC + Server machine, and to mount your local Windows or Samba shares on the + remote VNC Server machine. Basically these new features try to + automate the tricks described here: + http://www.karlrunge.com/x11vnc/faq.html#faq-smb-shares + http://www.karlrunge.com/x11vnc/faq.html#faq-cups + http://www.karlrunge.com/x11vnc/faq.html#faq-sound + _________________________________________________________________ + + Downloading: Downloads for this project are hosted at Sourceforge.net. + + Choose the archive file bundle that best suits you (e.g. no source + code, windows only, unix only, zip, tar etc). + + A quick guide: + + On some flavor of Unix, e.g. Linux or Solaris? Use + "ssvnc_unix_only" (or "ssvnc_no_windows" to recompile). + On Mac OS X? Use "ssvnc_no_windows". + On Windows? Use "ssvnc_windows_only". + ssvnc_windows_only-1.0.27.zip Windows Binaries Only. No source included + (6.2MB) + ssvnc_no_windows-1.0.27.tar.gz Unix and Mac OS X Only. No Windows binarie +s. Source included. (10.1MB) + ssvnc_unix_only-1.0.27.tar.gz Unix Binaries Only. No source included +. (7.2MB) + ssvnc_unix_minimal-1.0.27.tar.gz Unix Minimal. You must supply your own vn +cviewer and stunnel. (0.2MB) + + ssvnc-1.0.27.tar.gz All Unix, Mac OS X, and Windows binaries a +nd source TGZ. (16.1MB) + ssvnc-1.0.27.zip All Unix, Mac OS X, and Windows binaries a +nd source ZIP. (16.4MB) + ssvnc_all-1.0.27.zip All Unix, Mac OS X, and Windows binaries a +nd source AND full archives in the zip dir. (19.2MB) + + + Here is a conventional source tarball: + ssvnc-1.0.27.src.tar.gz Conventional Source for SSVNC GUI and Unix + VNCviewer (0.5MB) + + it will be of use to those who do not want the SSVNC + "one-size-fits-all" bundles. For example, package/distro maintainers + will find this more familiar and useful to them (i.e. they run: "make + config; make all; make install"). Note that it does not include the + stunnel source, and so has a dependency that the system stunnel is + installed. + + Read the README.src file for more information on using the + conventional source tarball. + + + Note: even with the Unix bundles, e.g. "ssvnc_no_windows" or + "ssvnc_all", you may need to run the "./build.unix" script in the top + directory to recompile for your operating system. + + Here are the corresponding 1.0.28 development bundles (Please help + test them): + + ssvnc_windows_only-1.0.28.zip + ssvnc_no_windows-1.0.28.tar.gz + ssvnc_unix_only-1.0.28.tar.gz + ssvnc_unix_minimal-1.0.28.tar.gz + + ssvnc-1.0.28.tar.gz + ssvnc-1.0.28.zip + ssvnc_all-1.0.28.zip + + ssvnc-1.0.28.src.tar.gz Conventional Source for SSVNC GUI and Unix + VNCviewer (0.5MB) + + + For any Unix system, a self-extracting and running file for the + "ssvnc_unix_minimal" package is here: ssvnc. Save it as filename + "ssvnc", type "chmod 755 ./ssvnc", and then launch the GUI via typing + "./ssvnc". Note that this "ssvnc_unix_minimal" mode requires you + install the "stunnel" and "vncviewer" programs externally (for + example, install your distros' versions, e.g. on debian: "apt-get + install stunnel4 xtightvncviewer".) It will work, but many of the + SSVNC features will be missing. + + Previous releases: + Release 1.0.18 at Sourceforge.net + Release 1.0.19 at Sourceforge.net + Release 1.0.20 at Sourceforge.net + Release 1.0.21 at Sourceforge.net + Release 1.0.22 at Sourceforge.net + Release 1.0.23 at Sourceforge.net + Release 1.0.24 at Sourceforge.net + Release 1.0.25 at Sourceforge.net + Release 1.0.26 at Sourceforge.net + Release 1.0.27 at Sourceforge.net + + + Please help test the UltraVNC File Transfer support in the native Unix + VNC viewer! Let us know how it went. + + Current Unix binaries in the archives: + Linux.i686 + Linux.x86_64 + Linux.ppc64 X (removed) + Linux.alpha X (removed) + SunOS.sun4u + SunOS.sun4m + SunOS.i86pc + Darwin.Power.Macintosh + Darwin.i386 + HP-UX.9000 X (removed) + FreeBSD.i386 X (removed) + NetBSD.i386 X (removed) + OpenBSD.i386 X (removed) + + (some of these are out of date, marked with 'X' above, because I no + longer have access to machines running those OS's. Use the + "build.unix" script to recompile on your system). + + Note: some of the above binaries depend on libssl.so.0.9.7, whereas + some recent distros only provide libssl.so.0.9.8 by default (for + compatibility reasons they should install both by default but not all + do). So you may need to instruct your distro to install the 0.9.7 + library (it is fine to have both runtimes installed simultaneously + since the libraries have different names). Update: I now try to + statically link libssl.a for all of the binaries in the archive. + + You can also run the included build.unix script to try to + automatically build the binaries if your OS is not in the above list + or the included binary does not run properly on your system. Let me + know how that goes. + _________________________________________________________________ + + IMPORTANT: there may be restrictions for you to download, use, or + redistribute the above because of cryptographic software they contain + or for other reasons. Please check out your situation and information + at the following and related sites: + http://stunnel.mirt.net + http://www.stunnel.org + http://www.openssl.org + http://www.chiark.greenend.org.uk/~sgtatham/putty/ + http://www.tightvnc.com + http://www.realvnc.com + http://sourceforge.net/projects/cotvnc/ + _________________________________________________________________ + + README: Here is the toplevel README from the bundle. + +======================================================================= +http://www.karlrunge.com/x11vnc/x11vnc_opts.html: + + + _________________________________________________________________ + +x11vnc: a VNC server for real X displays + + Here are all of x11vnc command line options: +% x11vnc -opts (see below for -help long descriptions) + +x11vnc: allow VNC connections to real X11 displays. 0.9.11 lastmod: 2010-05-08 + +x11vnc options: + -display disp -auth file -N + -autoport n -rfbport str -6 + -no6 -noipv6 -noipv4 + -reopen -reflect host:N -id windowid + -sid windowid -appshare -clip WxH+X+Y + -flashcmap -shiftcmap n -notruecolor + -advertise_truecolor -visual n -overlay + -overlay_nocursor -8to24 [opts] -24to32 + -scale fraction -geometry WxH -scale_cursor frac + -viewonly -shared -once + -forever -loop -timeout n + -sleepin n -inetd -tightfilexfer + -ultrafilexfer -http -http_ssl + -avahi -mdns -zeroconf + -connect string -connect_or_exit str -proxy string + -vncconnect -novncconnect -allow host1[,host2..] + -localhost -listen6 str -nolookup + -input string -grabkbd -grabptr + -grabalways -viewpasswd string -passwdfile filename + -showrfbauth filename -unixpw [list] -unixpw_nis [list] + -unixpw_cmd cmd -find -finddpy + -listdpy -findauth [disp] -create + -xdummy -xvnc -xvnc_redirect + -xdummy_xvfb -create_xsrv str -svc + -svc_xdummy -svc_xvnc -svc_xdummy_xvfb + -xdmsvc -sshxdmsvc -unixpw_system_greeter + -redirect port -display WAIT:... -vencrypt mode + -anontls mode -sslonly -dhparams file + -nossl -ssl [pem] -ssltimeout n + -sslnofail -ssldir dir -sslverify path + -sslCRL path -sslGenCA [dir] -sslGenCert type name + -sslEncKey pem -sslCertInfo pem -sslDelCert pem + -sslScripts -stunnel [pem] -stunnel3 [pem] + -enc cipher:keyfile -https [port] -httpsredir [port] + -http_oneport -ssh user@host:disp -usepw + -storepasswd pass file -nopw -accept string + -afteraccept string -gone string -users list + -noshm -flipbyteorder -onetile + -solid [color] -blackout string -xinerama + -noxinerama -xtrap -xrandr [mode] + -rotate string -padgeom WxH -o logfile + -flag file -rmflag file -rc filename + -norc -env VAR=VALUE -prog /path/to/x11vnc + -h, -help -?, -opts -V, -version + -license -dbg -q, -quiet + -v, -verbose -bg -modtweak + -nomodtweak -xkb -noxkb + -capslock -skip_lockkeys -noskip_lockkeys + -skip_keycodes string -sloppy_keys -skip_dups + -noskip_dups -add_keysyms -noadd_keysyms + -clear_mods -clear_keys -clear_all + -remap string -norepeat -repeat + -nofb -nobell -nosel + -noprimary -nosetprimary -noclipboard + -nosetclipboard -seldir string -cursor [mode] + -nocursor -cursor_drag -arrow n + -noxfixes -alphacut n -alphafrac fraction + -alpharemove -noalphablend -nocursorshape + -cursorpos -nocursorpos -xwarppointer + -noxwarppointer -buttonmap string -nodragging + -ncache n -ncache_cr -ncache_no_moveraise + -ncache_no_dtchange -ncache_no_rootpixmap -ncache_keep_anims + -ncache_old_wm -ncache_pad n -debug_ncache + -wireframe [str] -nowireframe -nowireframelocal + -wirecopyrect mode -nowirecopyrect -debug_wireframe + -scrollcopyrect mode -noscrollcopyrect -scr_area n + -scr_skip list -scr_inc list -scr_keys list + -scr_term list -scr_keyrepeat lo-hi -scr_parms string + -fixscreen string -debug_scroll -noxrecord + -grab_buster -nograb_buster -debug_grabs + -debug_sel -pointer_mode n -input_skip n + -allinput -input_eagerly -speeds rd,bw,lat + -wmdt string -debug_pointer -debug_keyboard + -defer time -wait time -extra_fbur n + -wait_ui factor -setdefer n -nowait_bog + -slow_fb time -xrefresh time -nap + -nonap -sb time -readtimeout n + -ping n -nofbpm -fbpm + -nodpms -dpms -forcedpms + -clientdpms -noserverdpms -noultraext + -chatwindow -noxdamage -xd_area A + -xd_mem f -sigpipe string -threads + -nothreads -fs f -gaps n + -grow n -fuzz n -debug_tiles + -snapfb -rawfb string -freqtab file + -pipeinput cmd -macnodim -macnosleep + -macnosaver -macnowait -macwheel n + -macnoswap -macnoresize -maciconanim n + -macmenu -macuskbd -gui [gui-opts] + -remote command -query variable -QD variable + -sync -query_retries str -remote_prefix str + -noremote -yesremote -unsafe + -safer -privremote -nocmds + -allowedcmds list -deny_all + +LibVNCServer options: +-rfbport port TCP port for RFB protocol +-rfbwait time max time in ms to wait for RFB client +-rfbauth passwd-file use authentication on RFB protocol + (use 'storepasswd' to create a password file) +-rfbversion 3.x Set the version of the RFB we choose to advertise +-permitfiletransfer permit file transfer support +-passwd plain-password use authentication + (use plain-password as password, USE AT YOUR RISK) +-deferupdate time time in ms to defer updates (default 40) +-deferptrupdate time time in ms to defer pointer updates (default none) +-desktop name VNC desktop name (default "LibVNCServer") +-alwaysshared always treat new clients as shared +-nevershared never treat new clients as shared +-dontdisconnect don't disconnect existing clients when a new non-shared + connection comes in (refuse new connection instead) +-httpdir dir-path enable http server using dir-path home +-httpport portnum use portnum for http connection +-enablehttpproxy enable http proxy support +-progressive height enable progressive updating for slow links +-listen ipaddr listen for connections only on network interface with + addr ipaddr. '-listen localhost' and hostname work too. + +libvncserver-tight-extension options: +-disablefiletransfer disable file transfer +-ftproot string set ftp root + + + + +% x11vnc -help + +x11vnc: allow VNC connections to real X11 displays. 0.9.11 lastmod: 2010-05-08 + +(type "x11vnc -opts" to just list the options.) + +Typical usage is: + + Run this command in a shell on the remote machine "far-host" + with X session you wish to view: + + x11vnc -display :0 + + Then run this in another window on the machine you are sitting at: + + vncviewer far-host:0 + +Once x11vnc establishes connections with the X11 server and starts listening +as a VNC server it will print out a string: PORT=XXXX where XXXX is typically +5900 (the default VNC server port). One would next run something like +this on the local machine: "vncviewer hostname:N" where "hostname" is +the name of the machine running x11vnc and N is XXXX - 5900, i.e. usually +"vncviewer hostname:0". + +By default x11vnc will not allow the screen to be shared and it will exit +as soon as the client disconnects. See -shared and -forever below to override +these protections. See the FAQ for details how to tunnel the VNC connection +through an encrypted channel such as ssh(1). In brief: + + ssh -t -L 5900:localhost:5900 far-host 'x11vnc -localhost -display :0' + + vncviewer -encodings 'copyrect tight zrle hextile' localhost:0 + +Also, use of a VNC password (-rfbauth or -passwdfile) is strongly recommended. + +For additional info see: http://www.karlrunge.com/x11vnc/ + and http://www.karlrunge.com/x11vnc/faq.html + + +Config file support: if the file $HOME/.x11vncrc exists then each line in +it is treated as a single command line option. Disable with -norc. For +each option name, the leading character "-" is not required. E.g. a line +that is either "forever" or "-forever" may be used and are equivalent. +Likewise "wait 100" or "-wait 100" are acceptable and equivalent lines. +The "#" character comments out to the end of the line in the usual way +(backslash it for a literal). Leading and trailing whitespace is trimmed off. +Lines may be continued with a "\" as the last character of a line (it +becomes a space character). + +Options: + +-display disp X11 server display to connect to, usually :0. The X + server process must be running on same machine and + support MIT-SHM. Equivalent to setting the DISPLAY + environment variable to "disp". + + See the description below of the "-display WAIT:..." + extensions, where alias "-find" will find the user's + display automatically, and "-create" will create a + Xvfb session if no session is found. + +-auth file Set the X authority file to be "file", equivalent to + setting the XAUTHORITY environment variable to "file" + before startup. Same as -xauth file. See Xsecurity(7), + xauth(1) man pages for more info. + + Use '-auth guess' to have x11vnc use its -findauth + mechanism (described below) to try to guess the + XAUTHORITY filename and use it. + + XDM/GDM/KDM: if you are running x11vnc as root and want + to find the XAUTHORITY before anyone has logged into an + X session yet, use: x11vnc -env FD_XDM=1 -auth guess ... + (This will also find the XAUTHORITY if a user is already + logged into the X session.) When running as root, + FD_XDM=1 will be tried if the initial -auth guess fails. + +-N If the X display is :N, try to set the VNC display to + also be :N This just sets the -rfbport option to 5900+N + The program will exit immediately if that port is not + available. The -N option only works with normal -display + usage, e.g. :0 or :8, -N is ignored in the -display + WAIT:..., -create, -find, -svc, -redirect, etc modes. + +-autoport n Automatically probe for a free VNC port starting at n. + The default is to start probing at 5900. Use this to + stay away from other VNC servers near 5900. + +-rfbport str The VNC port to listen on (a LibVNCServer option), e.g. + 5900, 5901, etc. If specified as "-rfbport PROMPT" + then the x11vnc -gui is used to prompt the user to + enter the port number. + +-6 IPv6 listening support. In addition to IPv4, the + IPv6 address is listened on for incoming connections. + The same port number as IPv4 is used. + + NOTE: This x11vnc binary was compiled to have the + "-6" IPv6 listening mode ENABLED by default (CPPFLAGS + -DX11VNC_LISTEN6=1). So to disable IPv6 listening mode + you MUST supply the "-no6" option (see below.) + + The "-6" mode works for both normal connections and + -ssl encrypted ones. Nearly everything is supported + for the IPv6 case, but there are a few exceptions. + See -stunnel for its IPv6 support. + + Currently, for absolutely everything to work correctly + the machine may need to have some IPv4 support, at the + least for the loopback interface. However, for nearly + all usage modes no IPv4 support is required. See -nopiv4 +. + + If you have trouble compiling or running in IPv6 mode, + set -DX11VNC_IPV6=0 in CPPFLAGS when configuring to + disable IPv6 support. + +-no6 Disable IPv6 listening support (only useful if the + "-6" mode is compiled in to be the default; see the + X11VNC_LISTEN6 description above under "-6".) + +-noipv6 Do not try to use IPv6 for any listening or connecting + sockets. This includes both the listening service + port(s) and outgoing connections from -connect, + -connect_or_exit, or -proxy. Use this if you are having + problems due to IPv6. + +-noipv4 Do not try to use IPv4 for any listening or connecting + sockets. This is mainly for exploring the behavior of + x11vnc on an IPv6-only system, but may have other uses. + +-reopen If the X server connection is disconnected, try to + reopen the X display (up to one time.) This is of use + for display managers like GDM (KillInitClients option) + that kill x11vnc just after the user logs into the + X session. Note: the reopened state may be unstable. + Set X11VNC_REOPEN_DISPLAY=n to reopen n times and + set X11VNC_REOPEN_SLEEP_MAX to the number of seconds, + default 10, to keep trying to reopen the display (once + per second.) + + Update: as of 0.9.9, x11vnc tries to automatically avoid + being killed by the display manager by delaying creating + windows or using XFIXES. So you shouldn't need to use + KillInitClients=false as long as you log in quickly + enough (within 45 seconds of connecting.) You can + disable this by setting X11VNC_AVOID_WINDOWS=never. + You can also set it to the number of seconds to delay. + +-reflect host:N Instead of connecting to and polling an X display, + connect to the remote VNC server host:N and be a + reflector/repeater for it. This is useful for trying + to manage the case of many simultaneous VNC viewers + (e.g. classroom broadcasting) where, e.g. you put + a repeater on each network switch, etc, to improve + performance by distributing the load and network + traffic. Implies -shared (use -noshared as a later + option to disable). See the discussion below under + -rawfb vnc:host:N for more details. + +-id windowid Show the X window corresponding to "windowid" not + the entire display. New windows like popup menus, + transient toplevels, etc, may not be seen or may be + clipped. Disabling SaveUnders or BackingStore in the + X server may help show them. x11vnc may crash if the + window is initially partially obscured, changes size, + is iconified, etc. Some steps are taken to avoid this + and the -xrandr mechanism is used to track resizes. Use + xwininfo(1) to get the window id, or use "-id pick" + to have x11vnc run xwininfo(1) for you and extract + the id. The -id option is useful for exporting very + simple applications (e.g. the current view on a webcam). +-sid windowid As -id, but instead of using the window directly it + shifts a root view to it: this shows SaveUnders menus, + etc, although they will be clipped if they extend beyond + the window. + +-appshare Simple application sharing based on the -id/-sid + mechanism. Every new toplevel window that the + application creates induces a new viewer window via + a reverse connection. The -id/-sid and -connect + options are required. Run 'x11vnc -appshare -help' + for more info. + +-clip WxH+X+Y Only show the sub-region of the full display that + corresponds to the rectangle geometry with size WxH and + offset +X+Y. The VNC display has size WxH (i.e. smaller + than the full display). This also works for -id/-sid + mode where the offset is relative to the upper left + corner of the selected window. An example use of this + option would be to split a large (e.g. Xinerama) display + into two parts to be accessed via separate viewers by + running a separate x11vnc on each part. + + Use '-clip xinerama0' to clip to the first xinerama + sub-screen (if xinerama is active). xinerama1 for the + 2nd sub-screen, etc. This way you don't need to figure + out the WxH+X+Y of the desired xinerama sub-screen. + screens are sorted in increasing distance from the + (0,0) origin (I.e. not the Xserver's order). + +-flashcmap In 8bpp indexed color, let the installed colormap flash + as the pointer moves from window to window (slow). + Also try the -8to24 option to avoid flash altogether. +-shiftcmap n Rare problem, but some 8bpp displays use less than 256 + colorcells (e.g. 16-color grayscale, perhaps the other + bits are used for double buffering) *and* also need to + shift the pixels values away from 0, .., ncells. "n" + indicates the shift to be applied to the pixel values. + To see the pixel values set DEBUG_CMAP=1 to print out + a colormap histogram. Example: -shiftcmap 240 +-notruecolor For 8bpp displays, force indexed color (i.e. a colormap) + even if it looks like 8bpp TrueColor (rare problem). +-advertise_truecolor If the X11 display is indexed color, lie to clients + when they first connect by telling them it is truecolor. + To workaround RealVNC: inPF has colourMap but not 8bpp + Use '-advertise_truecolor reset' to reset client fb too. + +-visual n This option probably does not do what you think. + It simply *forces* the visual used for the framebuffer; + this may be a bad thing... (e.g. messes up colors or + cause a crash). It is useful for testing and for some + workarounds. n may be a decimal number, or 0x hex. + Run xdpyinfo(1) for the values. One may also use + "TrueColor", etc. see for a list. If the + string ends in ":m" then for better or for worse + the visual depth is forced to be m. You may want to + use -noshm when using this option (so XGetImage may + automatically translate the pixel data). + +-overlay Handle multiple depth visuals on one screen, e.g. 8+24 + and 24+8 overlay visuals (the 32 bits per pixel are + packed with 8 for PseudoColor and 24 for TrueColor). + + Currently -overlay only works on Solaris via + XReadScreen(3X11) and IRIX using XReadDisplay(3). + On Solaris there is a problem with image "bleeding" + around transient popup menus (but not for the menu + itself): a workaround is to disable SaveUnders + by passing the "-su" argument to Xsun (in + /etc/dt/config/Xservers). + + Use -overlay as a workaround for situations like these: + Some legacy applications require the default visual to + be 8bpp (8+24), or they will use 8bpp PseudoColor even + when the default visual is depth 24 TrueColor (24+8). + In these cases colors in some windows will be incorrect + in x11vnc unless -overlay is used. Another use of + -overlay is to enable showing the exact mouse cursor + shape (details below). + + Under -overlay, performance will be somewhat slower + due to the extra image transformations required. + For optimal performance do not use -overlay, but rather + configure the X server so that the default visual is + depth 24 TrueColor and try to have all apps use that + visual (e.g. some apps have -use24 or -visual options). +-overlay_nocursor Sets -overlay, but does not try to draw the exact mouse + cursor shape using the overlay mechanism. + +-8to24 [opts] Try this option if -overlay is not supported on your + OS, and you have a legacy 8bpp app that you want to + view on a multi-depth display with default depth 24 + (and is 32 bpp) OR have a default depth 8 display with + depth 24 overlay windows for some apps. This option + may not work on all X servers and hardware (tested + on XFree86/Xorg mga driver and Xsun). The "opts" + string is not required and is described below. + + This mode enables a hack where x11vnc monitors windows + within 3 levels from the root window. If it finds + any that are 8bpp it extracts the indexed color + pixel values using XGetImage() and then applies a + transformation using the colormap(s) to create TrueColor + RGB values that it in turn inserts into bits 1-24 of + the framebuffer. This creates a depth 24 "view" + of the display that is then exported via VNC. + + Conversely, for default depth 8 displays, the depth + 24 regions are read by XGetImage() and everything is + transformed and inserted into a depth 24 TrueColor + framebuffer. + + Note that even if there are *no* depth 24 visuals or + windows (i.e. pure 8bpp), this mode is potentially + an improvement over -flashcmap because it avoids the + flashing and shows each window in the correct color. + + This method works OK, but may still have bugs and it + does hog resources. If there are multiple 8bpp windows + using different colormaps, one may have to iconify all + but one for the colors to be correct. + + There may be painting errors for clipping and switching + between windows of depths 8 and 24. Heuristics are + applied to try to minimize the painting errors. One can + also press 3 Alt_L's in a row to refresh the screen + if the error does not repair itself. Also the option + -fixscreen 8=3.0 or -fixscreen V=3.0 may be used to + periodically refresh the screen at the cost of bandwidth + (every 3 sec for this example). + + The [opts] string can contain the following settings. + Multiple settings are separated by commas. + + For for some X servers with default depth 24 a + speedup may be achieved via the option "nogetimage". + This enables a scheme were XGetImage() is not used + to retrieve the 8bpp data. Instead, it assumes that + the 8bpp data is in bits 25-32 of the 32bit X pixels. + There is no requirement that the X server should put + the data there for our poll requests, but some do and + so the extra steps to retrieve it can be skipped. + Tested with mga driver with XFree86/Xorg. For the + default depth 8 case this option is ignored. + + To adjust how often XGetImage() is used to poll the + non-default visual regions for changes, use the option + "poll=t" where "t" is a floating point time. + (default: 0.05) + + Setting the option "level2" will limit the search + for non-default visual windows to two levels from the + root window. Do this on slow machines where you know + the window manager only imposes one extra window between + the app window and the root window. + + Also for very slow machines use "cachewin=t" + where t is a floating point amount of time to cache + XGetWindowAttributes results. E.g. cachewin=5.0. + This may lead to the windows being unnoticed for this + amount of time when deiconifying, painting errors, etc. + + While testing on a very old SS20 these options gave + tolerable response: -8to24 poll=0.2,cachewin=5.0. For + this machine -overlay is supported and gives better + response. + + Debugging for this mode can be enabled by setting + "dbg=1", "dbg=2", or "dbg=3". + +-24to32 Very rare problem: if the framebuffer (X display + or -rawfb) is 24bpp instead of the usual 32bpp, then + dynamically transform the pixels to 32bpp. This will be + slower, but can be used to work around problems where + VNC viewers cannot handle 24bpp (e.g. "main: setPF: + not 8, 16 or 32 bpp?"). See the FAQ for more info. + + In the case of -rawfb mode, the pixels are directly + modified by inserting a 0 byte to pad them out to 32bpp. + For X displays, a kludge is done that is equivalent to + "-noshm -visual TrueColor:32". (If better performance + is needed for the latter, feel free to ask). + +-scale fraction Scale the framebuffer by factor "fraction". Values + less than 1 shrink the fb, larger ones expand it. Note: + the image may not be sharp and response may be slower. + If "fraction" contains a decimal point "." it + is taken as a floating point number, alternatively + the notation "m/n" may be used to denote fractions + exactly, e.g. -scale 2/3 + + To scale asymmetrically in the horizontal and vertical + directions, specify a WxH geometry to stretch to: + e.g. '-scale 1024x768', or also '-scale 0.9x0.75' + + Scaling Options: can be added after "fraction" via + ":", to supply multiple ":" options use commas. + If you just want a quick, rough scaling without + blending, append ":nb" to "fraction" (e.g. -scale + 1/3:nb). No blending is the default for 8bpp indexed + color, to force blending for this case use ":fb". + + To disable -scrollcopyrect and -wirecopyrect under + -scale use ":nocr". If you need to to enable them use + ":cr" or specify them explicitly on the command line. + If a slow link is detected, ":nocr" may be applied + automatically. Default: :cr + + More esoteric options: for compatibility with vncviewers + the scaled width is adjusted to be a multiple of 4: + to disable this use ":n4". ":in" use interpolation + scheme even when shrinking, ":pad" pad scaled width + and height to be multiples of scaling denominator + (e.g. 3 for 2/3). + +-geometry WxH Same as -scale WxH + +-scale_cursor frac By default if -scale is supplied the cursor shape is + scaled by the same factor. Depending on your usage, + you may want to scale the cursor independently of the + screen or not at all. If you specify -scale_cursor + the cursor will be scaled by that factor. When using + -scale mode to keep the cursor at its "natural" size + use "-scale_cursor 1". Most of the ":" scaling + options apply here as well. + +-viewonly All VNC clients can only watch (default off). +-shared VNC display is shared, i.e. more than one viewer can + connect at the same time (default off). +-once Exit after the first successfully connected viewer + disconnects, opposite of -forever. This is the Default. +-forever Keep listening for more connections rather than exiting + as soon as the first client(s) disconnect. Same as -many + +-loop Create an outer loop restarting the x11vnc process + whenever it terminates. -bg and -inetd are ignored + in this mode (however see -loopbg below). + + Useful for continuing even if the X server terminates + and restarts (at that moment the process will need + permission to reconnect to the new X server of course). + + Use, e.g., -loop100 to sleep 100 millisecs between + restarts, etc. Default is 2000ms (i.e. 2 secs) Use, + e.g. -loop300,5 to sleep 300 ms and only loop 5 times. + + If -loopbg (plus any numbers) is specified instead, + the "-bg" option is implied and the mode approximates + inetd(8) usage to some degree. In this case when + it goes into the background any listening sockets + (i.e. ports 5900, 5800) are closed, so the next one + in the loop can use them. This mode will only be of + use if a VNC client (the only client for that process) + is already connected before the process goes into the + background, for example, usage of -display WAIT:.., + -svc, and -connect can make use of this "poor man's" + inetd mode. The default wait time is 500ms in this + mode. This usage could use useful: -svc -bg -loopbg + +-timeout n Exit unless a client connects within the first n seconds + after startup. + + If there have been no connection attempts after n + seconds x11vnc exits immediately. If a client is + trying to connect but has not progressed to the normal + operating state, x11vnc gives it a few more seconds + to finish and exits if it does not make it to the + normal state. + + For reverse connections via -connect or -connect_or_exit + a timeout of n seconds will be set for all reverse + connects. If the connect timeout alarm goes off, + x11vnc will exit immediately. + +-sleepin n At startup sleep n seconds before proceeding (e.g. to + allow redirs and listening clients to start up) + + If a range is given: '-sleepin min-max', a random value + between min and max is slept. E.g. '-sleepin 0-20' and + '-sleepin 10-30'. Floats are allowed too. + +-inetd Launched by inetd(8): stdio instead of listening socket. + Note: if you are not redirecting stderr to a log file + (via shell 2> or -o option) you MUST also specify the -q + option, otherwise the stderr goes to the viewer which + will cause it to abort. Specifying both -inetd and -q + and no -o will automatically close the stderr. + +-tightfilexfer Enable the TightVNC file transfer extension. Note that + that when the -viewonly option is supplied all file + transfers are disabled. Also clients that log in + viewonly cannot transfer files. However, if the remote + control mechanism is used to change the global or + per-client viewonly state the filetransfer permissions + will NOT change. + + IMPORTANT: please understand if -tightfilexfer is + specified and you run x11vnc as root for, say, inetd + or display manager (gdm, kdm, ...) access and you do + not have it switch users via the -users option, then + VNC Viewers that connect are able to do filetransfer + reads and writes as *root*. + + Also, tightfilexfer is disabled in -unixpw mode. + +-ultrafilexfer Note: to enable UltraVNC filetransfer and to get it to + work you probably need to supply these LibVNCServer + options: "-rfbversion 3.6 -permitfiletransfer" + "-ultrafilexfer" is an alias for this combination. + + IMPORTANT: please understand if -ultrafilexfer is + specified and you run x11vnc as root for, say, inetd + or display manager (gdm, kdm, ...) access and you do + not have it switch users via the -users option, then + VNC Viewers that connect are able to do filetransfer + reads and writes as *root*. + + Note that sadly you cannot do both -tightfilexfer and + -ultrafilexfer at the same time because the latter + requires setting the version to 3.6 and tightvnc will + not do filetransfer when it sees that version number. + +-http Instead of using -httpdir (see below) to specify + where the Java vncviewer applet is, have x11vnc try + to *guess* where the directory is by looking relative + to the program location and in standard locations + (/usr/local/share/x11vnc/classes, etc). Under -ssl or + -stunnel the ssl classes subdirectory is sought. +-http_ssl As -http, but force lookup for ssl classes subdir. + + Note that for HTTPS, single-port Java applet delivery + you can set X11VNC_HTTPS_DOWNLOAD_WAIT_TIME to the + max number of seconds to wait for the applet download + to finish. The default is 15. + +-avahi Use the Avahi/mDNS ZeroConf protocol to advertise + this VNC server to the local network. (Related terms: + Rendezvous, Bonjour). Depending on your setup, you + may need to start avahi-daemon and open udp port 5353 + in your firewall. + + If the avahi API cannot be found at build time, a helper + program like avahi-publish(1) or dns-sd(1) will be tried + +-mdns Same as -avahi. +-zeroconf Same as -avahi. + +-connect string For use with "vncviewer -listen" reverse connections. + If "string" has the form "host" or "host:port" + the connection is made once at startup. + + Use commas for a list of host's and host:port's. + E.g. -connect host1,host2 or host1:0,host2:5678. + Note that to reverse connect to multiple hosts at the + same time you will likely need to also supply: -shared + + Note that unlike most vnc servers, x11vnc will require a + password for reverse as well as for forward connections. + (provided password auth has been enabled, -rfbauth, etc) + If you do not want to require a password for reverse + connections set X11VNC_REVERSE_CONNECTION_NO_AUTH=1 in + your environment before starting x11vnc. + + If "string" contains "/" it is instead interpreted + as a file to periodically check for new hosts. + The first line is read and then the file is truncated. + Be careful about the location of this file if x11vnc + is running as root (e.g. via gdm(1), etc). + + + Repeater mode: Some services provide an intermediate + "vnc repeater": http://www.uvnc.com/addons/repeater.html + (and also http://koti.mbnet.fi/jtko/ for linux port) + that acts as a proxy/gateway. Modes like these require + an initial string to be sent for the reverse connection + before the VNC protocol is started. Here are the ways + to do this: + + -connect pre=some_string+host:port + -connect pre128=some_string+host:port + -connect repeater=ID:1234+host:port + -connect repeater=23.45.67.89::5501+host:port + + SSVNC notation is also supported: + + -connect repeater://host:port+ID:1234 + + As with normal -connect usage, if the repeater port is + not supplied 5500 is assumed. + + The basic idea is between the special tag, e.g. "pre=" + and "+" is the pre-string to be sent. Note that in + this case host:port is the repeater server, NOT the + vnc viewer. Somehow the pre-string tells the repeater + server how to find the vnc viewer and connect you to it. + + In the case pre=some_string+host:port, "some_string" + is simply sent. In the case preNNN=some_string+host:port + "some_string" is sent in a null padded buffer of + length NNN. repeater= is the same as pre250=, this is + the ultravnc repeater buffer size. + + Strings like "\n" and "\r", etc. are expanded to + newline and carriage return. "\c" is expanded to + "," since the connect string is comma separated. + + See also the -proxy option below for additional ways + to plumb reverse connections. + + Reverse SSL: using -connect in -ssl mode makes x11vnc + act as an SSL client (initiates SSL connection) rather + than an SSL server. The idea is x11vnc might be + connecting to stunnel on the viewer side with the + viewer in listening mode. If you do not want this + behavior, use -env X11VNC_DISABLE_SSL_CLIENT_MODE=1. + With this the viewer side can act as the SSL client + as it normally does for forward connections. + + Reverse SSL Repeater mode: This will work, but note + that if the VNC Client does any sort of a 'Fetch Cert' + action before connecting, then the Repeater will + likely drop the connection and both sides will need + to restart. Consider the use of -connect_or_exit + and -loop300,2 to have x11vnc reconnect once to the + repeater after the fetch. You will probably also want + to supply -sslonly to avoid x11vnc thinking the delay + in response means the connection is VeNCrypt. The env + var X11VNC_DISABLE_SSL_CLIENT_MODE=1 discussed above + may also be useful (i.e. the viewer can do a forward + connection as it normally does.) + + IPv6: as of x11vnc 0.9.10 the -connect option should + connect to IPv6 hosts properly. If there are problems + you can disable IPv6 by setting -DX11VNC_IPV6=0 + in CPPFLAGS when configuring. If there problems + connecting to IPv6 hosts consider a relay like the + included inet6to4 script or the -proxy option. + +-connect_or_exit str As with -connect, except if none of the reverse + connections succeed, then x11vnc shuts down immediately + + An easier to type alias for this option is '-coe' + + By the way, if you do not want x11vnc to listen on + ANY interface use -rfbport 0 which is handy for the + -connect_or_exit mode. + +-proxy string Use proxy in string (e.g. host:port) as a proxy for + making reverse connections (-connect or -connect_or_exit + options). + + Web proxies are supported, but note by default most of + them only support destination connections to ports 443 + or 563, so this might not be very useful (the viewer + would need to listen on that port or the router would + have to do a port redirection). + + A web proxy may be specified by either "host:port" + or "http://host:port" (the port is required even if + it is the common choices 80 or 8080) + + SOCKS4, SOCKS4a, and SOCKS5 are also supported. + SOCKS proxies normally do not have restrictions on the + destination port number. + + Use a format like this: socks://host:port or + socks5://host:port. Note that ssh -D does not support + SOCKS4a, so use socks5://. For socks:// SOCKS4 is used + on a numerical IP and "localhost", otherwise SOCKS4a + is used (and so the proxy tries to do the DNS lookup). + + An experimental mode is "-proxy http://host:port/..." + Note the "/" after the port that distinguishes it from + a normal web proxy. The port must be supplied even if + it is the default 80. For this mode a GET is done to + the supplied URL with the string host=H&port=P appended. + H and P will be the -connect reverse connect host + and port. Use the string "__END__" to disable the + appending. The basic idea here is that maybe some cgi + script provides the actual viewer hookup and tunnelling. + How to actually achieve this within cgi, php, etc. is + not clear... A custom web server or apache module + would be straight-forward. + + Another experimental mode is "-proxy ssh://user@host" + in which case a SSH tunnel is used for the proxying. + "user@" is not needed unless your unix username is + different on "host". For a non-standard SSH port + use ssh://user@host:port. If proxies are chained (see + next paragraph) then the ssh one must be the first one. + If ssh-agent is not active, then the ssh password needs + to be entered in the terminal where x11vnc is running. + Examples: + + -connect localhost:0 -proxy ssh://me@friends-pc:2222 + + -connect snoopy:0 -proxy ssh://ssh.company.com + + Multiple proxies may be chained together in case one + needs to ricochet off of a number of hosts to finally + reach the VNC viewer. Up to 3 may be chained, separate + them by commas in the order they are to be connected to. + E.g.: http://host1:port1,socks5://host2:port2 or three + like: first,second,third + + IPv6: as of x11vnc 0.9.10 the -proxy option should + connect to IPv6 hosts properly. If there are problems + you can disable IPv6 by setting -DX11VNC_IPV6=0 + in CPPFLAGS when configuring. If there problems + connecting to IPv6 hosts consider a relay like the + included inet6to4 script. + +-vncconnect Monitor the VNC_CONNECT X property set by the standard +-novncconnect VNC program vncconnect(1). When the property is + set to "host" or "host:port" establish a reverse + connection. Using xprop(1) instead of vncconnect may + work (see the FAQ). The -remote control mechanism uses + X11VNC_REMOTE channel, and this option disables/enables + it as well. Default: -vncconnect + + To use different names for these X11 properties (e.g. to + have separate communication channels for multiple + x11vnc's on the same display) set the VNC_CONNECT or + X11VNC_REMOTE env. vars. to the string you want, for + example: -env X11VNC_REMOTE=X11VNC_REMOTE_12345 + Both sides of the channel must use the same unique name. + The same can be done for the internal X11VNC_TICKER + property (heartbeat and timestamp) if desired. + +-allow host1[,host2..] Only allow client connections from hosts matching + the comma separated list of hostnames or IP addresses. + Can also be a numerical IP prefix, e.g. "192.168.100." + to match a simple subnet, for more control build + LibVNCServer with libwrap support (See the FAQ). If the + list contains a "/" it instead is a interpreted + as a file containing addresses or prefixes that is + re-read each time a new client connects. Lines can be + commented out with the "#" character in the usual way. + + -allow applies in -ssl mode, but not in -stunnel mode. + + IPv6: as of x11vnc 0.9.10 a host can be specified + in IPv6 numerical format, e.g. 2001:4860:b009::93. + +-localhost Basically the same as "-allow 127.0.0.1". + + Note: if you want to restrict which network interface + x11vnc listens on, see the -listen option below. + E.g. "-listen localhost" or "-listen 192.168.3.21". + As a special case, the option "-localhost" implies + "-listen localhost". + + A rare case, but for non-localhost -listen usage, if + you use the remote control mechanism (-R) to change + the -listen interface you may need to manually adjust + the -allow list (and vice versa) to avoid situations + where no connections (or too many) are allowed. + + If you do not want x11vnc to listen on ANY interface + (evidently you are using -connect or -connect_or_exit, + or plan to use remote control: -R connect:host), use + -rfbport 0 + + IPv6: if IPv6 is supported, this option automatically + implies the IPv6 loopback address '::1' as well. + +-listen6 str When in IPv6 listen mode "-6", listen only on the + network interface with address "str". It also works + for link scope addresses (fe80::219:dbff:fee5:3f92%eth0) + and IPv6 hostname strings (e.g. ipv6.google.com.) + Use LibVNCServer -listen option for the IPv4 interface. + +-nolookup Do not use gethostbyname() or gethostbyaddr() to look up + host names or IP numbers. Use this if name resolution + is incorrectly set up and leads to long pauses as name + lookups time out, etc. + +-input string Fine tuning of allowed user input. If "string" does + not contain a comma "," the tuning applies only to + normal clients. Otherwise the part before "," is + for normal clients and the part after for view-only + clients. "K" is for Keystroke input, "M" for + Mouse-motion input, "B" for Button-click input, "C" + is for Clipboard input, and "F" is for File transfer + (ultravnc only). Their presence in the string enables + that type of input. E.g. "-input M" means normal + users can only move the mouse and "-input KMBCF,M" + lets normal users do anything and enables view-only + users to move the mouse. This option is ignored when + a global -viewonly is in effect (all input is discarded + in that case). + +-grabkbd When VNC viewers are connected, attempt to the grab + the keyboard so a (non-malicious) user sitting at the + physical display is not able to enter keystrokes. + This method uses XGrabKeyboard(3X11) and so it is + not secure and does not rule out the person at the + physical display injecting keystrokes by flooding the + server with them, grabbing the keyboard himself, etc. + Some degree of cooperation from the person at the + display is assumed. This is intended for remote + help-desk or educational usage modes. +-grabptr As -grabkbd, but for the mouse pointer using + XGrabPointer(3X11). Unfortunately due to the way the X + server works, the mouse can still be moved around by the + user at the physical display, but he will not be able to + change window focus with it. Also some window managers + that call XGrabServer(3X11) for resizes, etc, will + act on the local user's input. Again, some degree of + cooperation from the person at the display is assumed. + +-grabalways Apply both -grabkbd and -grabptr even when no VNC + viewers are connected. If you only want one of them, + use the -R remote control to turn the other back on, + e.g. -R nograbptr. + +-viewpasswd string Supply a 2nd password for view-only logins. The -passwd + (full-access) password must also be supplied. + +-passwdfile filename Specify the LibVNCServer password via the first line + of the file "filename" (instead of via -passwd on + the command line where others might see it via ps(1)). + + See the descriptions below for how to supply multiple + passwords, view-only passwords, to specify external + programs for the authentication, and other features. + + If the filename is prefixed with "rm:" it will be + removed after being read. Perhaps this is useful in + limiting the readability of the file. In general, the + password file should not be readable by untrusted users + (BTW: neither should the VNC -rfbauth file: it is NOT + encrypted, only obscured with a fixed key). + + If the filename is prefixed with "read:" it will + periodically be checked for changes and reread. It is + guaranteed to be reread just when a new client connects + so that the latest passwords will be used. + + If "filename" is prefixed with "cmd:" then the + string after the ":" is run as an external command: + the output of the command will be interpreted as if it + were read from a password file (see below). If the + command does not exit with 0, then x11vnc terminates + immediately. To specify more than 1000 passwords this + way set X11VNC_MAX_PASSWDS before starting x11vnc. + The environment variables are set as in -accept. + + Note that due to the VNC protocol only the first 8 + characters of a password are used (DES key). + + If "filename" is prefixed with "custom:" then a + custom password checker is supplied as an external + command following the ":". The command will be run + when a client authenticates. If the command exits with + 0 the client is accepted, otherwise it is rejected. + The environment variables are set as in -accept. + + The standard input to the custom command will be a + decimal digit "len" followed by a newline. "len" + specifies the challenge size and is usually 16 (the + VNC spec). Then follows len bytes which is the random + challenge string that was sent to the client. This is + then followed by len more bytes holding the client's + response (i.e. the challenge string encrypted via DES + with the user password in the standard situation). + + The "custom:" scheme can be useful to implement + dynamic passwords or to implement methods where longer + passwords and/or different encryption algorithms + are used. The latter will require customizing the VNC + client as well. One could create an MD5SUM based scheme + for example. + + File format for -passwdfile: + + If multiple non-blank lines exist in the file they are + all taken as valid passwords. Blank lines are ignored. + Password lines may be "commented out" (ignored) if + they begin with the character "#" or the line contains + the string "__SKIP__". Lines may be annotated by use + of the "__COMM__" string: from it to the end of the + line is ignored. An empty password may be specified + via the "__EMPTY__" string on a line by itself (note + your viewer might not accept empty passwords). + + If the string "__BEGIN_VIEWONLY__" appears on a + line by itself, the remaining passwords are used for + viewonly access. For compatibility, as a special case + if the file contains only two password lines the 2nd + one is automatically taken as the viewonly password. + Otherwise the "__BEGIN_VIEWONLY__" token must be + used to have viewonly passwords. (tip: make the 3rd + and last line be "__BEGIN_VIEWONLY__" to have 2 + full-access passwords) + +-showrfbauth filename Print to the screen the obscured VNC password kept in + the rfbauth file "filename" and then exit. + +-unixpw [list] Use Unix username and password authentication. x11vnc + will use the su(1) program to verify the user's + password. [list] is an optional comma separated list + of allowed Unix usernames. If the [list] string begins + with the character "!" then the entire list is taken + as an exclude list. See below for per-user options + that can be applied. + + A familiar "login:" and "Password:" dialog is + presented to the user on a black screen inside the + vncviewer. The connection is dropped if the user fails + to supply the correct password in 3 tries or does not + send one before a 45 second timeout. Existing clients + are view-only during this period. + + If the first character received is "Escape" then the + unix username will not be displayed after "login:" + as it is typed. This could be of use for VNC viewers + that automatically type the username and password. + + Since the detailed behavior of su(1) can vary from + OS to OS and for local configurations, test the mode + before deployment to make sure it is working properly. + x11vnc will attempt to be conservative and reject a + login if anything abnormal occurs. + + One case to note: FreeBSD and the other BSD's by + default it is impossible for the user running x11vnc to + validate his *own* password via su(1) (commenting out + the pam_self.so entry in /etc/pam.d/su eliminates this + behavior). So the x11vnc login will always *FAIL* for + this case (even when the correct password is supplied). + + A possible workaround for this on *BSD would be to + start x11vnc as root with the "-users +nobody" option + to immediately switch to user nobody where the su'ing + will proceed normally. + + Another source of potential problems are PAM modules + that prompt for extra info, e.g. password aging modules. + These logins will fail as well even when the correct + password is supplied. + + **IMPORTANT**: to prevent the Unix password being sent + in *clear text* over the network, one of two schemes + will be enforced: 1) the -ssl builtin SSL mode, or 2) + require both -localhost and -stunnel be enabled. + + Method 1) ensures the traffic is encrypted between + viewer and server. A PEM file will be required, see the + discussion under -ssl below (under some circumstances + a temporary one can be automatically generated). + + Method 2) requires the viewer connection to appear + to come from the same machine x11vnc is running on + (e.g. from a ssh -L port redirection). And that the + -stunnel SSL mode be used for encryption over the + network. (see the description of -stunnel below). + + Note: as a convenience, if you ssh(1) in and start + x11vnc it will check if the environment variable + SSH_CONNECTION is set and appears reasonable. If it + does, then the -ssl or -stunnel requirement will be + dropped since it is assumed you are using ssh for the + encrypted tunnelling. -localhost is still enforced. + Use -ssl or -stunnel to force SSL usage even if + SSH_CONNECTION is set. + + To override the above restrictions you can set + environment variables before starting x11vnc: + + Set UNIXPW_DISABLE_SSL=1 to disable requiring either + -ssl or -stunnel (as under SSH_CONNECTION.) Evidently + you will be using a different method to encrypt the + data between the vncviewer and x11vnc: perhaps ssh(1) + or an IPSEC VPN. -localhost is still enforced (however, + see the next paragraph.) + + Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost + requirement in -unixpw modes. One should never do this + (i.e. allow the Unix passwords to be sniffed on the + network.) This also disables the localhost requirement + for reverse connections (see below.) + + Note that use of -localhost with ssh(1) (and no -unixpw) + is roughly the same as requiring a Unix user login + (since a Unix password or the user's public key + authentication is used by sshd on the machine where + x11vnc runs and only local connections from that machine + are accepted). + + Regarding reverse connections (e.g. -R connect:host + and -connect host), when the -localhost constraint is + in effect then reverse connections can only be used + to connect to the same machine x11vnc is running on + (default port 5500). Please use a ssh or stunnel port + redirection to the viewer machine to tunnel the reverse + connection over an encrypted channel. + + In -inetd mode the Method 1) will be enforced (not + Method 2). With -ssl in effect reverse connections + are disabled. If you override this via env. var, be + sure to also use encryption from the viewer to inetd. + Tip: you can also have your own stunnel spawn x11vnc + in -inetd mode (thereby bypassing inetd). See the FAQ + for details. + + The user names in the comma separated [list] may have + per-user options after a ":", e.g. "fred:opts" + where "opts" is a "+" separated list of + "viewonly", "fullaccess", "input=XXXX", or + "deny", e.g. "karl,wally:viewonly,boss:input=M". + For "input=" it is the K,M,B,C described under -input. + + If an item in the list is "*" that means those + options apply to all users. It ALSO implies all users + are allowed to log in after supplying a valid password. + Use "deny" to explicitly deny some users if you use + "*" to set a global option. If [list] begins with the + "!" character then "*" is ignored for checking if + the user is allowed, but the option values associated + with it do apply as normal. + + There are also some utilities for checking passwords + if [list] starts with the "%" character. See the + quick_pw() function for more details. Description: + "%-" or "%stdin" means read one line from stdin. + "%env" means it is in $UNIXPW env var. A leading + "%/" or "%." means read the first line from the + filename that follows after the % character. % by + itself means prompt for the username and password. + Otherwise: %user:pass E.g. -unixpw %fred:swordfish + For the other cases user:pass is read from the indicated + source. If the password is correct 'Y user' is printed + and the program exit code is 0. If the password is + incorrect it prints 'N user' and the exit code is 1. + If there is some other error the exit code is 2. + This feature enables x11vnc to be a general unix user + password checking tool; it could be used from scripts + or other programs. These % password checks also apply + to the -unixpw_nis and -unixpw_cmd options. + + For the % password check, if the env. var. UNIXPW_CMD + is set to a command then it is run as the user (assuming + the password is correct.) The output of the command is + not printed, the program or script must manage that by + some other means. The exit code of x11vnc will depend + on the exit code of the command that is run. + + Use -nounixpw to disable unixpw mode if it was enabled + earlier in the cmd line (e.g. -svc mode) + +-unixpw_nis [list] As -unixpw above, however do not use su(1) but rather + use the traditional getpwnam(3) + crypt(3) method to + verify passwords. All of the above -unixpw options and + constraints apply. + + This mode requires that the encrypted passwords be + readable. Encrypted passwords stored in /etc/shadow + will be inaccessible unless x11vnc is run as root. + + This is called "NIS" mode simply because in most + NIS setups user encrypted passwords are accessible + (e.g. "ypcat passwd") by an ordinary user and so that + user can authenticate ANY user. + + NIS is not required for this mode to work (only that + getpwnam(3) return the encrypted password is required), + but it is unlikely it will work (as an ordinary user) + for most modern environments unless NIS is available. + On the other hand, when x11vnc is run as root it will + be able to to access /etc/shadow even if NIS is not + available (note running as root is often done when + running x11vnc from inetd and xdm/gdm/kdm). + + Looked at another way, if you do not want to use the + su(1) method provided by -unixpw (i.e. su_verify()), you + can run x11vnc as root and use -unixpw_nis. Any users + with passwords in /etc/shadow can then be authenticated. + + In -unixpw_nis mode, under no circumstances is x11vnc's + user password verifying function based on su called + (i.e. the function su_verify() that runs /bin/su + in a pseudoterminal to verify passwords.) However, + if -unixpw_nis is used in conjunction with the -find + and -create -display WAIT:... modes then, if x11vnc is + running as root, /bin/su may be called externally to + run the find or create commands. + +-unixpw_cmd cmd As -unixpw above, however do not use su(1) but rather + run the externally supplied command "cmd". The first + line of its stdin will be the username and the second + line the received password. If the command exits + with status 0 (success) the VNC user will be accepted. + It will be rejected for any other return status. + + Dynamic passwords and non-unix passwords, e.g. LDAP, + can be implemented this way by providing your own custom + helper program. Note that the remote viewer is given 3 + tries to enter the correct password, and so the program + may be called in a row that many (or more) times. + + If a list of allowed users is needed to limit who can + log in, use -unixpw [list] in addition to this option. + + In FINDDISPLAY and FINDCREATEDISPLAY modes the "cmd" + will also be run with the RFB_UNIXPW_CMD_RUN env. var. + non-empty and set to the corresponding display + find/create command. The first two lines of input are + the username and passwd as in the normal case described + above. To support FINDDISPLAY and FINDCREATEDISPLAY, + "cmd" should run the requested command as the user + (and most likely refusing to run it if the password is + not correct.) Here is an example script (note it has + a hardwired bogus password "abc"!) + + #!/bin/sh + # Example x11vnc -unixpw_cmd script. + # Read the first two lines of stdin (user and passwd) + read user + read pass + + debug=0 + if [ $debug = 1 ]; then + echo "user: $user" 1>&2 + echo "pass: $pass" 1>&2 + env | egrep -i 'rfb|vnc' 1>&2 + fi + + # Check if the password is valid. + # (A real example would use ldap lookup, etc!) + if [ "X$pass" != "Xabc" ]; then + exit 1 # incorrect password + fi + + if [ "X$RFB_UNIXPW_CMD_RUN" = "X" ]; then + exit 0 # correct password + else + # Run the requested command (finddisplay) + if [ $debug = 1 ]; then + echo "run: $RFB_UNIXPW_CMD_RUN" 1>&2 + fi + exec /bin/su - "$user" -c "$RFB_UNIXPW_CMD_RUN" + fi + + In -unixpw_cmd mode, under no circumstances is x11vnc's + user password verifying function based on su called + (i.e. the function su_verify() that runs /bin/su in a + pseudoterminal to verify passwords.) It is up to the + supplied unixpw_cmd to do user switching if desired + and if it has the permissions to do so. + +-find Find the user's display using FINDDISPLAY. This + is an alias for "-display WAIT:cmd=FINDDISPLAY". + + Note: if a -display occurs later on the command line + it will override the -find setting. + + For this and the next few options see -display WAIT:... + below for all of the details. + +-finddpy Run the FINDDISPLAY program, print out the found + display (if any) and exit. Output is like: DISPLAY=:0.0 + DISPLAY=:0.0,XPID=12345 or DISPLAY=:0.0,VT=7. XPID is + the process ID of the found X server. VT is the Linux + virtual terminal of the X server. +-listdpy Have the FINDDISPLAY program list all of your displays + (i.e. all the X displays on the local machine that you + have access rights to). + +-findauth [disp] Apply the -find/-finddpy heuristics to try to guess + the XAUTHORITY file for DISPLAY 'disp'. If 'disp' + is not supplied, then the value in the -display on + the cmdline is used; failing that $DISPLAY is used; + and failing that ":0" is used. + + If nothing is printed out, that means no XAUTHORITY was + found for 'disp'; i.e. failure. If "XAUTHORITY=" + is printed out, that means use the default (i.e. do + not set XAUTHORITY). If "XAUTHORITY=/path/to/file" + is printed out, then use that file. + + XDM/GDM/KDM: if you are running x11vnc as root and want + to find the XAUTHORITY before anyone has logged into an + X session yet, use: x11vnc -env FD_XDM=1 -findauth ... + (This will also find the XAUTHORITY if a user is already + logged into the X session.) When running as root, + FD_XDM=1 will be tried if the initial -findauth fails. + +-create First try to find the user's display using FINDDISPLAY, + if that doesn't succeed create an X session via the + FINDCREATEDISPLAY method. This is an alias for + "-display WAIT:cmd=FINDCREATEDISPLAY-Xvfb". + + Note: if a -display occurs later on the command line + it will override the -create setting. + + SSH NOTE: for both -find and -create you can (should!) + add the "-localhost" option to force SSH tunnel access. + +-xdummy As in -create, except Xdummy instead of Xvfb. +-xvnc As in -create, except Xvnc instead of Xvfb. +-xvnc_redirect As in -create, except Xvnc.redirect instead of Xvfb. +-xdummy_xvfb Sets WAIT:cmd=FINDCREATEDISPLAY-Xdummy,Xvfb + +-create_xsrv str Sets WAIT:cmd=FINDCREATEDISPLAY- Can be on cmdline + after anything that sets WAIT:.. and other things + (e.g. -svc, -xdmsvc) to adjust the X server list. + Example: -svc ... -create_xsrv Xdummy,X + +-svc Terminal services mode based on SSL access. Alias for + -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb -unixpw -users + unixpw= -ssl SAVE Also "-service". + + Note: if a -display, -unixpw, -users, or -ssl occurs + later on the command line it will override the -svc + setting. + +-svc_xdummy As -svc except Xdummy instead of Xvfb. +-svc_xvnc As -svc except Xvnc instead of Xvfb. +-svc_xdummy_xvfb As -svc with Xdummy,Xvfb. + +-xdmsvc Display manager Terminal services mode based on SSL. + Alias for -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp + -unixpw -users unixpw= -ssl SAVE Also "-xdm_service". + + Note: if a -display, -unixpw, -users, or -ssl occurs + later on the command line it will override the -xdmsvc + setting. + + To create a session a user will have to first log in + to the -unixpw dialog and then log in again to the + XDM/GDM/KDM prompt. Subsequent re-connections will + only require the -unixpw password. See the discussion + under -display WAIT:... for more details about XDM, + etc configuration. + + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + +-sshxdmsvc Display manager Terminal services mode based on SSH. + Alias for -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp + -localhost. + + The -localhost option constrains connections to come + in via a SSH tunnel (which will require a login). + To create a session a user will also have to log into + the XDM GDM KDM prompt. Subsequent re-connections will + only only require the SSH login. See the discussion + under -display WAIT:... for more details about XDM, + etc configuration. + + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + +-unixpw_system_greeter Present a "Press 'Escape' for System Greeter" option + to the connecting VNC client in combined -unixpw + and xdmcp FINDCREATEDISPLAY modes (e.g. -xdmsvc). + + Normally in a -unixpw mode the VNC client must + supply a valid username and password to gain access. + However, if -unixpw_system_greeter is supplied AND + the FINDCREATEDISPLAY command matches 'xdmcp', then + the user has the option to press Escape and then get a + XDM/GDM/KDM login/greeter panel instead. They will then + supply a username and password directly to the greeter. + + Otherwise, in xdmcp FINDCREATEDISPLAY mode the user + must supply his username and password TWICE. First to + the initial unixpw login dialog, and second to the + subsequent XDM/GDM/KDM greeter. Note that if the user + re-connects and supplies his username and password in + the unixpw dialog the xdmcp greeter is skipped and + he is connected directly to his existing X session. + So the -unixpw_system_greeter option avoids the extra + password at X session creation time. + + Example: x11vnc -xdmsvc -unixpw_system_greeter + See -unixpw and -display WAIT:... for more info. + + The special options after a colon at the end of the + username (e.g. user:solid) described under -display + WAIT: are also applied in this mode if they are typed + in before the user hits Escape. The username is ignored + but the colon options are not. + + The default message is 2 lines in a small font, set + the env. var. X11VNC_SYSTEM_GREETER1=true for a 1 line + message in a larger font. + + If the user pressed Escape the FINDCREATEDISPLAY command + will be run with the env. var. X11VNC_XDM_ONLY=1. + + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + +-redirect port As in FINDCREATEDISPLAY-Xvnc.redirect mode except + redirect immediately (i.e. without X session finding + or creation) to a VNC server listening on port. You + can also supply host:port to redirect to a different + machine. + + If 0 <= port < 200 it is taken as a VNC display (5900 is + added to get the actual port), if port < 0 then -port + is used. + + Probably the only reason to use the -redirect option + is in conjunction with SSL support, e.g. -ssl SAVE. + This provides an easy way to add SSL encryption to a VNC + server that does not support SSL (e.g. Xvnc or vnc.so) + In fact, the protocol does not even need to be VNC, + and so "-rfbport port1 -ssl SAVE -redirect host:port2" + can act as a replacement for stunnel(1). + + This mode only allows one redirected connection. + The -forever option does not apply. Use -inetd or + -loop for persistent service. + +-display_WAIT :... A special usage mode for the normal -display option. + Useful with -unixpw, but can be used independently + of it. If the display string begins with WAIT: then + x11vnc waits until a VNC client connects before opening + the X display (or -rawfb device). + + This could be useful for delaying opening the display + for certain usage modes (say if x11vnc is started at + boot time and no X server is running or users logged + in yet). + + If the string is, e.g. WAIT:0.0 or WAIT:1, i.e. "WAIT" + in front of a normal X display, then that indicated + display is used. + + One can also insert a geometry between colons, e.g. + WAIT:1280x1024:... to set the size of the display the + VNC client first attaches to since some VNC viewers + will not automatically adjust to a new framebuffer size. + + A more interesting case is like this: + + WAIT:cmd=/usr/local/bin/find_display + + in which case the command after "cmd=" is run to + dynamically work out the DISPLAY and optionally the + XAUTHORITY data. The first line of the command output + must be of the form DISPLAY=. On Linux + if the virtual terminal is known append ",VT=n" to + this string and the chvt(1) program will also be run. + Any remaining output is taken as XAUTHORITY data. + It can be either of the form XAUTHORITY= or raw + xauthority data for the display. For example; + + xauth extract - $DISPLAY" + + In the case of -unixpw (and -unixpw_nis only if x11vnc + is running as root), then the cmd= command is run + as the user who just authenticated via the login and + password prompt. + + In the case of -unixpw_cmd, the commands will also be + run as the logged-in user, as long as the user-supplied + helper program supports RFB_UNIXPW_CMD_RUN (see the + -unixpw_cmd option.) + + Also in the case of -unixpw, the user logging in can + place a colon at the end of her username and supply + a few options: scale=, scale_cursor= (or sc=), solid + (or so), id=, clear_mods (or cm), clear_keys (or + ck), clear_all (or ca), repeat, speeds= (or sp=), + readtimeout= (or rd=), viewonly (or vo), nodisplay= + (or nd=), rotate= (or ro=), or noncache (or nc), + all separated by commas if there is more than one. + After the user logs in successfully, these options will + be applied to the VNC screen. For example, + + login: fred:scale=3/4,sc=1,repeat + Password: ... + + login: runge:sp=modem,rd=120,solid + + for convenience m/n implies scale= e.g. fred:3/4 If you + type and enter your password incorrectly, to retrieve + your long "login:" line press the Up arrow once + (before typing anything else). + + In the login panel, press F1 to get a list of the + available options that you can add after the username. + + Another option is "geom=WxH" or "geom=WxHxD" (or + ge=). This only has an effect in FINDCREATEDISPLAY + mode when a virtual X server such as Xvfb is going + to be created. It sets the width and height of + the new display, and optionally the color depth as + well. + + You can also supply "gnome", "kde", "twm", + "fvwm", "mwm", "dtwm", "wmaker", "xfce", + "lxde", "enlightenment", "Xsession", or + "failsafe" (same as "xterm") to have the created + display use that mode for the user session. + + Specify "tag=..." to set the unique FD_TAG desktop + session tag described below. Note: this option will + be ignored if the FD_TAG env. var. is already set or + if the viewer-side supplied value is not completely + composed of alphanumeric or '_' or '-' characters. + + To troubleshoot the FINDCREATEDISPLAY mechanism, + set the following env. var. to an ouput log file, + e.g -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt + + To disable the option setting set the environment + variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc. + To set any other options, the user can use the gui + (x11vnc -gui connect) or the remote control method + (x11vnc -R opt:val) during his VNC session. + + The combination of -display WAIT:cmd=... and -unixpw + allows automatic pairing of an unix authenticated VNC + user with his desktop. This could be very useful on + SunRays and also any system where multiple users share + a given machine. The user does not need to remember + special ports or passwords set up for his desktop + and VNC. + + A nice way to use WAIT:cmd=... is out of inetd(8) + (it automatically forks a new x11vnc for each user). + You can have the x11vnc inetd spawned process run as, + say, root or nobody. When run as root (for either inetd + or display manager), you can also supply the option + "-users unixpw=" to have the x11vnc process switch to + the user as well. Note: there will be a 2nd SSL helper + process that will not switch, but it is only encoding + and decoding the encrypted stream at that point. + + Automatic Finding of User X Sessions: + + As a special case, WAIT:cmd=FINDDISPLAY will run a + script that works on most Unixes to determine a user's + DISPLAY variable and xauthority data (see who(1)). + + The option "-find" is an alias for this mode. + + To have this default script printed to stdout (e.g. for + customization) run with WAIT:cmd=FINDDISPLAY-print To + have the script run to print what display it would find + use "-finddpy" or WAIT:cmd=FINDDISPLAY-run + + The standard script runs xdpyinfo(1) run on potential + displays. If your X server(s) have a login greeter + that exclusively grabs the Xserver, then xdpyinfo + blocks forever and this mode will not work. See + www.karlrunge.com/x11vnc/faq.html#faq-display-manager + for how to disable this for dtgreet on Solaris and + possibly for other greeters. + + In -find/cmd=FINDDISPLAY mode, if you set FD_XDM=1, + e.g. 'x11vnc -env FD_XDM=1 -find ...' and x11vnc is + running as root (e.g. inetd) then it will try to find + the XAUTHORITY file of a running XDM/GDM/KDM login + greeter (i.e. no user has logged into an X session yet.) + + As another special case, WAIT:cmd=HTTPONCE will allow + x11vnc to service one http request and then exit. + This is usually done in -inetd mode to run on, say, + port 5800 and allow the Java vncviewer to be downloaded + by client web browsers. For example: + + 5815 stream tcp nowait root /usr/sbin/tcpd /.../x11vnc +\ + -inetd -q -http_ssl -prog /.../x11vnc \ + -display WAIT:cmd=HTTPONCE + + Where /.../x11vnc is the full path to x11vnc. + It is used in the Apache SSL-portal example (see FAQ). + + In this mode you can set X11VNC_SKIP_DISPLAY to a + comma separated list of displays (e.g. ":0,:1") to + ignore in the finding process. The ":" is optional. + Ranges n-m e.g. 0-20 can also be supplied. This string + can also be set by the connecting user via "nd=" + using "+" instead of "," If "nd=all" or you set + X11VNC_SKIP_DISPLAY=all then all display finding fails + as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.) + + Automatic Creation of User X Sessions: + + An interesting option is WAIT:cmd=FINDCREATEDISPLAY + that is like FINDDISPLAY in that is uses the same method + to find an existing display. However, if it does not + find one it will try to *start* up an X server session + for the user. This is the only time x11vnc tries to + actually start up an X server. + + The option "-create" is an alias for this mode. + + It will start looking for an open display number at :20 + Override via X11VNC_CREATE_STARTING_DISPLAY_NUMBER=n + + By default FINDCREATEDISPLAY will try Xvfb and then + Xdummy: + + The Xdummy wrapper is part of the x11vnc source code + (x11vnc/misc/Xdummy) It should be available in PATH + and have run "Xdummy -install" once to create the + shared library. Xdummy only works on Linux. As of + 12/2009 it no longer needs to be run as root, and the + default is to not run as root. In some circumstances + permissions may require running it as root, in these + cases specify FD_XDUMMY_RUN_AS_ROOT=1, this is the same + as supplying -root to the Xdummy cmdline. + + Xvfb is available on most platforms and does not + require root. + + An advantage of Xdummy over Xvfb is that Xdummy supports + RANDR dynamic screen resizing. + + When x11vnc exits (i.e. user disconnects) the X + server session stays running in the background. + The FINDDISPLAY will find it directly next time. + The user must exit the X session in the usual way for + it to terminate (or kill the X server process if all + else fails). + + So this is a somewhat odd mode for x11vnc in that it + will start up and poll virtual X servers! This can + be used from, say, inetd(8) to provide a means of + definitely getting a desktop (either real or virtual) + on the machine. E.g. a desktop service: + + 5900 stream tcp nowait root /usr/sbin/tcpd /.../x11vnc + -inetd -q -http -ssl SAVE -unixpw -users unixpw=\ + -passwd secret -prog /.../x11vnc \ + -display WAIT:cmd=FINDCREATEDISPLAY + + Where /.../x11vnc is the full path to x11vnc. + + See the -svc/-service option alias above. + + If for some reason you do not want x11vnc to ever + try to find an existing display set the env. var + X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (also -env ...) + This is the same as setting X11VNC_SKIP_DISPLAY=all or + supplying "nd=all" after "username:" + + Use WAIT:cmd=FINDCREATEDISPLAY-print to print out the + script that is used for this. + + You can specify the preferred X server order via e.g., + WAIT:cmd=FINDCREATEDISPLAY-Xdummy,Xvfb,X and/or leave + out ones you do not want. The the case "X" means try + to start up a real, hardware X server using xinit(1) + or startx(1). If there is already an X server running + the X case may only work on Linux (see startx(1)). + + "Xvnc" will start up a VNC X server (real- + or tight-vnc, e.g. use if Xvfb is not available). + "Xsrv" will start up the server program in the + variable "FD_XSRV" if it is non-empty. You can make + this be a wrapper script if you like (it must handle :N, + -geometry, and -depth and other X server options). + + You can set the environment variable FD_GEOM (or + X11VNC_CREATE_GEOM) to WxH or WxHxD to set the width + and height and optionally the color depth of the + created display. You can also set FD_SESS to be the + session (short name of the windowmanager: kde, gnome, + twm, failsafe, etc.). FD_OPTS contains extra options + to pass to the X server. You can also set FD_PROG to + be the full path to the session/windowmanager program. + + More FD tricks: FD_CUPS=port or FD_CUPS=host:port + will set the cups printing environment. Similarly for + FD_ESD=port or FD_ESD=host:port for esddsp sound + redirection. Set FD_EXTRA to a command to be run a + few seconds after the X server starts up. Set FD_TAG + to be a unique name for the session, it is set as an + X property, that makes FINDDISPLAY only find sessions + with that tag value. + + Set FD_XDMCP_IF to the network interface that the + display manager is running on; default is 'localhost' + but you may need to set it to '::1' on some IPv6 only + systems or misconfigured display managers. + + If you want the FINDCREATEDISPLAY session to contact an + XDMCP login manager (xdm/gdm/kdm) on the same machine, + then use "Xvfb.xdmcp" instead of "Xvfb", etc. + The user will have to supply his username and password + one more time (but he gets to select his desktop type + so that can be useful). For this to work, you will + need to enable localhost XDMCP (udp port 177) for the + display manager. This seems to be: + + for gdm in gdm.conf: Enable=true in section [xdmcp] + for kdm in kdmrc: Enable=true in section [Xdmcp] + for xdm in xdm-config: DisplayManager.requestPort: 177 + + See the shorthand options above "-svc", "-xdmsvc" + and "-sshxdmsvc" that specify the above options for + some useful cases. + + If you set the env. var WAITBG=1 x11vnc will go into + the background once listening in wait mode. + + Another special mode is FINDCREATEDISPLAY-Xvnc.redirect, + (or FINDDISPLAY-Xvnc.redirect). In this case it will + start up Xvnc as above if needed, but instead of + polling it in its normal way, it simply does a socket + redirection of the connected VNC viewer to the Xvnc. + + So in Xvnc.redirect x11vnc does no VNC but merely + transfers the data back and forth. This should be + faster then x11vnc's polling method, but not as fast + as connecting directly to the Xvnc with the VNC Viewer. + The idea here is to take advantage of x11vnc's display + finding/creating scheme, SSL, and perhaps a few others. + Most of x11vnc's options do not apply in this mode. + + Xvnc.redirect should also work for the vnc.so X server + module for the h/w display however it will work only + for finding the display and the user must already be + logged into the X console. + +-vencrypt mode The VeNCrypt extension to the VNC protocol allows + encrypted SSL/TLS connections. If the -ssl mode is + enabled, then VeNCrypt is enabled as well BY DEFAULT + (they both use a SSL/TLS tunnel, only the protocol + handshake is a little different.) + + To control when and how VeNCrypt is used, specify the + mode string. If mode is "never", then VeNCrypt is + not used. If mode is "support" (the default) then + VeNCrypt is supported. If mode is "only", then the + similar and older ANONTLS protocol is not simultaneously + supported. x11vnc's normal SSL mode (vncs://) will be + supported under -ssl unless you set mode to "force". + + If mode is prefixed with "nodh:", then Diffie Hellman + anonymous key exchange is disabled. If mode is prefixed + with "nox509:", then X509 key exchange is disabled. + + To disable all Anonymous Diffie-Hellman access + (susceptible to Man-In-The-Middle attack) you will need + to supply "-vencrypt nodh:support -anontls never" + or "-vencrypt nodh:only" + + If mode is prefixed with "newdh:", then new Diffie + Hellman parameters are generated for each connection + (this can be time consuming: 1-60 secs; see -dhparams + below for a faster way) rather than using the + fixed values in the program. Using fixed, publicly + known values is not known to be a security problem. + This setting applies to ANONTLS as well. + + Long example: -vencrypt newdh:nox509:support + + Also, if mode is prefixed with "plain:", then + if -unixpw mode is active the VeNCrypt "*Plain" + username+passwd method is enabled for Unix logins. + Otherwise in -unixpw mode the normal login panel is + provided. + + You *MUST* supply the -ssl option for VeNCrypt to + be active. The -vencrypt option only fine-tunes its + operation. + +-anontls mode The ANONTLS extension to the VNC protocol allows + encrypted SSL/TLS connections. If the -ssl mode is + enabled, then ANONTLS is enabled as well BY DEFAULT + (they both use a SSL/TLS tunnel, only the protocol + handshake is a little different.) + + ANONTLS is an older SSL/TLS mode introduced by vino. + + It is referred to as 'TLS' for its registered VNC + security-type name, but we use the more descriptive + 'ANONTLS' here because it provides only Anonymous + Diffie-Hellman encrypted connections, and hence no + possibility for certificate authentication. + + To control when and how ANONTLS is used, specify the + mode string. If mode is "never", then ANONTLS is not + used. If mode is "support" (the default) then ANONTLS + is supported. If mode is "only", then the similar + VeNCrypt protocol is not simultaneously supported. + x11vnc's normal SSL mode (vncs://) will be supported + under -ssl unless you set mode to "force". + + If mode is prefixed with "newdh:", then new Diffie + Hellman parameters are generated for each connection + (this can be time consuming: 1-60 secs; see -dhparams + below for a faster way) rather than using the + fixed values in the program. Using fixed, publicly + known values is not known to be a security problem. + This setting applies to VeNCrypt as well. See the + description of "plain:" under -vencrypt. + + Long example: -anontls newdh:plain:support + + You *MUST* supply the -ssl option for ANONTLS to + be active. The -anontls option only fine-tunes its + operation. + +-sslonly Same as: "-vencrypt never -anontls never" i.e. it + disables the VeNCrypt and ANONTLS encryption methods + and only allows standard SSL tunneling. You must also + supply the -ssl ... option (see below.) + + +-dhparams file For some operations a set of Diffie Hellman parameters + (prime and generator) is needed. If so, use the + parameters in "file". In particular, the VeNCrypt and + ANONTLS anonymous DH mode need them. By default a + fixed set is used. If you do not want to do that you + can specify "newdh:" to the -vencrypt and -anontls + options to generate a new set each session. If that + is too slow for you, use -dhparams file to a set you + created manually via "openssl dhparam -out file 1024" + +-nossl Disable the -ssl option (see below). Since -ssl is off + by default -nossl would only be used on the commandline + to unset any *earlier* -ssl option (or -svc...) + +-ssl [pem] Use the openssl library (www.openssl.org) to provide a + built-in encrypted SSL/TLS tunnel between VNC viewers + and x11vnc. This requires libssl support to be + compiled into x11vnc at build time. If x11vnc is not + built with libssl support it will exit immediately when + -ssl is prescribed. See the -stunnel option below for + an alternative. + + The VNC Viewer-side needs to support SSL/TLS as well. + See this URL and also the discussion below for + ideas on how to enable SSL support for the viewer: + http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tun + nel-viewers . x11vnc provides an SSL enabled Java + viewer applet in the classes/ssl directory (-http or + -httpdir options.) The SSVNC viewer package supports + SSL tunnels too. + + If the VNC Viewer supports VeNCrypt or ANONTLS (vino's + encryption mode) they are also supported by the -ssl + mode (see the -vencrypt and -anontls options for more + info; use -sslonly to disable both of them.) + + Use "-ssl /path/to/mycert.pem" to specify an SSL + certificate file in PEM format to use to identify and + provide a key for this server. See openssl(1) for more + info about PEMs and the -sslGenCert and "-ssl SAVE" + options below for how to create them. + + The connecting VNC viewer SSL tunnel can (at its option) + authenticate this server if it has the public key part + of the certificate (or a common certificate authority, + CA, is a more sophisticated way to verify this server's + cert, see -sslGenCA below). This authentication is + done to prevent Man-In-The-Middle attacks. Otherwise, + if the VNC viewer simply accepts this server's key + WITHOUT verification, the traffic is protected from + passive sniffing on the network, but *NOT* from + Man-In-The-Middle attacks. There are hacker tools + like dsniff/webmitm and cain that implement SSL + Man-In-The-Middle attacks. + + If [pem] is empty or the string "SAVE" then the + openssl(1) command must be available to generate the + certificate the first time. A self-signed certificate + is generated (see -sslGenCA and -sslGenCert for use + of a Certificate Authority.) It will be saved to the + file ~/.vnc/certs/server.pem. On subsequent calls if + that file already exists it will be used directly. + + Use "SAVE_NOPROMPT" to avoid being prompted to + protect the generated key with a passphrase. However in + -inetd and -bg modes there will be no prompting for a + passphrase in either case. + + If [pem] is "SAVE_PROMPT" the server.pem certificate + will be created based on your answers to its prompts for + all info such as OrganizationalName, CommonName, etc. + + Use "SAVE-" and "SAVE_PROMPT-" + to refer to the file ~/.vnc/certs/server-.pem + instead (it will be generated if it does not already + exist). E.g. "SAVE-charlie" will store to the file + ~/.vnc/certs/server-charlie.pem + + Examples: x11vnc -ssl SAVE -display :0 ... + x11vnc -ssl SAVE-someother -display :0 ... + + If [pem] is "TMP" and the openssl(1) utility + command exists in PATH, then a temporary, self-signed + certificate will be generated for this session. If + openssl(1) cannot be used to generate a temporary + certificate x11vnc exits immediately. The temporary + cert will be discarded when x11vnc exits. + + If successful in using openssl(1) to generate a + temporary certificate in "SAVE" or "TMP" creation + modes, the public part of it will be displayed to stderr + (e.g. one could copy it to the client-side to provide + authentication of the server to VNC viewers.) + + NOTE: In "TMP" mode, unless you safely copy the + public part of the temporary Cert to the viewer for + authenticate *every time* (unlikely...), then only + passive sniffing attacks are prevented and you are + still open to Man-In-The-Middle attacks. This is + why the default "SAVE" mode is preferred (and more + sophisticated CA mode too). Only with saved keys AND + the VNC viewer authenticating them (via the public + certificate), are Man-In-The-Middle attacks prevented. + + If [pem] is "ANON" then the Diffie-Hellman anonymous + key exchange method is used. In this mode there + are *no* SSL certificates and so it is not possible + to authenticate either the VNC server or VNC client. + Thus only passive network sniffing attacks are avoided: + the "ANON" method is susceptible to Man-In-The-Middle + attacks. "ANON" is not recommended; instead use + a SSL PEM you created or the default "SAVE" method. + + See -ssldir below to use a directory besides the + default ~/.vnc/certs + + If your x11vnc binary was not compiled with OpenSSL + library support, use of the -ssl option will induce an + immediate failure and exit. For such binaries, consider + using the -stunnel option for SSL encrypted connections. + + Misc Info: In temporary cert creation mode "TMP", set + the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc print + out the entire certificate, including the PRIVATE KEY + part, to stderr. There are better ways to get/save this + info. See "SAVE" above and "-sslGenCert" below. + +-ssltimeout n Set SSL read timeout to n seconds. In some situations + (i.e. an iconified viewer in Windows) the viewer stops + talking and the connection is dropped after the default + timeout (25s for about the first minute, 43200s later). + Set to zero to poll forever. Set to a negative value + to use the builtin setting. + + Note that this value does NOT apply to the *initial* ssl + init connection. The default timeout for that is 20sec. + Use -env SSL_INIT_TIMEOUT=n to modify it. + +-sslnofail Exit at the first SSL connection failure. Useful when + scripting SSL connections (e.g. x11vnc is started via + ssh) and you do not want x11vnc waiting around for more + connections, tying up ports, etc. + +-ssldir dir Use "dir" as an alternate ssl certificate and key + management toplevel directory. The default is + ~/.vnc/certs + + This directory is used to store server and other + certificates and keys and also other materials. E.g. in + the simplest case, "-ssl SAVE" will store the x11vnc + server cert in dir/server.pem + + Use of alternate directories via -ssldir allows you to + manage multiple VNC Certificate Authority (CA) keys. + Another use is if ~/.vnc/cert is on an NFS share you + might want your certificates and keys to be on a local + filesystem to prevent network snooping (for example + -ssldir /var/lib/x11vnc-certs). + + -ssldir affects nearly all of the other -ssl* options, + e.g. -ssl SAVE, -sslGenCert, etc.. + +-sslverify path For either of the -ssl or -stunnel modes, use "path" + to provide certificates to authenticate incoming VNC + *Client* connections (normally only the server is + authenticated in SSL.) This can be used as a method + to replace standard password authentication of clients. + + If "path" is a directory it contains the client (or CA) + certificates in separate files. If path is a file, + it contains one or more certificates. See special tokens + below. These correspond to the "CApath = dir" and + "CAfile = file" stunnel options. See the stunnel(8) + manpage for details. + + Examples: + x11vnc -ssl -sslverify ~/my.crt + x11vnc -ssl -sslverify ~/my_pem_dir/ + + Note that if path is a directory, it must contain + the certs in separate files named like .0, where + the value of is found by running the command + "openssl x509 -hash -noout -in file.crt". Evidently + one uses .1 if there is a collision... + + The the key-management utility "-sslCertInfo HASHON" + and "-sslCertInfo HASHOFF" will create/delete these + hashes for you automatically (via symlink) in the HASH + subdirs it manages. Then you can point -sslverify to + the HASH subdir. + + Special tokens: in -ssl mode, if "path" is not a file or + a directory, it is taken as a comma separated list of + tokens that are interpreted as follows: + + If a token is "CA" that means load the CA/cacert.pem + file from the ssl directory. If a token is "clients" + then all the files clients/*.crt in the ssl directory + are loaded. Otherwise the file clients/token.crt + is attempted to be loaded. As a kludge, use a token + like ../server-foo to load a server cert if you find + that necessary. + + Use -ssldir to use a directory different from the + ~/.vnc/certs default. + + Note that if the "CA" cert is loaded you do not need + to load any of the certs that have been signed by it. + You will need to load any additional self-signed certs + however. + + Examples: + x11vnc -ssl -sslverify CA + x11vnc -ssl -sslverify self:fred,self:jim + x11vnc -ssl -sslverify CA,clients + + Usually "-sslverify CA" is the most effective. + See the -sslGenCA and -sslGenCert options below for + how to set up and manage the CA framework. + + + + NOTE: the following utilities, -sslGenCA, -sslGenCert, + -sslEncKey, -sslCertInfo, and -sslCRL are provided for + completeness, but for casual usage they are overkill. + + They provide VNC Certificate Authority (CA) key creation + and server / client key generation and signing. So they + provide a basic Public Key management framework for + VNC-ing with x11vnc. (note that they require openssl(1) + be installed on the system) + + However, the simplest usage mode, "-ssl TMP" (where + x11vnc automatically generates its own, self-signed, + temporary key and the VNC viewers always accept it, + e.g. accepting via a dialog box) is probably safe enough + for most scenarios. CA management is not needed. + + To protect against Man-In-The-Middle attacks the "TMP" + mode can be improved by using "-ssl SAVE" (same as + "-ssl", i.e. the default) to have x11vnc create a + longer term self-signed certificate, and then (safely) + copy the corresponding public key cert to the desired + client machines (care must be taken the private key part + is not stolen; you will be prompted for a passphrase). + + So keep in mind no CA key creation or management + (-sslGenCA and -sslGenCert) is needed for either of + the above two common usage modes. + + One might want to use -sslGenCA and -sslGenCert + if you had a large number of VNC client and server + workstations. That way the administrator could generate + a single CA key with -sslGenCA and distribute its + certificate part to all of the workstations. + + Next, he could create signed VNC server keys + (-sslGenCert server ...) for each workstation or user + that then x11vnc would use to authenticate itself to + any VNC client that has the CA cert. + + Optionally, the admin could also make it so the + VNC clients themselves are authenticated to x11vnc + (-sslGenCert client ...) For this -sslverify would be + pointed to the CA cert (and/or self-signed certs). + + x11vnc will be able to use all of these cert and + key files. On the VNC client side, they will need to + be "imported" somehow. Web browsers have "Manage + Certificates" actions as does the Java applet plugin + Control Panel. stunnel can also use these files (see + the ss_vncviewer example script in the FAQ and SSVNC.) + +-sslCRL path Set the Certificate Revocation Lists (CRL) to "path". + This setting applies for both -ssl and -stunnel modes. + + If path is a file, the file contains one or more CRLs + in PEM format. If path is a directory, it contains + hash named files of CRLs in the usual OpenSSL manner. + See the OpenSSL and stunnel(8) documentation for + more info. + + This option only applies if -sslverify has been + supplied: it checks for revocation along the + certificate chain used to verify the VNC client. + The -sslCRL setting will be ignored when -sslverify is + not specified. + + Note that if a CRL's expiration date has passed, all + SSL connections will fail regardless of if they are + related to the subject of the CRL or not. + + Only rarely will one's x11vnc -ssl infrastructure be so + large that this option would be useful (since normally + maintaining the contents of the -sslverify file or + directory should be enough.) However, when using + x11vnc with a Certificate Authority (see -sslGenCA) + to authenticate Clients via SSL/TLS, the -sslCRL option + can be useful to revoke users' certs whose private SSL + keys were lost or stolen (e.g. laptop.) This way a new + CA cert+key does not need to be created and new signed + client keys generated and distributed to all users. + + To create a CRL file with revoked certificates the + commands 'openssl ca -revoke ...' and 'openssl ca + -gencrl ...' are useful. (Run them in ~/.vnc/certs) + +-sslGenCA [dir] Generate your own Certificate Authority private key, + certificate, and other files in directory [dir]. + + If [dir] is not supplied, a -ssldir setting is used, + or otherwise ~/.vnc/certs is used. + + This command also creates directories where server and + client certs and keys will be stored. The openssl(1) + program must be installed on the system and available + in PATH. + + After the CA files and directories are created the + command exits; the VNC server is not run. + + You will be prompted for information to put into the CA + certificate. The info does not have to be accurate just + as long as clients accept the cert for VNC connections. + You will also need to supply a passphrase of at least + 4 characters for the CA private key. + + Once you have generated the CA you can distribute + its certificate part, [dir]/CA/cacert.pem, to other + workstations where VNC viewers will be run. One will + need to "import" this certificate in the applications, + e.g. Web browser, Java applet plugin, stunnel, etc. + Next, you can create and sign keys using the CA with + the -sslGenCert option below. + + Examples: + x11vnc -sslGenCA + x11vnc -sslGenCA ~/myCAdir + x11vnc -ssldir ~/myCAdir -sslGenCA + + (the last two lines are equivalent) + +-sslGenCert type name Generate a VNC server or client certificate and private + key pair signed by the CA created previously with + -sslGenCA. The openssl(1) program must be installed + on the system and available in PATH. + + After the Certificate is generated the command exits; + the VNC server is not run. + + The type of key to be generated is the string "type". + It is either "server" (i.e. for use by x11vnc) or + "client" (for a VNC viewer). Note that typically + only "server" is used: the VNC clients authenticate + themselves by a non-public-key method (e.g. VNC or + unix password). "type" is required. + + An arbitrary default name you want to associate with + the key is supplied by the "name" string. You can + change it at the various prompts when creating the key. + "name" is optional. + + If name is left blank for clients keys then "nobody" + is used. If left blank for server keys, then the + primary server key: "server.pem" is created (this + is the saved one referenced by "-ssl SAVE" when the + server is started) + + If "name" begins with the string "self:" then + a self-signed certificate is created instead of one + signed by your CA key. + + If "name" begins with the string "req:" then only a + key (.key) and a certificate signing *request* (.req) + are generated. You can then send the .req file to + an external CA (even a professional one, e.g. Thawte) + and then combine the .key and the received cert into + the .pem file with the same basename. + + The distinction between "server" and "client" is + simply the choice of output filenames and sub-directory. + This makes it so the -ssl SAVE-name option can easily + pick up the x11vnc PEM file this option generates. + And similarly makes it easy for the -sslverify option + to pick up your client certs. + + There is nothing special about the filename or directory + location of either the "server" and "client" certs. + You can rename the files or move them to wherever + you like. + + Precede this option with -ssldir [dir] to use a + directory other than the default ~/.vnc/certs You will + need to run -sslGenCA on that directory first before + doing any -sslGenCert key creation. + + Note you cannot recreate a cert with exactly the same + distiguished name (DN) as an existing one. To do so, + you will need to edit the [dir]/CA/index.txt file to + delete the line. + + Similar to -sslGenCA, you will be prompted to fill + in some information that will be recorded in the + certificate when it is created. + + Tip: if you know the fully-qualified hostname other + people will be connecting to, you can use that as the + CommonName "CN" to avoid some applications (e.g. web + browsers and java plugin) complaining that it does not + match the hostname. + + You will also need to supply the CA private key + passphrase to unlock the private key created from + -sslGenCA. This private key is used to sign the server + or client certificate. + + The "server" certs can be used by x11vnc directly by + pointing to them via the -ssl [pem] option. The default + file will be ~/.vnc/certs/server.pem. This one would + be used by simply typing -ssl SAVE. The pem file + contains both the certificate and the private key. + server.crt file contains the cert only. + + The "client" cert + private key file will need + to be copied and imported into the VNC viewer + side applications (Web browser, Java plugin, + stunnel, etc.) Once that is done you can delete the + "client" private key file on this machine since + it is only needed on the VNC viewer side. The, + e.g. ~/.vnc/certs/clients/.pem contains both + the cert and private key. The .crt contains the + certificate only. + + NOTE: It is very important to know one should + generate new keys with a passphrase. Otherwise if an + untrusted user steals the key file he could use it to + masquerade as the x11vnc server (or VNC viewer client). + You will be prompted whether to encrypt the key with + a passphrase or not. It is recommended that you do. + One inconvenience to a passphrase is that it must + be typed in EVERY time x11vnc or the client app is + started up. + + Examples: + + x11vnc -sslGenCert server + x11vnc -ssl SAVE -display :0 ... + + and then on viewer using ss_vncviewer stunnel wrapper + (see the FAQ): + ss_vncviewer -verify ./cacert.crt hostname:0 + + (this assumes the cacert.crt cert from -sslGenCA + was safely copied to the VNC viewer machine where + ss_vncviewer is run) + + Example using a name: + + x11vnc -sslGenCert server charlie + x11vnc -ssl SAVE-charlie -display :0 ... + + Example for a client certificate (rarely used): + + x11vnc -sslGenCert client roger + scp ~/.vnc/certs/clients/roger.pem somehost:. + rm ~/.vnc/certs/clients/roger.pem + + x11vnc is then started with the the option -sslverify + ~/.vnc/certs/clients/roger.crt (or simply -sslverify + roger), and on the viewer user on somehost could do + for example: + + ss_vncviewer -mycert ./roger.pem hostname:0 + + If you set the env. var REQ_ARGS='...' it will be + passed to openssl req(1). A common use would be + REQ_ARGS='-days 1095' to bump up the expiration date + (3 years in this case). + +-sslEncKey pem Utility to encrypt an existing PEM file with a + passphrase you supply when prompted. For that key to be + used (e.g. by x11vnc) the passphrase must be supplied + each time. + + The "SAVE" notation described under -ssl applies as + well. (precede this option with -ssldir [dir] to refer + a directory besides the default ~/.vnc/certs) + + The openssl(1) program must be installed on the system + and available in PATH. After the Key file is encrypted + the command exits; the VNC server is not run. + + Examples: + x11vnc -sslEncKey /path/to/foo.pem + x11vnc -sslEncKey SAVE + x11vnc -sslEncKey SAVE-charlie + +-sslCertInfo pem Prints out information about an existing PEM file. + In addition the public certificate is also printed. + The openssl(1) program must be in PATH. Basically the + command "openssl x509 -text" is run on the pem. + + The "SAVE" notation described under -ssl applies + as well. + + Using "LIST" will give a list of all certs being + managed (in the ~/.vnc/certs dir, use -ssldir to refer + to another dir). "ALL" will print out the info for + every managed key (this can be very long). Giving a + client or server cert shortname will also try a lookup + (e.g. -sslCertInfo charlie). Use "LISTL" or "LL" + for a long (ls -l style) listing. + + Using "HASHON" will create subdirs [dir]/HASH and + [dir]/HASH with OpenSSL hash filenames (e.g. 0d5fbbf1.0) + symlinks pointing up to the corresponding *.crt file. + ([dir] is ~/.vnc/certs or one given by -ssldir.) + This is a useful way for other OpenSSL applications + (e.g. stunnel) to access all of the certs without + having to concatenate them. x11vnc will not use them + unless you specifically reference them. "HASHOFF" + removes these HASH subdirs. + + The LIST, LISTL, LL, ALL, HASHON, HASHOFF words can + also be lowercase, e.g. "list". + +-sslDelCert pem Prompts you to delete all .crt .pem .key .req files + associated with [pem]. "SAVE" and lookups as in + -sslCertInfo apply as well. + +-sslScripts Prints out both the 'genCA' and 'genCert' x11vnc + openssl wrapper scripts for you to examine, modify, etc. + The scripts are printed to stdout and then the program + exits. + + +-stunnel [pem] Use the stunnel(8) (stunnel.mirt.net) to provide an + encrypted SSL tunnel between viewers and x11vnc. + + This external tunnel method was implemented prior to the + integrated -ssl encryption described above. It still + works well and avoids the requirement of linking with + the OpenSSL libraries. This mode requires stunnel + to be installed on the system and available via PATH + (n.b. stunnel is often installed in sbin directories). + Version 4.x of stunnel is assumed (but see -stunnel3 + below.) + + [pem] is optional, use "-stunnel /path/to/stunnel.pem" + to specify a PEM certificate file to pass to stunnel. + See the -ssl option for more info on certificate files. + + Whether or not your stunnel has its own certificate + depends on your stunnel configuration; stunnel often + generates one at install time. See your stunnel + documentation for details. In any event, if you want to + use this certificate you must supply the full path to it + as [pem]. Note: the file may only be readable by root. + + [pem] may also be the special strings "TMP", "SAVE", + and "SAVE..." as described in the -ssl option. + If [pem] is not supplied, "SAVE" is assumed. + + Note that the VeNCrypt, ANONTLS, and "ANON" modes + are not supported in -stunnel mode. + + stunnel is started up as a child process of x11vnc and + any SSL connections stunnel receives are decrypted and + sent to x11vnc over a local socket. The strings + "The SSL VNC desktop is ..." and "SSLPORT=..." + are printed out at startup to indicate this. + + The -localhost option is enforced by default to avoid + people routing around the SSL channel. Use -env + STUNNEL_DISABLE_LOCALHOST=1 to disable this security + requirement. + + Set -env STUNNEL_DEBUG=1 for more debugging printout. + + Set -env STUNNEL_PROG=xxx to the full path of stunnel + program you want to be used (e.g. /usr/bin/stunnel4). + + Set -env STUNNEL_LISTEN=xxx to the address of the + network interface to listen on (the default is to listen + on all interfaces), e.g. STUNNEL_LISTEN=192.168.1.100. + + A simple way to add IPv6 support is STUNNEL_LISTEN=:: + + Your VNC viewer will also need to be able to connect + via SSL. Unfortunately not too many do this. See the + information about SSL viewers under the -ssl option. + The x11vnc project's SSVNC is an option. + + Also, in the x11vnc distribution, patched TightVNC + and UltraVNC Java applet jar files are provided in + the classes/ssl directory that do SSL connections. + Enable serving them with the -http, -http_ssl, or + -httpdir (see the option descriptions for more info.) + + Note that for the Java viewer applet usage the + "?PORT=xxxx" in the various URLs printed at startup + will need to be supplied to the web browser to connect + properly. + + Currently the automatic "single port" HTTPS mode of + -ssl is not fully supported in -stunnel mode. However, + it can be emulated via: + + % x11vnc -stunnel -http_ssl -http_oneport ... + + In general, it is also not too difficult to set up + an stunnel or other SSL tunnel on the viewer side. + A simple example on Unix using stunnel 3.x is: + + % stunnel -c -d localhost:5901 -r remotehost:5900 + % vncviewer localhost:1 + + For Windows, stunnel has been ported to it and there + are probably other such tools available. See the FAQ + and SSVNC for more examples. + +-stunnel3 [pem] Use version 3.x stunnel command line syntax instead of + version 4.x. The -http/-httpdir Java applet serving + is currently not available in this mode. + +-enc cipher:keyfile Use symmetric encryption with cipher "cipher" + and secret key data in "keyfile". If keyfile is + pw= then "string" is used as the key data. + + NOTE: It is recommended that you use SSL via the -ssl + option instead of this option because SSL is well + understood and takes great care to establish unique + session keys and is more compatible with other software. + Use this option if you do not want to deal with SSL + certificates for authentication and do not want to + use SSH but want some encryption for your VNC session. + Or if you must interface with a symmetric key tunnel + that you do not have control over. + + Note that this mode will NOT work with the UltraVNC DSM + plugins because they alter the RFB protocol in addition + to tunnelling with the symmetric cipher (an unfortunate + choice of implementation...) + + cipher can be one of: arc4, aesv2, aes-cfb, blowfish, + aes256, or 3des. See the OpenSSL documentation for + more info. The keysize is 128 bits (except for aes256). + Here is one way to make a keyfile with that many bits: + + dd if=/dev/random of=./my.key bs=16 count=1 + + you will need to securely share this key with the other + side of the VNC connection (See SSVNC for examples). + + Example: -enc blowfish:./my.key + Example: -enc blowfish:pw=swordfish + + By default 16 bytes of random salt followed by 16 bytes + of random initialization vector are sent at the very + beginning of the stream. The other side must read these + and initialize their cipher with them. These values + make the session key unique (without them the security + is minimal). Similarly, the other side must send us + its random salt and IV with those same lengths. + + The salt and key data are combined to create a session + key using an md5 hash as described in EVP_BytesToKey(3). + + The exact call is: EVP_BytesToKey(Cipher, EVP_md5(), + salt, keydata, len, 1, keystr, NULL); where salt is + the random data as described above, and keydata is the + shared secret key data. keystr is the resulting session + key. The cipher is then seeded with keystr and uses + the random initialization vector as its first block. + + To modify the amount of random salt and initialization + vector use cipher@n,m where n is the salt length and + m the initialization vector length. E.g. + + -enc aes-cfb@8,16:./my.key + + It is not a good idea to set either one to zero, + although you may be forced to if the other side of the + tunnel is not under your control. + + To skip the salt and EVP_BytesToKey MD5 entirely (no + hashing is done: the keydata is directly inserted into + the cipher) specify "-1" for the salt, e.g. + + -enc blowfish@-1,16:./my.key + + The message digest can also be changed to something + besides the default MD5. Use cipher@md+n,m where "md" + can be one of sha, sha1, md5, or ripe. For example: + + -enc arc4@sha+8,16:./my.key + + The SSVNC vnc viewer project supplies a symmetric + encryption tool named "ultravnc_dsm_helper" that can + be used on the viewer side. For example: + + ssvncviewer exec='ultravnc_dsm_helper arc4 my.key 0 h:p' + + where h:p is the hostname and port of the x11vnc server. + ultravnc_dsm_helper may also be used standalone to + provide a symmetric encryption tunnel for any viewer + or server (VNC or otherwise.) The cipher (1st arg) + is basically the same syntax as we use above. + + Also see the 'Non-Ultra DSM' SSVNC option for the + 'UltraVNC DSM Encryption Plugin' advanced option. + + For both ways of using the viewer, you can specify the + salt,ivec sizes (in GUI or, e.g. arc4@8,16). + +-https [port] Use a special, separate HTTPS port (-ssl and + -stunnel modes only) for HTTPS Java viewer applet + downloading. I.e. not 5900 and not 5800 (the defaults.) + + BACKGROUND: In -ssl mode, it turns out you can use the + single VNC port (e.g. 5900) for both VNC and HTTPS + connections. (HTTPS is used to retrieve a SSL-aware + VncViewer.jar applet that is provided with x11vnc). + Since both use SSL the implementation was extended to + detect if HTTP traffic (i.e. GET) is taking place and + handle it accordingly. The URL would be, e.g.: + + https://mymachine.org:5900/ + + This is convenient for firewalls, etc, because only one + port needs to be allowed in. However, this heuristic + adds a few seconds delay to each connection and can be + unreliable (especially if the user takes much time to + ponder the Certificate dialogs in his browser, Java VM, + or VNC Viewer applet. That's right 3 separate "Are + you sure you want to connect?" dialogs!) + + END OF BACKGROUND. + + USAGE: So use the -https option to provide a separate, + more reliable HTTPS port that x11vnc will listen on. If + [port] is not provided (or is 0), one is autoselected. + The URL to use is printed out at startup. + + The SSL Java applet directory is specified via the + -httpdir option. If not supplied, -https will try + to guess the directory as though the -http option + was supplied. + +-httpsredir [port] In -ssl mode with the Java applet retrieved via HTTPS, + when the HTML file containing applet parameters + ('index.vnc' or 'proxy.vnc') is sent do NOT set the + applet PORT parameter to the actual VNC port but set it + to "port" instead. If "port" is not supplied, then + the port number is guessed from the Host: HTTP header. + + This is useful when an incoming TCP connection + redirection is performed by a router/gateway/firewall + from one port to an internal machine where x11vnc is + listening on a different port. The Java applet needs to + connect to the firewall/router port, not the VNC port + on the internal workstation. For example, one could + redir from mygateway.com:443 to workstation:5900. + + This spares the user from having to type in + https://mygateway.com/?PORT=443 into their web + browser. Note that port 443 is the default https port; + other ports must be explicitly indicated, for example: + https://mygateway.com:8000/?PORT=8000. To avoid having + to include the PORT= in the browser URL, simply supply + "-httpsredir" to x11vnc. + + This option does not work in -stunnel mode. + + More tricks: set the env var X11VNC_EXTRA_HTTPS_PARAMS + to be extra URL parameters to use. This way you do + not need to specify extra PARAMS in the index.vnc file. + E.g. x11vnc -env X11VNC_EXTRA_HTTPS_PARAMS='?GET=1' ... + + If you do not want to expose the non-SSL HTTP port to + the network (i.e. you just want the single VNC/HTTPS + port, e.g. 5900, open for connections) then specify the + option -env X11VNC_HTTP_LISTEN_LOCALHOST=1 This way + the connection to the LibVNCServer httpd server will + only be available on localhost (note that in -ssl mode, + HTTPS requests are redirected from SSL to the non-SSL + LibVNCServer HTTP server.) + +-http_oneport For UN-encrypted connections mode (i.e. no -ssl, + -stunnel, or -enc options), allow the Java VNC Viewer + applet to be downloaded thru the VNC port via HTTP. + + That is to say, you can use a single port for Java + applet viewer connections by using a URL in your web + browser like this, for example: + + http://hostname:5900 + + The regular, two-port mode, URL http://hostname:5800 + will continue to work as well. + + As mentioned above, this mode will NOT work with + the -ssl, -stunnel, or -enc encryption options. + Note that is it equivalent to '-enc none' (i.e. it + uses the same detection mechanism as for HTTPS, but + with no encryption.) + + HTTPS single-port is on by default in -ssl encrypted + mode (and -enc too), so you only need -http_oneport + when doing non-SSL encrypted connections. + + This mode could also be useful for SSH tunnels since + it means only one port needs to be redirected. + + The -httpsredir option may also be useful for this + mode when using an SSH tunnel as well as for router + port redirections. + + Note that the -env X11VNC_HTTP_LISTEN_LOCALHOST=1 + option described above under -httpsredir applies for + the LibVNCServer httpd server in all cases (ssl or not.) + +-ssh user@host:disp Create a remote listening port on machine "host" + via a SSH tunnel using the -R rport:localhost:lport + method. lport will be the local x11vnc listening port, + so a connection to rport (5900+disp) on "host" + will reach x11vnc. E.g. fred@snoopy.com:0 + + This could be useful if a firewall/router prevents + incoming connections to the x11vnc machine, but + the ssh machine "host" can be reached by the VNC + viewer. "user@" is not needed unless the remote unix + username differs from the current one. + + By default the remote sshd is usually configured to + listen only on localhost for rport, so the viewer may + need to ssh -L redir to "host" as well (See SSVNC to + automate this). The sshd setting GatewayPorts enables + listening on all interfaces for rport; viewers can + reach it more easily. + + "disp" is the VNC display for the remote SSH side, + e.g. 0 corresponds to port 5900, etc. If disp is + greater than 200 the value is used as the port. Use a + negative value to force a low port, e.g. host:-80 will + use port 80. + + If ssh-agent is not active, then the ssh password needs + to be entered in the terminal where x11vnc is running. + + By default the remote ssh will issue a 'sleep 300' to + wait for the incoming connection for 5 mins. To modify + this use user@host:disp+secs. + + If the remote SSH server is on a non-standard port + (i.e. not 22) use user@host:port:disp+secs. + + Note that the ssh process MAY NOT be killed when + x11vnc exits. It tries by looking at ps(1) output. + +-usepw If no other password method was supplied on the command + line, first look for ~/.vnc/passwd and if found use it + with -rfbauth; next, look for ~/.vnc/passwdfile and + use it with -passwdfile; otherwise, prompt the user + for a password to create ~/.vnc/passwd and use it with + the -rfbauth option. If none of these succeed x11vnc + exits immediately. + +-storepasswd pass file Store password "pass" as the VNC password in the + file "file". Once the password is stored the + program exits. Use the password via "-rfbauth file" + + If called with no arguments, "x11vnc -storepasswd", + the user is prompted for a password and it is stored + in the file ~/.vnc/passwd. Called with one argument, + that will be the file to store the prompted password in. + +-nopw Disable the big warning message when you use x11vnc + without some sort of password. + +-accept string Run a command (possibly to prompt the user at the + X11 display) to decide whether an incoming client + should be allowed to connect or not. "string" is + an external command run via system(3) or some special + cases described below. Be sure to quote "string" + if it contains spaces, shell characters, etc. If the + external command returns 0 the client is accepted, + otherwise the client is rejected. See below for an + extension to accept a client view-only. + + If x11vnc is running as root (say from inetd(8) or from + display managers xdm(1), gdm(1), etc), think about the + security implications carefully before supplying this + option (likewise for the -gone option). + + Environment: The RFB_CLIENT_IP environment variable will + be set to the incoming client IP number and the port + in RFB_CLIENT_PORT (or -1 if unavailable). Similarly, + RFB_SERVER_IP and RFB_SERVER_PORT (the x11vnc side + of the connection), are set to allow identification + of the tcp virtual circuit. The x11vnc process + id will be in RFB_X11VNC_PID, a client id number in + RFB_CLIENT_ID, and the number of other connected clients + in RFB_CLIENT_COUNT. RFB_MODE will be "accept". + RFB_STATE will be PROTOCOL_VERSION, SECURITY_TYPE, + AUTHENTICATION, INITIALISATION, NORMAL, or UNKNOWN + indicating up to which state the client has achieved. + RFB_LOGIN_VIEWONLY will be 0, 1, or -1 (unknown). + RFB_USERNAME, RFB_LOGIN_TIME, and RFB_CURRENT_TIME may + also be set. + + If "string" is "popup" then a builtin popup window + is used. The popup will time out after 120 seconds, + use "popup:N" to modify the timeout to N seconds + (use 0 for no timeout). + + In the case of "popup" and when the -unixpw option + is specified, then a *second* window will be popped + up after the user successfully logs in via his UNIX + password. This time the user will be identified as + UNIX:username@hostname, the "UNIX:" prefix indicates + which user the viewer logged as via -unixpw. The first + popup is only for whether to allow him to even *try* + to login via unix password. + + If "string" is "xmessage" then an xmessage(1) + invocation is used for the command. xmessage must be + installed on the machine for this to work. + + Both "popup" and "xmessage" will present an option + for accepting the client "View-Only" (the client + can only watch). This option will not be presented if + -viewonly has been specified, in which case the entire + display is view only. + + If the user supplied command is prefixed with something + like "yes:0,no:*,view:3 mycommand ..." then this + associates the numerical command return code with + the actions: accept, reject, and accept-view-only, + respectively. Use "*" instead of a number to indicate + the default action (in case the command returns an + unexpected value). E.g. "no:*" is a good choice. + + Note that x11vnc blocks while the external command + or popup is running (other clients may see no updates + during this period). So a person sitting a the physical + display is needed to respond to an popup prompt. (use + a 2nd x11vnc if you lock yourself out). + + More -accept tricks: use "popupmouse" to only allow + mouse clicks in the builtin popup to be recognized. + Similarly use "popupkey" to only recognize + keystroke responses. These are to help avoid the + user accidentally accepting a client by typing or + clicking. All 3 of the popup keywords can be followed + by +N+M to supply a position for the popup window. + The default is to center the popup window. +-afteraccept string As -accept, except to run a user supplied command after + a client has been accepted and authenticated. RFB_MODE + will be set to "afteraccept" and the other RFB_* + variables are as in -accept. Unlike -accept, the + command return code is not interpreted by x11vnc. + Example: -afteraccept 'killall xlock &' +-gone string As -accept, except to run a user supplied command when + a client goes away (disconnects). RFB_MODE will be + set to "gone" and the other RFB_* variables are as + in -accept. The "popup" actions apply as well. + Unlike -accept, the command return code is not + interpreted by x11vnc. Example: -gone 'xlock &' + +-users list If x11vnc is started as root (say from inetd(8) or from + display managers xdm(1), gdm(1), etc), then as soon + as possible after connections to the X display are + established try to switch to one of the users in the + comma separated "list". If x11vnc is not running as + root this option is ignored. + + Why use this option? In general it is not needed since + x11vnc is already connected to the X display and can + perform its primary functions. The option was added + to make some of the *external* utility commands x11vnc + occasionally runs work properly. In particular under + GNOME and KDE to implement the "-solid color" feature + external commands (gconftool-2 and dcop) unfortunately + must be run as the user owning the desktop session. + Since this option switches userid it also affects the + userid used to run the processes for the -accept and + -gone options. It also affects the ability to read + files for options such as -connect, -allow, and -remap + and also the ultra and tight filetransfer feature if + enabled. Note that the -connect file is also sometimes + written to. + + So be careful with this option since in some situations + its use can decrease security. + + In general the switch to a user will only take place + if the display can still be successfully opened as that + user (this is primarily to try to guess the actual owner + of the session). Example: "-users fred,wilma,betty". + Note that a malicious local user "barney" by + quickly using "xhost +" when logging in may possibly + get the x11vnc process to switch to user "fred". + What happens next? + + Under display managers it may be a long time before + the switch succeeds (i.e. a user logs in). To instead + make it switch immediately regardless if the display + can be reopened prefix the username with the "+" + character. E.g. "-users +bob" or "-users +nobody". + + The latter (i.e. switching immediately to user + "nobody") is the only obvious use of the -users option + that increases security. + + Use the following notation to associate a group with + a user: user1.group1,user2.group2,... Note that + initgroups(2) will still be called first to try to + switch to ALL of a user's groups (primary and additional + groups). Only if that fails or it is not available + then the single group specified as above (or the user's + primary group if not specified) is switched to with + setgid(2). Use -env X11VNC_SINGLE_GROUP=1 to prevent + trying initgroups(2) and only switch to the single + group. This sort of setting is only really needed to + make the ultra or tight filetransfer permissions work + properly. This format applies to any comma separated lis +t + of users, even the special "=" modes described below. + + In -unixpw mode, if "-users unixpw=" is supplied + then after a user authenticates himself via the + -unixpw mechanism, x11vnc will try to switch to that + user as though "-users +username" had been supplied. + If you want to limit which users this will be done for, + provide them as a comma separated list after "unixpw=" + Groups can also be specified as described above. + + Similarly, in -ssl mode, if "-users sslpeer=" is + supplied then after an SSL client authenticates with his + cert (the -sslverify option is required for this) x11vnc + will extract a UNIX username from the "emailAddress" + field (username@hostname.com) of the "Subject" of the + x509 SSL cert and then try to switch to that user as + though "-users +username" had been supplied. If you + want to limit which users this will be done for, provide + them as a comma separated list after "sslpeer=". + Set the env. var X11VNC_SSLPEER_CN to use the Common + Name (normally a hostname) instead of the Email field. + + NOTE: for sslpeer= mode the x11vnc administrator must + take care that any client certs he adds to -sslverify + have the intended UNIX username in the "emailAddress" + field of the cert. Otherwise a user may be able to + log in as another. This command can be of use in + checking: "openssl x509 -text -in file.crt", see the + "Subject:" line. Also, along with the normal RFB_* + env. vars. (see -accept) passed to external cmd= + commands, RFB_SSL_CLIENT_CERT will be set to the + client's x509 certificate string. + + The sslpeer= mode can aid finding X sessions via the + FINDDISPLAY and FINDCREATEDISPLAY mechanisms. + + To immediately switch to a user *before* connections + to the X display are made or any files opened use the + "=" character: "-users =bob". That user needs to + be able to open the X display and any files of course. + + The special user "guess=" means to examine the utmpx + database (see who(1)) looking for a user attached to + the display number (from DISPLAY or -display option) + and try him/her. To limit the list of guesses, use: + "-users guess=bob,betty". + + Even more sinister is the special user "lurk=" + that means to try to guess the DISPLAY from the utmpx + login database as well. So it "lurks" waiting for + anyone to log into an X session and then connects to it. + Specify a list of users after the = to limit which users + will be tried. To enable a different searching mode, if + the first user in the list is something like ":0" or + ":0-2" that indicates a range of DISPLAY numbers that + will be tried (regardless of whether they are in the + utmpx database) for all users that are logged in. Also + see the "-display WAIT:..." functionality. Examples: + "-users lurk=" and also "-users lurk=:0-1,bob,mary" + + Be especially careful using the "guess=" and "lurk=" + modes. They are not recommended for use on machines + with untrustworthy local users. + +-noshm Do not use the MIT-SHM extension for the polling. + Remote displays can be polled this way: be careful this + can use large amounts of network bandwidth. This is + also of use if the local machine has a limited number + of shm segments and -onetile is not sufficient. +-flipbyteorder Sometimes needed if remotely polled host has different + endianness. Ignored unless -noshm is set. +-onetile Do not use the new copy_tiles() framebuffer mechanism, + just use 1 shm tile for polling. Limits shm segments + used to 3. + +-solid [color] To improve performance, when VNC clients are connected + try to change the desktop background to a solid color. + The [color] is optional: the default color is "cyan4". + For a different one specify the X color (rgb.txt name, + e.g. "darkblue" or numerical "#RRGGBB"). + + Currently this option only works on GNOME, KDE, CDE, + XFCE, and classic X (i.e. with the background image + on the root window). The "gconftool-2", "dcop" + and "xfconf-query" external commands are run for + GNOME, KDE, and XFCE respectively. This also works + on native MacOSX. (There is no color selection for + MacOSX or XFCE.) Other desktops won't work, (send + us the corresponding commands if you find them). + If x11vnc is running as root (inetd(8) or gdm(1)), + the -users option may be needed for GNOME, KDE, XFCE. + If x11vnc guesses your desktop incorrectly, you can + force it by prefixing color with "gnome:", "kde:", + "cde:", "xfce:", or "root:". + + Update: -solid no longer works on KDE4. + + This mode works in a limited way on the Mac OS X Console + with one color ('kelp') using the screensaver writing + to the background. Look in "~/Library/Screen Savers" + for VncSolidColor.png to change the color. + +-blackout string Black out rectangles on the screen. "string" is a + comma separated list of WxH+X+Y type geometries for + each rectangle. If one of the items on the list is the + string "noptr" the mouse pointer will not be allowed + to go into a blacked out region. +-xinerama If your screen is composed of multiple monitors +-noxinerama glued together via XINERAMA, and that screen is + not a rectangle this option will try to guess the + areas to black out (if your system has libXinerama). + default: -xinerama + + In general, we have noticed on XINERAMA displays you may + need to use the "-xwarppointer" option if the mouse + pointer misbehaves and it is enabled by default. Use + "-noxwarppointer" if you do not want this. + +-xtrap Use the DEC-XTRAP extension for keystroke and mouse + input insertion. For use on legacy systems, e.g. X11R5, + running an incomplete or missing XTEST extension. + By default DEC-XTRAP will be used if XTEST server grab + control is missing, use -xtrap to do the keystroke and + mouse insertion via DEC-XTRAP as well. + +-xrandr [mode] If the display supports the XRANDR (X Resize, Rotate + and Reflection) extension, and you expect XRANDR events + to occur to the display while x11vnc is running, this + options indicates x11vnc should try to respond to + them (as opposed to simply crashing by assuming the + old screen size). See the xrandr(1) manpage and run + 'xrandr -q' for more info. [mode] is optional and + described below. + + Since watching for XRANDR events and trapping errors + increases polling overhead, only use this option if + XRANDR changes are expected. For example on a rotatable + screen PDA or laptop, or using a XRANDR-aware Desktop + where you resize often. It is best to be viewing with a + vncviewer that supports the NewFBSize encoding, since it + knows how to react to screen size changes. Otherwise, + LibVNCServer tries to do so something reasonable for + viewers that cannot do this (portions of the screen + may be clipped, unused, etc). + + Note: the default now is to check for XRANDR events, but + do not trap every X call that may fail due to resize. + If a resize event is received, the full -xrandr mode + is enabled. To disable even checking for events supply: + -noxrandr. + + "mode" defaults to "resize", which means create a + new, resized, framebuffer and hope all viewers can cope + with the change. "newfbsize" means first disconnect + all viewers that do not support the NewFBSize VNC + encoding, and then resize the framebuffer. "exit" + means disconnect all viewer clients, and then terminate + x11vnc. + +-rotate string Rotate and/or flip the framebuffer view exported by VNC. + This transformation is independent of XRANDR and is + done in software in main memory and so may be slower. + This mode could be useful on a handheld with portrait or + landscape modes that do not correspond to the scanline + order of the actual framebuffer. "string" can be: + + x flip along x-axis + y flip along y-axis + xy flip along x- and y-axes + +90 rotate 90 degrees clockwise + -90 rotate 90 degrees counter-clockwise + +90x rotate 90 degrees CW, then flip along x + +90y rotate 90 degrees CW, then flip along y + + these give all possible rotations and reflections. + + Aliases: same as xy: yx, +180, -180, 180 + same as -90: +270, 270 + same as +90: 90, (ditto for 90x, 90y) + + Like -scale, this transformation is applied at the very + end of any chain of framebuffer transformations and so + any options with geometries, e.g. -blackout, -clip, etc. + are relative to the original X (or -rawfb) framebuffer, + not the final one sent to VNC viewers. + + If you do not want the cursor shape to be rotated + prefix "string" with "nc:", e.g. "nc:+90", + "nc:xy", etc. + +-padgeom WxH Whenever a new vncviewer connects, the framebuffer is + replaced with a fake, solid black one of geometry WxH. + Shortly afterwards the framebuffer is replaced with the + real one. This is intended for use with vncviewers + that do not support NewFBSize and one wants to make + sure the initial viewer geometry will be big enough + to handle all subsequent resizes (e.g. under -xrandr, + -remote id:windowid, rescaling, etc.) + + In -unixpw mode this sets the size of the login screen. + Use "once:WxH" it ignore padgeom after the login + screen is set up. + +-o logfile Write stderr messages to file "logfile" instead of to + the terminal. Same as "-logfile file". To append + to the file use "-oa file" or "-logappend file". + If "logfile" contains the string "%VNCDISPLAY" + it is expanded to the vnc display (the name may need + to be guessed at.) "%HOME" works too. + +-flag file Write the "PORT=NNNN" (e.g. PORT=5900) string to + "file" in addition to stdout. This option could be + useful by wrapper script to detect when x11vnc is ready. + +-rmflag file Remove "file" at exit to signal when x11vnc is done. + The file is created at startup if it does not already + exist or if "file" is prefixed with "create:". + If the file is created, the x11vnc PID is placed in + the file. Otherwise the files contents is not changed. + Use prefix "nocreate:" to prevent creation. + +-rc filename Use "filename" instead of $HOME/.x11vncrc for rc file. +-norc Do not process any .x11vncrc file for options. + +-env VAR=VALUE Set the environment variable 'VAR' to value 'VALUE' + at x11vnc startup. This is a convenience utility to + avoid shell script wrappers, etc. to set the env. var. + You may specify as many of these as needed on the + command line. +-prog /path/to/x11vnc Set the full path to the x11vnc program for cases when + it cannot be determined from argv[0] (e.g. tcpd/inetd) + +-h, -help Print this help text. +-?, -opts Only list the x11vnc options. +-V, -version Print program version and last modification date. +-license Print out license information. Same as -copying and + -warranty. + +-dbg Instead of exiting after cleaning up, run a simple + "debug crash shell" when fatal errors are trapped. + +-q, -quiet Be quiet by printing less informational output to + stderr. (use -noquiet to undo an earlier -quiet.) + + The -quiet option does not eliminate all informational + output, it only reduces it. It is ignored in most + auxiliary usage modes, e.g. -storepasswd. To eliminate + all output use: 2>/dev/null 1>&2, etc. + +-v, -verbose Print out more information to stderr. + +-bg Go into the background after screen setup. Messages to + stderr are lost unless -o logfile is used. Something + like this could be useful in a script: + port=`ssh -t $host "x11vnc -display :0 -bg" | grep PORT +` + port=`echo "$port" | sed -e 's/PORT=//'` + port=`expr $port - 5900` + vncviewer $host:$port + +-modtweak Option -modtweak automatically tries to adjust the AltGr +-nomodtweak and Shift modifiers for differing language keyboards + between client and host. Otherwise, only a single key + press/release of a Keycode is simulated (i.e. ignoring + the state of the modifiers: this usually works for + identical keyboards). Also useful in resolving cases + where a Keysym is bound to multiple keys (e.g. "<" + ">" + and "," + "<" keys). Default: -modtweak + + If you are having trouble with with keys and -xkb or + -noxkb, and similar things don't help, try -nomodtweak. + + On some HP-UX systems it is been noted that they have + an odd keymapping where a single keycode will have a + keysym, e.g. "#", up to three times. You can check + via "xmodmap -pk" or the -dk option. The failure + is when you try to type "#" it yields "3". If you + see this problem try setting the environment variable + MODTWEAK_LOWEST=1 to see if it helps. + +-xkb When in modtweak mode, use the XKEYBOARD extension (if +-noxkb the X display supports it) to do the modifier tweaking. + This is powerful and should be tried if there are still + keymapping problems when using -modtweak by itself. + The default is to check whether some common keysyms, + e.g. !, @, [, are only accessible via -xkb mode and if + so then automatically enable the mode. To disable this + automatic detection use -noxkb. + + When -xkb mode is active you can set these env. vars. + They apply only when there is ambiguity as to which + key to choose (i.e the mapping is not one-to-one). + NOKEYHINTS=1: for up ascii keystrokes do not use score + hints saved when the key was pressed down. NOANYDOWN=1: + for up keystrokes do not resort to searching through + keys that are currently pressed down. KEYSDOWN=N: + remember the last N keys press down for tie-breaking + when an up keystroke comes in. + +-capslock When in -modtweak (the default) or -xkb mode, + if a keysym in the range A-Z comes in check the X + server to see if the Caps_Lock is set. If it is do + not artificially press Shift to generate the keysym. + This will enable the CapsLock key to behave correctly + in some circumstances: namely *both* the VNC viewer + machine and the x11vnc X server are in the CapsLock + on state. If one side has CapsLock on and the other + off and the keyboard is not behaving as you think it + should you should correct the CapsLock states (hint: + pressing CapsLock inside and outside of the viewer can + help toggle them both to the correct state). However, + for best results do not use this option, but rather + *only* enable CapsLock on the VNC viewer side (i.e. by + pressing CapsLock outside of the viewer window, also + -skip_lockkeys below). Also try -nomodtweak for a + possible workaround. + +-skip_lockkeys Have x11vnc ignore all Caps_Lock, Shift_Lock, Num_Lock, +-noskip_lockkeys Scroll_Lock keysyms received from viewers. The idea is + you press Caps_Lock on the VNC Viewer side but that does + not change the lock state in the x11vnc-side X server. + Nevertheless your capitalized letters come in over + the wire and are applied correctly to the x11vnc-side + X server. Note this mode probably won't do what you + want in -nomodtweak mode. Also, a kludge for KP_n + digits is always done it this mode: they are mapped to + regular digit keysyms. See also -capslock above. + The default is -noskip_lockkeys. + +-skip_keycodes string Ignore the comma separated list of decimal keycodes. + Perhaps these are keycodes not on your keyboard but + your X server thinks exist. Currently only applies + to -xkb mode. Use this option to help x11vnc in the + reverse problem it tries to solve: Keysym -> Keycode(s) + when ambiguities exist (more than one Keycode per + Keysym). Run 'xmodmap -pk' to see your keymapping. + Example: "-skip_keycodes 94,114" +-sloppy_keys Experimental option that tries to correct some + "sloppy" key behavior. E.g. if at the viewer you + press Shift+Key but then release the Shift before + Key that could give rise to extra unwanted characters + (usually only between keyboards of different languages). + Only use this option if you observe problems with + some keystrokes. +-skip_dups Some VNC viewers send impossible repeated key events, +-noskip_dups e.g. key-down, key-down, key-up, key-up all for the same + key, or 20 downs in a row for the same modifier key! + Setting -skip_dups means to skip these duplicates and + just process the first event. Note: some VNC viewers + assume they can send down's without the corresponding + up's and so you should not set this option for + these viewers (symptom: some keys do not autorepeat) + Default: -noskip_dups +-add_keysyms If a Keysym is received from a VNC viewer and that +-noadd_keysyms Keysym does not exist in the X server, then add the + Keysym to the X server's keyboard mapping on an unused + key. Added Keysyms will be removed periodically and + also when x11vnc exits. Default: -add_keysyms +-clear_mods At startup and exit clear the modifier keys by sending + KeyRelease for each one. The Lock modifiers are skipped. + Used to clear the state if the display was accidentally + left with any pressed down. +-clear_keys As -clear_mods, except try to release ANY pressed key. + Note that this option and -clear_mods can interfere + with a person typing at the physical keyboard. +-clear_all As -clear_keys, except try to release any CapsLock, + NumLock, etc. locks as well. + +-remap string Read Keysym remappings from file named "string". + Format is one pair of Keysyms per line (can be name + or hex value) separated by a space. If no file named + "string" exists, it is instead interpreted as this + form: key1-key2,key3-key4,... See + header file for a list of Keysym names, or use xev(1). + + To map a key to a button click, use the fake Keysyms + "Button1", ..., etc. E.g: "-remap Super_R-Button2" + (useful for pasting on a laptop) + + I use these if the machine I am viewing from does not + have a scrollwheel or I don't like using the one it has: + + -remap Super_R-Button4,Menu-Button5 + -remap KP_Add-Button4,KP_Enter-Button5 + + the former would be used on a PC, the latter on a + MacBook. This way those little used keys can be used + to generate bigger hops than the Up and Down arrows + provide. One can scroll through text or web pages more + quickly this way (especially if x11vnc scroll detection + is active.) + + Use Button44, Button12, etc. for multiple clicks. + + To disable a keysym (i.e. make it so it will not be + injected), remap it to "NoSymbol" or "None". + + Dead keys: "dead" (or silent, mute) keys are keys that + do not produce a character but must be followed by a 2nd + keystroke. This is often used for accenting characters, + e.g. to put "`" on top of "a" by pressing the dead + key and then "a". Note that this interpretation + is not part of core X11, it is up to the toolkit or + application to decide how to react to the sequence. + The X11 names for these keysyms are "dead_grave", + "dead_acute", etc. However some VNC viewers send the + keysyms "grave", "acute" instead thereby disabling + the accenting. To work around this -remap can be used. + For example "-remap grave-dead_grave,acute-dead_acute" + As a convenience, "-remap DEAD" applies these remaps: + + g grave-dead_grave + a acute-dead_acute + c asciicircum-dead_circumflex + t asciitilde-dead_tilde + m macron-dead_macron + b breve-dead_breve + D abovedot-dead_abovedot + d diaeresis-dead_diaeresis + o degree-dead_abovering + A doubleacute-dead_doubleacute + r caron-dead_caron + e cedilla-dead_cedilla + + If you just want a subset use the first letter + label, e.g. "-remap DEAD=ga" to get the first two. + Additional remaps may also be supplied via commas, + e.g. "-remap DEAD=ga,Super_R-Button2". Finally, + "DEAD=missing" means to apply all of the above as + long as the left hand member is not already in the + X11 keymap. + +-norepeat Option -norepeat disables X server key auto repeat when +-repeat VNC clients are connected and VNC keyboard input is + not idle for more than 5 minutes. This works around a + repeating keystrokes bug (triggered by long processing + delays between key down and key up client events: + either from large screen changes or high latency). + Default: -norepeat + + You can set the env. var. X11VNC_IDLE_TIMEOUT to the + number of idle seconds you want (5min = 300secs). + + Note: your VNC viewer side will likely do autorepeating, + so this is no loss unless someone is simultaneously at + the real X display. + + Use "-norepeat N" to set how many times norepeat will + be reset if something else (e.g. X session manager) + undoes it. The default is 2. Use a negative value + for unlimited resets. + +-nofb Ignore video framebuffer: only process keyboard and + pointer. Intended for use with Win2VNC and x2vnc + dual-monitor setups. +-nobell Do not watch for XBell events. (no beeps will be heard) + Note: XBell monitoring requires the XKEYBOARD extension. +-nosel Do not manage exchange of X selection/cutbuffer between + VNC viewers and the X server at all. +-noprimary Do not poll the PRIMARY selection for changes to send + back to clients. (PRIMARY is still set on received + changes, however). +-nosetprimary Do not set the PRIMARY selection for changes received + from VNC clients. +-noclipboard Do not poll the CLIPBOARD selection for changes to send + back to clients. (CLIPBOARD is still set on received + changes, however). +-nosetclipboard Do not set the CLIPBOARD selection for changes + received from VNC clients. +-seldir string If direction string is "send", only send the selection + to viewers, and if it is "recv" only receive it from + viewers. To work around apps setting the selection + too frequently and messing up the other end. You can + actually supply a comma separated list of directions, + including "debug" to turn on debugging output. + +-cursor [mode] Sets how the pointer cursor shape (little icon at the +-nocursor mouse pointer) should be handled. The "mode" string + is optional and is described below. The default + is to show some sort of cursor shape(s). How this + is done depends on the VNC viewer and the X server. + Use -nocursor to disable cursor shapes completely. + + Some VNC viewers support the TightVNC CursorPosUpdates + and CursorShapeUpdates extensions (cuts down on + network traffic by not having to send the cursor image + every time the pointer is moved), in which case these + extensions are used (see -nocursorshape and -nocursorpos + below to disable). For other viewers the cursor shape + is written directly to the framebuffer every time the + pointer is moved or changed and gets sent along with + the other framebuffer updates. In this case, there + will be some lag between the vnc viewer pointer and + the remote cursor position. + + If the X display supports retrieving the cursor shape + information from the X server, then the default is + to use that mode. On Solaris this can be done with + the SUN_OVL extension using -overlay (see also the + -overlay_nocursor option). A similar overlay scheme + is used on IRIX. Xorg (e.g. Linux) and recent Solaris + Xsun servers support the XFIXES extension to retrieve + the exact cursor shape from the X server. If XFIXES + is present it is preferred over Overlay and is used by + default (see -noxfixes below). This can be disabled + with -nocursor, and also some values of the "mode" + option below. + + Note that under XFIXES cursors with transparency (alpha + channel) will usually not be exactly represented and one + may find Overlay preferable. See also the -alphacut + and -alphafrac options below as fudge factors to try + to improve the situation for cursors with transparency + for a given theme. + + The "mode" string can be used to fine-tune the + displaying of cursor shapes. It can be used the + following ways: + + "-cursor arrow" - just show the standard arrow + nothing more or nothing less. + + "-cursor none" - same as "-nocursor" + + "-cursor X" - when the cursor appears to be on the + root window, draw the familiar X shape. Some desktops + such as GNOME cover up the root window completely, + and so this will not work, try "X1", etc, to try to + shift the tree depth. On high latency links or slow + machines there will be a time lag between expected and + the actual cursor shape. + + "-cursor some" - like "X" but use additional + heuristics to try to guess if the window should have + a windowmanager-like resizer cursor or a text input + I-beam cursor. This is a complete hack, but may be + useful in some situations because it provides a little + more feedback about the cursor shape. + + "-cursor most" - try to show as many cursors as + possible. Often this will only be the same as "some" + unless the display has overlay visuals or XFIXES + extensions available. On Solaris and IRIX if XFIXES + is not available, -overlay mode will be attempted. + +-cursor_drag Show cursor shape changes even when the mouse is being + dragged with a mouse button down. This is useful if you + want to be able to see Drag-and-Drop cursor icons, etc. + +-arrow n Choose an alternate "arrow" cursor from a set of + some common ones. n can be 1 to 6. Default is: 1 + Ignored when in XFIXES cursor-grabbing mode. + +-noxfixes Do not use the XFIXES extension to draw the exact cursor + shape even if it is available. + + Note: To work around a crash in Xorg 1.5 and later + some people needed to use -noxfixes. The Xorg crash + occurred right after a Display Manager (e.g. GDM) login. + Starting with x11vnc 0.9.9 it tries to automatically + avoid using XFIXES until it is sure a window manager + is running. See the -reopen option for more info and + how to use X11VNC_AVOID_WINDOWS=never to disable it. + +-alphacut n When using the XFIXES extension for the cursor shape, + cursors with transparency will not usually be displayed + exactly (but opaque ones will). This option sets n as + a cutoff for cursors that have transparency ("alpha + channel" with values ranging from 0 to 255) Any cursor + pixel with alpha value less than n becomes completely + transparent. Otherwise the pixel is completely opaque. + Default 240 + +-alphafrac fraction With the threshold in -alphacut some cursors will become + almost completely transparent because their alpha values + are not high enough. For those cursors adjust the + alpha threshold until fraction of the non-zero alpha + channel pixels become opaque. Default 0.33 +-alpharemove By default, XFIXES cursors pixels with transparency have + the alpha factor multiplied into the RGB color values + (i.e. that corresponding to blending the cursor with a + black background). Specify this option to remove the + alpha factor. (useful for light colored semi-transparent + cursors). +-noalphablend In XFIXES mode do not send cursor alpha channel data + to LibVNCServer. The default is to send it. The + alphablend effect will only be visible in -nocursorshape + mode or for clients with cursorshapeupdates turned + off. (However there is a hack for 32bpp with depth 24, + it uses the extra 8 bits to store cursor transparency + for use with a hacked vncviewer that applies the + transparency locally. See the FAQ for more info). + +-nocursorshape Do not use the TightVNC CursorShapeUpdates extension + even if clients support it. See -cursor above. +-cursorpos Option -cursorpos enables sending the X cursor position +-nocursorpos back to all vnc clients that support the TightVNC + CursorPosUpdates extension. Other clients will be able + to see the pointer motions. Default: -cursorpos +-xwarppointer Move the pointer with XWarpPointer(3X) instead of +-noxwarppointer the XTEST extension. Use this as a workaround + if the pointer motion behaves incorrectly, e.g. + on touchscreens or other non-standard setups. + + It is also sometimes needed on XINERAMA displays and is + enabled by default if XINERAMA is found to be active. + To prevent this, use -noxwarppointer. + +-buttonmap string String to remap mouse buttons. Format: IJK-LMN, this + maps buttons I -> L, etc., e.g. -buttonmap 13-31 + + Button presses can also be mapped to keystrokes: replace + a button digit on the right of the dash with :: + or :+: etc. for multiple keys. For example, + if the viewing machine has a mouse-wheel (buttons 4 5) + but the x11vnc side does not, these will do scrolls: + -buttonmap 12345-123:Prior::Next: + -buttonmap 12345-123:Up+Up+Up::Down+Down+Down: + + See header file for a list of Keysyms, + or use the xev(1) program. Note: mapping of button + clicks to Keysyms may not work if -modtweak or -xkb is + needed for the Keysym. + + If you include a modifier like "Shift_L" the + modifier's up/down state is toggled, e.g. to send + "The" use :Shift_L+t+Shift_L+h+e: (the 1st one is + shift down and the 2nd one is shift up). (note: the + initial state of the modifier is ignored and not reset) + To include button events use "Button1", ... etc. + + -buttonmap currently does not work on MacOSX console + or in -rawfb mode. + + Workaround: use -buttonmap IJ...-LM...=n to limit the + number of mouse buttons to n, e.g. 123-123=3. This will + prevent x11vnc from crashing if the X server reports + there are 5 buttons (4/5 scroll wheel), but there are + only really 3. + +-nodragging Do not update the display during mouse dragging events + (mouse button held down). Greatly improves response on + slow setups, but you lose all visual feedback for drags, + text selection, and some menu traversals. It overrides + any -pointer_mode setting. + +-ncache n Client-side caching scheme. Framebuffer memory "n" + (an integer) times that of the full display is allocated + below the actual framebuffer to cache screen contents + for rapid retrieval. So a W x H frambuffer is expanded + to a W x (n+1)*H one. Use 0 to disable. + + The "n" is actually optional, the default is 10. + + For this and the other -ncache* options below you can + abbreviate "-ncache" with "-nc". Also, "-nonc" + is the same as "-ncache 0" + + This is an experimental option, currently implemented in + an awkward way in that in the VNC Viewer you can see the + pixel cache contents if you scroll down, etc. So you + will have to set things up so you can't see that region. + If this method is successful, the changes required for + clients to do this less awkwardly will be investigated. + + The SSVNC viewer does a good job at automatically hiding + the pixel cache region. Or use SSVNC's -ycrop option + to explicitly hide the region. + + Note that this mode consumes a huge amount of memory, + both on the x11vnc server side and on the VNC Viewer + side. If n=2 then the amount of RAM used is roughly + tripled for both x11vnc and the VNC Viewer. As a rule + of thumb, note that 1280x1024 at depth 24 is about 5MB + of pixel data. + + For reasonable response when cycling through 4 to 6 + large (e.g. web browser) windows a value n of 6 to 12 + is recommended. (that's right: ~10X more memory...) + + Because of the way window backingstore and saveunders + are implemented, n must be even. It will be incremented + by 1 if it is not. + + This mode also works for native MacOS X, but may not + be as effective as the X version. This is due to a + number of things, one is the drop-shadow compositing + that leaves extra areas that need to be repaired (see + -ncache_pad). Another is the window iconification + animations need to be avoided (see -macicontime). + It appears the that the 'Scale' animation mode gives + better results than the 'Genie' one. Also, window event + detection not as accurate as the X version. + +-ncache_cr In -ncache mode, try to do copyrect opaque window + moves/drags instead of wireframes (this can induce + painting errors). The wireframe will still be used when + moving a window whose save-unders has not yet been set + or has been invalidated. + + Some VNC Viewers provide better response than others + with this option. On Unix, realvnc viewer gives + smoother drags than tightvnc viewer. Response may also + be choppy if the server side machine is too slow. + + Sometimes on very slow modem connections, this actually + gives an improvement because no pixel data at all + (not even the box animation) is sent during the drag. + +-ncache_no_moveraise In -ncache mode, do not assume that moving a window + will cause the window manager to raise it to the top + of the stack. The default is to assume it does, and + so at the beginning of any wireframe, etc, window moves + the window will be pushed to top in the VNC viewer. + +-ncache_no_dtchange In -ncache mode, do not try to guess when the desktop + (viewport) changes to another one (i.e. another + workarea). The default is to try to guess and when + detected try to make the transistion more smoothly. + +-ncache_no_rootpixmap In -ncache mode, do not try to snapshot the desktop + background to use in guessing or reconstructing window + save-unders. + +-ncache_keep_anims In -ncache mode, do not try to disable window + manager animations and other effects (that usually + degrade ncache performance or cause painting errors). + The default is to try to disable them on KDE (but not + GNOME) when VNC clients are connected. + + For other window managers or desktops that provide + animations, effects, compositing, translucency, + etc. that interfere with the -ncache method you will + have to disable them manually. + +-ncache_old_wm In -ncache mode, enable some heuristics for old style + window managers such as fvwm and twm. + +-ncache_pad n In -ncache mode, pad each window with n pixels for the + caching rectangles. This can be used to try to improve + the situation with dropshadows or other compositing + (e.g. MacOS X window manager), although it could make + things worse. The default is 0 on Unix and 24 on + MacOS X. +-debug_ncache Turn on debugging and profiling output under -ncache. + +-wireframe [str] Try to detect window moves or resizes when a mouse +-nowireframe button is held down and show a wireframe instead of + the full opaque window. This is based completely on + heuristics and may not always work: it depends on your + window manager and even how you move things around. + See -pointer_mode below for discussion of the "bogging + down" problem this tries to avoid. + Default: -wireframe + + Shorter aliases: -wf [str] and -nowf + + The value "str" is optional and, of course, is + packed with many tunable parameters for this scheme: + + Format: shade,linewidth,percent,T+B+L+R,mod,t1+t2+t3+t4 + Default: 0xff,2,0,32+8+8+8,all,0.15+0.30+5.0+0.125 + + If you leave nothing between commas: ",," the default + value is used. If you don't specify enough commas, + the trailing parameters are set to their defaults. + + "shade" indicate the "color" for the wireframe, + usually a greyscale: 0-255, however for 16 and 32bpp you + can specify an rgb.txt X color (e.g. "dodgerblue") or + a value > 255 is treated as RGB (e.g. red is 0xff0000). + "linewidth" sets the width of the wireframe in pixels. + "percent" indicates to not apply the wireframe scheme + to windows with area less than this percent of the + full screen. + + "T+B+L+R" indicates four integers for how close in + pixels the pointer has to be from the Top, Bottom, Left, + or Right edges of the window to consider wireframing. + This is a speedup to quickly exclude a window from being + wireframed: set them all to zero to not try the speedup + (scrolling and selecting text will likely be slower). + + "mod" specifies if a button down event in the + interior of the window with a modifier key (Alt, Shift, + etc.) down should indicate a wireframe opportunity. + It can be "0" or "none" to skip it, "1" or "all" + to apply it to any modifier, or "Shift", "Alt", + "Control", "Meta", "Super", or "Hyper" to only + apply for that type of modifier key. + + "t1+t2+t3+t4" specify four floating point times in + seconds: t1 is how long to wait for the pointer to move, + t2 is how long to wait for the window to start moving + or being resized (for some window managers this can be + rather long), t3 is how long to keep a wireframe moving + before repainting the window. t4 is the minimum time + between sending wireframe "animations". If a slow + link is detected, these values may be automatically + changed to something better for a slow link. + +-nowireframelocal By default, mouse motion and button presses of a + user sitting at the LOCAL display are monitored for + wireframing opportunities (so that the changes will be + sent efficiently to the VNC clients). Use this option + to disable this behavior. + +-wirecopyrect mode Since the -wireframe mechanism evidently tracks moving +-nowirecopyrect windows accurately, a speedup can be obtained by + telling the VNC viewers to locally copy the translated + window region. This is the VNC CopyRect encoding: + the framebuffer update doesn't need to send the actual + new image data. + + Shorter aliases: -wcr [mode] and -nowcr + + "mode" can be "never" (same as -nowirecopyrect) + to never try the copyrect, "top" means only do it if + the window was not covered by any other windows, and + "always" means to translate the orginally unobscured + region (this may look odd as the remaining pieces come + in, but helps on a slow link). Default: "always" + + Note: there can be painting errors or slow response + when using -scale so you may want to disable CopyRect + in this case "-wirecopyrect never" on the command + line or by remote-control. Or you can also use the + "-scale xxx:nocr" scale option. + +-debug_wireframe Turn on debugging info printout for the wireframe + heuristics. "-dwf" is an alias. Specify multiple + times for more output. + +-scrollcopyrect mode Like -wirecopyrect, but use heuristics to try to guess +-noscrollcopyrect if a window has scrolled its contents (either vertically + or horizontally). This requires the RECORD X extension + to "snoop" on X applications (currently for certain + XCopyArea and XConfigureWindow X protocol requests). + Examples: Hitting in a terminal window when the + cursor was at the bottom, the text scrolls up one line. + Hitting arrow in a web browser window, the web + page scrolls up a small amount. Or scrolling with a + scrollbar or mouse wheel. + + Shorter aliases: -scr [mode] and -noscr + + This scheme will not always detect scrolls, but when + it does there is a nice speedup from using the VNC + CopyRect encoding (see -wirecopyrect). The speedup + is both in reduced network traffic and reduced X + framebuffer polling/copying. On the other hand, it may + induce undesired transients (e.g. a terminal cursor + being scrolled up when it should not be) or other + painting errors (window tearing, bunching-up, etc). + These are automatically repaired in a short period + of time. If this is unacceptable disable the feature + with -noscrollcopyrect. + + Screen clearing kludges: for testing at least, there + are some "magic key sequences" (must be done in less + than 1 second) to aid repairing painting errors that + may be seen when using this mode: + + 3 Alt_L's in a row: resend whole screen, + 4 Alt_L's in a row: reread and resend whole screen, + 3 Super_L's in a row: mark whole screen for polling, + 4 Super_L's in a row: reset RECORD context, + 5 Super_L's in a row: try to push a black screen + + note: Alt_L is the Left "Alt" key (a single key) + Super_L is the Left "Super" key (Windows flag). + Both of these are modifier keys, and so should not + generate characters when pressed by themselves. Also, + your VNC viewer may have its own refresh hot-key + or button. + + "mode" can be "never" (same as -noscrollcopyrect) + to never try the copyrect, "keys" means to try it + in response to keystrokes only, "mouse" means to + try it in response to mouse events only, "always" + means to do both. Default: "always" + + Note: there can be painting errors or slow response + when using -scale so you may want to disable CopyRect + in this case "-scrollcopyrect never" on the command + line or by remote-control. Or you can also use the + "-scale xxx:nocr" scale option. + +-scr_area n Set the minimum area in pixels for a rectangle + to be considered for the -scrollcopyrect detection + scheme. This is to avoid wasting the effort on small + rectangles that would be quickly updated the normal way. + E.g. suppose an app updated the position of its skinny + scrollbar first and then shifted the large panel + it controlled. We want to be sure to skip the small + scrollbar and get the large panel. Default: 60000 + +-scr_skip list Skip scroll detection for applications matching + the comma separated list of strings in "list". + Some applications implement their scrolling in + strange ways where the XCopyArea, etc, also applies + to invisible portions of the window: if we CopyRect + those areas it looks awful during the scroll and + there may be painting errors left after the scroll. + Soffice.bin is the worst known offender. + + Use "##" to denote the start of the application class + (e.g. "##XTerm") and "++" to denote the start + of the application instance name (e.g. "++xterm"). + The string your list is matched against is of the form + "^^WM_NAME##Class++Instance" + The "xlsclients -la" command will provide this info. + + If a pattern is prefixed with "KEY:" it only applies + to Keystroke generated scrolls (e.g. Up arrow). If it + is prefixed with "MOUSE:" it only applies to Mouse + induced scrolls (e.g. dragging on a scrollbar). + Default: ##Soffice.bin,##StarOffice,##OpenOffice + +-scr_inc list Opposite of -scr_skip: this list is consulted first + and if there is a match the window will be monitored + via RECORD for scrolls irrespective of -scr_skip. + Use -scr_skip '*' to skip anything that does not match + your -scr_inc. Use -scr_inc '*' to include everything. + +-scr_keys list For keystroke scroll detection, only apply the RECORD + heuristics to the comma separated list of keysyms in + "list". You may find the RECORD overhead for every + one of your keystrokes disrupts typing too much, but you + don't want to turn it off completely with "-scr mouse" + and -scr_parms does not work or is too confusing. + + The listed keysyms can be numeric or the keysym + names in the header file or from the + xev(1) program. Example: "-scr_keys Up,Down,Return". + One probably wants to have application specific lists + (e.g. for terminals, etc) but that is too icky to think + about for now... + + If "list" begins with the "-" character the list + is taken as an exclude list: all keysyms except those + list will be considered. The special string "builtin" + expands to an internal list of keysyms that are likely + to cause scrolls. BTW, by default modifier keys, + Shift_L, Control_R, etc, are skipped since they almost + never induce scrolling by themselves. + +-scr_term list Yet another cosmetic kludge. Apply shell/terminal + heuristics to applications matching comma separated + list (same as for -scr_skip/-scr_inc). For example an + annoying transient under scroll detection is if you + hit Enter in a terminal shell with full text window, + the solid text cursor block will be scrolled up. + So for a short time there are two (or more) block + cursors on the screen. There are similar scenarios, + (e.g. an output line is duplicated). + + These transients are induced by the approximation of + scroll detection (e.g. it detects the scroll, but not + the fact that the block cursor was cleared just before + the scroll). In nearly all cases these transient errors + are repaired when the true X framebuffer is consulted + by the normal polling. But they are distracting, so + what this option provides is extra "padding" near the + bottom of the terminal window: a few extra lines near + the bottom will not be scrolled, but rather updated + from the actual X framebuffer. This usually reduces + the annoying artifacts. Use "none" to disable. + Default: "term" + +-scr_keyrepeat lo-hi If a key is held down (or otherwise repeats rapidly) and + this induces a rapid sequence of scrolls (e.g. holding + down an Arrow key) the "scrollcopyrect" detection + and overhead may not be able to keep up. A time per + single scroll estimate is performed and if that estimate + predicts a sustainable scrollrate of keys per second + between "lo" and "hi" then repeated keys will be + DISCARDED to maintain the scrollrate. For example your + key autorepeat may be 25 keys/sec, but for a large + window or slow link only 8 scrolls per second can be + sustained, then roughly 2 out of every 3 repeated keys + will be discarded during this period. Default: "4-20" + +-scr_parms string Set various parameters for the scrollcopyrect mode. + The format is similar to that for -wireframe and packed + with lots of parameters: + + Format: T+B+L+R,t1+t2+t3,s1+s2+s3+s4+s5 + Default: 0+64+32+32,0.02+0.10+0.9,0.03+0.06+0.5+0.1+5.0 + + If you leave nothing between commas: ",," the default + value is used. If you don't specify enough commas, + the trailing parameters are set to their defaults. + + "T+B+L+R" indicates four integers for how close in + pixels the pointer has to be from the Top, Bottom, Left, + or Right edges of the window to consider scrollcopyrect. + If -wireframe overlaps it takes precedence. This is a + speedup to quickly exclude a window from being watched + for scrollcopyrect: set them all to zero to not try + the speedup (things like selecting text will likely + be slower). + + "t1+t2+t3" specify three floating point times in + seconds that apply to scrollcopyrect detection with + *Keystroke* input: t1 is how long to wait after a key + is pressed for the first scroll, t2 is how long to keep + looking after a Keystroke scroll for more scrolls. + t3 is how frequently to try to update surrounding + scrollbars outside of the scrolling area (0.0 to + disable) + + "s1+s2+s3+s4+s5" specify five floating point times + in seconds that apply to scrollcopyrect detection with + *Mouse* input: s1 is how long to wait after a mouse + button is pressed for the first scroll, s2 is how long + to keep waiting for additional scrolls after the first + Mouse scroll was detected. s3 is how frequently to + try to update surrounding scrollbars outside of the + scrolling area (0.0 to disable). s4 is how long to + buffer pointer motion (to try to get fewer, bigger + mouse scrolls). s5 is the maximum time to spend just + updating the scroll window without updating the rest + of the screen. + +-fixscreen string Periodically "repair" the screen based on settings + in "string". Hopefully you won't need this option, + it is intended for cases when the -scrollcopyrect or + -wirecopyrect features leave too many painting errors, + but it can be used for any scenario. This option + periodically performs costly operations and so + interactive response may be reduced when it is on. + You can use 3 Alt_L's (the Left "Alt" key) taps in + a row (as described under -scrollcopyrect) instead to + manually request a screen repaint when it is needed. + + "string" is a comma separated list of one or more of + the following: "V=t", "C=t", "X=t", and "8=t". + In these "t" stands for a time in seconds (it is + a floating point even though one should usually use + values > 2 to avoid wasting resources). V sets how + frequently the entire screen should be sent to viewers + (it is like the 3 Alt_L's). C sets how long to wait + after a CopyRect to repaint the full screen. X sets + how frequently to reread the full X11 framebuffer from + the X server and push it out to connected viewers. + Use of X should be rare, please report a bug if you + find you need it. 8= applies only for -8to24 mode: it + sets how often the non-default visual regions of the + screen (e.g. 8bpp windows) are refreshed. Examples: + -fixscreen V=10 -fixscreen C=10 + +-debug_scroll Turn on debugging info printout for the scroll + heuristics. "-ds" is an alias. Specify it multiple + times for more output. + +-noxrecord Disable any use of the RECORD extension. This is + currently used by the -scrollcopyrect scheme and to + monitor X server grabs. + +-grab_buster Some of the use of the RECORD extension can leave a +-nograb_buster tiny window for XGrabServer deadlock. This is only if + the whole-server grabbing application expects mouse or + keyboard input before releasing the grab. It is usually + a window manager that does this. x11vnc takes care to + avoid the the problem, but if caught x11vnc will freeze. + Without -grab_buster, the only solution is to go the + physical display and give it some input to satisfy the + grabbing app. Or manually kill and restart the window + manager if that is feasible. With -grab_buster, x11vnc + will fork a helper thread and if x11vnc appears to be + stuck in a grab after a period of time (20-30 sec) then + it will inject some user input: button clicks, Escape, + mouse motion, etc to try to break the grab. If you + experience a lot of grab deadlock, please report a bug. + +-debug_grabs Turn on debugging info printout with respect to + XGrabServer() deadlock for -scrollcopyrect mode. + +-debug_sel Turn on debugging info printout with respect to + PRIMARY, CLIPBOARD, and CUTBUFFER0 selections. + +-pointer_mode n Various pointer motion update schemes. "-pm" is + an alias. The problem is pointer motion can cause + rapid changes on the screen: consider the rapid + changes when you drag a large window around opaquely. + Neither x11vnc's screen polling and vnc compression + routines nor the bandwidth to the vncviewers can keep + up these rapid screen changes: everything will bog down + when dragging or scrolling. So a scheme has to be used + to "eat" much of that pointer input before re-polling + the screen and sending out framebuffer updates. The + mode number "n" can be 0 to 4 and selects one of + the schemes desribed below. + + Note that the -wireframe and -scrollcopyrect modes + complement -pointer_mode by detecting (and improving) + certain periods of "rapid screen change". + + n=0: does the same as -nodragging. (all screen polling + is suspended if a mouse button is pressed.) + + n=1: was the original scheme used to about Jan 2004: + it basically just skips -input_skip keyboard or pointer + events before repolling the screen. + + n=2 is an improved scheme: by watching the current rate + of input events it tries to detect if it should try to + "eat" additional pointer events before continuing. + + n=3 is basically a dynamic -nodragging mode: it detects + when the mouse motion has paused and then refreshes + the display. + + n=4 attempts to measures network rates and latency, + the video card read rate, and how many tiles have been + changed on the screen. From this, it aggressively tries + to push screen "frames" when it decides it has enough + resources to do so. NOT FINISHED. + + The default n is 2. Note that modes 2, 3, 4 will skip + -input_skip keyboard events (but it will not count + pointer events). Also note that these modes are not + available in -threads mode which has its own pointer + event handling mechanism. + + To try out the different pointer modes to see which + one gives the best response for your usage, it is + convenient to use the remote control function, for + example "x11vnc -R pm:4" or the tcl/tk gui (Tuning -> + pointer_mode -> n). + +-input_skip n For the pointer handling when non-threaded: try to + read n user input events before scanning display. n < 0 + means to act as though there is always user input. + Default: 10 + +-allinput Have x11vnc read and process all available client input + before proceeding. + +-input_eagerly Similar to -allinput but use the handleEventsEagerly + mechanism built into LibVNCServer. + +-speeds rd,bw,lat x11vnc tries to estimate some speed parameters that + are used to optimize scheduling (e.g. -pointer_mode + 4, -wireframe, -scrollcopyrect) and other things. + Use the -speeds option to set these manually. + The triple "rd,bw,lat" corresponds to video h/w + read rate in MB/sec, network bandwidth to clients in + KB/sec, and network latency to clients in milliseconds, + respectively. If a value is left blank, e.g. "-speeds + ,100,15", then the internal scheme is used to estimate + the empty value(s). + + Typical PC video cards have read rates of 5-10 MB/sec. + If the framebuffer is in main memory instead of video + h/w (e.g. SunRay, shadowfb, dummy driver, Xvfb), the + read rate may be much faster. "x11perf -getimage500" + can be used to get a lower bound (remember to factor + in the bytes per pixel). It is up to you to estimate + the network bandwith and latency to clients. For the + latency the ping(1) command can be used. + + For convenience there are some aliases provided, + e.g. "-speeds modem". The aliases are: "modem" for + 6,4,200; "dsl" for 6,100,50; and "lan" for 6,5000,1 + +-wmdt string For some features, e.g. -wireframe and -scrollcopyrect, + x11vnc has to work around issues for certain window + managers or desktops (currently kde and xfce). + By default it tries to guess which one, but it can + guess incorrectly. Use this option to indicate which + wm/dt. "string" can be "gnome", "kde", "cde", + "xfce", or "root" (classic X wm). Anything else + is interpreted as "root". + +-debug_pointer Print debugging output for every pointer event. +-debug_keyboard Print debugging output for every keyboard event. + Same as -dp and -dk, respectively. Use multiple + times for more output. + +-defer time Time in ms to delay sending updates to connected clients + (deferUpdateTime) Default: 20 + +-wait time Time in ms to pause between screen polls. Used to cut + down on load. Default: 20 + +-extra_fbur n Perform extra FrameBufferUpdateRequests checks to + try to be in better sync with the client's requests. + What this does is perform extra polls of the client + socket at critical times (before '-defer' and '-wait' + calls.) The default is n=1. Set to a larger number to + insert more checks or set to n=0 to disable. A downside + of these extra calls is that more mouse input may be + processed than desired. + +-wait_ui factor Factor by which to cut the -wait time if there + has been recent user input (pointer or keyboard). + Improves response, but increases the load whenever you + are moving the mouse or typing. Default: 2.00 +-setdefer n When the -wait_ui mechanism cuts down the wait time ms, + set the defer time to the same ms value. n=1 to enable, + 0 to disable, and -1 to set defer to 0 (no delay). + Similarly, 2 and -2 indicate 'urgent_update' mode should + be used to push the updates even sooner. Default: 1 +-nowait_bog Do not detect if the screen polling is "bogging down" + and sleep more. Some activities with no user input can + slow things down a lot: consider a large terminal window + with a long build running in it continuously streaming + text output. By default x11vnc will try to detect this + (3 screen polls in a row each longer than 0.25 sec with + no user input), and sleep up to 1.5 secs to let things + "catch up". Use this option to disable that detection. +-slow_fb time Floating point time in seconds to delay all screen + polling. For special purpose usage where a low frame + rate is acceptable and desirable, but you want the + user input processed at the normal rate so you cannot + use -wait. +-xrefresh time Floating point time in seconds to indicate how often to + do the equivalent of xrefresh(1) to force all windows + (in the viewable area if -id, -sid, or -clip is used) + to repaint themselves. Use this only if applications + misbehave by not repainting themselves properly. + See also -noxdamage. +-nap Monitor activity and if it is low take longer naps +-nonap between screen polls to really cut down load when idle. + Default: take naps +-sb time Time in seconds after NO activity (e.g. screen blank) + to really throttle down the screen polls (i.e. sleep + for about 1.5 secs). Use 0 to disable. Default: 60 + +-readtimeout n Set LibVNCServer rfbMaxClientWait to n seconds. On + slow links that take a long time to paint the first + screen LibVNCServer may hit the timeout and drop the + connection. Default: 20 seconds. +-ping n Send a 1x1 framebuffer update to all clients every n + seconds (e.g. to try to keep a network connection alive) + +-nofbpm If the system supports the FBPM (Frame Buffer Power +-fbpm Management) extension (i.e. some Sun systems), then + prevent the video h/w from going into a reduced power + state when VNC clients are connected. + + FBPM capable video h/w save energy when the workstation + is idle by going into low power states (similar to DPMS + for monitors). This interferes with x11vnc's polling + of the framebuffer data. + + "-nofbpm" means prevent FBPM low power states whenever + VNC clients are connected, while "-fbpm" means to not + monitor the FBPM state at all. See the xset(1) manpage + for details. -nofbpm is basically the same as running + "xset fbpm force on" periodically. Default: -fbpm + +-nodpms If the system supports the DPMS (Display Power Managemen +t +-dpms Signaling) extension, then prevent the monitor from + going into a reduced power state when VNC clients + are connected. + + DPMS reduced power monitor states are a good thing + and you normally want the power down to take place + (usually x11vnc has no problem exporting the display in + this state). You probably only want to use "-nodpms" + to work around problems with Screen Savers kicking + on in DPMS low power states. There is known problem + with kdesktop_lock on KDE where the screen saver keeps + kicking in every time user input stops for a second + or two. Specifying "-nodpms" works around it. + + "-nodpms" means prevent DPMS low power states whenever + VNC clients are connected, while "-dpms" means to not + monitor the DPMS state at all. See the xset(1) manpage + for details. -nodpms is basically the same as running + "xset dpms force on" periodically. Default: -dpms + +-forcedpms If the system supports the DPMS (Display Power + Management Signaling) extension, then try to keep the + monitor in a powered off state. This is to prevent + nosey people at the physical display from viewing what + is on the screen. Be sure to lock the screen before + disconnecting. + + This method is far from bullet proof, e.g. suppose + someone attaches a non-DPMS monitor, or loads the + machine so that there is a gap of time before x11vnc + restores the powered off state? On many machines if + he floods it with keyboard and mouse input he can see + flashes of what is on the screen before the DPMS off + state is reestablished. For this to work securely + there would need to be support in the X server to do + this exactly rather than approximately with DPMS. + +-clientdpms As -forcedpms but only when VNC clients are connected. + +-noserverdpms The UltraVNC ServerInput extension is supported. + This allows the VNC viewer to click a button that will + cause the server (x11vnc) to try to disable keyboard + and mouse input at the physical display and put the + monitor in dpms powered off state. Use this option to + skip powering off the monitor. + +-noultraext Disable the following UltraVNC extensions: SingleWindow + and ServerInput. The others managed by LibVNCServer + (textchat, 1/n scaling, rfbEncodingUltra) are not. + +-chatwindow Place a local UltraVNC chat window on the X11 display + that x11vnc is polling. That way the person on the VNC + viewer-side can chat with the person at the physical + X11 console. (e.g. helpdesk w/o telephone) + + For this to work the SSVNC package (version 1.0.21 or + later) MUST BE installed on the system where x11vnc runs + and the 'ssvnc' command must be available in $PATH. + The ssvncviewer is used as a chat window helper. + See http://www.karlrunge.com/x11vnc/ssvnc.html + + This option implies '-rfbversion 3.6' so as to trick + UltraVNC viewers, otherwise they assume chat is not + available. To specify a different rfbversion, place + it after the -chatwindow option on the cmdline. + + See also the remote control 'chaton' and 'chatoff' + actions. These can also be set from the tkx11vnc GUI. + +-noxdamage Do not use the X DAMAGE extension to detect framebuffer + changes even if it is available. Use -xdamage if your + default is to have it off. + + x11vnc's use of the DAMAGE extension: 1) significantly + reduces the load when the screen is not changing much, + and 2) detects changed areas (small ones by default) + more quickly. + + Currently the DAMAGE extension is overly conservative + and often reports large areas (e.g. a whole terminal + or browser window) as damaged even though the actual + changed region is much smaller (sometimes just a few + pixels). So heuristics were introduced to skip large + areas and use the damage rectangles only as "hints" + for the traditional scanline polling. The following + tuning parameters are introduced to adjust this + behavior: + +-xd_area A Set the largest DAMAGE rectangle area "A" (in + pixels: width * height) to trust as truly damaged: + the rectangle will be copied from the framebuffer + (slow) no matter what. Set to zero to trust *all* + rectangles. Default: 20000 +-xd_mem f Set how long DAMAGE rectangles should be "remembered", + "f" is a floating point number and is in units of the + scanline repeat cycle time (32 iterations). The default + (1.0) should give no painting problems. Increase it if + there are problems or decrease it to live on the edge + (perhaps useful on a slow machine). + +-sigpipe string Broken pipe (SIGPIPE) handling. "string" can be + "ignore" or "exit". For "ignore" LibVNCServer + will handle the abrupt loss of a client and continue, + for "exit" x11vnc will cleanup and exit at the 1st + broken connection. + + This option is not really needed since LibVNCServer + is doing the correct thing now for quite some time. + However, for convenience you can use it to ignore other + signals, e.g. "-sigpipe ignore:HUP,INT,TERM" in case + that would be useful for some sort of application. + You can also put "exit:.." in the list to have x11vnc + cleanup on the listed signals. "-sig" is an alias + for this option if you don't like the 'pipe'. Example: + -sig ignore:INT,TERM,exit:USR1 + +-threads Whether or not to use the threaded LibVNCServer +-nothreads algorithm [rfbRunEventLoop] if libpthread is available. + In this mode new threads (one for input and one + for output) are created to handle each new client. + Default: -nothreads. + + Thread stability is much improved in version 0.9.8. + + Multiple clients in threaded mode should be stable + for the ZRLE encoding on all platforms. The Tight and + Zlib encodings are currently only stable on Linux for + multiple clients. Compile with -DTLS=__thread if your + OS and compiler and linker support it. + + For resizes (randr, etc.) set this env. var. to the numb +er + of milliseconds to sleep: X11VNC_THREADS_NEW_FB_SLEEP + at various places in the do_new_fb() action. This is to + let various activities settle. Default is about 500ms. + + Multiple clients in threaded mode could yield better + performance for 'class-room' broadcasting usage; also in + -appshare broadcast mode. See also the -reflect option. + +-fs f If the fraction of changed tiles in a poll is greater + than f, the whole screen is updated. Default: 0.75 +-gaps n Heuristic to fill in gaps in rows or cols of n or + less tiles. Used to improve text paging. Default: 4 +-grow n Heuristic to grow islands of changed tiles n or wider + by checking the tile near the boundary. Default: 3 +-fuzz n Tolerance in pixels to mark a tiles edges as changed. + Default: 2 +-debug_tiles Print debugging output for tiles, fb updates, etc. + +-snapfb Instead of polling the X display framebuffer (fb) + for changes, periodically copy all of X display fb + into main memory and examine that copy for changes. + (This setting also applies for non-X -rawfb modes). + Under some circumstances this will improve interactive + response, or at least make things look smoother, but in + others (most!) it will make the response worse. If the + video h/w fb is such that reading small tiles is very + slow this mode could help. To keep the "framerate" + up the screen size x bpp cannot be too large. Note that + this mode is very wasteful of memory I/O resources + (it makes full screen copies even if nothing changes). + It may be of use in video capture-like applications, + webcams, or where window tearing is a problem. + +-rawfb string Instead of polling X, poll the memory object specified + in "string". + + For file polling, to memory map mmap(2) a file use: + "map:/path/to/a/file@WxHxB", with framebuffer Width, + Height, and Bits per pixel. "mmap:..." is the + same. + + If there is trouble with mmap, use "file:/..." + for slower lseek(2) based reading. + + Use "snap:..." to imply -snapfb mode and the "file:" + access (this is for unseekable devices that only provide + the fb all at once, e.g. a video camera provides the + whole frame). + + For shared memory segments string is of the form: + "shm:N@WxHxB" which specifies a shmid N and with + WxHxB as above. See shmat(1) and ipcs(1) + + If you do not supply a type "map" is assumed if + the file exists (see the next paragraphs for some + exceptions to this.) + + If string is "setup:cmd", then the command "cmd" + is run and the first line from it is read and used + as "string". This allows initializing the device, + determining WxHxB, etc. These are often done as root + so take care. + + If the string begins with "video", see the VIDEO4LINUX + discussion below where the device may be queried for + (and possibly set) the framebuffer parameters. + + If the string begins with "console", "/dev/fb", + "fb", or "vt", see the LINUX CONSOLE discussion + below where the framebuffer device is opened and + keystrokes (and possibly mouse events) are inserted + into the console. + + If the string begins with "vnc", see the VNC HOST + discussion below where the framebuffer is taken as that + of another remote VNC server. + + Optional suffixes are ":R/G/B" and "+O" to specify + red, green, and blue masks (in hex) and an offset into + the memory object. If the masks are not provided x11vnc + guesses them based on the bpp (if the colors look wrong, + you need to provide the masks.) + + Another optional suffix is the Bytes Per Line which in + some cases is not WxB/8. Specify it as WxHxB-BPL + e.g. 800x600x16-2048. This could be a normal width + 1024 at 16bpp fb, but only width 800 shows up. + + So the full format is: mode:file@WxHxB:R/G/B+O-BPL + + Examples: + -rawfb shm:210337933@800x600x32:ff/ff00/ff0000 + -rawfb map:/dev/fb0@1024x768x32 + -rawfb map:/tmp/Xvfb_screen0@640x480x8+3232 + -rawfb file:/tmp/my.pnm@250x200x24+37 + -rawfb file:/dev/urandom@128x128x8 + -rawfb snap:/dev/video0@320x240x24 -24to32 + -rawfb video0 + -rawfb video -pipeinput VID + -rawfb console + -rawfb vt2 + -rawfb vnc:somehost:0 + + (see ipcs(1) and fbset(1) for the first two examples) + + In general all user input is discarded by default (see + the -pipeinput option for how to use a helper program + to insert). Most of the X11 (screen, keyboard, mouse) + options do not make sense and many will cause this + mode to crash, so please think twice before setting or + changing them in a running x11vnc. + + If you DO NOT want x11vnc to close the X DISPLAY in + rawfb mode, prepend a "+" e.g. +file:/dev/fb0... + Keeping the display open enables the default + remote-control channel, which could be useful. + Alternatively, if you specify -noviewonly, then the + mouse and keyboard input are STILL sent to the X + display, this usage should be very rare, i.e. doing + something strange with /dev/fb0. + + If the device is not "seekable" (e.g. webcam) try + reading it all at once in full snaps via the "snap:" + mode (note: this is a resource hog). If you are using + file: or map: AND the device needs to be reopened for + *every* snapfb snapshot, set the environment variable: + SNAPFB_RAWFB_RESET=1 as well. + + If you want x11vnc to dynamically transform a 24bpp + rawfb to 32bpp (note that this will be slower) also + supply the -24to32 option. This would be useful for, + say, a video camera that delivers the pixel data as + 24bpp packed RGB. This is the default under "video" + mode if the bpp is 24. + + Normally the bits per pixel, B, is 8, 16, or 32 (or + rarely 24), however there is also some support for + B < 8 (e.g. old graphics displays 4 bpp or 1 bpp). + In this case you certainly must supply the masks as + well: WxHxB:R/G/B. The pixels will be padded out to + 8 bpp using depth 8 truecolor. The scheme currently + does not work with snap fb (ask if interested.) B=1 + monochrome example: file:/dev/urandom@128x128x1:1/1/1 + Some other like this are 128x128x2:3/3/3 128x128x4:7/7/7 + + For B < 8 framebuffers you can also set the env. var + RAWFB_CGA=1 to try a CGA mapping for B=4 (e.g. linux + vga16fb driver.) Note with low bpp and/or resolution + VGA and VGA16 modes on the Linux console one's attempt + to export them via x11vnc can often be thwarted due to + special color palettes, pixel packings, and even video + painting buffering. OTOH, often experimenting with the + RGB masks can yield something recognizable. + + VIDEO4LINUX: on Linux some attempt is made to handle + video devices (webcams or TV tuners) automatically. + The idea is the WxHxB will be extracted from the + device itself. So if you do not supply "@WxHxB... + parameters x11vnc will try to determine them. It first + tries the v4l API if that support has been compiled in. + Otherwise it will run the v4l-info(1) external program + if it is available. + + The simplest examples are "-rawfb video" and "-rawfb + video1" which imply the device file /dev/video and + /dev/video1, respectively. You can also supply the + /dev if you like, e.g. "-rawfb /dev/video0" + + Since the video capture device framebuffer usually + changes continuously (e.g. brightness fluctuations), + you may want to use the -wait, -slow_fb, or -defer + options to lower the "framerate" to cut down on + network VNC traffic. + + A more sophisticated video device scheme allows + initializing the device's settings using: + + -rawfb video: + + The prefix could also be, as above, e.g. "video1:" to + specify the device file. The v4l API must be available + for this to work. Otherwise, you will need to try + to initialize the device with an external program, + e.g. xawtv, spcaview, and hope they persist when x11vnc + re-opens the device. + + is a comma separated list of key=value pairs. + The device's brightness, color, contrast, and hue can + be set to percentages, e.g. br=80,co=50,cn=44,hu=60. + + The device filename can be set too if needed (if it + does not start with "video"), e.g. fn=/dev/qcam. + + The width, height and bpp of the framebuffer can be + set via, e.g., w=160,h=120,bpp=16. + + Related to the bpp above, the pixel format can be set + via the fmt=XXX, where XXX can be one of: GREY, HI240, + RGB555, RGB565, RGB24, and RGB32 (with bpp 8, 8, 16, 16, + 24, and 32 respectively). See http://www.linuxtv.org + for more info (V4L api). + + For TV/rf tuner cards one can set the tuning mode + via tun=XXX where XXX can be one of PAL, NTSC, SECAM, + or AUTO. + + One can switch the input channel by the inp=XXX setting, + where XXX is the name of the input channel (Television, + Composite1, S-Video, etc). Use the name that is in the + information about the device that is printed at startup. + + For input channels with tuners (e.g. Television) one + can change which station is selected by the sta=XXX + setting. XXX is the station number. Currently only + the ntsc-cable-us (US cable) channels are built into + x11vnc. See the -freqtab option below to supply one + from xawtv. If XXX is greater than 500, then it is + interpreted as a raw frequency in KHz. + + Example: + + -rawfb video:br=80,w=320,h=240,fmt=RGB32,tun=NTSC,sta=47 + + one might need to add inp=Television too for the input + channel to be TV if the card doesn't come up by default + in that one. + + Note that not all video capture devices will support + all of the above settings. + + See the -pipeinput VID option below for a way to control + the settings through the VNC Viewer via keystrokes. + As a shortcut, if the string begins "Video.." instead + of "video.." then -pipeinput VID is implied. + + As above, if you specify a "@WxHxB..." after the + string they are used verbatim: the device + is not queried for the current values. Otherwise the + device will be queried. + + LINUX CONSOLE: The following describes some ways to + view and possibly interact with the Linux text/graphics + console (i.e. not X11 XFree86/Xorg) + + Note: If the LibVNCServer LinuxVNC program is on your + system you may want to use that instead of the following + method because it will be faster and more accurate + for the Linux text console and includes mouse support. + There is, however, the basic LinuxVNC functionality in + x11vnc if you replace "console" with "vt" in the + examples below. + + If the rawfb string begins with "console" the + framebuffer device /dev/fb0 is opened and /dev/tty0 is + opened too. The latter is used to inject keystrokes + (not all are supported, but the basic ones are). + You will need to be root to inject keystrokes, but + not necessarily to open /dev/fb0. /dev/tty0 refers to + the active VT, to indicate one explicitly, use, e.g., + "console2" for /dev/tty2, etc. by indicating the + specific VT number. + + For the Linux framebuffer device, /dev/fb0, (fb1, + etc) to be enabled the appropriate kernel drivers must + be loaded. E.g. vesafb or vga16fb and also by setting + the boot parameter vga=0x301 (or 0x314, 0x317, etc.) + (The vga=... method is the preferred way; set your + machines up that way.) Otherwise there will be a + 'No such device' error. You can also load a Linux + framebuffer driver specific to your make of video card + for more functionality. Once the machine is booted one + can often 'modprobe' the fb driver as root to obtain + a framebuffer device. + + If you cannot get /dev/fb0 working on Linux, try + using the LinuxVNC emulation mode by "-rawfb vtN" + where N = 1, ... 6 is the Linux Virtual Terminal (aka + virtual console) you wish to view, e.g. "-rawfb vt2". + Unlike /dev/fb mode, it need not be the active Virtual + Terminal. Note that this mode can only show text and + not graphics. x11vnc polls the text in /dev/vcsaN + + Set the env. var. RAWFB_VCSA_BW=1 to disable colors in + the "vtN" mode (i.e. black and white only.) If you + do not prefer the default 16bpp set RAWFB_VCSA_BPP to + 8 or 32. If you need to tweak the rawfb parameters by + using the 'console_guess' string printed at startup, + be sure to indicate the snap: method. + + uinput: If the Linux version appears to be 2.6 or + later and the "uinput" module appears to be present + (modprobe uinput), then the uinput method will be used + instead of /dev/ttyN. uinput allows insertion of BOTH + keystrokes and mouse input and so it preferred when + accessing graphical (e.g. QT-embedded) linux console + apps. See -pipeinput UINPUT below for more information + on this mode; you will have to use -pipeinput if you + want to tweak any UINPUT parameters. You may also want + to also use the -nodragging and -cursor none options. + Use "console0", etc or -pipeinput CONSOLE to force + the /dev/ttyN method. + + Note you can change the Linux VT remotely using the + chvt(1) command to make the one you want be the active + one (e.g. 'chvt 3'). Sometimes switching out and back + corrects the framebuffer's graphics state. For the + "-rawfb vtN" mode there is no need to switch the VT's. + + To skip input injecting entirely use "consolex" + or "vtx". + + The string "/dev/fb0" (1, etc.) can be used instead + of "console". This can be used to specify a different + framebuffer device, e.g. /dev/fb1. As a shortcut the + "/dev/" can be dropped. If the name is something + nonstandard, use "console:/dev/foofb" + + If you do not want x11vnc to guess the framebuffer's + WxHxB and masks automatically (sometimes the kernel + gives incorrect information), specify them with a @WxHxB + (and optional :R/G/B masks) at the end of the string. + + Examples: + -rawfb console + -rawfb /dev/fb0 (same) + -rawfb console3 (force /dev/tty3) + -rawfb consolex (no keystrokes or mouse) + -rawfb console:/dev/nonstd + -rawfb console -pipeinput UINPUT:accel=4.0 + -rawfb vt3 (/dev/tty3 w/o /dev/fb0) + + VNC HOST: if the -rawfb string is of the form + "vnc:host:N" then the VNC display "N" on the remote + VNC server "host" is connected to (i.e. x11vnc acts as + a VNC client itself) and that framebuffer is exported. + + This mode is really only of use if you are trying + to improve performance in the case of many (e.g. > + 10) simultaneous VNC viewers, and you try a divide + and conquer scheme to reduce bandwidth and improve + responsiveness. + + For example, if there will be 64 simultaneous VNC + viewers this can lead to a lot of redundant VNC traffic + to and from the server host:N, extra CPU usage, + and all viewers response can be reduced by having + to wait for writes to the slowest client to finish. + However, if you set up 8 reflectors/repeaters started + with option -rawfb vnc:host:N, then there are only + 8 connections to host:N. Each repeater then handles + 8 vnc viewer connections thereby spreading the load + around. In classroom broadcast usage, try to put the + repeaters on different switches. This mode is the same + as -reflect host:N. Replace "host:N" by "listen" + or "listen:port" for a reverse connection. + + Overall performance will not be as good as a single + direct connection because, among other things, + there is an additional level of framebuffer polling + and pointer motion can still induce many changes per + second that must be propagated. Tip: if the remote VNC + is x11vnc doing wireframing, or an X display that does + wireframing that gives much better response than opaque + window dragging. Consider the -nodragging option if + the problem is severe. + + The env. var. X11VNC_REFLECT_PASSWORD can be set to + the password needed to log into the vnc host server, or + to "file:path_to_file" to indicate a file containing + the password as its first line. + + The VNC HOST mode implies -shared. Use -noshared as + a subsequent cmdline option to disable sharing. + +-freqtab file For use with "-rawfb video" for TV tuner devices to + specify station frequencies. Instead of using the built + in ntsc-cable-us mapping of station number to frequency, + use the data in file. For stations that are not + numeric, e.g. SE20, they are placed above the highest + numbered station in the order they are found. Example: + "-freqtab /usr/X11R6/share/xawtv/europe-west.list" + You can make your own freqtab by copying the xawtv + format. + +-pipeinput cmd This option lets you supply an external command in + "cmd" that x11vnc will pipe all of the user input + events to in a simple format. In -pipeinput mode by + default x11vnc will not process any of the user input + events. If you prefix "cmd" with "tee:" it will + both send them to the pipe command and process them. + For a description of the format run "-pipeinput + tee:/bin/cat". Another prefix is "reopen" which + means to reopen pipe if it exits. Separate multiple + prefixes with commas. + + In combination with -rawfb one might be able to + do amusing things (e.g. control non-X devices). + To facilitate this, if -rawfb is in effect then the + value is stored in X11VNC_RAWFB_STR for the pipe command + to use if it wants. Do 'env | grep X11VNC' for more. + + Built-in pipeinput modes (no external program required): + + If cmd is "VID" and you are using the -rawfb for a + video capture device, then an internal list of keyboard + mappings is used to set parameters of the video. + The mappings are: + + "B" and "b" adjust the brightness up and down. + "H" and "h" adjust the hue. + "C" and "c" adjust the colour. + "N" and "n" adjust the contrast. + "S" and "s" adjust the size of the capture screen. + "I" and "i" cycle through input channels. + Up and Down arrows adjust the station (if a tuner) + F1, F2, ..., F6 will switch the video capture pixel + format to HI240, RGB565, RGB24, RGB32, RGB555, and + GREY respectively. See -rawfb video for details. + + If cmd is "CONSOLE" or "CONSOLEn" where n + is a Linux console number, then the linux console + keystroke insertion to /dev/ttyN (see -rawfb console) + is performed. + + If cmd begins with "UINPUT" then the Linux uinput + module is used to insert both keystroke and mouse events + to the Linux console (see -rawfb above). This usually + is the /dev/input/uinput device file (you may need to + create it with "mknod /dev/input/uinput c 10 223" + and insert the module with "modprobe uinput". + + The UINPUT mode currently only does US keyboards (a + scan code option may be added), and not all keysyms + are supported. + + You may want to use the options -cursor none and + -nodragging in this mode. + + Additional tuning options may be supplied via: + UINPUT:opt1,opt2,... (a comma separated list). If an + option begins with "/" it is taken as the uinput + device file. + + Which uinput is injected can be controlled by an option + string made of the characters "K", "M", and "B" + (see the -input option), e.g. "KM" allows keystroke + and motion but not button clicks. + + A UINPUT option of the form: accel=f, or accel=fx+fy + sets the mouse motion "acceleration". This is used + to correct raw mouse relative motion into how much the + application cursor moves (x11vnc has no control over, + or knowledge of how the windowing application interprets + the raw mouse motions). Typically the acceleration + for an X display is 2 (see xset "m" option). "f" + is a floating point number, e.g. 3.0. Use "fx+fy" + if you need to supply different corrections for x and y. + + Note: the default acceleration is 2.0 since it seems + both X and qt-embedded often (but not always) use + this value. + + Even with a correct accel setting the mouse position + will get out of sync (probably due to a mouse + "threshold" setting where the acceleration doe not + apply, set xset(1)). The option reset=N sets the + number of ms (default 150) after which the cursor is + attempted to be reset (by forcing the mouse to (0, + 0) via small increments and then back out to (x, y) + in 1 jump), This correction seems to be needed but can + cause jerkiness or unexpected behavior with menus, etc. + Use reset=0 to disable. + + If the uinput device has an absolute pointer (as opposed + to a normal mouse that is a relative pointer) you can + specify the option "abs". Note that a touchpad + on a laptop is an absolute device to some degree. + This (usually) avoids all the problems with mouse + acceleration. If x11vnc has trouble deducing the size + of the device, use "abs=WxH". Furthermore, if the + device is a touchscreen (assumed to have an absolute + pointer) use "touch" or "touch=WxH". + + If you set the env. var X11VNC_UINPUT_THRESHOLDS then + the thresh=n mode will be enabled. It is currently + not working well. If |dx| <= thresh and |dy| < thresh + no acceleration is applied. Use "thresh=+n" |dx| + + |dy| < thresh to be used instead (X11?) + + Example: + -pipeinput UINPUT:accel=4.0 -cursor none + + You can also set the env. var X11VNC_UINPUT_DEBUG=1 or + higher to get debugging output for UINPUT mode. + +-macnodim For the native MacOSX server, disable dimming. +-macnosleep For the native MacOSX server, disable display sleep. +-macnosaver For the native MacOSX server, disable screensaver. +-macnowait For the native MacOSX server, do not wait for the + user to switch back to his display. +-macwheel n For the native MacOSX server, set the mouse wheel + speed to n (default 5). +-macnoswap For the native MacOSX server, do not swap mouse + buttons 2 and 3. +-macnoresize For the native MacOSX server, do not resize or reset + the framebuffer even if it is detected that the screen + resolution or depth has changed. +-maciconanim n For the native MacOSX server, set n to the number + of milliseconds that the window iconify/deiconify + animation takes. In -ncache mode this value will be + used to skip the animation if possible. (default 400) +-macmenu For the native MacOSX server, in -ncache client-side + caching mode, try to cache pull down menus (not perfect + because they have animated fades, etc.) +-macuskbd For the native MacOSX server, use the original + keystroke insertion code based on a US keyboard. + +-gui [gui-opts] Start up a simple tcl/tk gui based on the the remote + control options -remote/-query described below. + Requires the "wish" program to be installed on the + machine. "gui-opts" is not required: the default + is to start up both the full gui and x11vnc with the + gui showing up on the X display in the environment + variable DISPLAY. + + "gui-opts" can be a comma separated list of items. + Currently there are these types of items: 1) a gui + mode, a 2) gui "simplicity", 3) the X display the + gui should display on, 4) a "tray" or "icon" mode, + and 5) a gui geometry. + + 1) The gui mode can be "start", "conn", or "wait" + "start" is the default mode above and is not required. + "conn" means do not automatically start up x11vnc, + but instead just try to connect to an existing x11vnc + process. "wait" means just start the gui and nothing + else (you will later instruct the gui to start x11vnc + or connect to an existing one.) + + 2) The gui simplicity is off by default (a power-user + gui with all options is presented) To start with + something less daunting supply the string "simple" + ("ez" is an alias for this). Once the gui is + started you can toggle between the two with "Misc -> + simple_gui". + + 3) Note the possible confusion regarding the potentially + two different X displays: x11vnc polls one, but you + may want the gui to appear on another. For example, if + you ssh in and x11vnc is not running yet you may want + the gui to come back to you via your ssh redirected X + display (e.g. localhost:10). + + If you do not specify a gui X display in "gui-opts" + then the DISPLAY environment variable and -display + option are tried (in that order). Regarding the x11vnc + X display the gui will try to communication with, it + first tries -display and then DISPLAY. For example, + "x11vnc -display :0 -gui otherhost:0", will remote + control an x11vnc polling :0 and display the gui on + otherhost:0 The "tray/icon" mode below reverses this + preference, preferring to display on the x11vnc display. + + 4) When "tray" or "icon" is specified, the gui + presents itself as a small icon with behavior typical + of a "system tray" or "dock applet". The color + of the icon indicates status (connected clients) and + there is also a balloon status. Clicking on the icon + gives a menu from which properties, etc, can be set and + the full gui is available under "Advanced". To be + fully functional, the gui mode should be "start" + (the default). + + Note that tray or icon mode will imply the -forever + x11vnc option (if the x11vnc server is started along + with the gui) unless -connect or -connect_or_exit has + been specified. So x11vnc (and the tray/icon gui) + will wait for more connections after the first client + disconnects. If you want only one viewer connection + include the -once option. + + For "icon" the gui just a small standalone window. + For "tray" it will attempt to embed itself in the + "system tray" if possible. If "=setpass" is appended the +n + at startup the X11 user will be prompted to set the + VNC session password. If = is appended + that icon will attempt to embed itself in the window + given by hexnumber. Use =noadvanced to disable the + full gui. (To supply more than one, use "+" sign). + E.g. -gui tray=setpass and -gui icon=0x3600028 + + Other modes: "full", the default and need not be + specified. "-gui none", do not show a gui, useful + to override a ~/.x11vncrc setting, etc. + + 5) When "geom=+X+Y" is specified, that geometry + is passed to the gui toplevel. This is the icon in + icon/tray mode, or the full gui otherwise. You can + also specify width and height, i.e. WxH+X+Y, but it + is not recommended. In "tray" mode the geometry is + ignored unless the system tray manager does not seem + to be running. One could imagine using something like + "-gui tray,geom=+4000+4000" with a display manager + to keep the gui invisible until someone logs in... + + More icon tricks, "icon=minimal" gives an icon just + with the VNC display number. You can also set the font + with "iconfont=...". The following could be useful: + "-gui icon=minimal,iconfont=5x8,geom=24x10+0-0" + + General examples of the -gui option: "x11vnc -gui", + "x11vnc -gui ez" "x11vnc -gui localhost:10", + "x11vnc -gui conn,host:0", "x11vnc -gui tray,ez" + "x11vnc -gui tray=setpass" + + If you do not intend to start x11vnc from the gui + (i.e. just remote control an existing one), then the + gui process can run on a different machine from the + x11vnc server as long as X permissions, etc. permit + communication between the two. + + FONTS: On some systems the tk fonts can be too small, + jagged, or otherwise unreadable. There are 4 env vars + you can set to be the tk font you prefer: + + X11VNC_FONT_BOLD main font for menus and buttons. + X11VNC_FONT_FIXED font for fixed width text. + + X11VNC_FONT_BOLD_SMALL tray icon font. + X11VNC_FONT_REG_SMALL tray icon menu font. + + The last two only apply for the tray icon mode. + + Here are some examples: + + -env X11VNC_FONT_BOLD='Helvetica -16 bold' + -env X11VNC_FONT_FIXED='Courier -14' + -env X11VNC_FONT_REG_SMALL='Helvetica -12' + + You can put the lines like the above (without the + quotes) in your ~/.x11vncrc file to avoid having to + specify them on the x11vnc command line. + +-remote command Remotely control some aspects of an already running + x11vnc server. "-R" and "-r" are aliases for + "-remote". After the remote control command is + sent to the running server the 'x11vnc -remote ...' + command exits. You can often use the -query command + (see below) to see if the x11vnc server processed your + -remote command. + + The default communication channel is that of X + properties (specifically X11VNC_REMOTE), and so this + command must be run with correct settings for DISPLAY + and possibly XAUTHORITY to connect to the X server + and set the property. Alternatively, use the -display + and -auth options to set them to the correct values. + The running server cannot use the -novncconnect option + because that disables the communication channel. + See below for alternate channels. + + For example: 'x11vnc -remote stop' (which is the same as + 'x11vnc -R stop') will close down the x11vnc server. + 'x11vnc -R shared' will enable shared connections, and + 'x11vnc -R scale:3/4' will rescale the desktop. + + To use a different name for the X11 property (e.g. to + have separate communication channels for multiple + x11vnc's on the same display) set the X11VNC_REMOTE + environment variable to the string you want, for + example: -env X11VNC_REMOTE=X11VNC_REMOTE_12345 + Both sides of the channel must use the same unique name. + + To run a bunch of commands in a sequence use something + like: x11vnc -R 'script:firstcmd;secondcmd;...' + + Use x11vnc -R script:file=/path/to/file to read commands + from a file (can be multi-line and use the comment '#' + character in the normal way. The ';' separator must + still be used to separate each command.) + + To not try to contact another x11vnc process and instead + just run the command (or query) directly, prefix the + command with the string "DIRECT:" + + The following -remote/-R commands are supported: + + stop terminate the server, same as "quit" + "exit" or "shutdown". + ping see if the x11vnc server responds. + return is: ans=ping: + ping:mystring as above, but use your own unique string +. + return is: ans=ping:mystring: + blacken try to push a black fb update to all + clients (due to timings a client + could miss it). Same as "zero", also + "zero:x1,y1,x2,y2" for a rectangle. + refresh send the entire fb to all clients. + reset recreate the fb, polling memory, etc. + id:windowid set -id window to "windowid". empty + or "root" to go back to root window + sid:windowid set -sid window to "windowid" + id_cmd:cmd cmds: raise, lower, map, unmap, iconify, + move:dXdY, resize:dWdH, geom:WxH+X+Y. dX + dY, dW, and dH must have a leading "+" + or "-" e.g.: move:-30+10 resize:+20+35 + also: wm_delete, wm_name:string and + icon_name:string. Also id_cmd:win=N:cmd + waitmapped wait until subwin is mapped. + nowaitmapped do not wait until subwin is mapped. + clip:WxH+X+Y set -clip mode to "WxH+X+Y" + flashcmap enable -flashcmap mode. + noflashcmap disable -flashcmap mode. + shiftcmap:n set -shiftcmap to n. + notruecolor enable -notruecolor mode. + truecolor disable -notruecolor mode. + overlay enable -overlay mode (if applicable). + nooverlay disable -overlay mode. + overlay_cursor in -overlay mode, enable cursor drawing. + overlay_nocursor disable cursor drawing. same as + nooverlay_cursor. + 8to24 enable -8to24 mode (if applicable). + no8to24 disable -8to24 mode. + 8to24_opts:str set the -8to24 opts to "str". + 24to32 enable -24to32 mode (if applicable). + no24to32 disable -24to32 mode. + visual:vis set -visual to "vis" + scale:frac set -scale to "frac" + scale_cursor:f set -scale_cursor to "f" + viewonly enable -viewonly mode. + noviewonly disable -viewonly mode. + shared enable -shared mode. + noshared disable -shared mode. + forever enable -forever mode. + noforever disable -forever mode. + timeout:n reset -timeout to n, if there are + currently no clients, exit unless one + connects in the next n secs. + tightfilexfer enable filetransfer for NEW clients. + notightfilexfer disable filetransfer for NEW clients. + ultrafilexfer enable filetransfer for clients. + noultrafilexfer disable filetransfer for clients. + rfbversion:n.m set -rfbversion for new clients. + http enable http client connections. + nohttp disable http client connections. + deny deny any new connections, same as "lock" + nodeny allow new connections, same as "unlock" + avahi enable avahi service advertising. + noavahi disable avahi service advertising. + mdns enable avahi service advertising. + nomdns disable avahi service advertising. + zeroconf enable avahi service advertising. + nozeroconf disable avahi service advertising. + connect:host do reverse connection to host, "host" + may be a comma separated list of hosts + or host:ports. See -connect. Passwords + required as with fwd connections. + See X11VNC_REVERSE_CONNECTION_NO_AUTH=1 + disconnect:host disconnect any clients from "host" + same as "close:host". Use host + "all" to close all current clients. + If you know the client internal hex ID, + e.g. 0x3 (returned by "-query clients" + and RFB_CLIENT_ID) you can use that too. + proxy:host:port set reverse connection proxy (empty to + disable). + allowonce:host For the next connection only, allow + connection from "host". In -ssl mode + two connections are allowed (i.e. Fetch + Cert) unless X11VNC_NO_SSL_ALLOW_TWICE=1 + allow:hostlist set -allow list to (comma separated) + "hostlist". See -allow and -localhost. + Do not use with -allow /path/to/file + Use "+host" to add a single host, and + use "-host" to delete a single host + localhost enable -localhost mode + nolocalhost disable -localhost mode + listen:str set -listen to str, empty to disable. + noipv6 enable -noipv6 mode. + ipv6 disable -noipv6 mode. + noipv4 enable -noipv4 mode. + ipv4 disable -noipv4 mode. + 6 enable -6 IPv6 listening mode. + no6 disable -6 IPv6 listening mode. + lookup disable -nolookup mode. + nolookup enable -nolookup mode. + lookup disable -nolookup mode. + input:str set -input to "str", empty to disable. + grabkbd enable -grabkbd mode. + nograbkbd disable -grabkbd mode. + grabptr enable -grabptr mode. + nograbptr disable -grabptr mode. + grabalways enable -grabalways mode. + nograbalways disable -grabalways mode. + grablocal:n set -grablocal to n. + client_input:str set the K, M, B -input on a per-client + basis. select which client as for + disconnect, e.g. client_input:host:MB + or client_input:0x2:K + accept:cmd set -accept "cmd" (empty to disable). + afteraccept:cmd set -afteraccept (empty to disable). + gone:cmd set -gone "cmd" (empty to disable). + noshm enable -noshm mode. + shm disable -noshm mode (i.e. use shm). + flipbyteorder enable -flipbyteorder mode, you may need + to set noshm for this to do something. + noflipbyteorder disable -flipbyteorder mode. + onetile enable -onetile mode. (you may need to + set shm for this to do something) + noonetile disable -onetile mode. + solid enable -solid mode + nosolid disable -solid mode. + solid_color:color set -solid color (and apply it). + blackout:str set -blackout "str" (empty to disable). + See -blackout for the form of "str" + (basically: WxH+X+Y,...) + Use "+WxH+X+Y" to append a single + rectangle use "-WxH+X+Y" to delete one + xinerama enable -xinerama mode. (if applicable) + noxinerama disable -xinerama mode. + xtrap enable -xtrap input mode(if applicable) + noxtrap disable -xtrap input mode. + xrandr enable -xrandr mode. (if applicable) + noxrandr disable -xrandr mode. + xrandr_mode:mode set the -xrandr mode to "mode". + rotate:mode set the -rotate mode to "mode". + padgeom:WxH set -padgeom to WxH (empty to disable) + If WxH is "force" or "do" the padded + geometry fb is immediately applied. + quiet enable -quiet mode. + noquiet disable -quiet mode. + modtweak enable -modtweak mode. + nomodtweak enable -nomodtweak mode. + xkb enable -xkb modtweak mode. + noxkb disable -xkb modtweak mode. + capslock enable -capslock mode. + nocapslock disable -capslock mode. + skip_lockkeys enable -skip_lockkeys mode. + noskip_lockkeys disable -skip_lockkeys mode. + skip_keycodes:str enable -xkb -skip_keycodes "str". + sloppy_keys enable -sloppy_keys mode. + nosloppy_keys disable -sloppy_keys mode. + skip_dups enable -skip_dups mode. + noskip_dups disable -skip_dups mode. + add_keysyms enable -add_keysyms mode. + noadd_keysyms stop adding keysyms. those added will + still be removed at exit. + clear_mods enable -clear_mods mode and clear them. + noclear_mods disable -clear_mods mode. + clear_keys enable -clear_keys mode and clear them. + noclear_keys disable -clear_keys mode. + clear_locks do the clear_locks action. + clear_all do the clear_all action. + keystate have x11vnc print current keystate. + remap:str set -remap "str" (empty to disable). + See -remap for the form of "str" + (basically: key1-key2,key3-key4,...) + Use "+key1-key2" to append a single + keymapping, use "-key1-key2" to delete. + norepeat enable -norepeat mode. + repeat disable -norepeat mode. + nofb enable -nofb mode. + fb disable -nofb mode. + bell enable bell (if supported). + nobell disable bell. + sendbell ring the bell now. + nosel enable -nosel mode. + sel disable -nosel mode. + noprimary enable -noprimary mode. + primary disable -noprimary mode. + nosetprimary enable -nosetprimary mode. + setprimary disable -nosetprimary mode. + noclipboard enable -noclipboard mode. + clipboard disable -noclipboard mode. + nosetclipboard enable -nosetclipboard mode. + setclipboard disable -nosetclipboard mode. + seldir:str set -seldir to "str" + resend_cutbuffer resend the most recent CUTBUFFER0 copy + resend_clipboard resend the most recent CLIPBOARD copy + resend_primary resend the most recent PRIMARY copy + cursor:mode enable -cursor "mode". + show_cursor enable showing a cursor. + noshow_cursor disable showing a cursor. (same as + "nocursor") + cursor_drag enable cursor changes during drag. + nocursor_drag disable cursor changes during drag. + arrow:n set -arrow to alternate n. + xfixes enable xfixes cursor shape mode. + noxfixes disable xfixes cursor shape mode. + alphacut:n set -alphacut to n. + alphafrac:f set -alphafrac to f. + alpharemove enable -alpharemove mode. + noalpharemove disable -alpharemove mode. + alphablend disable -noalphablend mode. + noalphablend enable -noalphablend mode. + cursorshape disable -nocursorshape mode. + nocursorshape enable -nocursorshape mode. + cursorpos disable -nocursorpos mode. + nocursorpos enable -nocursorpos mode. + xwarp enable -xwarppointer mode. + noxwarp disable -xwarppointer mode. + buttonmap:str set -buttonmap "str", empty to disable + dragging disable -nodragging mode. + nodragging enable -nodragging mode. + ncache reenable -ncache mode. + noncache disable -ncache mode. + ncache_size:n set -ncache size to n. + ncache_cr enable -ncache_cr mode. + noncache_cr disable -ncache_cr mode. + ncache_no_moveraise enable no_moveraise mode. + noncache_no_moveraise disable no_moveraise mode. + ncache_no_dtchange enable ncache_no_dtchange mode. + noncache_no_dtchange disable ncache_no_dtchange mode. + ncache_old_wm enable ncache_old_wm mode. + noncache_old_wm disable ncache_old_wm mode. + ncache_no_rootpixmap enable ncache_no_rootpixmap. + noncache_no_rootpixmap disable ncache_no_rootpixmap. + ncache_reset_rootpixmap recheck the root pixmap, ncrp + ncache_keep_anims enable ncache_keep_anims. + noncache_keep_anims disable ncache_keep_anims. + ncache_pad:n set -ncache_pad to n. + wireframe enable -wireframe mode. same as "wf" + nowireframe disable -wireframe mode. same as "nowf" + wireframe:str enable -wireframe mode string. + wireframe_mode:str enable -wireframe mode string. + wireframelocal enable wireframelocal. same as "wfl" + nowireframe disable wireframelocal. same as "nowfl" + wirecopyrect:str set -wirecopyrect string. same as "wcr: +" + scrollcopyrect:str set -scrollcopyrect string. same "scr +" + noscrollcopyrect disable -scrollcopyrect mode. "noscr" + scr_area:n set -scr_area to n + scr_skip:list set -scr_skip to "list" + scr_inc:list set -scr_inc to "list" + scr_keys:list set -scr_keys to "list" + scr_term:list set -scr_term to "list" + scr_keyrepeat:str set -scr_keyrepeat to "str" + scr_parms:str set -scr_parms parameters. + fixscreen:str set -fixscreen to "str". + noxrecord disable all use of RECORD extension. + xrecord enable use of RECORD extension. + reset_record reset RECORD extension (if avail.) + pointer_mode:n set -pointer_mode to n. same as "pm" + input_skip:n set -input_skip to n. + allinput enable use of -allinput mode. + noallinput disable use of -allinput mode. + input_eagerly enable use of -input_eagerly mode. + noinput_eagerly disable use of -input_eagerly mode. + ssltimeout:n set -ssltimeout to n. + speeds:str set -speeds to str. + wmdt:str set -wmdt to str. + debug_pointer enable -debug_pointer, same as "dp" + nodebug_pointer disable -debug_pointer, same as "nodp" + debug_keyboard enable -debug_keyboard, same as "dk" + nodebug_keyboard disable -debug_keyboard, same as "nodk" + keycode:n inject keystroke 'keycode' (xmodmap -pk) + keycode:n,down inject 'keycode' (down=0,1) + keysym:str inject keystroke 'keysym' (number/name) + keysym:str,down inject 'keysym' (down=0,1) + ptr:x,y,mask inject pointer event x, y, button-mask + fakebuttonevent:button,down direct XTestFakeButtonEvent. + sleep:t sleep floating point time t. + get_xprop:p get X property named 'p'. + set_xprop:p:val set X property named 'p' to 'val'. + p -> id=NNN:p for hex/dec window id. + wininfo:id get info about X window id. use 'root' + for root window, use +id for children. + grab_state get state of pointer and keyboard grab. + pointer_pos print XQueryPointer x,y cursor position. + pointer_x print XQueryPointer x cursor position. + pointer_y print XQueryPointer y cursor position. + pointer_same print XQueryPointer ptr on same screen. + pointer_root print XQueryPointer curr ptr rootwin. + pointer_mask print XQueryPointer button and mods mask + mouse_x print x11vnc's idea of cursor position. + mouse_y print x11vnc's idea of cursor position. + noop do nothing. + defer:n set -defer to n ms,same as deferupdate:n + wait:n set -wait to n ms. + extra_fbur:n set -extra_fbur to n. + wait_ui:f set -wait_ui factor to f. + setdefer:n set -setdefer to -2,-1,0,1, or 2. + wait_bog disable -nowait_bog mode. + nowait_bog enable -nowait_bog mode. + slow_fb:f set -slow_fb to f seconds. + xrefresh:f set -xrefresh to f seconds. + readtimeout:n set read timeout to n seconds. + nap enable -nap mode. + nonap disable -nap mode. + sb:n set -sb to n s, same as screen_blank:n + fbpm disable -nofbpm mode. + nofbpm enable -nofbpm mode. + dpms disable -nodpms mode. + nodpms enable -nodpms mode. + forcedpms enable -forcedpms mode. + noforcedpms disable -forcedpms mode. + clientdpms enable -clientdpms mode. + noclientdpms disable -clientdpms mode. + noserverdpms enable -noserverdpms mode. + serverdpms disable -noserverdpms mode. + noultraext enable -noultraext mode. + ultraext disable -noultraext mode. + chatwindow enable local chatwindow mode. + nochatwindow disable local chatwindow mode. + chaton begin chat using local window. + chatoff end chat using local window. + xdamage enable xdamage polling hints. + noxdamage disable xdamage polling hints. + xd_area:A set -xd_area max pixel area to "A" + xd_mem:f set -xd_mem remembrance to "f" + fs:frac set -fs fraction to "frac", e.g. 0.5 + gaps:n set -gaps to n. + grow:n set -grow to n. + fuzz:n set -fuzz to n. + snapfb enable -snapfb mode. + nosnapfb disable -snapfb mode. + rawfb:str set -rawfb mode to "str". + uinput_accel:f set uinput_accel to f. + uinput_thresh:n set uinput_thresh to n. + uinput_reset:n set uinput_reset to n ms. + uinput_always:n set uinput_always to 1/0. + progressive:n set LibVNCServer -progressive slice + height parameter to n. + desktop:str set -desktop name to str for new clients +. + rfbport:n set -rfbport to n. + macnosaver enable -macnosaver mode. + macsaver disable -macnosaver mode. + macnowait enable -macnowait mode. + macwait disable -macnowait mode. + macwheel:n set -macwheel to n. + macnoswap enable -macnoswap mouse button mode. + macswap disable -macnoswap mouse button mode. + macnoresize enable -macnoresize mode. + macresize disable -macnoresize mode. + maciconanim:n set -maciconanim to n. + macmenu enable -macmenu mode. + macnomenu disable -macmenu mode. + macuskbd enable -macuskbd mode. + macnouskbd disable -macuskbd mode. + httpport:n set -httpport to n. + httpdir:dir set -httpdir to dir (and enable http). + enablehttpproxy enable -enablehttpproxy mode. + noenablehttpproxy disable -enablehttpproxy mode. + alwaysshared enable -alwaysshared mode. + noalwaysshared disable -alwaysshared mode. + (may interfere with other options) + nevershared enable -nevershared mode. + nonevershared disable -nevershared mode. + (may interfere with other options) + dontdisconnect enable -dontdisconnect mode. + nodontdisconnect disable -dontdisconnect mode. + (may interfere with other options) + debug_xevents enable debugging X events. + nodebug_xevents disable debugging X events. + debug_xdamage enable debugging X DAMAGE mechanism. + nodebug_xdamage disable debugging X DAMAGE mechanism. + debug_wireframe enable debugging wireframe mechanism. + nodebug_wireframe disable debugging wireframe mechanism. + debug_scroll enable debugging scrollcopy mechanism. + nodebug_scroll disable debugging scrollcopy mechanism. + debug_tiles enable -debug_tiles + nodebug_tiles disable -debug_tiles + debug_grabs enable -debug_grabs + nodebug_grabs disable -debug_grabs + debug_sel enable -debug_sel + nodebug_sel disable -debug_sel + debug_ncache enable -debug_ncache + nodebug_ncache disable -debug_ncache + dbg enable -dbg crash shell + nodbg disable -dbg crash shell + + noremote disable the -remote command processing, + it cannot be turned back on. + + bcx_xattach:str This remote control command is for + use with the BARCO xattach program or the x2x program. + Both of these programs are for 'pointer and keyboard' + sharing between separate X displays. In general the + two displays are usually nearby, e.g. on the same desk, + and this allows the user to share a single pointer and + keyboard between them. The user moves the mouse to + an edge and then the mouse pointer appears to 'jump' + to the other display screen. Thus it emulates what a + single X server would do for two screens (e.g. :0.0 and + :0.1) The illusion of a single Xserver with multiple + screens is achieved by forwarding events to the 2nd + one via the XTEST extension. + + What the x11vnc bcx_xattach command does is to perform + some pointer movements to try to INDUCE xattach/x2x + to 'jump' to the other display. In what follows the + 'master' display refers to the one that when it has + 'focus' it is basically doing nothing besides watching + for the mouse to go over an edge. The 'slave' + display refers to the one to which the mouse and + keyboard is redirected to once an edge in the master + has been crossed. Note that the x11vnc executing the + bcx_xattach command MUST be the one connected to the + *master* display. + + Also note that when input is being redirected (via + XTEST) from the master display to the slave display, + the master display's pointer and keyboard are *grabbed* + by xattach/x2x. x11vnc can use this info to verify that + the master/slave mode change has taken place correctly. + If you specify the "ifneeded" option (see below) + and the initial grab state is that of the desired + final state, then no pointer movements are injected + and "DONE,GRAB_OK" is returned. + + "str" must contain one of "up", "down", "left", + or "right" to indicate the direction of the 'jump'. + "str" must also contain one of "master_to_slave" + or "slave_to_master" to indicate the type of mode + change induced by the jump. Use "M2S" and "S2M" + as shorter aliases. + + "str" may be a "+" separated list of additional + tuning options. The "shift=n" option indicates an + offset shift position away from (0,0) (default 20). + "final=x+y" specifies the final position of the cursor + at the end of the normal move sequence; default 30+30. + "extra_move=x+y" means to do one more pointer move + after "final" to x+y. "dt=n" sets the sleep time + in milliseconds between pointer moves (default: 40ms) + "retry=n" specifies the maximum number of retries if + the grab state change fails. "ifneeded" means to not + apply the pointer movements if the initial grab state is + that of the desired final state. "nograbcheck" means + to not check if the grab state changed as expected and + only apply the pointer movements (default is to check + the grab states.) + + If you do not specify "up", etc., to bcx_xattach + nothing will be attempted and the command returns + the string FAIL,NO_DIRECTION_SPECIFIED. If you do + not specify "master_to_slave" or "M2S", etc., to + bcx_xattach nothing will be attempted and the command + returns the string FAIL,NO_MODE_CHANGE_SPECIFIED. + + Otherwise, the returned string will contain "DONE". + It will be "DONE,GRAB_OK" if the grab state changed + as expected (or if "ifneeded" was supplied and + the initial grab state was already the desired + one.) If the initial grab state was incorrect, + but the final grab state was correct then it is + "DONE,GRAB_FAIL_INIT". If the initial grab state + was correct, but the final grab state was incorrect + then it is "DONE,GRAB_FAIL_FINAL". If both are + incorrect it will be "DONE,GRAB_FAIL". Under grab + failure the string will be followed by ":p1,k1-p2,k2" + where p1,k1 indicates the initial pointer and keyboard + grab states and p2,k2 the final ones. If GRAB_FAIL or + GRAB_FAIL_FINAL occurs, the action will be retried up + to 3 times; trying to reset the state and sleeping a + bit between each try. Set retry=n to adjust the number + of retries, zero to disable retries. + + Examples: + -R bcx_xattach:down+M2S + -R bcx_xattach:up+S2M + -R bcx_xattach:up+S2M+nograbcheck+dt=30 + -R bcx_xattach:down+M2S+extra_move=100+100 + + or use -Q instead of -R to retrieve the result text. + + End of the bcx_xattach:str description. + + The vncconnect(1) command from standard VNC + distributions may also be used if string is prefixed + with "cmd=" E.g. 'vncconnect cmd=stop'. Under some + circumstances xprop(1) can used if it supports -set + (see the FAQ). + + If "-connect /path/to/file" has been supplied to the + running x11vnc server then that file can be used as a + communication channel (this is the only way to remote + control one of many x11vnc's polling the same X display) + Simply run: 'x11vnc -connect /path/to/file -remote ...' + or you can directly write to the file via something + like: "echo cmd=stop > /path/to/file", etc. + +-query variable Like -remote, except just query the value of + "variable". "-Q" is an alias for "-query". + Multiple queries can be done by separating variables + by commas, e.g. -query var1,var2. The results come + back in the form ans=var1:value1,ans=var2:value2,... + to the standard output. If a variable is read-only, + it comes back with prefix "aro=" instead of "ans=". + + Some -remote commands are pure actions that do not make + sense as variables, e.g. "stop" or "disconnect", in + these cases the value returned is "N/A". To direct a + query straight to the X11VNC_REMOTE property or connect + file use "qry=..." instead of "cmd=..." + + ans= stop quit exit shutdown ping resend_cutbuffer + resend_clipboard resend_primary blacken zero refresh + reset close disconnect id_cmd id sid waitmapped + nowaitmapped clip flashcmap noflashcmap shiftcmap + truecolor notruecolor overlay nooverlay overlay_cursor + overlay_yescursor nooverlay_nocursor nooverlay_cursor + nooverlay_yescursor overlay_nocursor 8to24 no8to24 + 8to24_opts 24to32 no24to32 visual scale scale_cursor + viewonly noviewonly shared noshared forever noforever + once timeout tightfilexfer notightfilexfer ultrafilexfer + noultrafilexfer rfbversion deny lock nodeny unlock avahi + mdns zeroconf noavahi nomdns nozeroconf connect proxy + allowonce allow noipv6 ipv6 noipv4 ipv4 no6 6 localhost + nolocalhost listen lookup nolookup accept afteraccept + gone shm noshm flipbyteorder noflipbyteorder onetile + noonetile solid_color solid nosolid blackout xinerama + noxinerama xtrap noxtrap xrandr noxrandr xrandr_mode + rotate padgeom quiet q noquiet modtweak nomodtweak xkb + noxkb capslock nocapslock skip_lockkeys noskip_lockkeys + skip_keycodes sloppy_keys nosloppy_keys skip_dups + noskip_dups add_keysyms noadd_keysyms clear_mods + noclear_mods clear_keys noclear_keys clear_all + clear_locks keystate remap repeat norepeat fb nofb bell + nobell sendbell sel nosel primary noprimary setprimary + nosetprimary clipboard noclipboard setclipboard + nosetclipboard seldir cursorshape nocursorshape + cursorpos nocursorpos cursor_drag nocursor_drag cursor + show_cursor noshow_cursor nocursor arrow xfixes + noxfixes xdamage noxdamage xd_area xd_mem alphacut + alphafrac alpharemove noalpharemove alphablend + noalphablend xwarppointer xwarp noxwarppointer + noxwarp buttonmap dragging nodragging ncache_cr + noncache_cr ncache_no_moveraise noncache_no_moveraise + ncache_no_dtchange noncache_no_dtchange + ncache_no_rootpixmap noncache_no_rootpixmap + ncache_reset_rootpixmap ncrp ncache_keep_anims + noncache_keep_anims ncache_old_wm noncache_old_wm + ncache_pad ncache noncache ncache_size debug_ncache + nodebug_ncache wireframe_mode wireframe wf nowireframe + nowf wireframelocal wfl nowireframelocal nowfl + wirecopyrect wcr nowirecopyrect nowcr scr_area + scr_skip scr_inc scr_keys scr_term scr_keyrepeat + scr_parms scrollcopyrect scr noscrollcopyrect + noscr fixscreen noxrecord xrecord reset_record + pointer_mode pm input_skip allinput noallinput + input_eagerly noinput_eagerly input grabkbd nograbkbd + grabptr nograbptr grabalways nograbalways grablocal + client_input ssltimeout speeds wmdt debug_pointer dp + nodebug_pointer nodp debug_keyboard dk nodebug_keyboard + nodk keycode keysym ptr fakebuttonevent sleep get_xprop + set_xprop wininfo bcx_xattach deferupdate defer + setdefer extra_fbur wait_ui wait_bog nowait_bog + slow_fb xrefresh wait readtimeout nap nonap sb + screen_blank fbpm nofbpm dpms nodpms clientdpms + noclientdpms forcedpms noforcedpms noserverdpms + serverdpms noultraext ultraext chatwindow nochatwindow + chaton chatoff fs gaps grow fuzz snapfb nosnapfb + rawfb uinput_accel uinput_thresh uinput_reset + uinput_always progressive rfbport http nohttp httpport + httpdir enablehttpproxy noenablehttpproxy alwaysshared + noalwaysshared nevershared noalwaysshared dontdisconnect + nodontdisconnect desktop debug_xevents nodebug_xevents + debug_xevents debug_xdamage nodebug_xdamage + debug_xdamage debug_wireframe nodebug_wireframe + debug_wireframe debug_scroll nodebug_scroll debug_scroll + debug_tiles dbt nodebug_tiles nodbt debug_tiles + debug_grabs nodebug_grabs debug_sel nodebug_sel dbg + nodbg macnosaver macsaver nomacnosaver macnowait macwait + nomacnowait macwheel macnoswap macswap nomacnoswap + macnoresize macresize nomacnoresize maciconanim macmenu + macnomenu nomacmenu macuskbd nomacuskbd noremote + + aro= noop display vncdisplay icon_mode autoport + loop loopbg desktopname guess_desktop guess_dbus + http_url auth xauth users rootshift clipshift scale_str + scaled_x scaled_y scale_numer scale_denom scale_fac_x + scale_fac_y scaling_blend scaling_nomult4 scaling_pad + scaling_interpolate inetd privremote unsafe safer nocmds + passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem + sslverify stunnel stunnel_pem https httpsredir usepw + using_shm logfile o flag rmflag rc norc h help V version + lastmod bg sigpipe threads readrate netrate netlatency + pipeinput clients client_count pid ext_xtest ext_xtrap + ext_xrecord ext_xkb ext_xshm ext_xinerama ext_overlay + ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons + button_mask mouse_x mouse_y grab_state pointer_pos + pointer_x pointer_y pointer_same pointer_root + pointer_mask bpp depth indexed_color dpy_x dpy_y wdpy_x + wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y rfbauth + passwd viewpasswd + +-QD variable Just like -query variable, but returns the default + value for that parameter (no running x11vnc server + is consulted) + +-sync By default -remote commands are run asynchronously, that + is, the request is posted and the program immediately + exits. Use -sync to have the program wait for an + acknowledgement from the x11vnc server that command was + processed (somehow). On the other hand -query requests + are always processed synchronously because they have + to wait for the answer. + + Also note that if both -remote and -query requests are + supplied on the command line, the -remote is processed + first (synchronously: no need for -sync), and then + the -query request is processed in the normal way. + This allows for a reliable way to see if the -remote + command was processed by querying for any new settings. + Note however that there is timeout of a few seconds + (see the next paragraph) so if the x11vnc takes longer + than that to process the requests the requester will + think that a failure has taken place. + + The default is to wait 3.5 seconds. Or if cmd=stop + only 1.0 seconds. If cmd matches 'script:' then it + will wait up to 10.0 seconds. Set X11VNC_SYNC_TIMEOUT + to the number of seconds you want it to wait. + +-query_retries str If a query fails to get a response from an x11vnc + server, retry up to n times. "str" is specified as + n[:t][/match] Optionally the delay between tries may + be specified by "t" a floating point time (default + 0.5 seconds.) Note: the response is not checked for + validity or whether it corresponds to the query sent. + The query "ping:mystring" may be used to help uniquely + identify the query. Optionally, a matching string after + a "/" will be used to check the result text. Up to + n retries will take place until the matching string is + found in the output text. If the match string is never + found the program's exit code is 1; if the match is + found it exits with 0. Note that there may be stdout + printed for each retry (i.e. multiple lines printed + out to stdout.) + Example: -query_retries 4:1.5/grab_state + +-remote_prefix str Enable a remote-control communication channel for + connected VNC clients. str is a non-empty string. If a + VNC client sends rfbCutText having the prefix "str" + then the part after it is processed as though it were + sent via 'x11vnc -remote ...'. If it begins with + neither 'cmd=' nor 'qry=' then 'qry=' is assumed. + Any corresponding output text for that remote control + command is sent back to all client as rfbCutText. + The returned output is also prefixed with "str". + Example: -remote_prefix DO_THIS: + + Note that enabling -remote_prefix allows the remote + VNC viewers to run x11vnc -remote commands. Do not + use this option if they are not to be trusted. + +-noremote Do not process any remote control commands or queries. +-yesremote Do process remote control commands or queries. + Default: -yesremote + + A note about security wrt remote control commands. + If someone can connect to the X display and change + the property X11VNC_REMOTE, then they can remotely + control x11vnc. Normally access to the X display is + protected. Note that if they can modify X11VNC_REMOTE + on the X server, they have enough permissions to also + run their own x11vnc and thus have complete control + of the desktop. If the "-connect /path/to/file" + channel is being used, obviously anyone who can write + to /path/to/file can remotely control x11vnc. So be + sure to protect the X display and that file's write + permissions. See -privremote below. + + If you are paranoid and do not think -noremote is + enough, to disable the X11VNC_REMOTE property channel + completely use -novncconnect, or use the -safer option + that shuts many things off. + +-unsafe A few remote commands are disabled by default + (currently: id:pick, accept:, gone:, and + rawfb:setup:) because they are associated with + running external programs. If you specify -unsafe, then + these remote-control commands are allowed. Note that + you can still specify these parameters on the command + line, they just cannot be invoked via remote-control. +-safer Equivalent to: -novncconnect -noremote and prohibiting + -gui and the -connect file. Shuts off communcation + channels. +-privremote Perform some sanity checks and disable remote-control + commands if it appears that the X DISPLAY and/or + connectfile can be accessed by other users. Once + remote-control is disabled it cannot be turned back on. +-nocmds No external commands (e.g. system(3), popen(3), exec(3)) + will be run at all. +-allowedcmds list "list" contains a comma separated list of the only + external commands that can be run. The full list of + associated options is: + + stunnel, ssl, unixpw, WAIT, zeroconf, id, accept, + afteraccept, gone, pipeinput, v4l-info, rawfb-setup, + dt, gui, ssh, storepasswd, passwdfile, custom_passwd, + findauth, crash. + + See each option's help to learn the associated external + command. Note that the -nocmds option takes precedence + and disables all external commands. + +-deny_all For use with -remote nodeny: start out denying all + incoming clients until "-remote nodeny" is used to + let them in. + + + +These options are passed to LibVNCServer: + +-rfbport port TCP port for RFB protocol +-rfbwait time max time in ms to wait for RFB client +-rfbauth passwd-file use authentication on RFB protocol + (use 'storepasswd' to create a password file) +-rfbversion 3.x Set the version of the RFB we choose to advertise +-permitfiletransfer permit file transfer support +-passwd plain-password use authentication + (use plain-password as password, USE AT YOUR RISK) +-deferupdate time time in ms to defer updates (default 40) +-deferptrupdate time time in ms to defer pointer updates (default none) +-desktop name VNC desktop name (default "LibVNCServer") +-alwaysshared always treat new clients as shared +-nevershared never treat new clients as shared +-dontdisconnect don't disconnect existing clients when a new non-shared + connection comes in (refuse new connection instead) +-httpdir dir-path enable http server using dir-path home +-httpport portnum use portnum for http connection +-enablehttpproxy enable http proxy support +-progressive height enable progressive updating for slow links +-listen ipaddr listen for connections only on network interface with + addr ipaddr. '-listen localhost' and hostname work too. + +libvncserver-tight-extension options: +-disablefiletransfer disable file transfer +-ftproot string set ftp root + + Pretty wild huh? Contact me if you have any questions or problems. + + Personally, I use: +x11vnc -rfbauth $HOME/.vnc/passwd -solid diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/allowed_input_t.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/allowed_input_t.h new file mode 100755 index 0000000..99e814e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/allowed_input_t.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_ALLOWED_INPUT_T_H +#define _X11VNC_ALLOWED_INPUT_T_H + +/* -- allowed_input_t.h -- */ + +typedef struct allowed_input { + int keystroke; + int motion; + int button; + int clipboard; + int files; +} allowed_input_t; + +#endif /* _X11VNC_ALLOWED_INPUT_T_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/appshare.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/appshare.c new file mode 100755 index 0000000..fc3c29e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/appshare.c @@ -0,0 +1,2124 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- appshare.c -- */ + +#include "x11vnc.h" + +extern int pick_windowid(unsigned long *num); +extern char *get_xprop(char *prop, Window win); +extern int set_xprop(char *prop, Window win, char *value); +extern void set_env(char *name, char *value); +extern double dnow(void); + +static char *usage = +"\n" +" x11vnc -appshare: an experiment in application sharing via x11vnc.\n" +"\n" +#if !SMALL_FOOTPRINT +" Usage: x11vnc -appshare -id windowid -connect viewer_host:0\n" +" x11vnc -appshare -id pick -connect viewer_host:0\n" +"\n" +" Both the -connect option and the -id (or -sid) option are required.\n" +" (However see the -control option below that can replace -connect.)\n" +"\n" +" The VNC viewer at viewer_host MUST be in 'listen' mode. This is because\n" +" a new VNC connection (and viewer window) is established for each new\n" +" toplevel window that the application creates. For example:\n" +"\n" +" vncviewer -listen 0\n" +"\n" +" The '-connect viewer_host:0' indicates the listening viewer to connect to.\n" +"\n" +" No password should be used, otherwise it will need to be typed for each\n" +" new window (or one could use vncviewer -passwd file if the viewer supports\n" +" that.) For security an SSH tunnel can be used:\n" +"\n" +" ssh -R 5500:localhost:5500 user@server_host\n" +"\n" +" (then use -connect localhost:0)\n" +"\n" +" The -id/-sid option is as in x11vnc(1). It is either a numerical window\n" +" id or the string 'pick' which will ask the user to click on an app window.\n" +" To track more than one application at the same time, list their window ids\n" +" separated by commas (see also the 'add_app' command below.)\n" +"\n" +" Additional options:\n" +"\n" +" -h, -help Print this help.\n" +" -debug Print debugging output (same as X11VNC_APPSHARE_DEBUG=1)\n" +" -showmenus Create a new viewer window even if a new window is\n" +" completely inside of an existing one. Default is to\n" +" try to not show them in a new viewer window.\n" +" -noexit Do not exit if the main app (windowid/pick) window\n" +" goes away. Default is to exit.\n" +" -display dpy X DISPLAY to use.\n" +" -trackdir dir Set tracking directory to 'dir'. x11vnc -appshare does\n" +" better if it can communicate with the x11vnc's via a\n" +" file channel. By default a dir in /tmp is used, -trackdir\n" +" specifies another directory, or use 'none' to disable.\n" +" -args 'string' Pass options 'string' to x11vnc (e.g. -scale 3/4,\n" +" -viewonly, -wait, -once, etc.)\n" +" -env VAR=VAL Set environment variables on cmdline as in x11vnc.\n" +"\n" +" -control file This is a file that one edits to manage the appshare\n" +" mode. It replaces -connect. Lines beginning with '#'\n" +" are ignored. Initially start off with all of the\n" +" desired clients in the file, one per line. If you add\n" +" a new client-line, that client is connected to. If you\n" +" delete (or comment out) a client-line, that client is\n" +" disconnected (for this to work, do not disable trackdir.)\n" +"\n" +" You can also put cmd= lines in the control file to perform\n" +" different actions. These are supported:\n" +"\n" +" cmd=quit Disconnect all clients and exit.\n" +" cmd=restart Restart all of the x11vnc's.\n" +" cmd=noop Do nothing (e.g. ping)\n" +" cmd=x11vnc Run ps(1) looking for x11vnc's\n" +" cmd=help Print out help text.\n" +" cmd=add_window:win Add a window to be watched.\n" +" cmd=del_window:win Delete a window.\n" +" cmd=add_app:win Add an application to be watched.\n" +" cmd=del_app:win Delete an application.\n" +" cmd=add_client:host Add client ('internal' mode only)\n" +" cmd=del_client:host Del client ('internal' mode only)\n" +" cmd=list_windows List all tracked windows.\n" +" cmd=list_apps List all tracked applications.\n" +" cmd=list_clients List all connected clients.\n" +" cmd=list_all List all three.\n" +" cmd=print_logs Print out the x11vnc logfiles.\n" +" cmd=debug:n Set -debug to n (0 or 1).\n" +" cmd=showmenus:n Set -showmenus to n (0 or 1).\n" +" cmd=noexit:n Set -noexit to n (0 or 1).\n" +"\n" +" See the '-command internal' mode described below for a way\n" +" that tracks connected clients internally (not in a file.)\n" +"\n" +" In '-shell' mode (see below) you can type in the above\n" +" without the leading 'cmd='.\n" +"\n" +" For 'add_window' and 'del_window' the 'win' can be a\n" +" numerical window id or 'pick'. Same for 'add_app'. Be\n" +" sure to remove or comment out the add/del line quickly\n" +" (e.g. before picking) or it will be re-run the next time\n" +" the file is processed.\n" +"\n" +" If a file with the same name as the control file but\n" +" ending with suffix '.cmd' is found, then commands in it\n" +" (cmd=...) are processed and then the file is truncated.\n" +" This allows 'one time' command actions to be run. Any\n" +" client hostnames in the '.cmd' file are ignored. Also\n" +" see below for the X11VNC_APPSHARE_COMMAND X property\n" +" which is similar to '.cmd'\n" +"\n" +" -control internal Manage connected clients internally, see below.\n" +" -control shell Same as: -shell -control internal\n" +"\n" +" -delay secs Maximum timeout delay before re-checking the control file.\n" +" It can be a fraction, e.g. -delay 0.25 Default 0.5\n" +"\n" +" -shell Simple command line for '-control internal' mode (see the\n" +" details of this mode below.) Enter '?' for command list.\n" +"\n" +" To stop x11vnc -appshare press Ctrl-C, or (if -noexit not supplied) delete\n" +" the initial app window or exit the application. Or cmd=quit in -control mode.\n" +"\n" +#if 0 +" If you want your setup to survive periods of time where there are no clients\n" +" connected you will need to supply -args '-forever' otherwise the x11vnc's\n" +" will exit when the last client disconnects. Howerver, _starting_ with no\n" +" clients (e.g. empty control file) will work without -args '-forever'.\n" +"\n" +#endif +" In addition to the '.cmd' file channel, for faster response you can set\n" +" X11VNC_APPSHARE_COMMAND X property on the root window to the string that\n" +" would go into the '.cmd' file. For example:\n" +"\n" +" xprop -root -f X11VNC_APPSHARE_COMMAND 8s -set X11VNC_APPSHARE_COMMAND cmd=quit\n" +"\n" +" The property value will be set to 'DONE' after the command(s) is processed.\n" +"\n" +" If -control file is specified as 'internal' then no control file is used\n" +" and client tracking is done internally. You must add and delete clients\n" +" with the cmd=add_client: and cmd=del_client: commands.\n" +" Note that '-control internal' is required for '-shell' mode. Using\n" +" '-control shell' implies internal mode and -shell.\n" +"\n" +" Limitations:\n" +"\n" +" This is a quick lash-up, many things will not work properly.\n" +"\n" +" The main idea is to provide simple application sharing for two or more\n" +" parties to collaborate without needing to share the entire desktop. It\n" +" provides an improvement over -id/-sid that only shows a single window.\n" +"\n" +" Only reverse connections can be done. (Note: one can specify multiple\n" +" viewing hosts via: -connect host1,host2,host3 or add/remove them\n" +" dynamically as described above.)\n" +"\n" +" If a new window obscures an old one, you will see some or all of the\n" +" new window in the old one. The hope is this is a popup dialog or menu\n" +" that will go away soon. Otherwise a user at the physical display will\n" +" need to move it. (See also the SSVNC viewer features described below.) \n" +"\n" +" The viewer side cannot resize or make windows move on the physical\n" +" display. Again, a user at the physical display may need to help, or\n" +" use the SSVNC viewer (see Tip below.)\n" +"\n" +" Tip: If the application has its own 'resize corner', then dragging\n" +" it may successfully resize the application window.\n" +" Tip: Some desktop environments enable moving a window via, say,\n" +" Alt+Left-Button-Drag. One may be able to move a window this way.\n" +" Also, e.g., Alt+Right-Button-Drag may resize a window.\n" +" Tip: Clicking on part of an obscured window may raise it to the top.\n" +" Also, e.g., Alt+Middle-Button may toggle Raise/Lower.\n" +"\n" +" Tip: The SSVNC 1.0.25 unix and macosx vncviewer has 'EscapeKeys' hot\n" +" keys that will move, resize, raise, and lower the window via the\n" +" x11vnc -remote_prefix X11VNC_APPSHARE_CMD: feature. So in the\n" +" viewer while holding down Shift_L+Super_L+Alt_L the arrow keys\n" +" move the window, PageUp/PageDn/Home/End resize it, and - and +\n" +" raise and lower it. Key 'M' or Button1 moves the remote window\n" +" to the +X+Y of the viewer window. Key 'D' or Button3 deletes\n" +" the remote window.\n" +"\n" +" You can run the SSVNC vncviewer with options '-escape default',\n" +" '-multilisten' and '-env VNCVIEWER_MIN_TITLE=1'; or just run\n" +" with option '-appshare' to enable these and automatic placement.\n" +"\n" +" If any part of a window goes off of the display screen, then x11vnc\n" +" may be unable to poll it (without crashing), and so the window will\n" +" stop updating until the window is completely on-screen again.\n" +"\n" +" The (stock) vnc viewer does not know where to best position each new\n" +" viewer window; it likely centers each one (including when resized.)\n" +" Note: The SSVNC viewer in '-appshare' mode places them correctly.\n" +"\n" +" Deleting a viewer window does not delete the real window.\n" +" Note: The SSVNC viewer Shift+EscapeKeys+Button3 deletes it.\n" +"\n" +" Sometimes new window detection fails.\n" +"\n" +" Sometimes menu/popup detection fails.\n" +"\n" +" Sometimes the contents of a menu/popup window have blacked-out regions.\n" +" Try -sid or -showmenus as a workaround.\n" +"\n" +" If the application starts up a new application (a different process)\n" +" that new application will not be tracked (but, unfortunately, it may\n" +" cover up existing windows that are being tracked.) See cmd=add_window\n" +" and cmd=add_app described above.\n" +"\n" +#endif +; + +#include +#include +#include + +#define WMAX 192 +#define CMAX 128 +#define AMAX 32 + +static Window root = None; +static Window watch[WMAX]; +static Window apps[WMAX]; +static int state[WMAX]; +static char *clients[CMAX]; +static XWindowAttributes attr; +static char *ticker_atom_str = "X11VNC_APPSHARE_TICKER"; +static Atom ticker_atom = None; +static char *cmd_atom_str = "X11VNC_APPSHARE_COMMAND"; +static Atom cmd_atom = None; +static char *connect_to = NULL; +static char *x11vnc_args = ""; +static char *id_opt = "-id"; +static int skip_menus = 1; +static int exit_no_app_win = 1; +static int shell = 0; +static int tree_depth = 3; +static char *prompt = "appshare> "; +static char *x11vnc = "x11vnc"; +static char *control = NULL; +static char *trackdir = "unset"; +static char *trackpre = "/tmp/x11vnc-appshare-trackdir-tmp"; +static char *tracktmp = NULL; +static char unique_tag[100]; +static int use_forever = 1; +static int last_event_type = 0; +static pid_t helper_pid = 0; +static pid_t parent_pid = 0; +static double helper_delay = 0.5; +static int appshare_debug = 0; +static double start_time = 0.0; + +static void get_wm_name(Window win, char **name); +static int win_attr(Window win); +static int get_xy(Window win, int *x, int *y); +static Window check_inside(Window win); +static int ours(Window win); +static void destroy_win(Window win); +static int same_app(Window win, Window app); + +static void ff(void) { + fflush(stdout); + fflush(stderr); +} + +static int find_win(Window win) { + int i; + for (i=0; i < WMAX; i++) { + if (watch[i] == win) { + return i; + } + } + return -1; +} + +static int find_app(Window app) { + int i; + for (i=0; i < AMAX; i++) { + if (apps[i] == app) { + return i; + } + } + return -1; +} + +static int find_client(char *cl) { + int i; + for (i=0; i < CMAX; i++) { + if (cl == NULL) { + if (clients[i] == NULL) { + return i; + } + continue; + } + if (clients[i] == NULL) { + continue; + } + if (!strcmp(clients[i], cl)) { + return i; + } + } + return -1; +} + +static int trackdir_pid(Window win) { + FILE *f; + int ln = 0, pid = 0; + char line[1024]; + + if (!trackdir) { + return 0; + } + sprintf(tracktmp, "%s/0x%lx.log", trackdir, win); + f = fopen(tracktmp, "r"); + if (!f) { + return 0; + } + while (fgets(line, sizeof(line), f) != NULL) { + if (ln++ > 30) { + break; + } + if (strstr(line, "x11vnc version:")) { + char *q = strstr(line, "pid:"); + if (q) { + int p; + if (sscanf(q, "pid: %d", &p) == 1) { + if (p > 0) { + pid = p; + break; + } + } + } + } + } + fclose(f); + return pid; +} + +static void trackdir_cleanup(Window win) { + char *suffix[] = {"log", "connect", NULL}; + int i=0; + if (!trackdir) { + return; + } + while (suffix[i] != NULL) { + sprintf(tracktmp, "%s/0x%lx.%s", trackdir, win, suffix[i]); + if (appshare_debug && !strcmp(suffix[i], "log")) { + fprintf(stderr, "keeping: %s\n", tracktmp); + ff(); + } else { + if (appshare_debug) { + fprintf(stderr, "removing: %s\n", tracktmp); + ff(); + } + unlink(tracktmp); + } + i++; + } +} + +static void launch(Window win) { + char *cmd, *tmp, *connto, *name; + int len, timeo = 30, uf = use_forever; + int w = 0, h = 0, x = 0, y = 0; + + if (win_attr(win)) { + /* maybe switch to debug only. */ + w = attr.width; + h = attr.height; + get_xy(win, &x, &y); + } + + get_wm_name(win, &name); + + if (strstr(x11vnc_args, "-once")) { + uf = 0; + } + + if (control) { + int i = 0; + len = 0; + for (i=0; i < CMAX; i++) { + if (clients[i] != NULL) { + len += strlen(clients[i]) + 2; + } + } + connto = (char *) calloc(len, 1); + for (i=0; i < CMAX; i++) { + if (clients[i] != NULL) { + if (connto[0] != '\0') { + strcat(connto, ","); + } + strcat(connto, clients[i]); + } + } + } else { + connto = strdup(connect_to); + } + if (!strcmp(connto, "")) { + timeo = 0; + } + if (uf) { + timeo = 0; + } + + len = 1000 + strlen(x11vnc) + strlen(connto) + strlen(x11vnc_args) + + 3 * (trackdir ? strlen(trackdir) : 100); + + cmd = (char *) calloc(len, 1); + tmp = (char *) calloc(len, 1); + + sprintf(cmd, "%s %s 0x%lx -bg -quiet %s -nopw -rfbport 0 " + "-timeout %d -noxdamage -noxinerama -norc -repeat -speeds dsl " + "-env X11VNC_AVOID_WINDOWS=never -env X11VNC_APPSHARE_ACTIVE=1 " + "-env X11VNC_NO_CHECK_PM=1 -env %s -novncconnect -shared -nonap " + "-remote_prefix X11VNC_APPSHARE_CMD:", + x11vnc, id_opt, win, use_forever ? "-forever" : "-once", timeo, unique_tag); + + if (trackdir) { + FILE *f; + sprintf(tracktmp, " -noquiet -o %s/0x%lx.log", trackdir, win); + strcat(cmd, tracktmp); + sprintf(tracktmp, "%s/0x%lx.connect", trackdir, win); + f = fopen(tracktmp, "w"); + if (f) { + fprintf(f, "%s", connto); + fclose(f); + sprintf(tmp, " -connect_or_exit '%s'", tracktmp); + strcat(cmd, tmp); + } else { + sprintf(tmp, " -connect_or_exit '%s'", connto); + strcat(cmd, tmp); + } + } else { + if (!strcmp(connto, "")) { + sprintf(tmp, " -connect '%s'", connto); + } else { + sprintf(tmp, " -connect_or_exit '%s'", connto); + } + strcat(cmd, tmp); + } + if (uf) { + char *q = strstr(cmd, "-connect_or_exit"); + if (q) q = strstr(q, "_or_exit"); + if (q) { + unsigned int i; + for (i=0; i < strlen("_or_exit"); i++) { + *q = ' '; + q++; + } + } + } + + strcat(cmd, " "); + strcat(cmd, x11vnc_args); + + fprintf(stdout, "launching: x11vnc for window 0x%08lx %dx%d+%d+%d \"%s\"\n", + win, w, h, x, y, name); + + if (appshare_debug) { + fprintf(stderr, "\nrunning: %s\n\n", cmd); + } + ff(); + + system(cmd); + + free(cmd); + free(tmp); + free(connto); + free(name); +} + +static void stop(Window win) { + char *cmd; + int pid = -1; + int f = find_win(win); + if (f < 0 || win == None) { + return; + } + if (state[f] == 0) { + return; + } + if (trackdir) { + pid = trackdir_pid(win); + if (pid > 0) { + if (appshare_debug) {fprintf(stderr, + "sending SIGTERM to: %d\n", pid); ff();} + kill((pid_t) pid, SIGTERM); + } + } + + cmd = (char *) malloc(1000 + strlen(x11vnc)); + sprintf(cmd, "pkill -TERM -f '%s %s 0x%lx -bg'", x11vnc, id_opt, win); + if (appshare_debug) { + fprintf(stdout, "stopping: 0x%08lx - %s\n", win, cmd); + } else { + fprintf(stdout, "stopping: x11vnc for window 0x%08lx " + "(pid: %d)\n", win, pid); + } + ff(); + system(cmd); + + sprintf(cmd, "(sleep 0.25 2>/dev/null || sleep 1; pkill -KILL -f '%s " + "%s 0x%lx -bg') &", x11vnc, id_opt, win); + system(cmd); + + if (trackdir) { + trackdir_cleanup(win); + } + + free(cmd); +} + +static void kill_helper_pid(void) { + int status; + if (helper_pid <= 0) { + return; + } + fprintf(stderr, "stopping: helper_pid: %d\n", (int) helper_pid); + kill(helper_pid, SIGTERM); + usleep(50 * 1000); + kill(helper_pid, SIGKILL); + usleep(25 * 1000); +#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID + waitpid(helper_pid, &status, WNOHANG); +#endif +} + +static void be_helper_pid(char *dpy_str) { + int cnt = 0; + int ms = (int) (1000 * helper_delay); + double last_check = 0.0; + + if (ms < 50) ms = 50; + +#if NO_X11 + fprintf(stderr, "be_helper_pid: not compiled with X11.\n"); +#else + dpy = XOpenDisplay(dpy_str); + ticker_atom = XInternAtom(dpy, ticker_atom_str, False); + + while (1) { + char tmp[32]; + sprintf(tmp, "HELPER_CNT_%08d", cnt++); + XChangeProperty(dpy, DefaultRootWindow(dpy), ticker_atom, XA_STRING, 8, + PropModeReplace, (unsigned char *) tmp, strlen(tmp)); + XFlush(dpy); + usleep(ms*1000); + if (parent_pid > 0) { + if(dnow() > last_check + 1.0) { + last_check = dnow(); + if (kill(parent_pid, 0) != 0) { + fprintf(stderr, "be_helper_pid: parent %d is gone.\n", (int) parent_pid); + break; + } + } + } + } +#endif + exit(0); +} + +static void print_logs(void) { + if (trackdir) { + DIR *dir = opendir(trackdir); + if (dir) { + struct dirent *dp; + while ( (dp = readdir(dir)) != NULL) { + FILE *f; + char *name = dp->d_name; + if (!strcmp(name, ".") || !strcmp(name, "..")) { + continue; + } + if (strstr(name, "0x") != name) { + continue; + } + if (strstr(name, ".log") == NULL) { + continue; + } + sprintf(tracktmp, "%s/%s", trackdir, name); + f = fopen(tracktmp, "r"); + if (f) { + char line[1024]; + fprintf(stderr, "===== x11vnc log %s =====\n", tracktmp); + while (fgets(line, sizeof(line), f) != NULL) { + fprintf(stderr, "%s", line); + } + fprintf(stderr, "\n"); + ff(); + fclose(f); + } + } + closedir(dir); + } + } +} + +static void appshare_cleanup(int s) { + int i; + if (s) {} + + if (use_forever) { + /* launch this backup in case they kill -9 us before we terminate everything */ + char cmd[1000]; + sprintf(cmd, "(sleep 3; pkill -TERM -f '%s') &", unique_tag); + if (appshare_debug) fprintf(stderr, "%s\n", cmd); + system(cmd); + } + + for (i=0; i < WMAX; i++) { + if (watch[i] != None) { + stop(watch[i]); + } + } + + if (trackdir) { + DIR *dir = opendir(trackdir); + if (dir) { + struct dirent *dp; + while ( (dp = readdir(dir)) != NULL) { + char *name = dp->d_name; + if (!strcmp(name, ".") || !strcmp(name, "..")) { + continue; + } + if (strstr(name, "0x") != name) { + fprintf(stderr, "skipping: %s\n", name); + continue; + } + if (!appshare_debug) { + fprintf(stderr, "removing: %s\n", name); + sprintf(tracktmp, "%s/%s", trackdir, name); + unlink(tracktmp); + } else { + if (appshare_debug) fprintf(stderr, "keeping: %s\n", name); + } + } + closedir(dir); + } + if (!appshare_debug) { + if (strstr(trackdir, trackpre) == trackdir) { + if (appshare_debug) fprintf(stderr, "removing: %s\n", trackdir); + rmdir(trackdir); + } + } + ff(); + } + + kill_helper_pid(); + +#if !NO_X11 + XCloseDisplay(dpy); +#endif + fprintf(stdout, "done.\n"); + ff(); + exit(0); +} + +static int trap_xerror(Display *d, XErrorEvent *error) { + if (d || error) {} + return 0; +} + +#if 0 +typedef struct { + int x, y; /* location of window */ + int width, height; /* width and height of window */ + int border_width; /* border width of window */ + int depth; /* depth of window */ + Visual *visual; /* the associated visual structure */ + Window root; /* root of screen containing window */ + int class; /* InputOutput, InputOnly*/ + int bit_gravity; /* one of bit gravity values */ + int win_gravity; /* one of the window gravity values */ + int backing_store; /* NotUseful, WhenMapped, Always */ + unsigned long backing_planes;/* planes to be preserved if possible */ + unsigned long backing_pixel;/* value to be used when restoring planes */ + Bool save_under; /* boolean, should bits under be saved? */ + Colormap colormap; /* color map to be associated with window */ + Bool map_installed; /* boolean, is color map currently installed*/ + int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ + long all_event_masks; /* set of events all people have interest in*/ + long your_event_mask; /* my event mask */ + long do_not_propagate_mask; /* set of events that should not propagate */ + Bool override_redirect; /* boolean value for override-redirect */ + Screen *screen; /* back pointer to correct screen */ +} XWindowAttributes; +#endif + +static void get_wm_name(Window win, char **name) { + int ok; + +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + ok = XFetchName(dpy, win, name); + XSetErrorHandler(old_handler); +#endif + + if (!ok || *name == NULL) { + *name = strdup("unknown"); + } +} + +static int win_attr(Window win) { + int ok = 0; +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + ok = XGetWindowAttributes(dpy, win, &attr); + XSetErrorHandler(old_handler); +#endif + + if (ok) { + return 1; + } else { + return 0; + } +} + +static void win_select(Window win, int ignore) { +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + if (ignore) { + XSelectInput(dpy, win, 0); + } else { + XSelectInput(dpy, win, SubstructureNotifyMask); + } + XSync(dpy, False); + XSetErrorHandler(old_handler); +#endif +} + +static Window get_parent(Window win) { + int ok; + Window r, parent = None, *list = NULL; + unsigned int nchild; + +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + ok = XQueryTree(dpy, win, &r, &parent, &list, &nchild); + XSetErrorHandler(old_handler); + + if (!ok) { + return None; + } + if (list) { + XFree(list); + } +#endif + return parent; +} + +static int get_xy(Window win, int *x, int *y) { + Window cr; + Bool rc = False; +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + + rc = XTranslateCoordinates(dpy, win, root, 0, 0, x, y, &cr); + XSetErrorHandler(old_handler); +#endif + + if (!rc) { + return 0; + } else { + return 1; + } +} + +static Window check_inside(Window win) { + int i, nwin = 0; + int w, h, x, y; + int Ws[WMAX], Hs[WMAX], Xs[WMAX], Ys[WMAX]; + Window wins[WMAX]; + + if (!win_attr(win)) { + return None; + } + + /* store them first to give the win app more time to settle. */ + for (i=0; i < WMAX; i++) { + int X, Y; + Window wchk = watch[i]; + if (wchk == None) { + continue; + } + if (state[i] == 0) { + continue; + } + if (!win_attr(wchk)) { + continue; + } + if (!get_xy(wchk, &X, &Y)) { + continue; + } + + Xs[nwin] = X; + Ys[nwin] = Y; + Ws[nwin] = attr.width; + Hs[nwin] = attr.height; + wins[nwin] = wchk; + nwin++; + } + + if (nwin == 0) { + return None; + } + + if (!win_attr(win)) { + return None; + } + w = attr.width; + h = attr.height; + + get_xy(win, &x, &y); + if (!get_xy(win, &x, &y)) { + return None; + } + + for (i=0; i < nwin; i++) { + int X, Y, W, H; + Window wchk = wins[i]; + X = Xs[i]; + Y = Ys[i]; + W = Ws[i]; + H = Hs[i]; + + if (appshare_debug) fprintf(stderr, "check inside: 0x%lx %dx%d+%d+%d %dx%d+%d+%d\n", wchk, w, h, x, y, W, H, X, Y); + + if (X <= x && Y <= y) { + if (x + w <= X + W && y + h < Y + H) { + return wchk; + } + } + } + + return None; +} + +static void add_win(Window win) { + int idx = find_win(win); + int free = find_win(None); + if (idx >= 0) { + if (appshare_debug) {fprintf(stderr, "already watching window: 0x%lx\n", win); ff();} + return; + } + if (free < 0) { + fprintf(stderr, "ran out of slots for window: 0x%lx\n", win); ff(); + return; + } + + if (appshare_debug) {fprintf(stderr, "watching: 0x%lx at %d\n", win, free); ff();} + + watch[free] = win; + state[free] = 0; + + win_select(win, 0); +} + +static void delete_win(Window win) { + int i; + for (i=0; i < WMAX; i++) { + if (watch[i] == win) { + watch[i] = None; + state[i] = 0; + if (appshare_debug) {fprintf(stderr, "deleting: 0x%lx at %d\n", win, i); ff();} + } + } +} + +static void recurse_search(int level, int level_max, Window top, Window app, int *nw) { + Window w, r, parent, *list = NULL; + unsigned int nchild; + int ok = 0; + + if (appshare_debug > 1) { + fprintf(stderr, "level: %d level_max: %d top: 0x%lx app: 0x%lx\n", level, level_max, top, app); + } + if (level >= level_max) { + return; + } + +#if !NO_X11 + ok = XQueryTree(dpy, top, &r, &parent, &list, &nchild); + if (ok) { + int i; + for (i=0; i < (int) nchild; i++) { + w = list[i]; + if (w == None || find_win(w) >= 0) { + continue; + } + if (ours(w) && w != app) { + if (appshare_debug) fprintf(stderr, "add level %d 0x%lx %d/%d\n", + level, w, i, nchild); + add_win(w); + (*nw)++; + } + } + for (i=0; i < (int) nchild; i++) { + w = list[i]; + if (w == None || ours(w)) { + continue; + } + recurse_search(level+1, level_max, w, app, nw); + } + } + if (list) { + XFree(list); + } +#endif +} + +static void add_app(Window app) { + int i, nw = 0, free = -1; + XErrorHandler old_handler; + +#if !NO_X11 + i = find_app(app); + if (i >= 0) { + fprintf(stderr, "already tracking app: 0x%lx\n", app); + return; + } + for (i=0; i < AMAX; i++) { + if (same_app(apps[i], app)) { + fprintf(stderr, "already tracking app: 0x%lx via 0x%lx\n", app, apps[i]); + return; + } + } + free = find_app(None); + if (free < 0) { + fprintf(stderr, "ran out of app slots.\n"); + return; + } + apps[free] = app; + + add_win(app); + + old_handler = XSetErrorHandler(trap_xerror); + recurse_search(0, tree_depth, root, app, &nw); + XSetErrorHandler(old_handler); +#endif + fprintf(stderr, "tracking %d windows related to app window 0x%lx\n", nw, app); +} + +static void del_app(Window app) { + int i; + for (i=0; i < WMAX; i++) { + Window win = watch[i]; + if (win != None) { + if (same_app(app, win)) { + destroy_win(win); + } + } + } + for (i=0; i < AMAX; i++) { + Window app2 = apps[i]; + if (app2 != None) { + if (same_app(app, app2)) { + apps[i] = None; + } + } + } +} + +static void wait_until_empty(char *file) { + double t = 0.0, dt = 0.05; + while (t < 1.0) { + struct stat sb; + if (stat(file, &sb) != 0) { + return; + } + if (sb.st_size == 0) { + return; + } + t += dt; + usleep( (int) (dt * 1000 * 1000) ); + } +} + +static void client(char *client, int add) { + DIR *dir; + struct dirent *dp; + + if (!client) { + return; + } + if (!trackdir) { + fprintf(stderr, "no trackdir, cannot %s client: %s\n", + add ? "add" : "disconnect", client); + ff(); + return; + } + fprintf(stdout, "%s client: %s\n", add ? "adding " : "deleting", client); + + dir = opendir(trackdir); + if (!dir) { + fprintf(stderr, "could not opendir trackdir: %s\n", trackdir); + return; + } + while ( (dp = readdir(dir)) != NULL) { + char *name = dp->d_name; + if (!strcmp(name, ".") || !strcmp(name, "..")) { + continue; + } + if (strstr(name, "0x") != name) { + continue; + } + if (strstr(name, ".connect")) { + FILE *f; + char *tmp; + Window twin; + + if (scan_hexdec(name, &twin)) { + int f = find_win(twin); + if (appshare_debug) { + fprintf(stderr, "twin: 0x%lx name=%s f=%d\n", twin, name, f); + ff(); + } + if (f < 0) { + continue; + } + } + + tmp = (char *) calloc(100 + strlen(client), 1); + sprintf(tracktmp, "%s/%s", trackdir, name); + if (add) { + sprintf(tmp, "%s\n", client); + } else { + sprintf(tmp, "cmd=close:%s\n", client); + } + wait_until_empty(tracktmp); + f = fopen(tracktmp, "w"); + if (f) { + if (appshare_debug) { + fprintf(stderr, "%s client: %s + %s", + add ? "add" : "disconnect", tracktmp, tmp); + ff(); + } + fprintf(f, "%s", tmp); + fclose(f); + } + free(tmp); + } + } + closedir(dir); +} + +static void mapped(Window win) { + int f; + if (win == None) { + return; + } + f = find_win(win); + if (f < 0) { + if (win_attr(win)) { + if (get_parent(win) == root) { + /* XXX more cases? */ + add_win(win); + } + } + } +} + +static void unmapped(Window win) { + int f = find_win(win); + if (f < 0 || win == None) { + return; + } + stop(win); + state[f] = 0; +} + +static void destroy_win(Window win) { + stop(win); + delete_win(win); +} + +static Window parse_win(char *str) { + Window win = None; + if (!str) { + return None; + } + if (!strcmp(str, "pick") || !strcmp(str, "p")) { + static double last_pick = 0.0; + if (dnow() < start_time + 15) { + ; + } else if (dnow() < last_pick + 2) { + return None; + } else { + last_pick = dnow(); + } + if (!pick_windowid(&win)) { + fprintf(stderr, "parse_win: bad window pick.\n"); + win = None; + } + if (win == root) { + fprintf(stderr, "parse_win: ignoring pick of rootwin 0x%lx.\n", win); + win = None; + } + ff(); + } else if (!scan_hexdec(str, &win)) { + win = None; + } + return win; +} + +static void add_or_del_app(char *str, int add) { + Window win = parse_win(str); + + if (win != None) { + if (add) { + add_app(win); + } else { + del_app(win); + } + } else if (!strcmp(str, "all")) { + if (!add) { + int i; + for (i=0; i < AMAX; i++) { + if (apps[i] != None) { + del_app(apps[i]); + } + } + } + } +} + +static void add_or_del_win(char *str, int add) { + Window win = parse_win(str); + + if (win != None) { + int f = find_win(win); + if (add) { + if (f < 0 && win_attr(win)) { + add_win(win); + } + } else { + if (f >= 0) { + destroy_win(win); + } + } + } else if (!strcmp(str, "all")) { + if (!add) { + int i; + for (i=0; i < WMAX; i++) { + if (watch[i] != None) { + destroy_win(watch[i]); + } + } + } + } +} + +static void add_or_del_client(char *str, int add) { + int i; + + if (!str) { + return; + } + if (strcmp(control, "internal")) { + return; + } + if (add) { + int idx = find_client(str); + int free = find_client(NULL); + + if (idx >=0) { + fprintf(stderr, "already tracking client: %s in slot %d\n", str, idx); + ff(); + return; + } + if (free < 0) { + static int cnt = 0; + if (cnt++ < 10) { + fprintf(stderr, "ran out of client slots.\n"); + ff(); + } + return; + } + clients[free] = strdup(str); + client(str, 1); + } else { + if (str[0] == '#' || str[0] == '%') { + if (sscanf(str+1, "%d", &i) == 1) { + i--; + if (0 <= i && i < CMAX) { + if (clients[i] != NULL) { + client(clients[i], 0); + free(clients[i]); + clients[i] = NULL; + return; + } + } + } + } else if (!strcmp(str, "all")) { + for (i=0; i < CMAX; i++) { + if (clients[i] == NULL) { + continue; + } + client(clients[i], 0); + free(clients[i]); + clients[i] = NULL; + } + return; + } + + i = find_client(str); + if (i >= 0) { + free(clients[i]); + clients[i] = NULL; + client(str, 0); + } + } +} + +static void restart_x11vnc(void) { + int i, n = 0; + Window win, active[WMAX]; + for (i=0; i < WMAX; i++) { + win = watch[i]; + if (win == None) { + continue; + } + if (state[i]) { + active[n++] = win; + stop(win); + } + } + if (n) { + usleep(1500 * 1000); + } + for (i=0; i < n; i++) { + win = active[i]; + launch(win); + } +} + +static unsigned long cmask = 0x3fc00000; /* 00111111110000000000000000000000 */ + +static void init_cmask(void) { + /* dependent on the X server implementation; XmuClientWindow better? */ + /* xc/programs/Xserver/include/resource.h */ + int didit = 0, res_cnt = 29, client_bits = 8; + + if (getenv("X11VNC_APPSHARE_CLIENT_MASK")) { + unsigned long cr; + if (sscanf(getenv("X11VNC_APPSHARE_CLIENT_MASK"), "0x%lx", &cr) == 1) { + cmask = cr; + didit = 1; + } + } else if (getenv("X11VNC_APPSHARE_CLIENT_BITS")) { + int cr = atoi(getenv("X11VNC_APPSHARE_CLIENT_BITS")); + if (cr > 0) { + client_bits = cr; + } + } + if (!didit) { + cmask = (((1 << client_bits) - 1) << (res_cnt-client_bits)); + } + fprintf(stderr, "client_mask: 0x%08lx\n", cmask); +} + +static int same_app(Window win, Window app) { + if ( (win & cmask) == (app & cmask) ) { + return 1; + } else { + return 0; + } +} + +static int ours(Window win) { + int i; + for (i=0; i < AMAX; i++) { + if (apps[i] != None) { + if (same_app(win, apps[i])) { + return 1; + } + } + } + return 0; +} + +static void list_clients(void) { + int i, n = 0; + for (i=0; i < CMAX; i++) { + if (clients[i] == NULL) { + continue; + } + fprintf(stdout, "client[%02d] %s\n", ++n, clients[i]); + } + fprintf(stdout, "total clients: %d\n", n); + ff(); +} + +static void list_windows(void) { + int i, n = 0; + for (i=0; i < WMAX; i++) { + char *name; + Window win = watch[i]; + if (win == None) { + continue; + } + get_wm_name(win, &name); + fprintf(stdout, "window[%02d] 0x%08lx state: %d slot: %03d \"%s\"\n", + ++n, win, state[i], i, name); + free(name); + } + fprintf(stdout, "total windows: %d\n", n); + ff(); +} + +static void list_apps(void) { + int i, n = 0; + for (i=0; i < AMAX; i++) { + char *name; + Window win = apps[i]; + if (win == None) { + continue; + } + get_wm_name(win, &name); + fprintf(stdout, "app[%02d] 0x%08lx state: %d slot: %03d \"%s\"\n", + ++n, win, state[i], i, name); + free(name); + } + fprintf(stdout, "total apps: %d\n", n); + ff(); +} + +static int process_control(char *file, int check_clients) { + int i, nnew = 0, seen[CMAX]; + char line[1024], *new[CMAX]; + FILE *f; + + f = fopen(file, "r"); + if (!f) { + return 1; + } + if (check_clients) { + for (i=0; i < CMAX; i++) { + seen[i] = 0; + } + } + while (fgets(line, sizeof(line), f) != NULL) { + char *q = strchr(line, '\n'); + if (q) *q = '\0'; + + if (appshare_debug) { + fprintf(stderr, "check_control: %s\n", line); + ff(); + } + + q = lblanks(line); + if (q[0] == '#') { + continue; + } + if (!strcmp(q, "")) { + continue; + } + if (strstr(q, "cmd=") == q) { + char *cmd = q + strlen("cmd="); + if (!strcmp(cmd, "quit")) { + if (strcmp(control, file) && strstr(file, ".cmd")) { + FILE *f2 = fopen(file, "w"); + if (f2) fclose(f2); + } + appshare_cleanup(0); + } else if (!strcmp(cmd, "wait")) { + return 0; + } else if (strstr(cmd, "bcast:") == cmd) { + ; + } else if (strstr(cmd, "del_window:") == cmd) { + add_or_del_win(cmd + strlen("del_window:"), 0); + } else if (strstr(cmd, "add_window:") == cmd) { + add_or_del_win(cmd + strlen("add_window:"), 1); + } else if (strstr(cmd, "del:") == cmd) { + add_or_del_win(cmd + strlen("del:"), 0); + } else if (strstr(cmd, "add:") == cmd) { + add_or_del_win(cmd + strlen("add:"), 1); + } else if (strstr(cmd, "del_client:") == cmd) { + add_or_del_client(cmd + strlen("del_client:"), 0); + } else if (strstr(cmd, "add_client:") == cmd) { + add_or_del_client(cmd + strlen("add_client:"), 1); + } else if (strstr(cmd, "-") == cmd) { + add_or_del_client(cmd + strlen("-"), 0); + } else if (strstr(cmd, "+") == cmd) { + add_or_del_client(cmd + strlen("+"), 1); + } else if (strstr(cmd, "del_app:") == cmd) { + add_or_del_app(cmd + strlen("del_app:"), 0); + } else if (strstr(cmd, "add_app:") == cmd) { + add_or_del_app(cmd + strlen("add_app:"), 1); + } else if (strstr(cmd, "debug:") == cmd) { + appshare_debug = atoi(cmd + strlen("debug:")); + } else if (strstr(cmd, "showmenus:") == cmd) { + skip_menus = atoi(cmd + strlen("showmenus:")); + skip_menus = !(skip_menus); + } else if (strstr(cmd, "noexit:") == cmd) { + exit_no_app_win = atoi(cmd + strlen("noexit:")); + exit_no_app_win = !(exit_no_app_win); + } else if (strstr(cmd, "use_forever:") == cmd) { + use_forever = atoi(cmd + strlen("use_forever:")); + } else if (strstr(cmd, "tree_depth:") == cmd) { + tree_depth = atoi(cmd + strlen("tree_depth:")); + } else if (strstr(cmd, "x11vnc_args:") == cmd) { + x11vnc_args = strdup(cmd + strlen("x11vnc_args:")); + } else if (strstr(cmd, "env:") == cmd) { + putenv(cmd + strlen("env:")); + } else if (strstr(cmd, "noop") == cmd) { + ; + } else if (!strcmp(cmd, "restart")) { + restart_x11vnc(); + } else if (!strcmp(cmd, "list_clients") || !strcmp(cmd, "lc")) { + list_clients(); + } else if (!strcmp(cmd, "list_windows") || !strcmp(cmd, "lw")) { + list_windows(); + } else if (!strcmp(cmd, "list_apps") || !strcmp(cmd, "la")) { + list_apps(); + } else if (!strcmp(cmd, "list_all") || !strcmp(cmd, "ls")) { + list_windows(); + fprintf(stderr, "\n"); + list_apps(); + fprintf(stderr, "\n"); + list_clients(); + } else if (!strcmp(cmd, "print_logs") || !strcmp(cmd, "pl")) { + print_logs(); + } else if (!strcmp(cmd, "?") || !strcmp(cmd, "h") || !strcmp(cmd, "help")) { + fprintf(stderr, "available commands:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " quit restart noop x11vnc help ? ! !!\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " add_window:win (add:win, add:pick)\n"); + fprintf(stderr, " del_window:win (del:win, del:pick, del:all)\n"); + fprintf(stderr, " add_app:win (add_app:pick)\n"); + fprintf(stderr, " del_app:win (del_app:pick, del_app:all)\n"); + fprintf(stderr, " add_client:host (+host)\n"); + fprintf(stderr, " del_client:host (-host, -all)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " list_windows (lw)\n"); + fprintf(stderr, " list_apps (la)\n"); + fprintf(stderr, " list_clients (lc)\n"); + fprintf(stderr, " list_all (ls)\n"); + fprintf(stderr, " print_logs (pl)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " debug:n showmenus:n noexit:n\n"); + } else { + fprintf(stderr, "unrecognized %s\n", q); + } + continue; + } + if (check_clients) { + int idx = find_client(q); + if (idx >= 0) { + seen[idx] = 1; + } else { + new[nnew++] = strdup(q); + } + } + } + fclose(f); + + if (check_clients) { + for (i=0; i < CMAX; i++) { + if (clients[i] == NULL) { + continue; + } + if (!seen[i]) { + client(clients[i], 0); + free(clients[i]); + clients[i] = NULL; + } + } + for (i=0; i < nnew; i++) { + int free = find_client(NULL); + if (free < 0) { + static int cnt = 0; + if (cnt++ < 10) { + fprintf(stderr, "ran out of client slots.\n"); + ff(); + break; + } + continue; + } + clients[free] = new[i]; + client(new[i], 1); + } + } + return 1; +} + +static int check_control(void) { + static int last_size = -1; + static time_t last_mtime = 0; + struct stat sb; + char *control_cmd; + + if (!control) { + return 1; + } + + if (!strcmp(control, "internal")) { + return 1; + } + + control_cmd = (char *)malloc(strlen(control) + strlen(".cmd") + 1); + sprintf(control_cmd, "%s.cmd", control); + if (stat(control_cmd, &sb) == 0) { + FILE *f; + if (sb.st_size > 0) { + process_control(control_cmd, 0); + } + f = fopen(control_cmd, "w"); + if (f) { + fclose(f); + } + } + free(control_cmd); + + if (stat(control, &sb) != 0) { + return 1; + } + if (last_size == (int) sb.st_size && last_mtime == sb.st_mtime) { + return 1; + } + last_size = (int) sb.st_size; + last_mtime = sb.st_mtime; + + return process_control(control, 1); +} + +static void update(void) { + int i, app_ok = 0; + if (last_event_type != PropertyNotify) { + if (appshare_debug) fprintf(stderr, "\nupdate ...\n"); + } else if (appshare_debug > 1) { + fprintf(stderr, "update ... propertynotify\n"); + } + if (!check_control()) { + return; + } + for (i=0; i < WMAX; i++) { + Window win = watch[i]; + if (win == None) { + continue; + } + if (!win_attr(win)) { + destroy_win(win); + continue; + } + if (find_app(win) >= 0) { + app_ok++; + } + if (state[i] == 0) { + if (attr.map_state == IsViewable) { + if (skip_menus) { + Window inside = check_inside(win); + if (inside != None) { + if (appshare_debug) {fprintf(stderr, "skip_menus: window 0x%lx is inside of 0x%lx, not tracking it.\n", win, inside); ff();} + delete_win(win); + continue; + } + } + launch(win); + state[i] = 1; + } + } else if (state[i] == 1) { + if (attr.map_state != IsViewable) { + stop(win); + state[i] = 0; + } + } + } + if (exit_no_app_win && !app_ok) { + for (i=0; i < AMAX; i++) { + if (apps[i] != None) { + fprintf(stdout, "main application window is gone: 0x%lx\n", apps[i]); + } + } + ff(); + appshare_cleanup(0); + } + if (last_event_type != PropertyNotify) { + if (appshare_debug) {fprintf(stderr, "update done.\n"); ff();} + } +} + +static void exiter(char *msg, int rc) { + fprintf(stderr, "%s", msg); + ff(); + kill_helper_pid(); + exit(rc); +} + +static void set_trackdir(void) { + char tmp[256]; + struct stat sb; + if (!strcmp(trackdir, "none")) { + trackdir = NULL; + return; + } + if (!strcmp(trackdir, "unset")) { + int fd; + sprintf(tmp, "%s.XXXXXX", trackpre); + fd = mkstemp(tmp); + if (fd < 0) { + strcat(tmp, ": failed to create file.\n"); + exiter(tmp, 1); + } + /* XXX race */ + close(fd); + unlink(tmp); + if (mkdir(tmp, 0700) != 0) { + strcat(tmp, ": failed to create dir.\n"); + exiter(tmp, 1); + } + trackdir = strdup(tmp); + } + if (stat(trackdir, &sb) != 0) { + if (mkdir(trackdir, 0700) != 0) { + exiter("could not make trackdir.\n", 1); + } + } else if (! S_ISDIR(sb.st_mode)) { + exiter("trackdir not a directory.\n", 1); + } + tracktmp = (char *) calloc(1000 + strlen(trackdir), 1); +} + +static void process_string(char *str) { + FILE *f; + char *file; + if (trackdir) { + sprintf(tracktmp, "%s/0xprop.cmd", trackdir); + file = strdup(tracktmp); + } else { + char tmp[] = "/tmp/x11vnc-appshare.cmd.XXXXXX"; + int fd = mkstemp(tmp); + if (fd < 0) { + return; + } + file = strdup(tmp); + close(fd); + } + f = fopen(file, "w"); + if (f) { + fprintf(f, "%s", str); + fclose(f); + process_control(file, 0); + } + unlink(file); + free(file); +} + +static void handle_shell(void) { + struct timeval tv; + static char lastline[1000]; + static int first = 1; + fd_set rfds; + int fd0 = fileno(stdin); + + if (first) { + memset(lastline, 0, sizeof(lastline)); + first = 0; + } + + FD_ZERO(&rfds); + FD_SET(fd0, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + select(fd0+1, &rfds, NULL, NULL, &tv); + if (FD_ISSET(fd0, &rfds)) { + char line[1000], line2[1010]; + if (fgets(line, sizeof(line), stdin) != NULL) { + char *str = lblanks(line); + char *q = strrchr(str, '\n'); + if (q) *q = '\0'; + if (strcmp(str, "")) { + if (!strcmp(str, "!!")) { + sprintf(line, "%s", lastline); + fprintf(stderr, "%s\n", line); + str = line; + } + if (strstr(str, "!") == str) { + system(str+1); + } else if (!strcmp(str, "x11vnc") || !strcmp(str, "ps")) { + char *cmd = "ps -elf | egrep 'PID|x11vnc' | grep -v egrep"; + fprintf(stderr, "%s\n", cmd); + system(cmd); + } else { + sprintf(line2, "cmd=%s", str); + process_string(line2); + } + sprintf(lastline, "%s", str); + } + } + fprintf(stderr, "\n%s", prompt); ff(); + } +} + +static void handle_prop_cmd(void) { + char *value, *str, *done = "DONE"; + + if (cmd_atom == None) { + return; + } + + value = get_xprop(cmd_atom_str, root); + if (value == NULL) { + return; + } + + str = lblanks(value); + if (!strcmp(str, done)) { + free(value); + return; + } + if (strstr(str, "cmd=quit") == str || strstr(str, "\ncmd=quit")) { + set_xprop(cmd_atom_str, root, done); + appshare_cleanup(0); + } + + process_string(str); + + free(value); + set_xprop(cmd_atom_str, root, done); +} + +#define PREFIX if(appshare_debug) fprintf(stderr, " %8.2f 0x%08lx : ", dnow() - start, ev.xany.window); + +static void monitor(void) { +#if !NO_X11 + XEvent ev; + double start = dnow(); + int got_prop_cmd = 0; + + if (shell) { + update(); + fprintf(stderr, "\n\n"); + process_string("cmd=help"); + fprintf(stderr, "\n%s", prompt); ff(); + } + + while (1) { + int t; + + if (XEventsQueued(dpy, QueuedAlready) == 0) { + update(); + if (got_prop_cmd) { + handle_prop_cmd(); + } + got_prop_cmd = 0; + if (shell) { + handle_shell(); + } + } + + XNextEvent(dpy, &ev); + + last_event_type = ev.type; + + switch (ev.type) { + case Expose: + PREFIX + if(appshare_debug) fprintf(stderr, "Expose %04dx%04d+%04d+%04d\n", ev.xexpose.width, ev.xexpose.height, ev.xexpose.x, ev.xexpose.y); + break; + case ConfigureNotify: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "ConfigureNotify %04dx%04d+%04d+%04d above: 0x%lx\n", ev.xconfigure.width, ev.xconfigure.height, ev.xconfigure.x, ev.xconfigure.y, ev.xconfigure.above); +#endif + break; + case VisibilityNotify: + PREFIX + if (appshare_debug) { + fprintf(stderr, "VisibilityNotify: "); + t = ev.xvisibility.state; + if (t == VisibilityFullyObscured) fprintf(stderr, "VisibilityFullyObscured\n"); + if (t == VisibilityPartiallyObscured) fprintf(stderr, "VisibilityPartiallyObscured\n"); + if (t == VisibilityUnobscured) fprintf(stderr, "VisibilityUnobscured\n"); + } + break; + case MapNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "MapNotify win: 0x%lx\n", ev.xmap.window); + if (ours(ev.xmap.window)) { + mapped(ev.xmap.window); + } + break; + case UnmapNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "UnmapNotify win: 0x%lx\n", ev.xmap.window); + if (ours(ev.xmap.window)) { + unmapped(ev.xmap.window); + } + break; + case MapRequest: + PREFIX + if(appshare_debug) fprintf(stderr, "MapRequest\n"); + break; + case CreateNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "CreateNotify parent: 0x%lx win: 0x%lx\n", ev.xcreatewindow.parent, ev.xcreatewindow.window); + if (ev.xcreatewindow.parent == root && ours(ev.xcreatewindow.window)) { + if (find_win(ev.xcreatewindow.window) >= 0) { + destroy_win(ev.xcreatewindow.window); + } + add_win(ev.xcreatewindow.window); + } + break; + case DestroyNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "DestroyNotify win: 0x%lx\n", ev.xdestroywindow.window); + if (ours(ev.xdestroywindow.window)) { + destroy_win(ev.xdestroywindow.window); + } + break; + case ConfigureRequest: + PREFIX + if(appshare_debug) fprintf(stderr, "ConfigureRequest\n"); + break; + case CirculateRequest: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "CirculateRequest parent: 0x%lx win: 0x%lx\n", ev.xcirculaterequest.parent, ev.xcirculaterequest.window); +#endif + break; + case CirculateNotify: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "CirculateNotify\n"); +#endif + break; + case PropertyNotify: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "PropertyNotify\n"); +#endif + if (cmd_atom != None && ev.xproperty.atom == cmd_atom) { + got_prop_cmd++; + } + break; + case ReparentNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "ReparentNotify parent: 0x%lx win: 0x%lx\n", ev.xreparent.parent, ev.xreparent.window); + if (ours(ev.xreparent.window)) { + if (ours(ev.xreparent.parent)) { + destroy_win(ev.xreparent.window); + } else if (ev.xreparent.parent == root) { + /* ??? */ + } + } + break; + default: + PREFIX + if(appshare_debug) fprintf(stderr, "Unknown: %d\n", ev.type); + break; + } + } +#endif +} + +int appshare_main(int argc, char *argv[]) { + int i; + char *app_str = NULL; + char *dpy_str = NULL; + long xselectinput = 0; +#if NO_X11 + exiter("not compiled with X11\n", 1); +#else + for (i=0; i < WMAX; i++) { + watch[i] = None; + state[i] = 0; + } + for (i=0; i < AMAX; i++) { + apps[i] = None; + } + for (i=0; i < CMAX; i++) { + clients[i] = NULL; + } + + x11vnc = strdup(argv[0]); + + for (i=1; i < argc; i++) { + int end = (i == argc-1) ? 1 : 0; + char *s = argv[i]; + if (strstr(s, "--") == s) { + s++; + } + + if (!strcmp(s, "-h") || !strcmp(s, "-help")) { + fprintf(stdout, "%s", usage); + exit(0); + } else if (!strcmp(s, "-id")) { + id_opt = "-id"; + if (end) exiter("no -id value supplied\n", 1); + app_str = strdup(argv[++i]); + } else if (!strcmp(s, "-sid")) { + id_opt = "-sid"; + if (end) exiter("no -sid value supplied\n", 1); + app_str = strdup(argv[++i]); + } else if (!strcmp(s, "-connect") || !strcmp(s, "-connect_or_exit") || !strcmp(s, "-coe")) { + if (end) exiter("no -connect value supplied\n", 1); + connect_to = strdup(argv[++i]); + } else if (!strcmp(s, "-control")) { + if (end) exiter("no -control value supplied\n", 1); + control = strdup(argv[++i]); + if (!strcmp(control, "shell")) { + free(control); + control = strdup("internal"); + shell = 1; + } + } else if (!strcmp(s, "-trackdir")) { + if (end) exiter("no -trackdir value supplied\n", 1); + trackdir = strdup(argv[++i]); + } else if (!strcmp(s, "-display")) { + if (end) exiter("no -display value supplied\n", 1); + dpy_str = strdup(argv[++i]); + set_env("DISPLAY", dpy_str); + } else if (!strcmp(s, "-delay")) { + if (end) exiter("no -delay value supplied\n", 1); + helper_delay = atof(argv[++i]); + } else if (!strcmp(s, "-args")) { + if (end) exiter("no -args value supplied\n", 1); + x11vnc_args = strdup(argv[++i]); + } else if (!strcmp(s, "-env")) { + if (end) exiter("no -env value supplied\n", 1); + putenv(argv[++i]); + } else if (!strcmp(s, "-debug")) { + appshare_debug++; + } else if (!strcmp(s, "-showmenus")) { + skip_menus = 0; + } else if (!strcmp(s, "-noexit")) { + exit_no_app_win = 0; + } else if (!strcmp(s, "-shell")) { + shell = 1; + } else if (!strcmp(s, "-nocmds") || !strcmp(s, "-safer")) { + fprintf(stderr, "ignoring %s in -appshare mode.\n", s); + } else if (!strcmp(s, "-appshare")) { + ; + } else { + fprintf(stderr, "unrecognized 'x11vnc -appshare' option: %s\n", s); + exiter("", 1); + } + } + + if (getenv("X11VNC_APPSHARE_DEBUG")) { + appshare_debug = atoi(getenv("X11VNC_APPSHARE_DEBUG")); + } + + /* let user override name for multiple instances: */ + if (getenv("X11VNC_APPSHARE_COMMAND_PROPNAME")) { + cmd_atom_str = strdup(getenv("X11VNC_APPSHARE_COMMAND_PROPNAME")); + } + if (getenv("X11VNC_APPSHARE_TICKER_PROPNAME")) { + ticker_atom_str = strdup(getenv("X11VNC_APPSHARE_TICKER_PROPNAME")); + } + + if (shell) { + if (!control || strcmp(control, "internal")) { + exiter("mode -shell requires '-control internal'\n", 1); + } + } + + if (connect_to == NULL && control != NULL) { + struct stat sb; + if (stat(control, &sb) == 0) { + int len = 100 + sb.st_size; + FILE *f = fopen(control, "r"); + + if (f) { + char *line = (char *) malloc(len); + connect_to = (char *) calloc(2 * len, 1); + while (fgets(line, len, f) != NULL) { + char *q = strchr(line, '\n'); + if (q) *q = '\0'; + q = lblanks(line); + if (q[0] == '#') { + continue; + } + if (connect_to[0] != '\0') { + strcat(connect_to, ","); + } + strcat(connect_to, q); + } + fclose(f); + } + fprintf(stderr, "set -connect to: %s\n", connect_to); + } + } + if (0 && connect_to == NULL && control == NULL) { + exiter("no -connect host or -control file specified.\n", 1); + } + + if (control) { + pid_t pid; + parent_pid = getpid(); + pid = fork(); + if (pid == (pid_t) -1) { + ; + } else if (pid == 0) { + be_helper_pid(dpy_str); + exit(0); + } else { + helper_pid = pid; + } + } + + dpy = XOpenDisplay(dpy_str); + if (!dpy) { + exiter("cannot open display\n", 1); + } + + root = DefaultRootWindow(dpy); + + xselectinput = SubstructureNotifyMask; + if (helper_pid > 0) { + ticker_atom = XInternAtom(dpy, ticker_atom_str, False); + xselectinput |= PropertyChangeMask; + } + XSelectInput(dpy, root, xselectinput); + + cmd_atom = XInternAtom(dpy, cmd_atom_str, False); + + init_cmask(); + + sprintf(unique_tag, "X11VNC_APPSHARE_TAG=%d-tag", getpid()); + + start_time = dnow(); + + if (app_str == NULL) { + exiter("no -id/-sid window specified.\n", 1); + } else { + char *p, *str = strdup(app_str); + char *alist[AMAX]; + int i, n = 0; + + p = strtok(str, ","); + while (p) { + if (n >= AMAX) { + fprintf(stderr, "ran out of app slots: %s\n", app_str); + exiter("", 1); + } + alist[n++] = strdup(p); + p = strtok(NULL, ","); + } + free(str); + + for (i=0; i < n; i++) { + Window app = None; + p = alist[i]; + app = parse_win(p); + free(p); + + if (app != None) { + if (!ours(app)) { + add_app(app); + } + } + } + } + + set_trackdir(); + + signal(SIGINT, appshare_cleanup); + signal(SIGTERM, appshare_cleanup); + + rfbLogEnable(0); + + if (connect_to) { + char *p, *str = strdup(connect_to); + int n = 0; + p = strtok(str, ","); + while (p) { + clients[n++] = strdup(p); + p = strtok(NULL, ","); + } + free(str); + } else { + connect_to = strdup(""); + } + + for (i=0; i < AMAX; i++) { + if (apps[i] == None) { + continue; + } + fprintf(stdout, "Using app win: 0x%08lx root: 0x%08lx\n", apps[i], root); + } + fprintf(stdout, "\n"); + + monitor(); + + appshare_cleanup(0); + +#endif + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.c new file mode 100755 index 0000000..7f38d57 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.c @@ -0,0 +1,409 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- avahi.c -- */ + +#include "x11vnc.h" +#include "connections.h" +#include "cleanup.h" + +void avahi_initialise(void); +void avahi_advertise(const char *name, const char *host, const uint16_t port); +void avahi_reset(void); +void avahi_cleanup(void); + +static pid_t avahi_pid = 0; + +static void kill_avahi_pid(void) { + if (avahi_pid != 0) { + kill(avahi_pid, SIGTERM); + avahi_pid = 0; + } +} + +static int try_avahi_helper(const char *name, const char *host, const uint16_t port) { +#if LIBVNCSERVER_HAVE_FORK + char *cmd, *p, *path = getenv("PATH"), portstr[32]; + int i; + + if (!name || !host || !port) {} + + /* avahi-publish */ + if (no_external_cmds || !cmd_ok("zeroconf")) { + return 0; + } + + if (!path) { + return 0; + } + + path = strdup(path); + cmd = (char *) malloc(strlen(path) + 100); + sprintf(portstr, "%d", (int) port); + + p = strtok(path, ":"); + while (p) { + struct stat sbuf; + + sprintf(cmd, "%s/avahi-publish", p); + if (stat(cmd, &sbuf) == 0) { + break; + } + sprintf(cmd, "%s/dns-sd", p); + if (stat(cmd, &sbuf) == 0) { + break; + } + sprintf(cmd, "%s/mDNS", p); + if (stat(cmd, &sbuf) == 0) { + break; + } + cmd[0] = '\0'; + + p = strtok(NULL, ":"); + } + free(path); + + if (!strcmp(cmd, "")) { + free(cmd); + rfbLog("Could not find an external avahi/zeroconf helper program.\n"); + return 0; + } + + avahi_pid = fork(); + + if (avahi_pid < 0) { + rfbLogPerror("fork"); + avahi_pid = 0; + free(cmd); + return 0; + } + + if (avahi_pid != 0) { + int status; + + usleep(500 * 1000); + waitpid(avahi_pid, &status, WNOHANG); + if (kill(avahi_pid, 0) != 0) { + waitpid(avahi_pid, &status, WNOHANG); + avahi_pid = 0; + free(cmd); + return 0; + } + if (! quiet) { + rfbLog("%s helper pid is: %d\n", cmd, (int) avahi_pid); + } + free(cmd); + return 1; + } + + for (i=3; i<256; i++) { + close(i); + } + + if (strstr(cmd, "/avahi-publish")) { + execlp(cmd, cmd, "-s", name, "_rfb._tcp", portstr, (char *) NULL); + } else { + execlp(cmd, cmd, "-R", name, "_rfb._tcp", ".", portstr, (char *) NULL); + } + exit(1); +#else + if (!name || !host || !port) {} + return 0; +#endif +} + +#if !defined(LIBVNCSERVER_HAVE_AVAHI) || !defined(LIBVNCSERVER_HAVE_LIBPTHREAD) +void avahi_initialise(void) { + rfbLog("avahi_initialise: no Avahi support at buildtime.\n"); +} + +void avahi_advertise(const char *name, const char *host, const uint16_t port) { + if (!try_avahi_helper(name, host, port)) { + rfbLog("avahi_advertise: no Avahi support at buildtime.\n"); + avahi = 0; + } +} + +void avahi_reset(void) { + kill_avahi_pid(); + rfbLog("avahi_reset: no Avahi support at buildtime.\n"); +} + +void avahi_cleanup(void) { + kill_avahi_pid(); + rfbLog("avahi_cleanup: no Avahi support at buildtime.\n"); +} +#else + +#include +#include +#include +#include + +#include +#include + + +static AvahiThreadedPoll *_poll = NULL; +static AvahiClient *_client = NULL; +static AvahiEntryGroup *_group = NULL; + +static int db = 0; + +typedef struct { + const char *name; + const char *host; + uint16_t port; +} avahi_service_t; + +typedef struct { + char *name; + char *host; + uint16_t port; +} avahi_reg_t; + +#define NREG 16 +static avahi_reg_t registered[NREG]; + +void avahi_initialise(void) { + int ret; + static int first = 1; + + if (getenv("AVAHI_DEBUG")) { + db = 1; + } + if (first) { + int i; + for (i=0; iname); +#if 0 /* is this the segv problem? */ + free(svc); +#endif + break; + case AVAHI_ENTRY_GROUP_COLLISION: + new_name = avahi_alternative_service_name(svc->name); + _avahi_create_services(new_name, svc->host, svc->port); + rfbLog("Avahi Entry group collision\n"); + avahi_free(new_name); + break; + case AVAHI_ENTRY_GROUP_FAILURE: + rfbLog("Avahi Entry group failure: %s\n", + avahi_strerror(avahi_client_errno( + avahi_entry_group_get_client(g)))); + break; + default: + break; + } +if (db) fprintf(stderr, "out _avahi_entry_group_callback\n"); +} + +static void _avahi_create_services(const char *name, const char *host, + const uint16_t port) { + avahi_service_t *svc = (avahi_service_t *)malloc(sizeof(avahi_service_t)); + int ret = 0; + +if (db) fprintf(stderr, "in _avahi_create_services %s %s %d\n", name, host, port); + svc->name = name; + svc->host = host; + svc->port = port; + + if (!_group) { +if (db) fprintf(stderr, " _avahi_create_services create group\n"); + _group = avahi_entry_group_new(_client, + _avahi_entry_group_callback, svc); + } + if (!_group) { + rfbLog("avahi_entry_group_new() failed: %s\n", + avahi_strerror(avahi_client_errno(_client))); + return; + } + + ret = avahi_entry_group_add_service(_group, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, 0, name, "_rfb._tcp", NULL, NULL, port, NULL); + if (ret < 0) { + rfbLog("Failed to add _rfb._tcp service: %s\n", + avahi_strerror(ret)); + return; + } + + ret = avahi_entry_group_commit(_group); + if (ret < 0) { + rfbLog("Failed to commit entry_group:: %s\n", + avahi_strerror(ret)); + return; + } +if (db) fprintf(stderr, "out _avahi_create_services\n"); +} + +void avahi_advertise(const char *name, const char *host, const uint16_t port) { + int i; +if (db) fprintf(stderr, "in avahi_advertise: %s %s %d\n", name, host, port); + if (!_client) { +if (db) fprintf(stderr, " avahi_advertise client null\n"); + return; + } + if (_poll == NULL) { + rfbLog("Avahi poll not initialized.\n"); + return; + } + /* well, we just track it ourselves... */ + for (i=0; i= 5900 ? port : 5900+port); + avahi_threaded_poll_unlock(_poll); +if (db) fprintf(stderr, "out avahi_advertise\n"); +} + +void avahi_reset(void) { + int i; +if (db) fprintf(stderr, "in avahi_reset\n"); + for (i=0; i + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_AVAHI_H +#define _X11VNC_AVAHI_H + +/* -- avahi.h -- */ + +extern void avahi_initialise(void); +extern void avahi_advertise(const char *name, const char *host, const uint16_t port); +extern void avahi_reset(void); +extern void avahi_cleanup(void); + +#endif /* _X11VNC_AVAHI_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/blackout_t.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/blackout_t.h new file mode 100755 index 0000000..014f5b4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/blackout_t.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_BLACKOUT_T_H +#define _X11VNC_BLACKOUT_T_H + +/* -- blackout_t.h -- */ + +typedef struct bout { + int x1, y1, x2, y2; +} blackout_t; + +#define BO_MAX 32 +typedef struct tbout { + blackout_t bo[BO_MAX]; /* hardwired max rectangles. */ + int cover; + int count; +} tile_blackout_t; + +#endif /* _X11VNC_BLACKOUT_T_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.c new file mode 100755 index 0000000..e9222b5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.c @@ -0,0 +1,755 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- cleanup.c -- */ + +#include "x11vnc.h" +#include "xwrappers.h" +#include "xdamage.h" +#include "remote.h" +#include "keyboard.h" +#include "scan.h" +#include "gui.h" +#include "solid.h" +#include "unixpw.h" +#include "sslcmds.h" +#include "sslhelper.h" +#include "connections.h" +#include "macosx.h" +#include "macosxCG.h" +#include "avahi.h" +#include "screen.h" +#include "xrecord.h" +#include "xevents.h" + +/* + * Exiting and error handling routines + */ + +int trapped_xerror = 0; +int trapped_xioerror = 0; +int trapped_getimage_xerror = 0; +int trapped_record_xerror = 0; +XErrorEvent *trapped_xerror_event; + +/* XXX CHECK BEFORE RELEASE */ +int crash_debug = 0; + +void clean_shm(int quick); +void clean_up_exit(int ret); +int trap_xerror(Display *d, XErrorEvent *error); +int trap_xioerror(Display *d); +int trap_getimage_xerror(Display *d, XErrorEvent *error); +char *xerror_string(XErrorEvent *error); +void initialize_crash_handler(void); +void initialize_signals(void); +void unset_signals(void); +void close_exec_fds(void); +int known_sigpipe_mode(char *s); + + +static int exit_flag = 0; +static int exit_sig = 0; + +static void clean_icon_mode(void); +static int Xerror(Display *d, XErrorEvent *error); +static int XIOerr(Display *d); +static void crash_shell_help(void); +static void crash_shell(void); +static void interrupted (int sig); + + +void clean_shm(int quick) { + int i, cnt = 0; + + /* + * to avoid deadlock, etc, under quick=1 we just delete the shm + * areas and leave the X stuff hanging. + */ + if (quick) { + shm_delete(&scanline_shm); + shm_delete(&fullscreen_shm); + shm_delete(&snaprect_shm); + } else { + shm_clean(&scanline_shm, scanline); + shm_clean(&fullscreen_shm, fullscreen); + shm_clean(&snaprect_shm, snaprect); + } + + /* + * Here we have to clean up quite a few shm areas for all + * the possible tile row runs (40 for 1280), not as robust + * as one might like... sometimes need to run ipcrm(1). + */ + for(i=1; i<=ntiles_x; i++) { + if (i > tile_shm_count) { + break; + } + if (quick) { + shm_delete(&tile_row_shm[i]); + } else { + shm_clean(&tile_row_shm[i], tile_row[i]); + } + cnt++; + if (single_copytile_count && i >= single_copytile_count) { + break; + } + } + if (!quiet && cnt > 0) { + rfbLog("deleted %d tile_row polling images.\n", cnt); + } +} + +static void clean_icon_mode(void) { + if (icon_mode && icon_mode_fh) { + fprintf(icon_mode_fh, "quit\n"); + fflush(icon_mode_fh); + fclose(icon_mode_fh); + icon_mode_fh = NULL; + if (icon_mode_file) { + unlink(icon_mode_file); + icon_mode_file = NULL; + } + } +} + +/* + * Normal exiting + */ +void clean_up_exit(int ret) { + static int depth = 0; + exit_flag = 1; + + if (depth++ > 2) { + exit(ret); + } + + if (icon_mode) { + clean_icon_mode(); + } + + /* remove the shm areas: */ + clean_shm(0); + + stop_stunnel(); + if (use_openssl) { + ssl_helper_pid(0, 0); /* killall */ + } + + if (avahi) { + avahi_cleanup(); + } + if (ssh_pid > 0) { + kill(ssh_pid, SIGTERM); + ssh_pid = 0; + } + +#ifdef MACOSX + if (client_connect_file) { + if (strstr(client_connect_file, "/tmp/x11vnc-macosx-remote") + == client_connect_file) { + unlink(client_connect_file); + } + } + if (macosx_console) { + macosxCG_fini(); + } +#endif + + if (pipeinput_fh != NULL) { + pclose(pipeinput_fh); + pipeinput_fh = NULL; + } + + if (! dpy) { /* raw_rb hack */ + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(ret); + } + + /* X keyboard cleanups */ + delete_added_keycodes(0); + + if (clear_mods == 1) { + clear_modifiers(0); + } else if (clear_mods == 2) { + clear_keys(); + } else if (clear_mods == 3) { + clear_keys(); + clear_locks(); + } + + if (no_autorepeat) { + autorepeat(1, 0); + } + if (use_solid_bg) { + solid_bg(1); + } + if (ncache || ncache0) { + kde_no_animate(1); + } + X_LOCK; + XTestDiscard_wr(dpy); +#if LIBVNCSERVER_HAVE_LIBXDAMAGE + if (xdamage) { + XDamageDestroy(dpy, xdamage); + } +#endif +#if LIBVNCSERVER_HAVE_LIBXTRAP + if (trap_ctx) { + XEFreeTC(trap_ctx); + } +#endif + /* XXX rdpy_ctrl, etc. cannot close w/o blocking */ + XCloseDisplay_wr(dpy); + X_UNLOCK; + + fflush(stderr); + + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + + exit(ret); +} + +/* X11 error handlers */ + +static XErrorHandler Xerror_def; +static XIOErrorHandler XIOerr_def; + +int trap_xerror(Display *d, XErrorEvent *error) { + trapped_xerror = 1; + trapped_xerror_event = error; + + if (d) {} /* unused vars warning: */ + + return 0; +} + +int trap_xioerror(Display *d) { + trapped_xioerror = 1; + + if (d) {} /* unused vars warning: */ + + return 0; +} + +int trap_getimage_xerror(Display *d, XErrorEvent *error) { + trapped_getimage_xerror = 1; + trapped_xerror_event = error; + + if (d) {} /* unused vars warning: */ + + return 0; +} + +/* Are silly Xorg people removing X_ShmAttach from XShm.h? */ +/* INDEED! What stupid, myopic morons... */ +/* Maintenance Monkeys busy typing at their keyboards... */ +#ifndef X_ShmAttach +#define X_ShmAttach 1 +#endif + +static int Xerror(Display *d, XErrorEvent *error) { + X_UNLOCK; + + if (getenv("X11VNC_PRINT_XERROR")) { + fprintf(stderr, "Xerror: major_opcode: %d minor_opcode: %d error_code: %d\n", + error->request_code, error->minor_code, error->error_code); + } + + if (xshm_opcode > 0 && error->request_code == xshm_opcode) { + if (error->minor_code == X_ShmAttach) { + char *dstr = DisplayString(dpy); + fprintf(stderr, "\nX11 MIT Shared Memory Attach failed:\n"); + fprintf(stderr, " Is your DISPLAY=%s on a remote machine?\n", dstr); + if (strstr(dstr, "localhost:")) { + fprintf(stderr, " Note: DISPLAY=localhost:N suggests a SSH X11 redir to a remote machine.\n"); + } else if (dstr[0] != ':') { + fprintf(stderr, " Note: DISPLAY=hostname:N suggests a remote display.\n"); + } + fprintf(stderr, " Suggestion, use: x11vnc -display :0 ... for local display :0\n\n"); + } + } + + interrupted(0); + + if (d) {} /* unused vars warning: */ + + return (*Xerror_def)(d, error); +} + +void watch_loop(void); + +static int XIOerr(Display *d) { + static int reopen = 0, rmax = 1; + X_UNLOCK; + + if (getenv("X11VNC_REOPEN_DISPLAY")) { + rmax = atoi(getenv("X11VNC_REOPEN_DISPLAY")); + } + +#if !NO_X11 + if (reopen < rmax && getenv("X11VNC_REOPEN_DISPLAY")) { + int db = getenv("X11VNC_REOPEN_DEBUG") ? 1 : 0; + int sleepmax = 10, i; + Display *save_dpy = dpy; + char *dstr = strdup(DisplayString(save_dpy)); + reopen++; + if (getenv("X11VNC_REOPEN_SLEEP_MAX")) { + sleepmax = atoi(getenv("X11VNC_REOPEN_SLEEP_MAX")); + } + rfbLog("*** XIO error: Trying to reopen[%d/%d] display '%s'\n", reopen, rmax, dstr); + rfbLog("*** XIO error: Note the reopened state may be unstable.\n"); + for (i=0; i < sleepmax; i++) { + usleep (1000 * 1000); + dpy = XOpenDisplay_wr(dstr); + rfbLog("dpy[%d/%d]: %p\n", i+1, sleepmax, dpy); + if (dpy) { + break; + } + } + last_open_xdisplay = time(NULL); + if (dpy) { + rfbLog("*** XIO error: Reopened display '%s' successfully.\n", dstr); + if (db) rfbLog("*** XIO error: '%s' 0x%x\n", dstr, dpy); + scr = DefaultScreen(dpy); + rootwin = RootWindow(dpy, scr); + if (db) rfbLog("*** XIO error: disable_grabserver\n"); + disable_grabserver(dpy, 0); + if (db) rfbLog("*** XIO error: xrecord\n"); + zerodisp_xrecord(); + initialize_xrecord(); + if (db) rfbLog("*** XIO error: xdamage\n"); + create_xdamage_if_needed(1); + if (db) rfbLog("*** XIO error: do_new_fb\n"); + if (using_shm) { + if (db) rfbLog("*** XIO error: clean_shm\n"); + clean_shm(1); + } + do_new_fb(1); + if (db) rfbLog("*** XIO error: check_xevents\n"); + check_xevents(1); + + /* sadly, we can never return... */ + if (db) rfbLog("*** XIO error: watch_loop\n"); + watch_loop(); + clean_up_exit(1); + } + } +#endif + + interrupted(-1); + + if (d) {} /* unused vars warning: */ + + return (*XIOerr_def)(d); +} + +static char *xerrors[] = { + "Success", + "BadRequest", + "BadValue", + "BadWindow", + "BadPixmap", + "BadAtom", + "BadCursor", + "BadFont", + "BadMatch", + "BadDrawable", + "BadAccess", + "BadAlloc", + "BadColor", + "BadGC", + "BadIDChoice", + "BadName", + "BadLength", + "BadImplementation", + "unknown" +}; +static int xerrors_max = BadImplementation; + +char *xerror_string(XErrorEvent *error) { + int index = -1; + if (error) { + index = (int) error->error_code; + } + if (0 <= index && index <= xerrors_max) { + return xerrors[index]; + } else { + return xerrors[xerrors_max+1]; + } +} + +static char *crash_stack_command1 = NULL; +static char *crash_stack_command2 = NULL; +static char *crash_debug_command = NULL; + +void initialize_crash_handler(void) { + int pid = program_pid; + crash_stack_command1 = (char *) malloc(1000); + crash_stack_command2 = (char *) malloc(1000); + crash_debug_command = (char *) malloc(1000); + + snprintf(crash_stack_command1, 500, "echo where > /tmp/gdb.%d;" + " env PATH=$PATH:/usr/local/bin:/usr/sfw/bin:/usr/bin" + " gdb -x /tmp/gdb.%d -batch -n %s %d;" + " rm -f /tmp/gdb.%d", pid, pid, program_name, pid, pid); + snprintf(crash_stack_command2, 500, "pstack %d", program_pid); + + snprintf(crash_debug_command, 500, "gdb %s %d", program_name, pid); +} + +static void crash_shell_help(void) { + int pid = program_pid; + fprintf(stderr, "\n"); + fprintf(stderr, " *** Welcome to the x11vnc crash shell! ***\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "PROGRAM: %s PID: %d\n", program_name, pid); + fprintf(stderr, "\n"); + fprintf(stderr, "POSSIBLE DEBUGGER COMMAND:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " %s\n", crash_debug_command); + fprintf(stderr, "\n"); + fprintf(stderr, "Press \"q\" to quit.\n"); + fprintf(stderr, "Press \"h\" or \"?\" for this help.\n"); + fprintf(stderr, "Press \"s\" to try to run some commands to" + " show a stack trace (gdb/pstack).\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Anything else is passed to -Q query function.\n"); + fprintf(stderr, "\n"); +} + +static void crash_shell(void) { + char qry[1000], cmd[1000], line[1000]; + char *str, *p; + + crash_shell_help(); + fprintf(stderr, "\ncrash> "); + while (fgets(line, 1000, stdin) != NULL) { + str = lblanks(line); + + p = str; + while(*p) { + if (*p == '\n') { + *p = '\0'; + } + p++; + } + + if (*str == 'q' && *(str+1) == '\0') { + fprintf(stderr, "quiting.\n"); + return; + } else if (*str == 'h' && *(str+1) == '\0') { + crash_shell_help(); + } else if (*str == '?' && *(str+1) == '\0') { + crash_shell_help(); + } else if (*str == 's' && *(str+1) == '\0') { + sprintf(cmd, "sh -c '(%s) &'", crash_stack_command1); + /* crash */ + if (no_external_cmds || !cmd_ok("crash")) { + fprintf(stderr, "\nno_external_cmds=%d\n", + no_external_cmds); + goto crash_prompt; + } + fprintf(stderr, "\nrunning:\n\t%s\n\n", + crash_stack_command1); + system(cmd); + usleep(1000*1000); + + sprintf(cmd, "sh -c '(%s) &'", crash_stack_command2); + fprintf(stderr, "\nrunning:\n\t%s\n\n", + crash_stack_command2); + system(cmd); + usleep(1000*1000); + } else { + snprintf(qry, 1000, "qry=%s", str); + p = process_remote_cmd(qry, 1); + fprintf(stderr, "\n\nresult:\n%s\n", p); + free(p); + } + +crash_prompt: + fprintf(stderr, "crash> "); + } +} + +/* + * General problem handler + */ +static void interrupted (int sig) { + exit_sig = sig; + if (exit_flag) { + fprintf(stderr, "extra[%d] signal: %d\n", exit_flag, sig); + exit_flag++; + if (use_threads) { + usleep2(250 * 1000); + } else if (exit_flag <= 2) { + return; + } + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(4); + } + exit_flag++; + if (sig == 0) { + fprintf(stderr, "caught X11 error:\n"); + if (crash_debug) { crash_shell(); } + } else if (sig == -1) { + fprintf(stderr, "caught XIO error:\n"); + } else { + fprintf(stderr, "caught signal: %d\n", sig); + } + if (sig == SIGINT) { + shut_down = 1; + return; + } + + if (crash_debug) { + crash_shell(); + } + + X_UNLOCK; + + if (icon_mode) { + clean_icon_mode(); + } + /* remove the shm areas with quick=1: */ + clean_shm(1); + + if (sig == -1) { + /* not worth trying any more cleanup, X server probably gone */ + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(3); + } + + /* X keyboard cleanups */ + delete_added_keycodes(0); + + if (clear_mods == 1) { + clear_modifiers(0); + } else if (clear_mods == 2) { + clear_keys(); + } else if (clear_mods == 3) { + clear_keys(); + clear_locks(); + } + if (no_autorepeat) { + autorepeat(1, 0); + } + if (use_solid_bg) { + solid_bg(1); + } + if (ncache || ncache0) { + kde_no_animate(1); + } + stop_stunnel(); + + if (crash_debug) { + crash_shell(); + } + + if (sig) { + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(2); + } +} + +static void ignore_sigs(char *list) { + char *str, *p; + int ignore = 1; + if (list == NULL || *list == '\0') { + return; + } + str = strdup(list); + p = strtok(str, ":,"); + +#define SETSIG(x, y) \ + if (strstr(p, x)) { \ + if (ignore) { \ + signal(y, SIG_IGN); \ + } else { \ + signal(y, interrupted); \ + } \ + } + +#ifdef SIG_IGN + while (p) { + if (!strcmp(p, "ignore")) { + ignore = 1; + } else if (!strcmp(p, "exit")) { + ignore = 0; + } + /* Take off every 'sig' ;-) */ +#ifdef SIGHUP + SETSIG("HUP", SIGHUP); +#endif +#ifdef SIGINT + SETSIG("INT", SIGINT); +#endif +#ifdef SIGQUIT + SETSIG("QUIT", SIGQUIT); +#endif +#ifdef SIGTRAP + SETSIG("TRAP", SIGTRAP); +#endif +#ifdef SIGABRT + SETSIG("ABRT", SIGABRT); +#endif +#ifdef SIGBUS + SETSIG("BUS", SIGBUS); +#endif +#ifdef SIGFPE + SETSIG("FPE", SIGFPE); +#endif +#ifdef SIGSEGV + SETSIG("SEGV", SIGSEGV); +#endif +#ifdef SIGPIPE + SETSIG("PIPE", SIGPIPE); +#endif +#ifdef SIGTERM + SETSIG("TERM", SIGTERM); +#endif +#ifdef SIGUSR1 + SETSIG("USR1", SIGUSR1); +#endif +#ifdef SIGUSR2 + SETSIG("USR2", SIGUSR2); +#endif +#ifdef SIGCONT + SETSIG("CONT", SIGCONT); +#endif +#ifdef SIGSTOP + SETSIG("STOP", SIGSTOP); +#endif +#ifdef SIGTSTP + SETSIG("TSTP", SIGTSTP); +#endif + p = strtok(NULL, ":,"); + } +#endif /* SIG_IGN */ + free(str); +} + +/* signal handlers */ +void initialize_signals(void) { + signal(SIGHUP, interrupted); + signal(SIGINT, interrupted); + signal(SIGQUIT, interrupted); + signal(SIGABRT, interrupted); + signal(SIGTERM, interrupted); + signal(SIGBUS, interrupted); + signal(SIGSEGV, interrupted); + signal(SIGFPE, interrupted); + + if (!sigpipe || *sigpipe == '\0' || !strcmp(sigpipe, "skip")) { + ; + } else if (strstr(sigpipe, "ignore:") == sigpipe) { + ignore_sigs(sigpipe); + } else if (strstr(sigpipe, "exit:") == sigpipe) { + ignore_sigs(sigpipe); + } else if (!strcmp(sigpipe, "ignore")) { +#ifdef SIG_IGN + signal(SIGPIPE, SIG_IGN); +#endif + } else if (!strcmp(sigpipe, "exit")) { + rfbLog("initialize_signals: will exit on SIGPIPE\n"); + signal(SIGPIPE, interrupted); + } + +#if NO_X11 + return; +#else + X_LOCK; + Xerror_def = XSetErrorHandler(Xerror); + XIOerr_def = XSetIOErrorHandler(XIOerr); + X_UNLOCK; +#endif /* NO_X11 */ +} + +void unset_signals(void) { + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGABRT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGPIPE, SIG_DFL); +} + +void close_exec_fds(void) { + int fd; +#ifdef FD_CLOEXEC + for (fd = 3; fd < 64; fd++) { + int flags = fcntl(fd, F_GETFD); + if (flags != -1) { + flags |= FD_CLOEXEC; + fcntl(fd, F_SETFD, flags); + } + } +#endif +} + +int known_sigpipe_mode(char *s) { +/* + * skip, ignore, exit + */ + if (strstr(s, "ignore:") == s) { + return 1; + } + if (strstr(s, "exit:") == s) { + return 1; + } + if (strcmp(s, "skip") && strcmp(s, "ignore") && + strcmp(s, "exit")) { + return 0; + } else { + return 1; + } +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.h new file mode 100755 index 0000000..0c4dcea --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_CLEANUP_H +#define _X11VNC_CLEANUP_H + +/* -- cleanup.h -- */ + +extern int trapped_xerror; +extern int trapped_xioerror; +extern int trapped_getimage_xerror; +extern int trapped_record_xerror; +extern XErrorEvent *trapped_xerror_event; + +extern int crash_debug; + +extern void clean_shm(int quick); +extern void clean_up_exit(int ret); + +extern int trap_xerror(Display *d, XErrorEvent *error); +extern int trap_xioerror(Display *d); +extern int trap_getimage_xerror(Display *d, XErrorEvent *error); +extern char *xerror_string(XErrorEvent *error); +extern void initialize_crash_handler(void); +extern void initialize_signals(void); +extern void unset_signals(void); +extern void close_exec_fds(void); +extern int known_sigpipe_mode(char *s); + +#endif /* _X11VNC_CLEANUP_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.c new file mode 100755 index 0000000..5dd80ba --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.c @@ -0,0 +1,4377 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- connections.c -- */ + +#include "x11vnc.h" +#include "inet.h" +#include "remote.h" +#include "keyboard.h" +#include "cleanup.h" +#include "gui.h" +#include "solid.h" +#include "rates.h" +#include "screen.h" +#include "unixpw.h" +#include "user.h" +#include "scan.h" +#include "sslcmds.h" +#include "sslhelper.h" +#include "xwrappers.h" +#include "xevents.h" +#include "win_utils.h" +#include "macosx.h" +#include "macosxCG.h" +#include "userinput.h" +#include "pointer.h" +#include "xrandr.h" + +/* + * routines for handling incoming, outgoing, etc connections + */ + +/* string for the VNC_CONNECT property */ +char vnc_connect_str[VNC_CONNECT_MAX+1]; +Atom vnc_connect_prop = None; +char x11vnc_remote_str[X11VNC_REMOTE_MAX+1]; +Atom x11vnc_remote_prop = None; +rfbClientPtr inetd_client = NULL; + +int all_clients_initialized(void); +char *list_clients(void); +int new_fb_size_clients(rfbScreenInfoPtr s); +void close_all_clients(void); +void close_clients(char *str); +void set_client_input(char *str); +void set_child_info(void); +int cmd_ok(char *cmd); +void client_gone(rfbClientPtr client); +void client_gone_chat_helper(rfbClientPtr client); +void reverse_connect(char *str); +void set_vnc_connect_prop(char *str); +void read_vnc_connect_prop(int); +void set_x11vnc_remote_prop(char *str); +void read_x11vnc_remote_prop(int); +void check_connect_inputs(void); +void check_gui_inputs(void); +rfbClientPtr create_new_client(int sock, int start_thread); +enum rfbNewClientAction new_client(rfbClientPtr client); +enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client); +rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len); +void start_client_info_sock(char *host_port_cookie); +void send_client_info(char *str); +void adjust_grabs(int grab, int quiet); +void check_new_clients(void); +int accept_client(rfbClientPtr client); +void check_ipv6_listen(long usec); +int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, + int len, FILE *output); +int check_access(char *addr); +void client_set_net(rfbClientPtr client); +char *get_xprop(char *prop, Window win); +int set_xprop(char *prop, Window win, char *value); +char *bcx_xattach(char *str, int *pg_init, int *kg_init); +void grab_state(int *ptr_grabbed, int *kbd_grabbed); +char *wininfo(Window win, int show_children); + +static rfbClientPtr *client_match(char *str); +static void free_client_data(rfbClientPtr client); +static void ugly_geom(char *p, int *x, int *y); +static int ugly_window(char *addr, char *userhost, int X, int Y, + int timeout, char *mode, int accept); +static int action_match(char *action, int rc); +static void check_connect_file(char *file); +static void send_client_connect(void); + + +/* + * check that all clients are in RFB_NORMAL state + */ +int all_clients_initialized(void) { + rfbClientIteratorPtr iter; + rfbClientPtr cl; + int ok = 1; + + if (! screen) { + return ok; + } + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + if (cl->state != RFB_NORMAL) { + ok = 0; + } else { + client_normal_count++; + } + } + rfbReleaseClientIterator(iter); + + return ok; +} + +char *list_clients(void) { + rfbClientIteratorPtr iter; + rfbClientPtr cl; + char *list, tmp[256]; + int count = 0; + + if (!screen) { + return strdup(""); + } + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + client_set_net(cl); + count++; + } + rfbReleaseClientIterator(iter); + + /* + * each client: + * ::::::::