Project

General

Profile

9709d_all.patch

Sergey Ivanovskiy, 03/27/2026 03:46 AM

Download (85 KB)

View differences:

new/src/com/goldencode/p2j/main/WebClientSpawner.java 2026-03-27 07:11:05 +0000
38 38
** 020 TJD 20250807 Added SNI_HOST_CHECK option to control Jetty's SNIHostCheck feature
39 39
** 021 SBI 20251019 Reused ConfigItem.BROKER_DEDICATED_MODE.
40 40
** 022 TG  20260121 Added support for quoted cfg overrides.
41
** 023 SBI 20260325 Provided WebTokensService parameter to startupServer.
41 42
*/
42 43
/*
43 44
** This program is free software: you can redistribute it and/or modify
......
411 412
         config.setConfigItem("security", "trust_mgr", "disable", "false");
412 413
         config.setConfigItem("security", "transport", "refresh", "true");
413 414

  
415
         WebTokensService webTokensService = null;
416
         try 
417
         {
418
            // create WebTokenService
419
            webTokensService = new WebTokensService();
420
         }
421
         catch (Exception e1)
422
         {
423
            LOG.severe("new WebTokensService() failed", e1);
424
            throw new RuntimeException(e1);
425
         }
426
         
414 427
         // get an explicit port and host set by the client
415 428
         int port = config.getInt(ConfigItem.PORT, 0);
416 429
         String host = config.getString(ConfigItem.HOST, null);
......
430 443
         ScreenDriver<?> driver = gui ? new GuiWebDriver(config) : new ChuiWebDriver(config);
431 444
         driver.init();
432 445
         
433
         String uri = ((EmbeddedWebServer) driver).startupServer(keyStore, config, host, port);
446
         String uri = ((EmbeddedWebServer) driver).startupServer(keyStore, config, host, port, webTokensService);
434 447
         
435 448
         String forwardedHost = config.getString(ConfigItem.PROXY_HOST, null);
436 449
         
new/src/com/goldencode/p2j/ui/chui/ThinClient.java 2026-03-27 07:12:44 +0000
3182 3182
**      PMP 20260223          Prevented focus reset also for (forward) TAB. Refs: #11085-8.
3183 3183
** 1083 DMM 20260127          Do not prevent MOUSE-PRESSED event for the drop-down of the active combo-box.
3184 3184
** 1084 SP  20260226          Added sendSsoReauth() for oidc SSO re-authentication.
3185
** 1085 SBI 20260325          Provided WebTokensService to web client.
3185 3186
*/
3186 3187

  
3187 3188
/*
......
3262 3263
import com.goldencode.p2j.ui.client.chui.driver.batch.*;
3263 3264
import com.goldencode.p2j.ui.client.driver.*;
3264 3265
import com.goldencode.p2j.ui.client.driver.ScreenDriver.*;
3266
import com.goldencode.p2j.ui.client.driver.web.WebTokensService;
3265 3267
import com.goldencode.p2j.ui.client.event.*;
3266 3268
import com.goldencode.p2j.ui.client.event.FocusEvent;
3267 3269
import com.goldencode.p2j.ui.client.event.InvocationEvent;
......
18409 18411
   }
18410 18412

  
18411 18413
   /**
18414
    * Expose the web tokens service for the client usages.
18415
    * 
18416
    * @return   The web tokens service.
18417
    */
18418
   public WebTokensService getWebTokensService()
18419
   {
18420
      ScreenDriver<?> driver = tk.getDriver();
18421
      if (driver.isWeb())
18422
      {
18423
         return ((IWebTokensServiceProvider) driver).getWebTokensService();
18424
      }
18425
      return null;
18426
   }
18427

  
18428
   /**
18412 18429
    * Get <code>Component</code> instance for a given ID.
18413 18430
    *
18414 18431
    * @param   componentId
new/src/com/goldencode/p2j/ui/client/chui/driver/web/ChuiWebDriver.java 2026-03-25 20:23:26 +0000
51 51
** 031 SBI 20250128 Removed usages of getKeyboardLayoutsSettings() as a part of removed code related to
52 52
**                  keyboard layouts implementation.
53 53
** 032 SP  20260226 Added sendSsoReauth for SSO re-authentication.
54
** 033 SBI 20260325 Provided WebTokensService parameter to startupServer.
54 55
*/
55 56

  
56 57
/*
......
137 138
public class ChuiWebDriver
138 139
extends AbstractChuiDriver
139 140
implements EmbeddedWebServer,
140
           ScreenWebDriver
141
           ScreenWebDriver,
142
           IWebTokensServiceProvider
141 143
{
142 144
   /** Driver name. */
143 145
   public static final String NAME = "web-chui";
......
169 171
   /** Web-Socket which provides protocol for communication with the browser. */
170 172
   private StorageMessagingWebSocket websock;
171 173

  
174
   /** The web tokens service */
175
   private WebTokensService webTokensService;
176

  
172 177
   /**
173 178
    * Constructor.
174 179
    * 
......
533 538
    *           The exported server KeyStore.
534 539
    * @param    config
535 540
    *           Client configuration.
536
    * @param    port
537
    *           An explicit port to start the web server or 0 to let the OS assign one.
538 541
    * @param    host
539 542
    *           An explicit host to start the web server or <code>null</code> to use the server's
540 543
    *           host.
544
    * @param    port
545
    *           An explicit port to start the web server or 0 to let the OS assign one.
546
    * @param    webTokensService
547
    *           The web tokens service
541 548
    * 
542 549
    * @return   The embedded web server's URI.
543 550
    */
544 551
   @Override
545
   public String startupServer(ServerKeyStore keyStore, BootstrapConfig config, String host, int port)
552
   public String startupServer(ServerKeyStore keyStore, BootstrapConfig config, String host, int port, WebTokensService webTokensService)
546 553
   {
547
      return websrv.startupServer(keyStore, config, host, port);
554
      this.webTokensService = webTokensService;
555
      return websrv.startupServer(keyStore, config, host, port, webTokensService);
548 556
   }
549 557
   
550 558
   /**
......
740 748
         simulator.setCursor(col, row);
741 749
      }
742 750
   }
751

  
752
   /**
753
    * Return web tokens service.
754
    * 
755
    * @return   Web tokens service
756
    */
757
   @Override
758
   public WebTokensService getWebTokensService()
759
   {
760
      return this.webTokensService;
761
   }
