Project

General

Profile

2683a_current.txt

Sergey Ivanovskiy, 06/21/2017 03:01 PM

Download (23 KB)

 
1
=== modified file 'src/com/goldencode/p2j/main/ClientCore.java'
2
--- src/com/goldencode/p2j/main/ClientCore.java	2017-04-01 23:33:34 +0000
3
+++ src/com/goldencode/p2j/main/ClientCore.java	2017-06-21 18:39:15 +0000
4
@@ -252,7 +252,13 @@
5
                
6
                // some client code must read configuration from the directory
7
                DirectoryManager.initRemote(session);
8
+               
9
+               WebClientRegistrator registrator =
10
+                        (WebClientRegistrator) RemoteObject.obtainNetworkInstance(
11
+                                 WebClientRegistrator.class, session);
12
+               registrator.registerWebClientSession(uuid, session.getNodeAddress());
13
             }
14
+            
15
          }
16
          catch (Exception exc)
17
          {
18
@@ -349,6 +355,11 @@
19
          // dependent threads need to be shutdown, even if the client restarts on CTRL-C
20
          ThinClient.terminate();
21
          
22
+         if (!running)
23
+         {
24
+            driver.shutdown();
25
+         }
26
+         
27
          // shut down session
28
          if (single)
29
          {
30
@@ -359,10 +370,6 @@
31
             session.terminate();
32
          }
33
 
34
-         if (!running)
35
-         {
36
-            driver.shutdown();
37
-         }
38
 
39
          // clear after me
40
          SecurityManager.clearInstance();
41

    
42
=== modified file 'src/com/goldencode/p2j/main/StandardServer.java'
43
--- src/com/goldencode/p2j/main/StandardServer.java	2017-04-01 23:33:34 +0000
44
+++ src/com/goldencode/p2j/main/StandardServer.java	2017-06-21 18:39:15 +0000
45
@@ -948,7 +948,7 @@
46
          ready.countDown();
47
          
48
          // main listening loop;  service incoming socket connections
49
-         sessMgr.listen(null);
50
+         sessMgr.listen(WebClientsManager.getInstance());
51
       }
52
       
53
       finally
