1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * httpd.c - a simple HTTP server 3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org> 7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Copyright (C) 2002 RealVNC Ltd. 8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. 9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This is free software; you can redistribute it and/or modify 11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * it under the terms of the GNU General Public License as published by 12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * the Free Software Foundation; either version 2 of the License, or 13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * (at your option) any later version. 14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This software is distributed in the hope that it will be useful, 16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * but WITHOUT ANY WARRANTY; without even the implied warranty of 17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * GNU General Public License for more details. 19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * You should have received a copy of the GNU General Public License 21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * along with this software; if not, write to the Free Software 22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * USA. 24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 261d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef __STRICT_ANSI__ 271d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define _BSD_SOURCE 281d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define _POSIX_SOURCE 291d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif 301d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman 31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfb.h> 32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <ctype.h> 34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_UNISTD_H 35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <unistd.h> 36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H 38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/types.h> 39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_FCNTL_H 41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <fcntl.h> 42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <errno.h> 44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef WIN32 461d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <io.h> 471d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <winsock2.h> 481d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <ws2tcpip.h> 49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define close closesocket 501d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#if defined(_MSC_VER) 511d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <BaseTsd.h> /* For the missing ssize_t */ 521d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define ssize_t SSIZE_T 531d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define read _read /* Prevent POSIX deprecation warnings */ 541d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif 55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else 56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H 57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/time.h> 58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H 60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/socket.h> 61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H 63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netinet/in.h> 64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netinet/tcp.h> 65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netdb.h> 66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <arpa/inet.h> 67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <pwd.h> 69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef USE_LIBWRAP 72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <tcpd.h> 73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\nConnection: close\r\n\r\n" \ 77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat "<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \ 78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat "<BODY><H1>File Not Found</H1></BODY>\n" 79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\nConnection: close\r\n\r\n" \ 81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat "<HEAD><TITLE>Invalid Request</TITLE></HEAD>\n" \ 82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat "<BODY><H1>Invalid request</H1></BODY>\n" 83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define OK_STR "HTTP/1.0 200 OK\r\nConnection: close\r\n\r\n" 85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define OK_STR_HTML "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n" 86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void httpProcessInput(rfbScreenInfoPtr screen); 90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool compareAndSkip(char **ptr, const char *str); 91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool parseParams(const char *request, char *result, int max_bytes); 92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool validateString(char *str); 93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define BUF_SIZE 32768 95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic char buf[BUF_SIZE]; 97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic size_t buf_filled=0; 98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * httpInitSockets sets up the TCP socket to listen for HTTP connections. 101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid 104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) 105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbScreen->httpInitDone) 107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpInitDone = TRUE; 110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (!rfbScreen->httpDir) 112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbScreen->httpPort == 0) { 115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpPort = rfbScreen->port-100; 116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((rfbScreen->httpListenSock = 119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) { 120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("ListenOnTCPPort"); 121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort); 124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort); 125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6 127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbScreen->http6Port == 0) { 128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->http6Port = rfbScreen->ipv6port-100; 129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((rfbScreen->httpListen6Sock 132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat = rfbListenOnTCP6Port(rfbScreen->http6Port, rfbScreen->listen6Interface)) < 0) { 133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* ListenOnTCP6Port has its own detailed error printout */ 134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Listening for HTTP connections on TCP6 port %d\n", rfbScreen->http6Port); 137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->http6Port); 138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { 142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(rfbScreen->httpSock>-1) { 143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat close(rfbScreen->httpSock); 144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds); 145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpSock=-1; 146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(rfbScreen->httpListenSock>-1) { 149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat close(rfbScreen->httpListenSock); 150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FD_CLR(rfbScreen->httpListenSock,&rfbScreen->allFds); 151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpListenSock=-1; 152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(rfbScreen->httpListen6Sock>-1) { 155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat close(rfbScreen->httpListen6Sock); 156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FD_CLR(rfbScreen->httpListen6Sock,&rfbScreen->allFds); 157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpListen6Sock=-1; 158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * httpCheckFds is called from ProcessInputEvents to check for input on the 163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * HTTP socket(s). If there is input to process, httpProcessInput is called. 164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid 167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) 168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int nfds; 170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat fd_set fds; 171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat struct timeval tv; 172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6 173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat struct sockaddr_storage addr; 174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else 175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat struct sockaddr_in addr; 176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat socklen_t addrlen = sizeof(addr); 178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (!rfbScreen->httpDir) 180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbScreen->httpListenSock < 0) 183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FD_ZERO(&fds); 186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FD_SET(rfbScreen->httpListenSock, &fds); 187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbScreen->httpListen6Sock >= 0) { 188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FD_SET(rfbScreen->httpListen6Sock, &fds); 189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbScreen->httpSock >= 0) { 191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FD_SET(rfbScreen->httpSock, &fds); 192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat tv.tv_sec = 0; 194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat tv.tv_usec = 0; 195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat nfds = select(max(rfbScreen->httpListen6Sock, max(rfbScreen->httpSock,rfbScreen->httpListenSock)) + 1, &fds, NULL, NULL, &tv); 196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (nfds == 0) { 197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (nfds < 0) { 200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef WIN32 201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat errno = WSAGetLastError(); 202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (errno != EINTR) 204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("httpCheckFds: select"); 205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) { 209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpProcessInput(rfbScreen); 210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (FD_ISSET(rfbScreen->httpListenSock, &fds) || FD_ISSET(rfbScreen->httpListen6Sock, &fds)) { 213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); 214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(FD_ISSET(rfbScreen->httpListenSock, &fds)) { 216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { 217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("httpCheckFds: accept"); 218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat else if(FD_ISSET(rfbScreen->httpListen6Sock, &fds)) { 222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((rfbScreen->httpSock = accept(rfbScreen->httpListen6Sock, (struct sockaddr *)&addr, &addrlen)) < 0) { 223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("httpCheckFds: accept"); 224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef USE_LIBWRAP 229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char host[1024]; 230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6 231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { 232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("httpCheckFds: error in getnameinfo"); 233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat host[0] = '\0'; 234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else 236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat memcpy(host, inet_ntoa(addr.sin_addr), sizeof(host)); 237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(!hosts_ctl("vnc",STRING_UNKNOWN, host, 239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat STRING_UNKNOWN)) { 240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Rejected HTTP connection from client %s\n", 241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat host); 242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat close(rfbScreen->httpSock); 243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpSock=-1; 244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(!rfbSetNonBlocking(rfbScreen->httpSock)) { 248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat close(rfbScreen->httpSock); 249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpSock=-1; 250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /*AddEnabledDevice(httpSock);*/ 253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void 258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehathttpCloseSock(rfbScreenInfoPtr rfbScreen) 259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat close(rfbScreen->httpSock); 261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpSock = -1; 262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat buf_filled = 0; 263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbClientRec cl; 266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * httpProcessInput is called when input is received on the HTTP socket. 269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void 272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehathttpProcessInput(rfbScreenInfoPtr rfbScreen) 273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6 275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat struct sockaddr_storage addr; 276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else 277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat struct sockaddr_in addr; 278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat socklen_t addrlen = sizeof(addr); 280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char fullFname[512]; 281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char params[1024]; 282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char *ptr; 283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char *fname; 284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned int maxFnameLen; 285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat FILE* fd; 286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbBool performSubstitutions = FALSE; 287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char str[256+32]; 288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifndef WIN32 289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char* user=getenv("USER"); 290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cl.sock=rfbScreen->httpSock; 293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strlen(rfbScreen->httpDir) > 255) { 295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("-httpd directory too long\n"); 296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat strcpy(fullFname, rfbScreen->httpDir); 300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat fname = &fullFname[strlen(fullFname)]; 301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat maxFnameLen = 511 - strlen(fullFname); 302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat buf_filled=0; 304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Read data from the HTTP client until we get a complete request. */ 306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat while (1) { 307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ssize_t got; 308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (buf_filled > sizeof (buf)) { 310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpProcessInput: HTTP request is too long\n"); 311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat got = read (rfbScreen->httpSock, buf + buf_filled, 316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat sizeof (buf) - buf_filled - 1); 317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (got <= 0) { 319a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (got == 0) { 320a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpd: premature connection close\n"); 321a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else { 322a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef WIN32 323a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat errno=WSAGetLastError(); 324a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (errno == EAGAIN) { 326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 327a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("httpProcessInput: read"); 329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 332a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 333a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 334a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat buf_filled += got; 335a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat buf[buf_filled] = '\0'; 336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 337a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Is it complete yet (is there a blank line)? */ 338a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strstr (buf, "\r\r") || strstr (buf, "\n\n") || 339a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r")) 340a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat break; 341a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 342a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 343a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 344a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Process the request. */ 345a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(rfbScreen->httpEnableProxyConnect) { 346a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat const static char* PROXY_OK_STR = "HTTP/1.0 200 OK\r\nContent-Type: octet-stream\r\nPragma: no-cache\r\n\r\n"; 347a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(!strncmp(buf, "CONNECT ", 8)) { 348a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(atoi(strchr(buf, ':')+1)!=rfbScreen->port) { 349a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpd: CONNECT format invalid.\n"); 350a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl,INVALID_REQUEST_STR, strlen(INVALID_REQUEST_STR)); 351a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 352a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 353a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 354a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* proxy connection */ 355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("httpd: client asked for CONNECT\n"); 356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR)); 357a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbNewClientConnection(rfbScreen,rfbScreen->httpSock); 358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpSock = -1; 359a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (!strncmp(buf, "GET ",4) && !strncmp(strchr(buf,'/'),"/proxied.connection HTTP/1.", 27)) { 362a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* proxy connection */ 363a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("httpd: client asked for /proxied.connection\n"); 364a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR)); 365a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbNewClientConnection(rfbScreen,rfbScreen->httpSock); 366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreen->httpSock = -1; 367a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 370a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 371a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strncmp(buf, "GET ", 4)) { 372a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpd: no GET line\n"); 373a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 374a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else { 376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Only use the first line. */ 377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat buf[strcspn(buf, "\n\r")] = '\0'; 378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 380a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strlen(buf) > maxFnameLen) { 381a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpd: GET line too long\n"); 382a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 383a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 384a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 385a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 386a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (sscanf(buf, "GET %s HTTP/1.", fname) != 1) { 387a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpd: couldn't parse GET line\n"); 388a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 389a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 390a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 391a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 392a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (fname[0] != '/') { 393a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpd: filename didn't begin with '/'\n"); 394a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); 395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 397a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen); 401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6 4021d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman { 4031d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman char host[1024]; 4041d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { 4051d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman rfbLogPerror("httpProcessInput: error in getnameinfo"); 4061d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman } 4071d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman rfbLog("httpd: get '%s' for %s\n", fname+1, host); 408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else 410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("httpd: get '%s' for %s\n", fname+1, 411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat inet_ntoa(addr.sin_addr)); 412a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Extract parameters from the URL string if necessary */ 415a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat params[0] = '\0'; 417a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr = strchr(fname, '?'); 418a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (ptr != NULL) { 419a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *ptr = '\0'; 420a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (!parseParams(&ptr[1], params, 1024)) { 421a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat params[0] = '\0'; 422a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbErr("httpd: bad parameters in the URL\n"); 423a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 424a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 425a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 426a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 427a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* If we were asked for '/', actually read the file index.vnc */ 428a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 429a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strcmp(fname, "/") == 0) { 430a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat strcpy(fname, "/index.vnc"); 431a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("httpd: defaulting to '%s'\n", fname+1); 432a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 433a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 434a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Substitutions are performed on files ending .vnc */ 435a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 436a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) { 437a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat performSubstitutions = TRUE; 438a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 439a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 440a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Open the file */ 441a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 442a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((fd = fopen(fullFname, "r")) == 0) { 443a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("httpProcessInput: open"); 444a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); 445a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 446a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 447a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 448a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 449a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if(performSubstitutions) /* is the 'index.vnc' file */ 450a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, OK_STR_HTML, strlen(OK_STR_HTML)); 451a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat else 452a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, OK_STR, strlen(OK_STR)); 453a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 454a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat while (1) { 455a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int n = fread(buf, 1, BUF_SIZE-1, fd); 456a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (n < 0) { 457a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("httpProcessInput: read"); 458a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat fclose(fd); 459a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 460a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 461a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 462a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 463a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (n == 0) 464a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat break; 465a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 466a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (performSubstitutions) { 467a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 468a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values. 469a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat This won't quite work properly if the .vnc file is longer than 470a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat BUF_SIZE, but it's reasonable to assume that .vnc files will 471a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat always be short. */ 472a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 473a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char *ptr = buf; 474a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char *dollar; 475a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat buf[n] = 0; /* make sure it's null-terminated */ 476a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 477a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat while ((dollar = strchr(ptr, '$'))!=NULL) { 478a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, ptr, (dollar - ptr)); 479a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 480a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr = dollar; 481a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 482a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (compareAndSkip(&ptr, "$WIDTH")) { 483a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 484a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat sprintf(str, "%d", rfbScreen->width); 485a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, str, strlen(str)); 486a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 487a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$HEIGHT")) { 488a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 489a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat sprintf(str, "%d", rfbScreen->height); 490a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, str, strlen(str)); 491a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 492a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) { 493a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 494a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat sprintf(str, "%d", rfbScreen->width); 495a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, str, strlen(str)); 496a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 497a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) { 498a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 499a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat sprintf(str, "%d", rfbScreen->height + 32); 500a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, str, strlen(str)); 501a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 502a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$PORT")) { 503a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 504a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat sprintf(str, "%d", rfbScreen->port); 505a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, str, strlen(str)); 506a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 507a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$DESKTOP")) { 508a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 509a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName)); 510a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 511a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$DISPLAY")) { 512a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 513a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat sprintf(str, "%s:%d", rfbScreen->thisHost, rfbScreen->port-5900); 514a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, str, strlen(str)); 515a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 516a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$USER")) { 517a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifndef WIN32 518a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (user) { 519a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, user, 520a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat strlen(user)); 521a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else 522a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 523a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, "?", 1); 524a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else if (compareAndSkip(&ptr, "$PARAMS")) { 525a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (params[0] != '\0') 526a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbWriteExact(&cl, params, strlen(params)); 527a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else { 528a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (!compareAndSkip(&ptr, "$$")) 529a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr++; 530a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 531a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbWriteExact(&cl, "$", 1) < 0) { 532a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat fclose(fd); 533a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 534a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return; 535a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 536a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 537a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 538a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbWriteExact(&cl, ptr, (&buf[n] - ptr)) < 0) 539a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat break; 540a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 541a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else { 542a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 543a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* For files not ending .vnc, just write out the buffer */ 544a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 545a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbWriteExact(&cl, buf, n) < 0) 546a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat break; 547a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 548a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 549a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 550a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat fclose(fd); 551a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat httpCloseSock(rfbScreen); 552a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 553a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 554a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 555a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool 556a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatcompareAndSkip(char **ptr, const char *str) 557a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 558a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strncmp(*ptr, str, strlen(str)) == 0) { 559a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *ptr += strlen(str); 560a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 561a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 562a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 563a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 564a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 565a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 566a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 567a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Parse the request tail after the '?' character, and format a sequence 568a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * of <param> tags for inclusion into an HTML page with embedded applet. 569a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 570a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 571a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool 572a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatparseParams(const char *request, char *result, int max_bytes) 573a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 574a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char param_request[128]; 575a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char param_formatted[196]; 576a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat const char *tail; 577a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char *delim_ptr; 578a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char *value_str; 579a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int cur_bytes, len; 580a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 581a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat result[0] = '\0'; 582a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cur_bytes = 0; 583a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 584a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat tail = request; 585a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (;;) { 586a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Copy individual "name=value" string into a buffer */ 587a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat delim_ptr = strchr((char *)tail, '&'); 588a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (delim_ptr == NULL) { 589a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strlen(tail) >= sizeof(param_request)) { 590a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 591a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 592a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat strcpy(param_request, tail); 593a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else { 594a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat len = delim_ptr - tail; 595a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (len >= sizeof(param_request)) { 596a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 597a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 598a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat memcpy(param_request, tail, len); 599a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat param_request[len] = '\0'; 600a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 601a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 602a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Split the request into parameter name and value */ 603a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat value_str = strchr(¶m_request[1], '='); 604a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (value_str == NULL) { 605a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 606a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 607a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *value_str++ = '\0'; 608a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (strlen(value_str) == 0) { 609a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 610a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 611a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 612a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Validate both parameter name and value */ 613a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (!validateString(param_request) || !validateString(value_str)) { 614a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 615a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 616a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 617a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Prepare HTML-formatted representation of the name=value pair */ 618a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat len = sprintf(param_formatted, 619a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat "<PARAM NAME=\"%s\" VALUE=\"%s\">\n", 620a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat param_request, value_str); 621a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (cur_bytes + len + 1 > max_bytes) { 622a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 623a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 624a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat strcat(result, param_formatted); 625a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cur_bytes += len; 626a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 627a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Go to the next parameter */ 628a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (delim_ptr == NULL) { 629a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat break; 630a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 631a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat tail = delim_ptr + 1; 632a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 633a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 634a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 635a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 636a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 637a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Check if the string consists only of alphanumeric characters, '+' 638a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * signs, underscores, dots, colons and square brackets. 639a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Replace all '+' signs with spaces. 640a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 641a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 642a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool 643a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatvalidateString(char *str) 644a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 645a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat char *ptr; 646a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 647a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (ptr = str; *ptr != '\0'; ptr++) { 648a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.' 649a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat && *ptr != ':' && *ptr != '[' && *ptr != ']' ) { 650a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (*ptr == '+') { 651a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *ptr = ' '; 652a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else { 653a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 654a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 655a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 656a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 657a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 658a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 659a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 660