743 762
}
new/src/com/goldencode/p2j/ui/client/driver/IWebTokensServiceProvider.java 2026-03-25 20:20:13 +0000
1
/*
2
** Module   : IWebTokensServiceProvide.java
3
** Abstract : Provides methods to get web tokens service.
4
**
5
** Copyright (c) 2026, Golden Code Development Corporation.
6
**
7
** -#- -I- --Date-- ---------------------------------------Description----------------------------------------
8
** 001 SBI 20260122 Created initial version.
9
*/
10
/*
11
** This program is free software: you can redistribute it and/or modify
12
** it under the terms of the GNU Affero General Public License as
13
** published by the Free Software Foundation, either version 3 of the
14
** License, or (at your option) any later version.
15
**
16
** This program is distributed in the hope that it will be useful,
17
** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
** GNU Affero General Public License for more details.
20
**
21
** You may find a copy of the GNU Affero GPL version 3 at the following
22
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
23
** 
24
** Additional terms under GNU Affero GPL version 3 section 7:
25
** 
26
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
27
**   terms apply to the works covered under the License.  These additional terms
28
**   are non-permissive additional terms allowed under Section 7 of the GNU
29
**   Affero GPL version 3 and may not be removed by you.
30
** 
31
**   0. Attribution Requirement.
32
** 
33
**     You must preserve all legal notices or author attributions in the covered
34
**     work or Appropriate Legal Notices displayed by works containing the covered
35
**     work.  You may not remove from the covered work any author or developer
36
**     credit already included within the covered work.
37
** 
38
**   1. No License To Use Trademarks.
39
** 
40
**     This license does not grant any license or rights to use the trademarks
41
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
42
**     of Golden Code Development Corporation. You are not authorized to use the
43
**     name Golden Code, FWD, or the names of any author or contributor, for
44
**     publicity purposes without written authorization.
45
** 
46
**   2. No Misrepresentation of Affiliation.
47
** 
48
**     You may not represent yourself as Golden Code Development Corporation or FWD.
49
** 
50
**     You may not represent yourself for publicity purposes as associated with
51
**     Golden Code Development Corporation, FWD, or any author or contributor to
52
**     the covered work, without written authorization.
53
** 
54
**   3. No Misrepresentation of Source or Origin.
55
** 
56
**     You may not represent the covered work as solely your work.  All modified
57
**     versions of the covered work must be marked in a reasonable way to make it
58
**     clear that the modified work is not originating from Golden Code Development
59
**     Corporation or FWD.  All modified versions must contain the notices of
60
**     attribution required in this license.
61
*/
62

  
63
package com.goldencode.p2j.ui.client.driver;
64

  
65
import com.goldencode.p2j.ui.client.driver.web.WebTokensService;
66

  
67
public interface IWebTokensServiceProvider
68
{
69
   /**
70
    * Return web tokens service.
71
    * 
72
    * @return   Web tokens service
73
    */
74
   WebTokensService getWebTokensService();
75
}
new/src/com/goldencode/p2j/ui/client/driver/web/AuthHandler.java 2026-03-27 07:34:36 +0000
2 2
** Module   : AuthHandler.java
3 3
** Abstract : web authorization
4 4
**
5
** Copyright (c) 2019-2025, Golden Code Development Corporation.
5
** Copyright (c) 2019-2026, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ---------------------------------Description----------------------------------
8 8
** 001 HC  20190910 Initial version.
......
13 13
** 004 GBB 20230908 Auth cookie name to contain port to be identifiable by JS.
14 14
** 005 GBB 20240529 Auth cookie to be secure, same-site and http only.
15 15
** 006 TJD 20250316 Upgrade to Jetty 12
16
** 007 SBI 20260301 Set cross-site partitioned cookie.
17
**         20260326 Added /open/resource and /document handlers to provide
18
**                  these resource to authorized users.
16 19
*/
17 20
/*
18 21
** This program is free software: you can redistribute it and/or modify
......
70 73
package com.goldencode.p2j.ui.client.driver.web;
71 74

  
72 75
import com.goldencode.p2j.main.*;
76
import com.goldencode.p2j.ui.client.gui.driver.OpenResourceTemplate;
77
import com.goldencode.p2j.ui.client.gui.driver.web.DocumentOutputHandler;
73 78
import com.goldencode.p2j.util.logging.*;
74 79
import org.apache.commons.codec.digest.*;
75 80
import org.eclipse.jetty.http.*;
......
93 98
   /** Logger. */
94 99
   private static final CentralLogger LOG = CentralLogger.get(AuthHandler.class.getName());
95 100

  
101
   /**
102
    * The secure host prefix used with CHIPS. See
103
    * https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#cookie_prefixes
104
    */
105
   private static final String HOST_SECURE_CHIPS_PREFIX = "__Host-";
106

  
107
   /** The local documents handler */
108
   private static final String DOCUMENT_HANDLER = "/document/";
109
   /** The embedded resource handler */
110
   private static final String EMBEDDED_RESOURCE_HANDLER = OpenResourceTemplate.REQUEST;
111
   /** API token name*/
112
   public static final String API_TOKEN_NAME = "api_token";
113

  
96 114
   /** Authorization cookie name */
97 115
   private String authorizationCookieName;
98 116

  
......
102 120
   /** Authorization token */
103 121
   private String authorizationToken;
104 122

  
123
   /** The web tokens service */
124
   private final WebTokensService webTokensService;
125

  
105 126
   /**
106 127
    * Constructor.
107 128
    *
108 129
    * @param    authorizationToken
109 130
    *           Authorization token.
110 131
    */
111
   public AuthHandler(String authorizationToken)
132
   public AuthHandler(String authorizationToken, WebTokensService webTokensService)
112 133
   {
113 134
      this.authorizationToken = authorizationToken;
135
      this.webTokensService = webTokensService;
114 136
   }
115
   
137

  
116 138
   /**
117 139
    * Handle the request.
118 140
    *    
......
161 183
      {
162 184
         return false;
163 185
      }
164

  
165
      return (cookieToken == null) ? checkQueryParam(request, response) : checkCookies(request);
186
      
187
      return (cookieToken == null) ? checkQueryParam(request, response) : checkCookies(request, response);
166 188
   }
167 189
   
168 190
   /**
......
174 196
    *          Request instance.
175 197
    * @param   response
176 198
    *          Response instance.
177
    *          
199
    * 
178 200
    * @return  <code>true</code> if authorized <code>false</code> otherwise.
179 201
    */