54

    
55
=== added file 'src/com/goldencode/p2j/main/WebClientAllocator.java'
56
--- src/com/goldencode/p2j/main/WebClientAllocator.java	1970-01-01 00:00:00 +0000
57
+++ src/com/goldencode/p2j/main/WebClientAllocator.java	2017-06-20 06:10:28 +0000
58
@@ -0,0 +1,8 @@
59
+package com.goldencode.p2j.main;
60
+
61
+
62
+
63
+public interface WebClientAllocator
64
+{
65
+   WebClientConfig allocateClient(String forwardedHost, String forwardedProto);
66
+}
67

    
68
=== added file 'src/com/goldencode/p2j/main/WebClientConfig.java'
69
--- src/com/goldencode/p2j/main/WebClientConfig.java	1970-01-01 00:00:00 +0000
70
+++ src/com/goldencode/p2j/main/WebClientConfig.java	2017-06-21 18:39:15 +0000
71
@@ -0,0 +1,88 @@
72
+package com.goldencode.p2j.main;
73
+
74
+import java.io.Serializable;
75
+
76
+public class WebClientConfig implements Serializable 
77
+{
78
+   /** web client id */
79
+   private String uuid;
80
+   /**
81
+    * A direct host assigned to launch the spawned web client
82
+    */
83
+   private String host;
84
+   
85
+   /**
86
+    * A direct port assigned for the spawned web client
87
+    */
88
+   private int port;
89
+   
90
+   /**
91
+    * A web root prefix for all resources of the web client
92
+    */
93
+   private String webRoot;
94
+
95
+   private String forwardedHost;
96
+   
97
+   private  String forwardedProto;
98
+   
99
+   public String getUuid()
100
+   {
101
+      return uuid;
102
+   }
103
+
104
+   public void setUuid(String uuid)
105
+   {
106
+      this.uuid = uuid;
107
+   }
108
+
109
+   public String getHost()
110
+   {
111
+      return host;
112
+   }
113
+
114
+   public int getPort()
115
+   {
116
+      return port;
117
+   }
118
+
119
+   public String getWebRoot()
120
+   {
121
+      return webRoot;
122
+   }
123
+
124
+   public String getForwardedHost()
125
+   {
126
+      return forwardedHost;
127
+   }
128
+
129
+   public String getForwardedProto()
130
+   {
131
+      return forwardedProto;
132
+   }
133
+
134
+   public void setHost(String host)
135
+   {
136
+      this.host = host;
137
+   }
138
+
139
+   public void setPort(int port)
140
+   {
141
+      this.port = port;
142
+   }
143
+
144
+   public void setWebRoot(String webRoot)
145
+   {
146
+      this.webRoot = webRoot;
147
+   }
148
+
149
+   public void setForwardedHost(String forwardedHost)
150
+   {
151
+      this.forwardedHost = forwardedHost;
152
+   }
153
+
154
+   public void setForwardedProto(String forwardedProto)
155
+   {
156
+      this.forwardedProto = forwardedProto;
157
+   }
158
+}
159
+
160

    
161
=== added file 'src/com/goldencode/p2j/main/WebClientRegistrator.java'
162
--- src/com/goldencode/p2j/main/WebClientRegistrator.java	1970-01-01 00:00:00 +0000
163
+++ src/com/goldencode/p2j/main/WebClientRegistrator.java	2017-06-21 18:39:15 +0000
164
@@ -0,0 +1,7 @@
165
+package com.goldencode.p2j.main;
166
+
167
+
168
+public interface WebClientRegistrator
169
+{
170
+   void registerWebClientSession(String webClientId, int peerNode);
171
+}
172

    
173
=== modified file 'src/com/goldencode/p2j/main/WebClientSpawner.java'
174
--- src/com/goldencode/p2j/main/WebClientSpawner.java	2017-04-01 23:33:34 +0000
175
+++ src/com/goldencode/p2j/main/WebClientSpawner.java	2017-06-21 18:39:15 +0000
176
@@ -75,8 +75,15 @@
177
 
178
 package com.goldencode.p2j.main;
179
 
180
+import java.net.URI;
181
+import java.net.URISyntaxException;
182
+
183
 import com.goldencode.p2j.cfg.*;
184
 import com.goldencode.p2j.directory.*;
185
+import com.goldencode.p2j.main.WebClientConfig;
186
+import com.goldencode.p2j.net.Session;
187
+import com.goldencode.p2j.net.SessionListener;
188
+import com.goldencode.p2j.net.SessionManager;
189
 import com.goldencode.p2j.ui.client.driver.web.*;
190
 import com.goldencode.p2j.ui.client.chui.driver.web.*;
191
 import com.goldencode.p2j.ui.client.gui.driver.web.*;
192
@@ -117,6 +124,8 @@
193
    /** Flag that denotes client type (<code>true</code> for GUI, <code>false</code> for ChUI). */
194
    private boolean gui;
195
 
196
+   private final WebClientConfig webClientConfig;
197
+   
198
    /**
199
     * Create a new web client spawner.
200
     *
201
@@ -131,10 +140,13 @@
202
     * @param    options
203
     *           The command-line configuration options.  May be <code>null</code>.
204
     */
205
-   public WebClientSpawner(boolean gui, boolean trusted, String referrer, String[] options)
206
+   public WebClientSpawner(WebClientConfig webClient,
207
+                           boolean gui, boolean trusted, String referrer, String[] options)
208
    {
209
       super(new WebClientBuilderParameters(gui, trusted, referrer, options));
210
       this.gui = gui;
211
+      this.webClientConfig = webClient;
212
+      WebClientsManager.getInstance().registerWebClientUuid(cfg.getUuid(), webClient);
213
    }
214
 
