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(&param_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