180 202
   @SuppressWarnings("deprecation")
......
191 213
      if (match)
192 214
      {
193 215
         // set a cookie using a new generated token
194
         authorizationCookieName = "Auth-" + authorizationToken + "-" + UUID.randomUUID().toString();
216
         authorizationCookieName = HOST_SECURE_CHIPS_PREFIX + "Auth-" + authorizationToken + "-" + UUID.randomUUID().toString();
195 217
         cookieToken = DigestUtils.shaHex(UUID.randomUUID().toString());
196 218
         HttpCookie cookie = HttpCookie.build(authorizationCookieName, cookieToken).
197 219
                                        path("/").
198 220
                                        secure(true).
199 221
                                        httpOnly(true).
200
                                        sameSite(HttpCookie.SameSite.STRICT).
222
                                        sameSite(HttpCookie.SameSite.NONE).
223
                                        partitioned(true).
201 224
                                        build();
202 225
         Response.addCookie(response, cookie);
203 226
      }
......
211 234
    * 
212 235
    * @param   request
213 236
    *          HttpServletRequest instance.
214
    *          
237
    * @param   response
238
    *          Response instance.
239
    * 
215 240
    * @return  <code>true</code> if authorized <code>false</code> otherwise.
216 241
    */
217
   private boolean checkCookies(Request request)
242
   private boolean checkCookies(Request request, Response response)
218 243
   {
219 244
      // check browser cookies
220 245
      List<HttpCookie> cookies = Request.getCookies(request);
221
   
246
      
222 247
      if (cookies != null)
223 248
      {
224 249
         // search for authorization cookie
......
233 258
            }
234 259
         }
235 260
      }
261
      Fields queryParameters = Request.extractQueryParameters(request, StandardCharsets.UTF_8);
262
      String target = request.getContext().getPathInContext(request.getHttpURI().getPath());
236 263
      
264
      String jwe = queryParameters.getValue(API_TOKEN_NAME);
265
      if (jwe != null && !jwe.isEmpty())
266
      {
267
         String subject = null;
268
         if (target != null && target.startsWith(DOCUMENT_HANDLER))
269
         {
270
            subject = DocumentOutputHandler.getUUID(target);
271
         }
272
         else if (target != null && target.startsWith(EMBEDDED_RESOURCE_HANDLER))
273
         {
274
            subject = queryParameters.getValue(OpenResourceTemplate.DOCUMENT_PATH);
275
         }
276
         
277
         // validate access rights
278
         if (subject != null)
279
         {
280
            return webTokensService.validateWebTokenValue(jwe, subject, null);
281
         }
282
      }
237 283
      return false;
238 284
   }
239 285
}
new/src/com/goldencode/p2j/ui/client/driver/web/EmbeddedWebServer.java 2026-03-25 19:45:15 +0000
2 2
** Module   : EmbeddedWebServer.java
3 3
** Abstract : embedded web server contract
4 4
**
5
** Copyright (c) 2013-2023, Golden Code Development Corporation.
5
** Copyright (c) 2013-2026, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ---------------------------------Description----------------------------------
8 8
** 001 MAG 20131218 Created initial version.
......
13 13
**                  that it has finished initialized.
14 14
** 006 HC  20190911 Implemented ad-hoc handler registration.
15 15
** 007 SBI 20230505 Fixed startupServer java doc.
16
** 008 SBI 20260325 Provided WebTokensService parameter to startupServer.
16 17
*/
17 18
/*
18 19
** This program is free software: you can redistribute it and/or modify
......
73 74
import com.goldencode.p2j.main.*;
74 75
import com.goldencode.p2j.util.*;
75 76
import org.eclipse.jetty.server.*;
76
import org.eclipse.jetty.util.resource.*;
77 77

  
78 78
/**
79 79
 * Embedded web server API. 
......
88 88
    *           The exported server KeyStore. 
89 89
    * @param    config
90 90
    *           Client configuration.
91
    * @param    port
92
    *           An explicit port to start the web server or 0 to let the OS assign one.
93 91
    * @param    host
94 92
    *           An explicit host to start the web server or <code>null</code> to use the server's
95 93
    *           host.
94
    * @param    port
95
    *           An explicit port to start the web server or 0 to let the OS assign one.
96
    * @param    webTokensService
97
    *           The web tokens service
96 98
    * 
97 99
    * @return   The embedded web server's URI.
98 100
    */
99
   public String startupServer(ServerKeyStore keyStore, BootstrapConfig config, String host, int port);
101
   public String startupServer(ServerKeyStore keyStore, BootstrapConfig config, String host, int port, WebTokensService webTokensService);
100 102

  
101 103
   /**
102 104
    * Shutdown the embedded web server.
new/src/com/goldencode/p2j/ui/client/driver/web/EmbeddedWebServerImpl.java 2026-03-25 19:59:43 +0000
2 2
** Module   : EmbeddedWebServerImpl.java
3 3
** Abstract : embedded web server shared implementation
4 4
**
5
** Copyright (c) 2013-2025, Golden Code Development Corporation.
5
** Copyright (c) 2013-2026, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ---------------------------------Description----------------------------------
8 8
** 001 GES 20150312 Created initial version by moving code from the ChUI web driver and making it
......
26 26
** 010 TJD 20250314 Migration to Jetty 12
27 27
**     TJD 20250807 Added SNI_HOST_CHECK option to control Jetty's SNIHostCheck feature
28 28
** 011 DDF 20250519 Use FileExtensions for all file extensions.
29
** 012 SBI 20260325 Provided WebTokensService parameter to startupServer.
29 30
*/
30 31

  
31 32
/*
......
175 176
    *           The exported server KeyStore. 
176 177
    * @param    config
177 178
    *           Client configuration.
178
    * @param    port
179
    *           An explicit port to start the web server or 0 to let the OS assign one.
180 179
    * @param    host
181 180
    *           An explicit host to start the web server or <code>null</code> to use the server's
182 181
    *           host.
182
    * @param    port
183
    *           An explicit port to start the web server or 0 to let the OS assign one.
184
    * @param    webTokensService
185
    *           The web tokens service
183 186
    * 
184 187
    * @return   The embedded web server's URI.
185 188
    */
186 189
   @Override
187
   public String startupServer(ServerKeyStore keyStore, BootstrapConfig config, String host, int port)
190
   public String startupServer(ServerKeyStore keyStore, BootstrapConfig config, String host, int port, WebTokensService webTokensService)