215
    /**
216
@@ -148,7 +160,6 @@
217
    public void clientIsReady(Object data)
218
    {
219
       remoteUri = (String) data;
220
-      
221
       super.clientIsReady(data);
222
    }
223
 
224
@@ -180,13 +191,19 @@
225
     * Get the remote server URI to which the browser will be redirected.
226
     * 
227
     * @return   The remote server URI or <code>null</code>.
228
+    * @throws URISyntaxException 
229
     */
230
-   public String getRemoteUri()
231
+   public String getRemoteUri() throws URISyntaxException
232
    {
233
       String uri = remoteUri;
234
       
235
       if (uri != null)
236
       {
237
+         if (webClientConfig.getForwardedHost() != null && !webClientConfig.getForwardedHost().isEmpty())
238
+         {
239
+            uri = rewriteUri(webClientConfig);
240
+         }
241
+         
242
          // set authorization token for the redirect
243
          Object store = getServerData();
244
          
245
@@ -203,6 +220,17 @@
246
       
247
       return uri;
248
    }
249
+   
250
+   private String rewriteUri(WebClientConfig webClient)
251
+            throws URISyntaxException
252
+   {
253
+      String forwardedProto = webClient.getForwardedProto();
254
+      String forwardedHost = webClient.getForwardedHost();
255
+      String forwardedPath = webClient.getWebRoot();
256
+      URI uri = URI.create(forwardedProto + "://" + forwardedHost +  forwardedPath + "/");
257
+      //rewrite uri
258
+      return uri.toString();
259
+   }
260
 
261
    /**
262
     * Get a {@link TemporaryClient} worker which will do the work after authenticating on the P2J
263
@@ -213,7 +241,7 @@
264
    @Override
265
    public TemporaryClient getTemporaryClient()
266
    {
267
-      return new TemporaryClientTask(gui);
268
+      return new TemporaryClientTask(gui, webClientConfig);
269
    }
270
 
271
    /**
272
@@ -229,6 +257,7 @@
273
       /** Flag that denotes client type. */
274
       private boolean gui;
275
       
276
+      private WebClientConfig webClient;
277
       /**
278
        * Create a new web client spawner.
279
        *
280
@@ -236,9 +265,10 @@
281
        *           Flag that denotes client type (<code>true</code> for GUI, <code>false</code>
282
        *           for ChUI).
283
        */
284
-      public TemporaryClientTask(boolean gui)
285
+      public TemporaryClientTask(boolean gui, WebClientConfig webClient)
286
       {
287
          this.gui = gui;
288
+         this.webClient = webClient;
289
       }
290
       
291
       /**
292
@@ -285,6 +315,30 @@
293
          int    port = config.getInt("client", "web", "port", 0);
294
          String host = config.getString("client", "web", "host", null);
295
          
296
+         if (webClient != null)
297
+         {
298
+            //override host and port if new values are provided
299
+            if (webClient.getPort() > 0)
300
+            {
301
+               port = webClient.getPort();
302
+               config.setConfigItem("client", "web", "port", String.valueOf(port));
303
+            }
304
+            if (webClient.getHost() != null    &&
305
+                !webClient.getHost().isEmpty() && 
306
+                !"localhost".equals(webClient.getHost()))
307
+            {
308
+               host = webClient.getHost();
309
+               config.setConfigItem("client", "web", "host", host);
310
+            }
311
+            // set web root
312
+            if (!"/".equals(webClient.getWebRoot()))
313
+            {
314
+               config.setConfigItem("client", "web", "webRoot", webClient.getWebRoot());
315
+            }
316
+//            config.setConfigItem("client", "web", "forwardedHost", webClient.getForwardedHost());
317
+//            config.setConfigItem("client", "web", "forwardedProto", webClient.getForwardedProtocol());
318
+         }
319
+         
320
          // create web screen driver
321
          ScreenDriver<?> driver = gui ? new GuiWebDriver(config) : new ChuiWebDriver(config);
322
          driver.init();
323

    
324
=== added file 'src/com/goldencode/p2j/main/WebClientsManager.java'
325
--- src/com/goldencode/p2j/main/WebClientsManager.java	1970-01-01 00:00:00 +0000
326
+++ src/com/goldencode/p2j/main/WebClientsManager.java	2017-06-21 18:39:15 +0000
327
@@ -0,0 +1,146 @@
328
+package com.goldencode.p2j.main;
329
+
330
+import java.util.LinkedHashMap;
331
+import java.util.LinkedHashSet;
332
+import java.util.Map;
333
+import java.util.Set;
334
+
335
+import com.goldencode.p2j.net.RemoteObject;
336
+import com.goldencode.p2j.net.Session;
337
+import com.goldencode.p2j.net.SessionListener;
338
+
339
+public class WebClientsManager implements WebClientAllocator, WebClientRegistrator, SessionListener
340
+{
341
+   /**
342
+    * one instance per standard server
343
+    */
344
+   private static WebClientsManager instance;
345
+   
346
+   private int port;
347
+   
348
+   private final Map<Integer, WebClientConfig> webClientSessions;
349
+   
350
+   private final Map<String, WebClientConfig> webClientConfigs;
351
+   
352
+   private final Set<Integer> usedLocalPorts;
353
+   
354
+   private WebClientsManager()
355
+   {
356
+      // range of ports
357
+      // range of hosts
358
+      // port varies from 7449 up
359
+      port = 7449;
360
+      
361
+      webClientSessions = new LinkedHashMap<Integer, WebClientConfig>();
362
+      
363
+      webClientConfigs = new LinkedHashMap<String, WebClientConfig>();
364
+      
365
+      usedLocalPorts = new LinkedHashSet<Integer>();
366
+      
367
+      RemoteObject.registerNetworkServer(WebClientRegistrator.class, this);
368
+   }
369
+
370
+   public static synchronized WebClientsManager getInstance()
371
+   {
372
+      if (instance == null)
373
+      {
374
+         instance = new WebClientsManager();
375
+      }
376
+      
377
+      return instance;
378
+   }
379
+   
380
+   /**
381
+    * Allocates free open port in a range
382
+    * 
383
+    * @return   The allocated resources for the web client will be spawned.
384
+    */
385
+   public synchronized WebClientConfig allocateClient(String forwardedHost, String forwardedProto)
386
+   {
387
+      StringBuilder webRootBuilder = new StringBuilder();
388
+      webRootBuilder.append("/");
389
+      int webClientPort = 0;
390
+      String webClientHost = "localhost";
391
+      if (forwardedHost != null && !forwardedHost.isEmpty())
392
+      {
393
+         int freePort = getFreeLocalPort();
394
+         
395
+         webRootBuilder.append("server");
396
+         //TODO to use provided port to name mappings
397
+         webRootBuilder.append("/").append(freePort);
398
+         
399
+         webClientPort = freePort;
400
+      }
401
+      WebClientConfig webClient = new WebClientConfig();
402
+      webClient.setHost(webClientHost);
403
+      webClient.setPort(webClientPort);
404
+      webClient.setWebRoot(webRootBuilder.toString());
405
+      webClient.setForwardedHost(forwardedHost);
406
+      webClient.setForwardedProto(forwardedProto);
407
+      
408
+      return webClient;
409
+   }
410
+
411
+   private int getFreeLocalPort()
412
+   {
413
+      int freePort = port;
414
+      
415
+      while(usedLocalPorts.contains(freePort))
416
+      {
417
+         freePort++;
418
+      }
419
+      
420
+      return freePort;
421
+   }
422
+   
423
+   @Override
424
+   public void registerWebClientSession(String webClientId, int peerNode)
425
+   {
426
+      System.err.println("register web client session: uuid=" + webClientId
427
+               + " peerNode=" + peerNode);
428
+      synchronized (this)
429
+      {
430
+         WebClientConfig config = webClientConfigs.get(webClientId);
431
+         if (config != null)
432
+         {
433
+            webClientSessions.put(peerNode, config);
434
+            usedLocalPorts.add(config.getPort());
435
+         }
436
+      }
437
+   }
438
+   
439
+   public void registerWebClientUuid(String webClientId, WebClientConfig config)
440
+   {
441
+      System.err.println("register web client uuid=" + webClientId
442
+               + " port=" + config.getPort());
443
+      synchronized (this)
444
+      {
445
+         config.setUuid(webClientId);
446
+         webClientConfigs.put(webClientId, config);
447
+      }
448
+   }
449
+
450
+   @Override
451
+   public void terminate(Session session)
452
+   {
453
+      System.err.println("server: terminate: node=" + session.getNodeAddress()
454
+               + " remote=" + session.getRemoteAddress());
455
+      int peerNode = session.getRemoteAddress();
456
+      synchronized (this)
457
+      {
458
+         WebClientConfig config = webClientSessions.remove(peerNode);
459
+         if (config != null)
460
+         {
461
+            System.err.println("terminate web client port=" + config.getPort() + " uuid=" + config.getUuid());
462
+            usedLocalPorts.remove(config.getPort());
463
+         }
464
+      }
465
+   }
466
+   
467
+   @Override
468
+   public void initialize(Session session)
469
+   {
470
+      System.err.println("server: initialize: node=" + session.getNodeAddress()
471
+               + " remote=" + session.getRemoteAddress());
472
+   }
473
+}
474

    
475
=== modified file 'src/com/goldencode/p2j/main/WebHandler.java'
476
--- src/com/goldencode/p2j/main/WebHandler.java	2017-04-01 23:33:34 +0000
477
+++ src/com/goldencode/p2j/main/WebHandler.java	2017-06-21 18:39:15 +0000
478
@@ -80,6 +80,8 @@
479
 package com.goldencode.p2j.main;
