Removed invirt-web-afs-apache
[invirt/packages/invirt-vnc-client.git] / debian / patches / invirt-ssl-proxy.patch
1 Index: invirt-vnc-client/InvirtTrustManager.java
2 ===================================================================
3 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
4 +++ invirt-vnc-client/InvirtTrustManager.java   2008-10-31 06:09:10.000000000 -0400
5 @@ -0,0 +1,123 @@
6 +// This code is based on http://svntrac.hanhuy.com/repo/browser/hanhuy/trunk/cms/src/com/hanhuy/ria/client/RIATrustManager.java
7 +/*
8 + * Copyright 2006 Perry Nguyen <pfnguyen@hanhuy.com>
9 + * Licensed under the Apache License, Version 2.0 (the "License");
10 + * you may not use this file except in compliance with the License.
11 + * You may obtain a copy of the License at
12 + *
13 + *     http://www.apache.org/licenses/LICENSE-2.0
14 + *
15 + * Unless required by applicable law or agreed to in writing, software
16 + * distributed under the License is distributed on an "AS IS" BASIS,
17 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 + * See the License for the specific language governing permissions and
19 + * limitations under the License.
20 + */
21 +import java.io.IOException;
22 +import java.io.InputStream;
23 +import java.security.KeyStore;
24 +import java.security.KeyStoreException;
25 +import java.security.NoSuchAlgorithmException;
26 +import java.security.cert.CertificateException;
27 +import java.security.cert.X509Certificate;
28 +import java.util.Enumeration;
29 +import java.util.logging.Level;
30 +import java.util.logging.Logger;
31 +
32 +import javax.net.ssl.TrustManager;
33 +import javax.net.ssl.TrustManagerFactory;
34 +import javax.net.ssl.X509TrustManager;
35 +
36 +public class InvirtTrustManager implements X509TrustManager {
37 +    private X509TrustManager trustManager;
38 +    private final static char[] KEY_STORE_PASSWORD =
39 +        { 'f', 'o', 'o', 'b', 'a', 'r' };
40 +    private final static String KEY_STORE_RESOURCE =
41 +        "trust.store";
42 +
43 +    private KeyStore loadKeyStore() throws Exception {
44 +        InputStream in = getClass().getClassLoader().getResourceAsStream(
45 +                KEY_STORE_RESOURCE);
46 +        KeyStore ks = null;
47 +        try {
48 +            if (in == null) {
49 +                //log.severe("Unable to open KeyStore");
50 +                throw new NullPointerException();
51 +            }
52 +            ks = KeyStore.getInstance(KeyStore.getDefaultType());
53 +            ks.load(in, KEY_STORE_PASSWORD);
54 +           /*if (log.isLoggable(Level.FINEST)) {
55 +                for (Enumeration<String> aliases = ks.aliases();
56 +                aliases.hasMoreElements();) {
57 +                    String alias = aliases.nextElement();
58 +                    log.finest("ALIAS: " + alias);
59 +                }
60 +               }*/
61 +        } catch (NoSuchAlgorithmException e) {
62 +            throwError(e);
63 +        } catch (CertificateException e) {
64 +            throwError(e);
65 +        } catch (IOException e) {
66 +            throwError(e);
67 +        } catch (KeyStoreException e) {
68 +            throwError(e);
69 +        } finally {
70 +            try {
71 +                if (in != null)
72 +                    in.close();
73 +            }
74 +            catch (IOException e) { } // ignore
75 +        }
76 +        return ks;
77 +    }
78 +    private void createTrustManager() {
79 +       try {
80 +           try {
81 +               KeyStore keystore = loadKeyStore();
82 +               TrustManagerFactory factory = TrustManagerFactory.getInstance(
83 +                                                                             TrustManagerFactory.getDefaultAlgorithm());
84 +               factory.init(keystore);
85 +               TrustManager[] trustManagers = factory.getTrustManagers();
86 +               if (trustManagers.length == 0)
87 +                   throw new IllegalStateException("No trust manager found");
88 +               setTrustManager((X509TrustManager) trustManagers[0]);
89 +           } catch (NoSuchAlgorithmException e) {
90 +               throwError(e);
91 +           } catch (KeyStoreException e) {
92 +               throwError(e);
93 +           }
94 +       } catch (Exception e) {
95 +           e.printStackTrace();
96 +       }
97 +    }
98 +    private void throwError(Exception e) throws Exception {
99 +        //HttpClientError error = new HttpClientError(e.getMessage());
100 +        //error.initCause(e);
101 +        throw e;
102 +    }
103 +    public X509TrustManager getTrustManager() {
104 +        if (trustManager == null)
105 +            createTrustManager();
106 +        return trustManager;
107 +    }
108 +
109 +    public void setTrustManager(X509TrustManager trustManager) {
110 +        this.trustManager = trustManager;
111 +    }
112 +
113 +    public void checkClientTrusted(X509Certificate[] chain, String authType)
114 +            throws CertificateException {
115 +        getTrustManager().checkClientTrusted(chain, authType);
116 +    }
117 +
118 +    public void checkServerTrusted(X509Certificate[] chain, String authType)
119 +            throws CertificateException {
120 +        getTrustManager().checkServerTrusted(chain, authType);
121 +
122 +    }
123 +
124 +    public X509Certificate[] getAcceptedIssuers() {
125 +        return getTrustManager().getAcceptedIssuers();
126 +    }
127 +
128 +}
129 \ No newline at end of file
130 Index: invirt-vnc-client/Makefile
131 ===================================================================
132 --- invirt-vnc-client.orig/Makefile     2008-10-31 06:09:10.000000000 -0400
133 +++ invirt-vnc-client/Makefile  2008-10-31 06:09:10.000000000 -0400
134 @@ -17,8 +17,10 @@
135           DesCipher.class CapabilityInfo.class CapsContainer.class \
136           RecordingFrame.class SessionRecorder.class \
137           SocketFactory.class HTTPConnectSocketFactory.class \
138 +         VNCProxyConnectSocketFactory.class VNCProxyConnectSocket.class \
139           HTTPConnectSocket.class ReloginPanel.class \
140 -         InStream.class MemInStream.class ZlibInStream.class
141 +         InStream.class MemInStream.class ZlibInStream.class \
142 +         VNCProxyConnectSocketWrapper.class SocketWrapper.class SocketWrapper\$$WrappingSocketImpl.class InvirtTrustManager.class
143  
144  SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \
145           VncCanvas2.java \
146 @@ -26,8 +28,10 @@
147           DesCipher.java CapabilityInfo.java CapsContainer.java \
148           RecordingFrame.java SessionRecorder.java \
149           SocketFactory.java HTTPConnectSocketFactory.java \
150 +         VNCProxyConnectSocketFactory.java VNCProxyConnectSocket.java \
151           HTTPConnectSocket.java ReloginPanel.java \
152 -         InStream.java MemInStream.java ZlibInStream.java
153 +         InStream.java MemInStream.java ZlibInStream.java \
154 +         VNCProxyConnectSocketWrapper.java SocketWrapper.java InvirtTrustManager.java
155  
156  all: $(CLASSES) $(ARCHIVE)
157  
158 Index: invirt-vnc-client/RfbProto.java
159 ===================================================================
160 --- invirt-vnc-client.orig/RfbProto.java        2007-04-26 22:36:00.000000000 -0400
161 +++ invirt-vnc-client/RfbProto.java     2008-10-31 06:09:10.000000000 -0400
162 @@ -208,11 +208,13 @@
163      port = p;
164  
165      if (viewer.socketFactory == null) {
166 +       System.out.println("Null socketFactory");
167        sock = new Socket(host, port);
168      } else {
169        try {
170         Class factoryClass = Class.forName(viewer.socketFactory);
171         SocketFactory factory = (SocketFactory)factoryClass.newInstance();
172 +       System.out.println("Using socketFactory " + factory);
173         if (viewer.inAnApplet)
174           sock = factory.createSocket(host, port, viewer);
175         else
176 @@ -236,7 +238,7 @@
177      try {
178        sock.close();
179        closed = true;
180 -      System.out.println("RFB socket closed");
181 +      System.out.println("RFB socket closed " + sock);
182        if (rec != null) {
183         rec.close();
184         rec = null;
185 Index: invirt-vnc-client/SocketWrapper.java
186 ===================================================================
187 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
188 +++ invirt-vnc-client/SocketWrapper.java        2008-10-31 06:09:10.000000000 -0400
189 @@ -0,0 +1,263 @@
190 +/*
191 + * Written by Dawid Kurzyniec and released to the public domain, as explained
192 + * at http://creativecommons.org/licenses/publicdomain
193 + */
194 +// Upstream is at http://www.dcl.mathcs.emory.edu/downloads/h2o/doc/api/edu/emory/mathcs/util/net/SocketWrapper.html
195 +
196 +//package edu.emory.mathcs.util.net;
197 +
198 +import java.io.*;
199 +import java.net.*;
200 +import java.nio.channels.*;
201 +
202 +/**
203 + * Wrapper for sockets which enables to add functionality in subclasses
204 + * on top of existing, connected sockets. It is useful when direct subclassing
205 + * of delegate socket class is not possible, e.g. if the delegate socket is
206 + * created by a library. Possible usage example is socket factory chaining.
207 + * This class delegates all socket-related requests to the wrapped delegate,
208 + * as of JDK 1.4.
209 + *
210 + * @author Dawid Kurzyniec
211 + * @version 1.4
212 + */
213 +public abstract class SocketWrapper extends Socket {
214 +
215 +    /**
216 +     * the wrapped delegate socket.
217 +     */
218 +    protected final Socket delegate;
219 +
220 +    /**
221 +     * Creates new socket wrapper for a given socket. The delegate
222 +     * must be connected and bound and it must not be closed.
223 +     * @param delegate the delegate socket to wrap
224 +     * @throws SocketException if the delegate socket is closed, not bound,
225 +     *                         or not connected
226 +     */
227 +    protected SocketWrapper(Socket delegate) throws SocketException {
228 +        super(new WrappingSocketImpl(delegate));
229 +        this.delegate = delegate;
230 +       System.out.println("Creating SocketWrapper $Rev$");
231 +    }
232 +
233 +    public SocketChannel getChannel() {
234 +        return delegate.getChannel();
235 +    }
236 +
237 +    /**
238 +     * Returns true, indicating that the socket is bound.
239 +     *
240 +     * @return true
241 +     */
242 +    public boolean isBound() {
243 +        return true;
244 +    }
245 +
246 +    public boolean isClosed() {
247 +        return super.isClosed() || delegate.isClosed();
248 +    }
249 +
250 +    /**
251 +     * Returns true, indicating that the socket is connected.
252 +     *
253 +     * @return true
254 +     */
255 +    public boolean isConnected() {
256 +        return true;
257 +    }
258 +
259 +    public boolean isInputShutdown() {
260 +        return super.isInputShutdown() || delegate.isInputShutdown();
261 +    }
262 +
263 +    public boolean isOutputShutdown() {
264 +        return super.isInputShutdown() || delegate.isOutputShutdown();
265 +    }
266 +
267 +    private static class WrappingSocketImpl extends SocketImpl {
268 +        private final Socket delegate;
269 +        WrappingSocketImpl(Socket delegate) throws SocketException {
270 +            if (delegate == null) {
271 +                throw new NullPointerException();
272 +            }
273 +            if (delegate.isClosed()) {
274 +                throw new SocketException("Delegate server socket is closed");
275 +            }
276 +            if (!(delegate.isBound())) {
277 +                throw new SocketException("Delegate server socket is not bound");
278 +            }
279 +            if (!(delegate.isConnected())) {
280 +                throw new SocketException("Delegate server socket is not connected");
281 +            }
282 +            this.delegate = delegate;
283 +        }
284 +
285 +        protected void create(boolean stream) {}
286 +
287 +        protected void connect(String host, int port) {
288 +            // delegate is always connected, thus this method is never called
289 +            throw new UnsupportedOperationException();
290 +        }
291 +
292 +        protected void connect(InetAddress address, int port) {
293 +            // delegate is always connected, thus this method is never called
294 +            throw new UnsupportedOperationException();
295 +        }
296 +
297 +        protected void connect(SocketAddress address, int timeout) {
298 +            // delegate is always connected, thus this method is never called
299 +            throw new UnsupportedOperationException();
300 +        }
301 +
302 +        protected void bind(InetAddress host, int port) {
303 +            // delegate is always bound, thus this method is never called
304 +            throw new UnsupportedOperationException();
305 +        }
306 +
307 +        protected void listen(int backlog) {
308 +            // this wrapper is never used by a ServerSocket
309 +            throw new UnsupportedOperationException();
310 +        }
311 +
312 +        protected void accept(SocketImpl s) {
313 +            // this wrapper is never used by a ServerSocket
314 +            throw new UnsupportedOperationException();
315 +        }
316 +
317 +        protected InputStream getInputStream() throws IOException {
318 +            return delegate.getInputStream();
319 +        }
320 +
321 +        protected OutputStream getOutputStream() throws IOException {
322 +            return delegate.getOutputStream();
323 +        }
324 +
325 +        protected int available() throws IOException {
326 +            return getInputStream().available();
327 +        }
328 +
329 +        protected void close() throws IOException {
330 +           System.out.println("Calling delegate.close");
331 +            delegate.close();
332 +        }
333 +
334 +        protected void shutdownInput() throws IOException {
335 +            delegate.shutdownInput();
336 +        }
337 +
338 +        protected void shutdownOutput() throws IOException {
339 +            delegate.shutdownOutput();
340 +        }
341 +
342 +        protected FileDescriptor getFileDescriptor() {
343 +            // this wrapper is never used by a ServerSocket
344 +            throw new UnsupportedOperationException();
345 +        }
346 +
347 +        protected InetAddress getInetAddress() {
348 +            return delegate.getInetAddress();
349 +        }
350 +
351 +        protected int getPort() {
352 +            return delegate.getPort();
353 +        }
354 +
355 +        protected boolean supportsUrgentData() {
356 +            return false; // must be overridden in sub-class
357 +        }
358 +
359 +        protected void sendUrgentData (int data) throws IOException {
360 +            delegate.sendUrgentData(data);
361 +        }
362 +
363 +        protected int getLocalPort() {
364 +            return delegate.getLocalPort();
365 +        }
366 +
367 +        public Object getOption(int optID) throws SocketException {
368 +            switch (optID) {
369 +                case SocketOptions.IP_TOS:
370 +                    return new Integer(delegate.getTrafficClass());
371 +                case SocketOptions.SO_BINDADDR:
372 +                    return delegate.getLocalAddress();
373 +                case SocketOptions.SO_KEEPALIVE:
374 +                    return Boolean.valueOf(delegate.getKeepAlive());
375 +                case SocketOptions.SO_LINGER:
376 +                    return new Integer(delegate.getSoLinger());
377 +                case SocketOptions.SO_OOBINLINE:
378 +                    return Boolean.valueOf(delegate.getOOBInline());
379 +                case SocketOptions.SO_RCVBUF:
380 +                    return new Integer(delegate.getReceiveBufferSize());
381 +                case SocketOptions.SO_REUSEADDR:
382 +                    return Boolean.valueOf(delegate.getReuseAddress());
383 +                case SocketOptions.SO_SNDBUF:
384 +                    return new Integer(delegate.getSendBufferSize());
385 +                case SocketOptions.SO_TIMEOUT:
386 +                    return new Integer(delegate.getSoTimeout());
387 +                case SocketOptions.TCP_NODELAY:
388 +                    return Boolean.valueOf(delegate.getTcpNoDelay());
389 +                case SocketOptions.SO_BROADCAST:
390 +                default:
391 +                    throw new IllegalArgumentException("Unsupported option type");
392 +            }
393 +        }
394 +
395 +        public void setOption(int optID, Object value) throws SocketException {
396 +            switch (optID) {
397 +                case SocketOptions.SO_BINDADDR:
398 +                    throw new IllegalArgumentException("Socket is bound");
399 +                case SocketOptions.SO_KEEPALIVE:
400 +                    delegate.setKeepAlive(((Boolean)value).booleanValue());
401 +                    break;
402 +                case SocketOptions.SO_LINGER:
403 +                    if (value instanceof Boolean) {
404 +                        delegate.setSoLinger(((Boolean)value).booleanValue(), 0);
405 +                    }
406 +                    else {
407 +                        delegate.setSoLinger(true, ((Integer)value).intValue());
408 +                    }
409 +                    break;
410 +                case SocketOptions.SO_OOBINLINE:
411 +                    delegate.setOOBInline(((Boolean)value).booleanValue());
412 +                    break;
413 +                case SocketOptions.SO_RCVBUF:
414 +                    delegate.setReceiveBufferSize(((Integer)value).intValue());
415 +                    break;
416 +                case SocketOptions.SO_REUSEADDR:
417 +                    delegate.setReuseAddress(((Boolean)value).booleanValue());
418 +                    break;
419 +                case SocketOptions.SO_SNDBUF:
420 +                    delegate.setSendBufferSize(((Integer)value).intValue());
421 +                    break;
422 +                case SocketOptions.SO_TIMEOUT:
423 +                    delegate.setSoTimeout(((Integer)value).intValue());
424 +                    break;
425 +                case SocketOptions.TCP_NODELAY:
426 +                    delegate.setTcpNoDelay(((Boolean)value).booleanValue());
427 +                    break;
428 +                case SocketOptions.SO_BROADCAST:
429 +                default:
430 +                    throw new IllegalArgumentException("Unsupported option type");
431 +            }
432 +        }
433 +    }
434 +
435 +    public void close() throws IOException {
436 +       System.out.println("Calling SocketWrapper.delegate.close");
437 +       delegate.close();
438 +    }
439 +
440 +    public boolean equals(Object obj) {
441 +        if (!(obj instanceof SocketWrapper)) return false;
442 +        SocketWrapper that = (SocketWrapper)obj;
443 +        return this.delegate.equals(that.delegate);
444 +    }
445 +
446 +    public int hashCode() {
447 +        return delegate.hashCode() ^ 0x01010101;
448 +    }
449 +    public String toString() {
450 +       return "<SocketWrapper " + super.toString() + "(delegating to " + delegate.toString() +  ")" + ">";
451 +    }
452 +}
453 \ No newline at end of file
454 Index: invirt-vnc-client/VNCProxyConnectSocket.java
455 ===================================================================
456 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
457 +++ invirt-vnc-client/VNCProxyConnectSocket.java        2008-10-31 06:09:10.000000000 -0400
458 @@ -0,0 +1,61 @@
459 +//
460 +//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
461 +//  Copyright 2007 MIT Student Information Processing Board
462 +//
463 +//  This is free software; you can redistribute it and/or modify
464 +//  it under the terms of the GNU General Public License as published by
465 +//  the Free Software Foundation; either version 2 of the License, or
466 +//  (at your option) any later version.
467 +//
468 +//  This software is distributed in the hope that it will be useful,
469 +//  but WITHOUT ANY WARRANTY; without even the implied warranty of
470 +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
471 +//  GNU General Public License for more details.
472 +//
473 +//  You should have received a copy of the GNU General Public License
474 +//  along with this software; if not, write to the Free Software
475 +//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
476 +//  USA.
477 +//
478 +
479 +//
480 +// VNCProxySocket.java together with VNCProxySocketFactory.java
481 +// implement an alternate way to connect to VNC servers via one or two
482 +// VNCProxy proxies supporting the VNCProxy VNCCONNECT method.
483 +//
484 +
485 +import java.net.*;
486 +import java.io.*;
487 +
488 +class VNCProxyConnectSocket extends Socket {
489 +
490 +  public VNCProxyConnectSocket(String host, int port,
491 +                               String vmname, String authtoken)
492 +    throws IOException {
493 +
494 +    // Connect to the specified HTTP proxy
495 +    super(host, port);
496 +
497 +    // Send the CONNECT request
498 +    getOutputStream().write(("CONNECTVNC " + vmname +
499 +                             " VNCProxy/1.0\r\nAuth-token: " + authtoken +
500 +                             "\r\n\r\n").getBytes());
501 +
502 +    // Read the first line of the response
503 +    DataInputStream is = new DataInputStream(getInputStream());
504 +    String str = is.readLine();
505 +
506 +    // Check the HTTP error code -- it should be "200" on success
507 +    if (!str.startsWith("VNCProxy/1.0 200 ")) {
508 +      if (str.startsWith("VNCProxy/1.0 "))
509 +        str = str.substring(13);
510 +      throw new IOException("Proxy reports \"" + str + "\"");
511 +    }
512 +
513 +    // Success -- skip remaining HTTP headers
514 +    do {
515 +      str = is.readLine();
516 +    } while (str.length() != 0);
517 +  }
518 +}
519 +
520 Index: invirt-vnc-client/VNCProxyConnectSocketFactory.java
521 ===================================================================
522 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
523 +++ invirt-vnc-client/VNCProxyConnectSocketFactory.java 2008-10-31 06:09:10.000000000 -0400
524 @@ -0,0 +1,98 @@
525 +//
526 +//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
527 +//  Copyright 2007 MIT Student Information Processing Board
528 +//
529 +//  This is free software; you can redistribute it and/or modify
530 +//  it under the terms of the GNU General Public License as published by
531 +//  the Free Software Foundation; either version 2 of the License, or
532 +//  (at your option) any later version.
533 +//
534 +//  This software is distributed in the hope that it will be useful,
535 +//  but WITHOUT ANY WARRANTY; without even the implied warranty of
536 +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
537 +//  GNU General Public License for more details.
538 +//
539 +//  You should have received a copy of the GNU General Public License
540 +//  along with this software; if not, write to the Free Software
541 +//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
542 +//  USA.
543 +//
544 +
545 +//
546 +// VNCProxyConnectSocketFactory.java together with VNCProxyConnectSocket.java
547 +// implement an alternate way to connect to VNC servers via one or two
548 +// VNCProxy proxies supporting the VNCProxy CONNECT method.
549 +//
550 +
551 +import java.applet.*;
552 +import java.net.*;
553 +import javax.net.ssl.*;
554 +import java.io.*;
555 +
556 +class VNCProxyConnectSocketFactory implements SocketFactory {
557 +
558 +    SSLSocketFactory factory;
559 +    
560 +    public VNCProxyConnectSocketFactory() {
561 +       try {
562 +           SSLContext c = SSLContext.getInstance("SSL");
563 +           c.init(null,
564 +                  new TrustManager[] { new InvirtTrustManager() },
565 +                  null);
566 +           factory =
567 +               (SSLSocketFactory)c.getSocketFactory();
568 +       } catch (Exception e) {
569 +           e.printStackTrace();
570 +       }
571 +    }
572 +
573 +  public Socket createSocket(String host, int port, Applet applet)
574 +    throws IOException {
575 +
576 +    return createSocket(host, port,
577 +                       applet.getParameter("VMNAME"),
578 +                       applet.getParameter("AUTHTOKEN"));
579 +  }
580 +
581 +  public Socket createSocket(String host, int port, String[] args)
582 +    throws IOException {
583 +
584 +    return createSocket(host, port,
585 +                       readArg(args, "VMNAME"),
586 +                       readArg(args, "AUTHTOKEN"));
587 +  }
588 +
589 +  public Socket createSocket(String host, int port,
590 +                            String vmname, String authtoken)
591 +    throws IOException {
592 +
593 +    if (vmname == null || authtoken == null) {
594 +      System.out.println("Incomplete parameter list for VNCProxyConnectSocket");
595 +      return new Socket(host, port);
596 +    }
597 +
598 +    System.out.println("VNCProxy CONNECT via proxy " + host +
599 +                      " port " + port + " to vm " + vmname);
600 +    SSLSocket ssls = (SSLSocket)factory.createSocket(host, port);
601 +    ssls.startHandshake();
602 +    VNCProxyConnectSocketWrapper s =
603 +      new VNCProxyConnectSocketWrapper(ssls, vmname, authtoken);
604 +
605 +    return (Socket)s;
606 +  }
607 +
608 +  private String readArg(String[] args, String name) {
609 +
610 +    for (int i = 0; i < args.length; i += 2) {
611 +      if (args[i].equalsIgnoreCase(name)) {
612 +       try {
613 +         return args[i+1];
614 +       } catch (Exception e) {
615 +         return null;
616 +       }
617 +      }
618 +    }
619 +    return null;
620 +  }
621 +}
622 +
623 Index: invirt-vnc-client/VNCProxyConnectSocketWrapper.java
624 ===================================================================
625 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
626 +++ invirt-vnc-client/VNCProxyConnectSocketWrapper.java 2008-10-31 06:09:10.000000000 -0400
627 @@ -0,0 +1,60 @@
628 +//
629 +//  Copyright (C) 2002 Constantin Kaplinsky, Inc.  All Rights Reserved.
630 +//  Copyright 2007 MIT Student Information Processing Board
631 +//
632 +//  This is free software; you can redistribute it and/or modify
633 +//  it under the terms of the GNU General Public License as published by
634 +//  the Free Software Foundation; either version 2 of the License, or
635 +//  (at your option) any later version.
636 +//
637 +//  This software is distributed in the hope that it will be useful,
638 +//  but WITHOUT ANY WARRANTY; without even the implied warranty of
639 +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
640 +//  GNU General Public License for more details.
641 +//
642 +//  You should have received a copy of the GNU General Public License
643 +//  along with this software; if not, write to the Free Software
644 +//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
645 +//  USA.
646 +//
647 +
648 +//
649 +// VNCProxySocket.java together with VNCProxySocketFactory.java
650 +// implement an alternate way to connect to VNC servers via one or two
651 +// VNCProxy proxies supporting the VNCProxy VNCCONNECT method.
652 +//
653 +
654 +import java.net.*;
655 +import java.io.*;
656 +
657 +class VNCProxyConnectSocketWrapper extends SocketWrapper {
658 +
659 +  public VNCProxyConnectSocketWrapper(Socket sock,
660 +                               String vmname, String authtoken)
661 +    throws IOException {
662 +
663 +    super(sock);
664 +
665 +    // Send the CONNECT request
666 +    getOutputStream().write(("CONNECTVNC " + vmname +
667 +                             " VNCProxy/1.0\r\nAuth-token: " + authtoken +
668 +                             "\r\n\r\n").getBytes());
669 +
670 +    // Read the first line of the response
671 +    DataInputStream is = new DataInputStream(getInputStream());
672 +    String str = is.readLine();
673 +
674 +    // Check the HTTP error code -- it should be "200" on success
675 +    if (!str.startsWith("VNCProxy/1.0 200 ")) {
676 +      if (str.startsWith("VNCProxy/1.0 "))
677 +        str = str.substring(13);
678 +      throw new IOException("Proxy reports \"" + str + "\"");
679 +    }
680 +
681 +    // Success -- skip remaining HTTP headers
682 +    do {
683 +      str = is.readLine();
684 +    } while (str.length() != 0);
685 +  }
686 +}
687 +