188 191
   {
189 192
      externalHost = host;
190 193
      
......
201 204
         server.setBootstrapConfig(config);
202 205
         
203 206
         // add authorization handler
204
         server.addHandler(new AuthHandler(token));
207
         server.addHandler(new AuthHandler(token, webTokensService));
205 208

  
206 209
         // process each handler
207 210
         for (int i = 0; i < hdlrs.length; i++)
new/src/com/goldencode/p2j/ui/client/driver/web/WebTokensService.java 2026-03-27 06:48:24 +0000
1
/*
2
** Module   : WebTokensService.java
3
** Abstract : Provides methods to generate and validate web tokens.
4
**
5
** Copyright (c) 2026, Golden Code Development Corporation.
6
**
7
** -#- -I- --Date-- ---------------------------------------Description----------------------------------------
8
** 001 SBI 20260325 Created initial version.
9
*/
10
/*
11
** This program is free software: you can redistribute it and/or modify
12
** it under the terms of the GNU Affero General Public License as
13
** published by the Free Software Foundation, either version 3 of the
14
** License, or (at your option) any later version.
15
**
16
** This program is distributed in the hope that it will be useful,
17
** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
** GNU Affero General Public License for more details.
20
**
21
** You may find a copy of the GNU Affero GPL version 3 at the following
22
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
23
** 
24
** Additional terms under GNU Affero GPL version 3 section 7:
25
** 
26
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
27
**   terms apply to the works covered under the License.  These additional terms
28
**   are non-permissive additional terms allowed under Section 7 of the GNU
29
**   Affero GPL version 3 and may not be removed by you.
30
** 
31
**   0. Attribution Requirement.
32
** 
33
**     You must preserve all legal notices or author attributions in the covered
34
**     work or Appropriate Legal Notices displayed by works containing the covered
35
**     work.  You may not remove from the covered work any author or developer
36
**     credit already included within the covered work.
37
** 
38
**   1. No License To Use Trademarks.
39
** 
40
**     This license does not grant any license or rights to use the trademarks
41
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
42
**     of Golden Code Development Corporation. You are not authorized to use the
43
**     name Golden Code, FWD, or the names of any author or contributor, for
44
**     publicity purposes without written authorization.
45
** 
46
**   2. No Misrepresentation of Affiliation.
47
** 
48
**     You may not represent yourself as Golden Code Development Corporation or FWD.
49
** 
50
**     You may not represent yourself for publicity purposes as associated with
51
**     Golden Code Development Corporation, FWD, or any author or contributor to
52
**     the covered work, without written authorization.
53
** 
54
**   3. No Misrepresentation of Source or Origin.
55
** 
56
**     You may not represent the covered work as solely your work.  All modified
57
**     versions of the covered work must be marked in a reasonable way to make it
58
**     clear that the modified work is not originating from Golden Code Development
59
**     Corporation or FWD.  All modified versions must contain the notices of
60
**     attribution required in this license.
61
*/
62

  
63
package com.goldencode.p2j.ui.client.driver.web;
64

  
65
import java.security.SecureRandom;
66
import java.util.Date;
67
import java.util.Map;
68

  
69
import javax.crypto.KeyGenerator;
70
import javax.crypto.SecretKey;
71

  
72

  
73
import com.goldencode.p2j.util.logging.CentralLogger;
74

  
75
import io.jsonwebtoken.Claims;
76
import io.jsonwebtoken.ExpiredJwtException;
77
import io.jsonwebtoken.InvalidClaimException;
78
import io.jsonwebtoken.Jwe;
79
import io.jsonwebtoken.Jwts;
80

  
81
/**
82
 * The web client web tokens service
83
 */
84
public class WebTokensService
85
{
86
   /** The class logger */
87
   private static final CentralLogger LOG = CentralLogger.get(WebTokensService.class);
88
   /** The encryption algorithm */
89
   private static final String ALGORITHM = "AES";
90
   /** 
91
    * Cypher internal parameter Jwts.ENC.A128GCM for external usages
92
    * String CIPHER_SPEC = "AES/GCM/NoPadding";
93
    * int GCM_IV_LENGTH = 12; // 96 = 12 * 8 bits
94
    * int GCM_TAG_LENGTH = 16; // 128 = 16 * 8 bits, standard default
95
    */
96
   /** The key length in bits */
97
   private static final int AES_KEY_LENGTH = 128; // 128, 192, or 256 bits
98
   /** The default validity interval in milliseconds */
99
   private static long VALIDITITY_IN_MILLISECONDS = 60000;
100
   
101
   /** The secret key */
102
   private final SecretKey secretKey;
103
   
104
   /** The token validity interval in milliseconds */
105
   private final long validityInterval;
106
   
107
   /**
108
    * Creates new cryptographic secret key for AES.
109
    * 
110
    * @return    The secret key
111
    * 
112
    * @throws    Exception
113
    *            It can be an invalid parameter exception or a runtime exception thrown during
114
    *            the key generation.
115
    */
116
   public static SecretKey generateKey()
117
   throws Exception
118
   {
119
      KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
120
      keyGen.init(AES_KEY_LENGTH, SecureRandom.getInstanceStrong());
121
      return keyGen.generateKey();
122
   }
123
   
124
   /**
125
    * Create the web tokens service instance.
126
    * 
127
    * @throws   Exception
128
    *           The secret key generation exception
129
    */
130
   public WebTokensService()
131
   throws Exception
132
   {
133
      this(generateKey(), VALIDITITY_IN_MILLISECONDS);
134
   }
135
   
136
   /**
137
    * Create the web tokens service instance for the given secret key and
138
    * validity interval.
139
    * 
140
    * @param    secretKey
141
    *           The secret key
142
    * @param    validityInterval
143
    *           The validity interval
144
    */
145
   public WebTokensService(SecretKey secretKey, long validityInterval)
146
   {
147
      this.secretKey = secretKey;
148
      this.validityInterval = validityInterval;
149
   }
150

  
151
   /**
152
    * Validate the encrypted web token.
153
    * 
154
    * @param    value
155
    *           The string value of the encrypted web token
156
    * @param    subject
157
    *           The value of "sub" key
158
    * @param    claims
159
    *           The additional values
160
    * 
161
    * @return   true if the token is valid, otherwise false
162
    */
163
   public boolean validateWebTokenValue(String value, String subject, Map<String, String> claims)
164
   {
165
     try
166
     {
167
         Jwe<Claims> jwe = Jwts.parser()
168
                 .requireSubject(subject)
169
                 .decryptWith(secretKey)
170
                 .build()
171
                 .parseEncryptedClaims(value);
172

  
173
         Claims payload = jwe.getPayload();
174
         if (claims != null)
175
         {
176
            for(Map.Entry<String, String> entry : claims.entrySet())
177
            {
178
               String claimValue = payload.get(entry.getKey(), String.class);
179
               if (claimValue == null || !claimValue.equals(entry.getValue()))
180
               {
181
                  return false;
182
               }
183
            }
184
         }
185
         
186
         return true;
187
     }
188
     catch (io.jsonwebtoken.security.SecurityException e1)
189
     {
190
        LOG.severe("", e1);
191
        return false;
192
     }
193
     catch (ExpiredJwtException e2)
194
     {
195
         LOG.severe("", e2);
196
         return false;
197
     }
198
     catch(InvalidClaimException e3)
199
     {
200
        LOG.severe("", e3);
201
        return false;
202
     }
203
     catch (Exception e4)
204
     {
205
         LOG.severe("", e4);
206
         return false;
207
     }
208
   }
209
   
210
   /**
211
    * Generate the encrypted web token.
212
    * 
213
    * @param    subject
214
    *           The value of "sub" key
215
    * @param    claims
216
    *           The additional values
217
    * 
218
    * @return   The string presentation of the encrypted web token
219
    * 
220
    * @throws   Exception
221
    *           The exception during this operation
222
    */
223
   public String generateWebTokenValue(String subject, Map<String, String> claims)
224
   throws Exception
225
   {
226
      String jwe = Jwts.builder()
227
            .header()
228
            .and()
229
            .subject(subject)
230
            .expiration(new Date(System.currentTimeMillis() + validityInterval))
231
            .issuedAt(new Date())
232
            .claims(claims)
233
            // Encrypt using Direct encryption (dir) and AES-128-GCM
234
            .encryptWith(secretKey, Jwts.ENC.A128GCM) 
235
            .compact();
236
      return jwe;
237
   }
238
}
new/src/com/goldencode/p2j/ui/client/driver/web/res/p2j.js 2026-03-27 06:50:22 +0000
2 2
** Module   : p2j.js
3 3
** Abstract : top-level web client java script object 
4 4
**
5
** Copyright (c) 2014-2025, Golden Code Development Corporation.
5
** Copyright (c) 2014-2026, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ------------------------------Description----------------------------------
8 8
** 001 MAG 20140110 First version.
......
72 72
** 029 PMP 20250916 Initialized networkSocket module. 
73 73
** 030 SB  20251113 Remove the cursor overlay on mouse clicks as well if there was no previous mouse move.
74 74
** 031 SBI 20251210 Added repeat key.(refs: #10984, #10982, #10836)
75
** 032 SBI 20260326 Refactored to protect openMimeResource access.
75 76
*/
76 77
/*
77 78
** This program is free software: you can redistribute it and/or modify
......
172 173
   /** The dialog identifiers */
173 174
   const DIALOGS = { OPENPOPUP : "openMimeResource"}
174 175
      
175
   /** The instance of the unique copy/cut/paste notification dialog. */
176
   var dialog;
177
   
178
   /** The open popup dialog */
179
   var openPopupDialog;
176
   /** The set of displayed ModalDialogs */
177
   var dialogs = new Set();
180 178
   
181 179
   /** The notification templates to prompt a user to do an action */
182 180
   var prompts = {};
......
218 216
      i18n = window.i18n();
219 217
      
220 218
      Object.defineProperty(
221
            p2j,
219
            me,
222 220
            "i18n",
223 221
            {
224 222
               get: function ()
225 223
               {
226 224
                  return i18n;
227
               }
225
               },
226
               enumerable : false,
227
               configurable : false
228 228
            });
229 229
      var lang = cfg["lang"];
230 230
      if (lang)
231 231
      {
232
         p2j.addTranslations(lang, cfg["translations"]);
232
         me.addTranslations(lang, cfg["translations"]);
233 233
      }
234 234
      /**
235 235
       * Prevent back navigation.
......
261 261
      container = document.getElementById(cfg.container) || document.body;
262 262
      
263 263
      // save off our client mode type
264
      p2j.isGui = cfg.isGui;
264
      me.isGui = cfg.isGui;
265 265
      
266 266
      // set the web client embedded mode and define a "get" access only 
267 267
      Object.defineProperty(
268
                            p2j,
268
                            me,
269 269
                            "embedded",
270 270
                            {
271 271
                               get: function ()
272 272
                               {
273 273
                                  return cfg.embedded;
274
                               }
274
                               },
275
                               enumerable : false,
276
                               configurable : false
275 277
                            });
276 278
      /** the body html css class name to display wait cursor */
277
      p2j.waitCursorClass = "wait";
279
      me.waitCursorClass = "wait";
278 280
      
279 281
      /** the body html css class name to display default cursor */
280
      p2j.bodyHtmlClass = document.body.className;
282
      me.bodyHtmlClass = document.body.className;
281 283
      
282 284
      /** to display the wait cursor for the document */
283
      p2j.displayWaitCursor = function ()
285
      me.displayWaitCursor = function ()
284 286
      {
285
         if (document.body.className === p2j.bodyHtmlClass)
287
         if (document.body.className === me.bodyHtmlClass)
286 288
         {
287
            document.body.className += (" " + p2j.waitCursorClass);
289
            document.body.className += (" " + me.waitCursorClass);
288 290
         }
289 291
      }
290 292
      
291 293
      /** to restore the cursor for the document */
292
      p2j.restoreCursor = function ()
294
      me.restoreCursor = function ()
293 295
      {
294
         document.body.className = p2j.bodyHtmlClass;
296
         document.body.className = me.bodyHtmlClass;
295 297
      }
296 298

  
297 299
      /**
......
300 302
       * @param   cursorStyle
301 303
       *          The id of the cursor style.
302 304
       */
303
      p2j.setGlobalCursor = function(cursorStyle)
305
      me.setGlobalCursor = function(cursorStyle)
304 306
      {
305 307
         var body = document.body;
306 308
         var style = p2j.screen.calculateCursorStyle(cursorStyle);
......
366 368
      /**
367 369
       * Remove the globally assigned cursor.
368 370
       */
369
      p2j.removeGlobalCursor = function()
371
      me.removeGlobalCursor = function()
370 372
      {
371 373
         var body = document.body;
372 374
         var bodyOverlay = document.getElementById("body-overlay");
......
382 384
       * @param    {String} rgb
383 385
       *           The CSS color string.
384 386
       */
385
      p2j.setDefaultDesktopBgcolor = function(rgb)
387
      me.setDefaultDesktopBgcolor = function(rgb)
386 388
      {
387
         p2j.defaultDesktopBgcolor = rgb;
389
         me.defaultDesktopBgcolor = rgb;
388 390
      };
389 391
      
390 392
      /**
......
393 395
       * @param    {String} rgb
394 396
       *           The CSS color string.
395 397
       */
396
      p2j.setDesktopBgColor = function (rgb)
398
      me.setDesktopBgColor = function (rgb)
397 399
      {
398
         if (p2j.embedded)
400
         if (me.embedded)
399 401
         {
400
            if (p2j.defaultDesktopBgcolor)
402
            if (me.defaultDesktopBgcolor)
401 403
            {
402
               rgb = p2j.defaultDesktopBgcolor;
404
               rgb = me.defaultDesktopBgcolor;
403 405
            }
404 406

  
405 407
            setStyleForElement(document.body, {background : rgb});
406 408
         }
407
      }
408
      
409
      };
410
      // initialize constants
409 411
      Object.defineProperty(
410
            p2j,
412
            me,
411 413
            "prompts",
412 414
            {
413 415
               get: function ()
......
421 423
                     
422 424
                     return prompt;
423 425
                  }
424
               }
426
               },
427
               enumerable : false,
428
               configurable : false
425 429
            });