480
 
481
 import java.io.*;
482
+import java.net.URI;
483
+import java.net.URISyntaxException;
484
 import java.util.*;
485
 import java.util.logging.*;
486
 
487
@@ -91,7 +93,8 @@
488
 import org.eclipse.jetty.server.handler.*;
489
 
490
 import com.goldencode.p2j.directory.*;
491
-import com.goldencode.p2j.security.*;
492
+import com.goldencode.p2j.main.WebClientConfig;
493
+import com.goldencode.p2j.main.WebClientAllocator;
494
 import com.goldencode.p2j.security.SecurityManager;
495
 import com.goldencode.p2j.util.*;
496
 
497
@@ -129,6 +132,8 @@
498
    /** Flag that denotes client type (<code>true</code> for GUI, <code>false</code> for ChUI). */
499
    private boolean isGui = false;
500
    
501
+   private final WebClientAllocator webClientAllocator = WebClientsManager.getInstance();
502
+   
503
    /**
504
     * Spawn a new web client process, returning the redirect URL if successful.
505
     * <p>
506
@@ -301,7 +306,7 @@
507
                   LogHelper.generate("Attempting spawn for user %s.", user));
508
       }
509
       
510
-      SpawnerResult result = spawnWorker(user, pw, gui, options, trusted, referrer);
511
+      SpawnerResult result = spawnWorker(user, pw, gui, options, trusted, referrer, null);
512
       
513
       String retval = null;
514
       
515
@@ -465,15 +470,20 @@
516
       
517
       // get referrer URL
518
       String referrer = base.getHeader(HttpHeader.REFERER.asString());
519
+      String forwardedHost  = base.getHeader(HttpHeader.X_FORWARDED_HOST.asString());
520
+      String forwardedProto = "https"; //base.getHeader(HttpHeader.X_FORWARDED_PROTO.asString());
521
       
522
       // get form parameters;
523
       String user = base.getParameter("usr");
524
       String pw   = base.getParameter("psw");
525
       
526
+      WebClientConfig webClientConfig = webClientAllocator.allocateClient(forwardedHost, forwardedProto);
527
+      
528
       // spawn a new web client (trusted mode should not be enabled here unless the proper
529
       // security plugin checks are added (see spawn() above)
530
-      SpawnerResult result = spawnWorker(user, pw, isGui, null, false, referrer);
531
-                                  
532
+      
533
+      SpawnerResult result = spawnWorker(user, pw, isGui, null, false, referrer, webClientConfig);
534
+      
535
       if (result.uri != null)
536
       {
537
          String type = isGui ? "GUI" : "ChUI";
538
@@ -641,7 +651,8 @@
539
                                             boolean  gui,
540
                                             String[] options,
541
                                             boolean  trusted,
542
-                                            String   referrer)
543
+                                            String   referrer,
544
+                                            WebClientConfig webClient)
545
    {
546
       if (!verifySpawnOptions(user, options))
547
       {
548
@@ -651,13 +662,24 @@
549
          return sr;
550
       }
551
       
552
-      WebClientSpawner spawner = new WebClientSpawner(gui, trusted, referrer, options);
553
+      WebClientSpawner spawner = new WebClientSpawner(webClient, gui, trusted, referrer, options);
554
       
555
       spawner.spawn(user, pw, null);
556
       
557
       SpawnerResult result = new SpawnerResult();
558
       
559
-      result.uri = spawner.getRemoteUri();
560
+      try
561
+      {
562
+         result.uri = spawner.getRemoteUri();
563
+      }
564
+      catch (URISyntaxException e)
565
+      {
566
+         LOG.logp(Level.SEVERE, 
567
+                  "WebClientSpawner", 
568
+                  "getRemoteUri",
569
+                  LogHelper.generate("Rewrite failed: X_FORWARDED_HOST=%s X_FORWARDED_PROTO=%s",
570
+                           webClient.getForwardedHost(), webClient.getForwardedProto()));
571
+      }
572
       
573
       if (result.uri == null)
574
       {
575

    
576
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/WebPageHandler.java'
577
--- src/com/goldencode/p2j/ui/client/driver/web/WebPageHandler.java	2017-04-01 23:33:34 +0000
578
+++ src/com/goldencode/p2j/ui/client/driver/web/WebPageHandler.java	2017-06-20 06:10:28 +0000
579
@@ -190,9 +190,10 @@
580
     */