426 430
      
427 431
      Object.defineProperty(
428
            p2j,
432
            me,
429 433
            "hints",
430 434
            {
431 435
               get: function ()
......
439 443
                     
440 444
                     return hint;
441 445
                  }
442
               }
446
               },
447
               enumerable : false,
448
               configurable : false
443 449
            });
444 450
      
445 451
      Object.defineProperty(
446
         p2j,
452
         me,
447 453
         "commandSupported",
448 454
         {
449 455
            get: function ()
......
452 458
               {
453 459
                  return queryCommandSupported[cmd];
454 460
               }
455
            }
461
            },
462
            enumerable : false,
463
            configurable : false
456 464
         });
457 465
      
458 466
      Object.defineProperty(
459
            p2j,
467
            me,
460 468
            "webRoot",
461 469
            {
462 470
               get: function ()
463 471
               {
464 472
                  return cfg.webRoot;
465
               }
473
               },
474
               enumerable : false,
475
               configurable : false
466 476
            });
467 477
      
468 478
      Object.defineProperty(
469
            p2j,
479
            me,
470 480
            "disablePixelManipulation",
471 481
            {
472 482
               get: function ()
473 483
               {
474 484
                  return cfg.disablePixelManipulation;
475
               }
485
               },
486
               enumerable : false,
487
               configurable : false
476 488
            });
477 489
      
478 490
      /** The container for application windows and tool bar */
479 491
      Object.defineProperty(
480
            p2j,
492
            me,
481 493
            "container",
482 494
            {
483 495
               get: function ()
484 496
               {
485 497
                  return container;
486
               }
498
               },
499
               enumerable : false,
500
               configurable : false
487 501
            });
488 502
      
489 503
      //Dialog help messages
490 504
      const pressEscape = "Press ESCAPE to dismiss this action.";
491 505
      Object.defineProperty(
492
            p2j,
506
            me,
493 507
            "pressEscape",
494 508
            {
495 509
               get: function ()
496 510
               {
497 511
                  return i18n.gettext(pressEscape);
498
               }
512
               },
513
               enumerable : false,
514
               configurable : false
499 515
            });
500 516
      
501 517
      const pressAnyKey = "Press any key to dismiss this action.";
502 518
      Object.defineProperty(
503
            p2j,
519
            me,
504 520
            "pressAnyKey",
505 521
            {
506 522
               get: function ()
507 523
               {
508 524
                  return i18n.gettext(pressAnyKey);
509
               }
510
            });
511
      
525
               },
526
               enumerable : false,
527
               configurable : false
528
            });
529
      Object.defineProperty(
530
            me,
531
            "dialogs",
532
            {
533
               get: function ()
534
               {
535
                  return function(id)
536
                  {
537
                     return DIALOGS[id];
538
                  }
539
               },
540
               enumerable : false,
541
               configurable : false
542
            });
543
      Object.defineProperty(
544
            me,
545
            "OPENPOPUP",
546
            {
547
               get: function ()
548
               {
549
                  return OPENPOPUP;
550
               },
551
               enumerable : false,
552
               configurable : false
553
            });
512 554
      var progressBarControlFunction;
513 555
      dojo.require("dijit.ProgressBar");
514 556
      
......
516 558
      {
517 559
         progressBarControlFunction = createProgressBar("webClientLoadingProgressBar", [0, 50, 100]);
518 560
         Object.defineProperty(
519
               p2j,
561
               me,
520 562
               "setLoadingCheckpoint",
521 563
               {
522 564
                  get: function ()
523 565
                  {
524 566
                     return progressBarControlFunction;
525
                  }
567
                  },
568
                  enumerable : false,
569
                  configurable : false
526 570
               });
527 571
      });
528 572
      
......
1181 1225
   me.getCodePoint = getCodePoint;
1182 1226
   
1183 1227
   /**
1184
    * Creates and displays the application modal dialog.
1185
    * 
1186
    * @param    {String} id
1187
    *           The dialog unique identifier.
1188
    * @param    {HtmlElement} container
1189
    *           The container element.
1190
    * @param    {String} text
1191
    *           The dialog content message.
1192
    * @param    {String} tooltip
1193
    *           The dialog tooltip message.
1194
    * @param    {Function} keyDownHandler
1195
    *           The "keydown" event's handler.
1196
    * 
1197
    * @return   The modal dialog.
1198
    */
1199
   function createInternalDialog(id, container, text, tooltip, keyDownHandler)
1200
   {
1201
      var dlg = new ModalDialog(id, container, text, tooltip, false);
1202
      
1203
      if (keyDownHandler)
1204
      {
1205
         dlg.addTrigger("keydown", keyDownHandler, true);
1206
      }
1207
      
1208
      return dlg;
1209
   };
1210
   