581
    protected String handleReplacements(Request base, String text)
582
    {
583
-      if (text.contains("${context}"))
584
+      String webRoot = config.getString("client", "web", "webRoot", "");
585
+      if (text.contains("${webRoot}"))
586
       {
587
-         text = text.replace("${context}", base.getContextPath());
588
+         text = text.replace("${webRoot}", webRoot);
589
       }
590
       
591
       if (text.contains("${referrer}"))
592

    
593
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/index.html'
594
--- src/com/goldencode/p2j/ui/client/driver/web/index.html	2017-04-01 23:33:34 +0000
595
+++ src/com/goldencode/p2j/ui/client/driver/web/index.html	2017-06-20 06:10:28 +0000
596
@@ -55,7 +55,7 @@
597
    <head>                                                                   
598
       <title>FWD ${client_title} Web Client</title>
599
       
600
-      <link rel="stylesheet" type="text/css" href="/dojo-toolkit/dijit/themes/claro/claro.css">
601
+      <link rel="stylesheet" type="text/css" href="${webRoot}/dojo-toolkit/dijit/themes/claro/claro.css">
602
       <style type="text/css">
603
          .wait, .wait * { cursor: wait !important; }
604
          .hidden   {
605
@@ -106,23 +106,23 @@
606
                    }
607
       </style>
608
       <!-- load dojo -->      
609
-      <script src="/dojo-toolkit/dojo/dojo.js" data-dojo-config="async: true"></script>  
610
+      <script src="${webRoot}/dojo-toolkit/dojo/dojo.js" data-dojo-config="async: true"></script>  
611
             
612
-      <script type="text/javascript" src="/common/p2j.js"></script>
613
-      <script type="text/javascript" src="/common/p2j.logger.js"></script>
614
-      <script type="text/javascript" src="/common/p2j.sound.js"></script>
615
-      <script type="text/javascript" src="/client/p2j.strokes.js"></script>
616
-      <script type="text/javascript" src="/client/p2j.canvas_renderer.js"></script>
617
-      <script type="text/javascript" src="/client/p2j.virtual_desktop.js"></script>
618
-      <script type="text/javascript" src="/client/p2j.mouse.js"></script>
619
-      <script type="text/javascript" src="/client/p2j.screen.js"></script>
620
-      <script type="text/javascript" src="/common/p2j.socket.js"></script>
621
-      <script type="text/javascript" src="/common/p2j.keymap.js"></script>
622
-      <script type="text/javascript" src="/common/p2j.keyboard.js"></script>
623
-      <script type="text/javascript" src="/client/p2j.clipboard_helpers.js"></script>
624
-      <script type="text/javascript" src="/common/p2j.clipboard.js"></script>
625
-      <script type="text/javascript" src="/common/p2j.fonts.js"></script>
626
-      <script type="text/javascript" src="/common/p2j.remote.js"></script>
627
+      <script type="text/javascript" src="${webRoot}/common/p2j.js"></script>
628
+      <script type="text/javascript" src="${webRoot}/common/p2j.logger.js"></script>
629
+      <script type="text/javascript" src="${webRoot}/common/p2j.sound.js"></script>
630
+      <script type="text/javascript" src="${webRoot}/client/p2j.strokes.js"></script>
631
+      <script type="text/javascript" src="${webRoot}/client/p2j.canvas_renderer.js"></script>
632
+      <script type="text/javascript" src="${webRoot}/client/p2j.virtual_desktop.js"></script>
633
+      <script type="text/javascript" src="${webRoot}/client/p2j.mouse.js"></script>
634
+      <script type="text/javascript" src="${webRoot}/client/p2j.screen.js"></script>
635
+      <script type="text/javascript" src="${webRoot}/common/p2j.socket.js"></script>
636
+      <script type="text/javascript" src="${webRoot}/common/p2j.keymap.js"></script>
637
+      <script type="text/javascript" src="${webRoot}/common/p2j.keyboard.js"></script>
638
+      <script type="text/javascript" src="${webRoot}/client/p2j.clipboard_helpers.js"></script>
639
+      <script type="text/javascript" src="${webRoot}/common/p2j.clipboard.js"></script>
640
+      <script type="text/javascript" src="${webRoot}/common/p2j.fonts.js"></script>
641
+      <script type="text/javascript" src="${webRoot}/common/p2j.remote.js"></script>
642
       
643
       <script>
644
       require(["dojo"], function(dojo)
645
@@ -148,7 +148,7 @@
646
                'cursor'    : {'type' : 'solid', 'visible' : true, 'blinking' : false},
647
                'sound'     : {'id' : 'beep', 'enabled' : true},
648
                'socket'    : {
649
-                              'url' : 'wss://' + window.location.host + '${context}/ajax',
650
+                              'url' : 'wss://' + window.location.host + '${webRoot}/ajax',
651
                               'maxBinaryMessage' : ${maxBinaryMessage},
652
                               'maxIdleTime'      : ${maxIdleTime},
653
                               'watchdogTimeout'  : ${watchdogTimeout}
654
@@ -176,9 +176,9 @@
655
          <noscript>Your browser does not support JavaScript!</noscript>
656
          
657
          <audio id="beep">
658
-            <source src="/common/beep.wav" type="audio/wav">
659
-            <source src="/common/beep.mp3" type="audio/mpeg">
660
-            <source src="/common/beep.ogg" type="audio/ogg">
661
+            <source src="${webRoot}/common/beep.wav" type="audio/wav">
662
+            <source src="${webRoot}/common/beep.mp3" type="audio/mpeg">
663
+            <source src="${webRoot}/common/beep.ogg" type="audio/ogg">
664
             Your browser does not support the HTML5 audio tag.
665
          </audio>
666
          
667