1211
   /**
1212 1228
    * Tests if the clipboard dialog is active.
1213 1229
    */
1214 1230
   function isDialogDisplayed()
1215 1231
   {
1216
      return (dialog != null) && (dialog != undefined);
1232
      return dialogs.size > 0;
1217 1233
   }
1218 1234
   
1219 1235
   me.isDialogDisplayed = isDialogDisplayed;
1220 1236
   
1221
   /**
1222
    * Creates and displays the open popup operation dialog.
1223
    * 
1224
    * @param    {Function} keyDownHandler
1225
    *           The "keydown" event's handler.
1226
    * 
1227
    * @return   The modal dialog.
1228
    */
1229
   function createOpenPopupDialog(keyDownHandler)
1230
   {
1231
      if (!openPopupDialog || openPopupDialog.disposed)
1232
      {
1233
         openPopupDialog = createInternalDialog(DIALOGS[OPENPOPUP],
1234
                                                document.body,
1235
                                                p2j.prompts(OPENPOPUP),
1236
                                                p2j.hints(OPENPOPUP),
1237
                                                keyDownHandler);
1238
      }
1239
      else
1240
      {
1241
         openPopupDialog.addTrigger("keydown", keyDownHandler, true);
1242
         openPopupDialog.show();
1243
      }
1244
      
1245
      return openPopupDialog;
1246
   };
1247
   
1248
   /**
1249
    * Returns the reference to the window with the target page if this operation is succedded,
1250
    * otherwise null.
1251
    * 
1252
    * @param    url
1253
    *           The target page
1254
    */
1255
   function openNewWindow(url)
1256
   {
1257
      var newWindow;
1258
      
1259
      try
1260
      {
1261
         newWindow = window.open(url, "_blank");
1262
      }
1263
      catch(ex)
1264
      {
1265
         console.error(ex);
1266
      }
1267
      
1268
      if (newWindow && !newWindow.closed)
1269
      {
1270
         return newWindow;
1271
      }
1272
      
1273
      return null;
1274
   }
1275
   
1276
   /**
1277
    * Retrieve filename from content-disposition header if there is filename key, otherwise
1278
    * returns the provided default file name.
1279
    * 
1280
    * @param    response
1281
    *           The response object
1282
    * @param    defaultFileName
1283
    *           The provided default file name
1284
    * 
1285
    * @returns  The value of filename key, otherwise the provided default file name.
1286
    */
1287
   function getFileName(response, defaultFileName)
1288
   {
1289
      var contentDisposition = response.headers.get("Content-disposition");
1290
      
1291
      if (contentDisposition)
1292
      {
1293
         var index = contentDisposition.indexOf("filename=");
1294
         if (index > 0)
1295
         {
1296
            var filename = contentDisposition.substring(index + 9);
1297
            // remove quotes
1298
            if (filename.length > 0)
1299
            {
1300
               var startQuote = filename.charAt(0);
1301
               var endQuote = filename.charAt(filename.length - 1);
1302
               if (startQuote == "\"" &&  endQuote == "\"")
1303
               {
1304
                  filename = filename.substring(1, filename.length - 1);
1305
               }
1306
               
1307
               return filename;
1308
            }
1309
         }
1310
      }
1311
      
1312
      return defaultFileName;
1313
   }
1314
   
1315
   /**
1316
    * Opens a target resource given by its url.
1317
    * 
1318
    * @param    url
1319
    *           The target url
1320
    * @param    mimeType
1321
    *           The resource mime type
1322
    * @param    openInNewWindow
1323
    *           The flag indicating that the document should be opened in new tab or window
1324
    */
1325
   function openMimeResource(url, mimeType, openInNewWindow)
1326
   {
1327
      if (openInNewWindow)
1328
      {
1329
         var newWindow = openNewWindow(url);
1330
         
1331
         if (!newWindow)
1332
         {
1333
            createOpenPopupDialog(
1334
                         function (evt)
1335
                         {
1336
                            if (evt.keyCode === keys.ENTER)
1337
                            {
1338
                               newWindow = openNewWindow(url);
1339
                               
1340
                               if (!newWindow)
1341
                               {
1342
                                  console.error("Failed to open " + url);
1343
                               }
1344
                               
1345
                               if (openPopupDialog)
1346
                               {
1347
                                  openPopupDialog.close();
1348
                               }
1349
                            }
1350
                         });
1351
         }
1352
      }
1353
      else
1354
      {
1355
         fetch(url).then(function(response)
1356
         {
1357
            if (response.ok)
1358
            {
1359
               var filename = getFileName(response, "filename");
1360
               response.blob().then(blob =>
1361
               {
1362
                 saveBlobAs(filename, new File([blob], filename, {type: mimeType}));
1363
               });
1364
            }
1365
            else
1366
            {
1367
               console.error("Failed to fetch " + url + " with status code " + response.status);
1368
            }
1369
         });
1370
      }
1371
   }
1372
   
1373
   me.openMimeResource = openMimeResource;
1374 1237
   
1375 1238
   /**
1376 1239
    * Calculates the maximal z-index on the current page.
......
1815 1678
   
1816 1679
   me.ScreenManager = ScreenManager;
1817 1680
   
1818
   /**
1819
    * Export the given content to the file on the client file system.
1820
    * 
1821
    * @param    {String} mimeType
1822
    *           The content mime type
1823
    * @param    {String} fileName
1824
    *           The target file name
1825
    * @param    {Array} content
1826
    *           The array of strings that represents the exported content.
1827
    */
1828
   function saveAs(mimeType, fileName, content)
1829
   {
1830
      var blob = new File(content, fileName, {type: mimeType});
1831
      saveBlobAs(fileName, blob)
1832
   }
1833
   
1834
   /**
1835
    * Export the content of the given blob to the file on the client file system.
1836
    * 
1837
    * @param    {String} fileName
1838
    *           The target file name
1839
    * @param    {Blob} blob
1840
    *           The blob that represents the exported content.
1841
    */
1842
   function saveBlobAs(fileName, blob)
1843
   {
1844
      var object_url = URL.createObjectURL(blob);
1845
      var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
1846
      var can_use_save_link = "download" in save_link;
1847
      
1848
      if (can_use_save_link)
1849
      {
1850
         save_link.href = object_url;
1851
         save_link.target = "_blank";
1852
         save_link.download = fileName;
1853
         save_link.click();
1854
      }
1855
      else
1856
      {
1857
         var opened = window.open(object_url, "_blank");
1858
         if (!opened)
1859
         {
1860
            window.location.href = object_url;
1861
         }
1862
      }
1863
      
1864
      URL.revokeObjectURL(object_url);
1865
   }
1866
   
1867
   /** Export the given content to the file on the client file system. */
1868
   me.saveAs = saveAs;
1869
   
1870
   /** Export the content of the given blob to the file on the client file system. */
1871
   me.saveBlobAs = saveBlobAs;
1681
   // Define protected methods 
1682
   (function()
1683
   {
1684
      /**
1685
       * Export the given content to the file on the client file system.
1686
       * 
1687
       * @param    {String} mimeType
1688
       *           The content mime type
1689
       * @param    {String} fileName
1690
       *           The target file name
1691
       * @param    {Array} content
1692
       *           The array of strings that represents the exported content.
1693
       */
1694
      function saveAs(mimeType, fileName, content)
1695
      {
1696
         var blob = new File(content, fileName, {type: mimeType});
1697
         saveBlobAs(fileName, blob)
1698
      }
1699
      
1700
      /**
1701
       * Export the content of the given blob to the file on the client file system.
1702
       * 
1703
       * @param    {String} fileName
1704
       *           The target file name
1705
       * @param    {Blob} blob
1706
       *           The blob that represents the exported content.
1707
       */
1708
      function saveBlobAs(fileName, blob)
1709
      {
1710
         var object_url = URL.createObjectURL(blob);
1711
         var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
1712
         var can_use_save_link = "download" in save_link;
1713
         
1714
         if (can_use_save_link)
1715
         {
1716
            save_link.href = object_url;
1717
            save_link.target = "_blank";
1718
            save_link.download = fileName;
1719
            save_link.click();
1720
         }
1721
         else
1722
         {
1723
            var opened = window.open(object_url, "_blank");
1724
            if (!opened)
1725
            {
1726
               window.location.href = object_url;
1727
            }
1728
         }
1729
         
1730
         URL.revokeObjectURL(object_url);
1731
      }
1732
      
1733
      /** Export the given content to the file on the client file system. */
1734
      Object.defineProperty(
1735
                            me,
1736
                            "saveAs",
1737
                            {
1738
                               get: function ()
1739
                               {
1740
                                  return saveAs;
1741
                               },
1742
                               enumerable : false,
1743
                               configurable : false
1744
                            });
1745
      
1746
      /** Export the content of the given blob to the file on the client file system. */
1747
      Object.defineProperty(
1748
                            me,
1749
                            "saveBlobAs",
1750
                            {
1751
                               get: function ()
1752
                               {
1753
                                  return saveBlobAs;
1754
                               },
1755
                               enumerable : false,
1756
                               configurable : false
1757
                            });
1758
   })();
1872 1759
   
1873 1760
   /** Defines chained listeners */
1874 1761
   function ChainedListeners(head, tail)
......
2026 1913
            changeDisplayStyle(overlay, "block");
2027 1914
            changeVisibilityStyle(dialog, "visible");
2028 1915
            setVisible(true);
1916
            dialogs.add(dialog);
2029 1917
         }
2030 1918
      }
2031 1919
      
......
2038 1926
            changeDisplayStyle(overlay, "none");
2039 1927
            changeVisibilityStyle(dialog, "collapse");
2040 1928
            setVisible(false);
1929
            dialogs.delete(dialog);
2041 1930
            var listener = dialog.listeners.get("onHide");
2042 1931
            if (listener)
2043 1932
            {
......
2379 2268
            });
2380 2269
            
2381 2270
            dialog.disposed = true;
2382
            
2271
            dialogs.delete(dialog);
2383 2272
            if (listener)
2384 2273
            {
2385 2274
               listener();
new/src/com/goldencode/p2j/ui/client/driver/web/res/p2j.socket.js 2026-03-27 06:37:29 +0000
200 200
**         20260312 Exposed doRedirectToLogoutPage as me.redirectToLogout for use by SSO re-auth module.
201 201
**                  Added me.loginPage and me.logoutPage accessors to expose the configured page URLs.
202 202
** 080 SB  20260310 When safely closing a websocket use code Normal_Closure.
203
** 081 SBI 20260326 Refactored to protect openMimeResource access.
203 204
*/
204 205

  
205 206
/*
......
4408 4409
            
4409 4410
            var anchor = message[offset + 2];
4410 4411
            
4411
            var url = p2j.socket.buildOpenResourceUrl("document", id, mimeType, embedded, local, anchor);
4412
            offset = offset + 3;
4413
            var webTokenForEmbedded = null;
4414
            if (embedded || local)
4415
            {
4416
               textLength = me.readInt32BinaryMessage(message, offset);
4417
               offset = offset + 4;
4418
               webTokenForEmbedded = me.readStringBinaryMessageByLength(message, offset, textLength);
4419
               offset = offset + 2 * textLength;
4420
            }
4421
            var url = buildOpenResourceUrl("document", id, mimeType, embedded, local,
4422
                anchor, webTokenForEmbedded);
4412 4423
            
4413 4424
            if (url != null)
4414 4425
            {
......
4421 4432
                           return element.toLowerCase() == mimeType.toLowerCase();
4422 4433
                        }).length > 0;
4423 4434
               }
4424
               p2j.openMimeResource(url, mimeType, !fetch);
4435
               openMimeResource(url, mimeType, !fetch);
4425 4436
            }
4426 4437
            
4427 4438
            break;
......
4854 4865
    * 
4855 4866
    * @return   The target resource url.
4856 4867
    */
4857
   me.buildOpenResourceUrl = function(handler, path, mimeType, embedded, local, anchor)
4868
   function buildOpenResourceUrl(handler, path, mimeType, embedded, local, 
4869
      anchor, webTokenForEmbedded)
4858 4870
   {
4859 4871
      var url = p2j.webRoot;
4860 4872
      
......
4871 4883
         
4872 4884
         if (local)
4873 4885
         {
4874
            url += "&stream=yes";
4886
            url += "&local=yes";
4887
         }
4888
         if (webTokenForEmbedded)
4889
         {
4890
            url = url.concat("&", "api_token", "=", encodeURIComponent(webTokenForEmbedded));
4875 4891
         }
4876 4892
      }
4877 4893
      else
......
4879 4895
         if (local)
4880 4896
         {
... This diff was truncated because it exceeds the maximum size that can be displayed.