1 package org.kde.kjas.server;
2 
3 import java.io.*;
4 import java.util.*;
5 import java.awt.*;
6 import java.net.*;
7 
8 /**
9  * Encapsulates the KJAS protocol and manages the contexts
10  *
11  */
12 public class KJASProtocolHandler
13 {
14     // Command codes- always need to be synced up with
15     // what's in kjavaappletserver.cpp
16     private static final int CreateContextCode   = 1;
17     private static final int DestroyContextCode  = 2;
18     private static final int CreateAppletCode    = 3;
19     private static final int DestroyAppletCode   = 4;
20     private static final int StartAppletCode     = 5;
21     private static final int StopAppletCode      = 6;
22     private static final int InitAppletCode      = 7;
23     private static final int ShowDocumentCode    = 8;
24     private static final int ShowURLInFrameCode  = 9;
25     private static final int ShowStatusCode      = 10;
26     private static final int ResizeAppletCode    = 11;
27     private static final int GetURLDataCode      = 12;
28     private static final int URLDataCode         = 13;
29     private static final int ShutdownServerCode  = 14;
30     private static final int JavaScriptEvent     = 15;
31     static final int GetMember                   = 16;
32     static final int CallMember                  = 17;
33     private static final int PutMember           = 18;
34     private static final int DerefObject         = 19;
35 
36     private static final int AudioClipPlayCode   = 20;
37     private static final int AudioClipLoopCode   = 21;
38     private static final int AudioClipStopCode   = 22;
39 
40     private static final int AppletStateNotificationCode = 23;
41     private static final int AppletFailedCode    = 24;
42     private static final int DataCommand         = 25;
43     private static final int PutURLDataCode      = 26;
44     private static final int PutDataCode         = 27;
45     private static final int SecurityConfirmCode = 28;
46     private static final int ShowConsole         = 29;
47 
48     //Holds contexts in contextID-context pairs
49     private Hashtable contexts;
50 
51     private PushbackInputStream commands;    //Stream for reading in commands
52     private PrintStream         signals;     //Stream for writing out callbacks
53 
54     //used for parsing each command as it comes in
55     private int cmd_index;
56     private final static char sep = (char) 0;
57 
KJASProtocolHandler( InputStream _commands, OutputStream _signals )58     public KJASProtocolHandler( InputStream  _commands,
59                                 OutputStream _signals )
60     {
61         commands = new PushbackInputStream( _commands );
62         signals  = new PrintStream( _signals );
63         contexts = new Hashtable();
64     }
65 
commandLoop()66     public void commandLoop()
67     {
68         try
69         {
70             while( true )
71             {
72                 try
73                 {
74                     int cmd_length = readPaddedLength( 8 );
75                     Main.debug( "PH: cmd_length = " + cmd_length );
76 
77                     //We need to have this while loop since we're not guaranteed to get
78                     //all the bytes we want back, especially with large jars
79                     byte[] cmd_data = new byte[cmd_length];
80                     int total_read = 0;
81                     while( total_read < cmd_length )
82                     {
83                         int numread = commands.read( cmd_data, total_read, cmd_length-total_read );
84                         Main.debug( "PH: read in " + numread + " bytes for command" );
85                         total_read += numread;
86                     }
87 
88                     //parse the rest of the command and execute it
89                     processCommand( cmd_data );
90                 }
91                 catch( NumberFormatException e )
92                 {
93                     Main.kjas_err( "Could not parse out message length", e );
94                     e.printStackTrace();
95                     System.exit( 1 );
96                 }
97                 catch( Throwable t )
98                 {
99                     Main.debug( "commandLoop caught a throwable, still going" );
100                     t.printStackTrace();
101                 }
102             }
103         }
104         catch( Exception i )
105         {
106             Main.kjas_err( "commandLoop exited on exception: ", i );
107                     i.printStackTrace();
108             System.exit( 1 );
109         }
110     }
111 
processCommand( byte[] command )112     public void processCommand( byte[] command )
113     {
114         // Sanity checks
115         if ( command == null )
116             return;
117 
118         //do all the parsing here and pass arguments as individual variables to the
119         //handler functions
120         int cmd_length = command.length;
121         cmd_index = 0;
122 
123         int cmd_code_value = (int) command[cmd_index++];
124         if( cmd_code_value == CreateContextCode )
125         {
126             //parse out contextID- 1 argument
127             String contextID = getArg( command );
128             Main.debug( "createContext, id = " + contextID );
129 
130             KJASAppletContext context = new KJASAppletContext( contextID );
131             contexts.put( contextID, context );
132         } else
133         if( cmd_code_value == DestroyContextCode )
134         {
135             //parse out contextID- 1 argument
136             String contextID = getArg( command );
137             Main.debug( "destroyContext, id = " + contextID );
138 
139             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
140             if( contexts != null )
141             {
142                 context.destroy();
143                 contexts.remove( contextID );
144             }
145         } else
146         if( cmd_code_value == CreateAppletCode )
147         {
148             //9 arguments- this order is important...
149             final String contextID  = getArg( command );
150             final String appletID   = getArg( command );
151             final String appletName = getArg( command );
152             final String className  = getArg( command );
153             final String baseURL    = getArg( command );
154             final String username   = getArg( command );
155             final String password   = getArg( command );
156             final String authname   = getArg( command );
157             final String codeBase   = getArg( command );
158             final String archives   = getArg( command );
159             final String width      = getArg( command );
160             final String height     = getArg( command );
161             final String title      = getArg( command );
162 
163             //get the number of parameter pairs...
164             String str_params = getArg( command );
165             int num_params = Integer.parseInt( str_params.trim() );
166             final Hashtable params = new Hashtable();
167             for( int i = 0; i < num_params; i++ )
168             {
169                 String name  = getArg( command ); // note name is in uppercase
170                 if( name == null )
171                     name = new String();
172 
173                 String value = getArg( command );
174                 if( value == null )
175                     value = new String();
176                 params.put( name, value );
177                 //Main.debug( "parameter, name = " + name + ", value = " + value );
178             }
179 
180             Main.debug( "createApplet, context = " + contextID + ", applet = " + appletID );
181             Main.debug( "              name = " + appletName + ", classname = " + className );
182             Main.debug( "              baseURL = " + baseURL + ", codeBase = " + codeBase );
183             Main.debug( "              archives = " + archives + ", width = " + width +
184                         ", height = " + height );
185 
186             final KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
187             if( context != null )
188             {
189                 context.createApplet( appletID, appletName, className,
190                                       baseURL, username, password, authname,
191                                       codeBase, archives,
192                                       width, height, title, params );
193             }
194 
195         } else
196         if( cmd_code_value == DestroyAppletCode )
197         {
198             //2 arguments
199             String contextID = getArg( command );
200             String appletID  = getArg( command );
201             Main.debug( "destroyApplet, context = " + contextID + ", applet = " + appletID );
202 
203             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
204             if ( context != null )
205                 context.destroyApplet( appletID );
206         } else
207         if( cmd_code_value == StartAppletCode )
208         {
209             //2 arguments
210             String contextID = getArg( command );
211             String appletID  = getArg( command );
212             Main.debug( "startApplet, context = " + contextID + ", applet = " + appletID );
213 
214             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
215             if ( context != null )
216                 context.startApplet( appletID );
217         } else
218         if( cmd_code_value == StopAppletCode )
219         {
220             //2 arguments
221             String contextID = getArg( command );
222             String appletID  = getArg( command );
223             Main.debug( "stopApplet, context = " + contextID + ", applet = " + appletID );
224 
225             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
226             if ( context != null )
227                 context.stopApplet( appletID );
228         } else
229         if( cmd_code_value == ShutdownServerCode )
230         {
231             Main.debug( "shutDownServer received" );
232             KJASAppletStub.waitForAppletThreads();
233             System.exit( 1 );
234         }
235         else
236         if( cmd_code_value == URLDataCode )
237         {
238 
239             String id = getArg( command );
240             String code = getArg( command );
241             Main.debug( "KIO URLData received(" + id + ") code:" + code );
242 
243             //rest of the command should be the data...
244             byte[] data = null;
245             if (cmd_length - cmd_index > 0) {
246                 data = new byte[ cmd_length - cmd_index ];
247                 System.arraycopy( command, cmd_index, data, 0, data.length );
248             }
249             KIOConnection.setData(id, Integer.parseInt(code), data);
250         } else
251         if (cmd_code_value == GetMember)
252         {
253             int ticketnr = Integer.parseInt( getArg( command ) );
254             String contextID = getArg( command );
255             String appletID  = getArg( command );
256             int objid  = Integer.parseInt( getArg( command ) );
257             String name  = getArg( command );
258             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
259             if ( context == null || !context.getMember(appletID, ticketnr, objid, name))
260                 sendMemberValue(contextID, GetMember, ticketnr, -1, 0, "");
261         } else
262         if (cmd_code_value == PutMember)
263         {
264             int ticketnr = Integer.parseInt( getArg( command ) );
265             String contextID = getArg( command );
266             String appletID  = getArg( command );
267             int objid  = Integer.parseInt( getArg( command ) );
268             String name  = getArg( command );
269             String value  = getArg( command );
270             boolean ret = false;
271             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
272             if (context == null || !context.putMember(appletID, ticketnr, objid, name, value))
273                 sendPutMember(contextID, ticketnr, false);
274         } else
275         if (cmd_code_value == CallMember)
276         {
277             int ticketnr = Integer.parseInt( getArg( command ) );
278             String contextID = getArg( command );
279             String appletID  = getArg( command );
280             int objid  = Integer.parseInt( getArg( command ) );
281             String name  = getArg( command );
282             java.util.List args = new java.util.Vector();
283             try { // fix getArg
284                 String param = getArg(command);
285                 while (param != null) {
286                     args.add(param);
287                     param = getArg(command);
288                 }
289             } catch (Exception e) {}
290 
291             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
292             if ( context == null || !context.callMember(appletID, ticketnr, objid, name, args))
293                 Main.protocol.sendMemberValue(contextID, CallMember, ticketnr, -1, 0, "");
294         } else
295         if (cmd_code_value == DerefObject)
296         {
297             String contextID = getArg( command );
298             String appletID  = getArg( command );
299             String objid  = getArg( command );
300             KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
301             if ( context != null )
302                 context.derefObject(appletID, Integer.parseInt(objid));
303             Main.debug( "DerefObject " + objid);
304         } else
305         if (cmd_code_value == SecurityConfirmCode)
306         {
307             String id = getArg( command );
308             String confirm = getArg( command );
309             Thread t = (Thread) KJASSecurityManager.confirmRequests.get(id);
310             Main.debug( "SecurityConfirmCode " + id + " confirm:" + confirm );
311             if (t != null) {
312                 KJASSecurityManager.confirmRequests.put(id, confirm);
313                 try {
314                     t.interrupt();
315                 } catch (SecurityException se) {}
316             }
317         } else
318         if (cmd_code_value == ShowConsole)
319         {
320             Main.console.setVisible(true);
321         }
322         else
323         {
324            throw new IllegalArgumentException( "Unknown command code" );
325         }
326     }
327 
328     /**************************************************************
329      *****  Methods for talking to the applet server **************
330      **************************************************************/
331 
332     /**
333     * sends get url request
334     */
sendGetURLDataCmd( String jobid, String url )335     public void sendGetURLDataCmd( String jobid, String url )
336     {
337         Main.debug( "sendGetURLCmd(" + jobid + ") url = " + url );
338         //length  = length of args plus 1 for code, 2 for seps and 1 for end
339         byte [] url_bytes = url.getBytes();
340         int length = jobid.length() + url_bytes.length + 4;
341         byte [] bytes = new byte[ length + 8 ];
342         byte [] tmp_bytes = getPaddedLengthBytes( length );
343         int index = 0;
344 
345         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
346         index += tmp_bytes.length;
347         bytes[index++] = (byte) GetURLDataCode;
348         bytes[index++] = sep;
349 
350         tmp_bytes = jobid.getBytes();
351         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
352         index += tmp_bytes.length;
353         bytes[index++] = sep;
354 
355         System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
356         index += url_bytes.length;
357         bytes[index++] = sep;
358 
359         signals.write( bytes, 0, bytes.length );
360     }
361 
362     /**
363     * sends command for get url request (stop/hold/resume) or put (stop)
364     */
sendDataCmd( String id, int cmd )365     public void sendDataCmd( String id, int cmd )
366     {
367         Main.debug( "sendDataCmd(" + id + ") command = " + cmd );
368         byte [] cmd_bytes = String.valueOf( cmd ).getBytes();
369         int length = id.length() + cmd_bytes.length + 4;
370         byte [] bytes = new byte[ length + 8 ];
371         byte [] tmp_bytes = getPaddedLengthBytes( length );
372         int index = 0;
373 
374         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
375         index += tmp_bytes.length;
376         bytes[index++] = (byte) DataCommand;
377         bytes[index++] = sep;
378 
379         tmp_bytes = id.getBytes();
380         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
381         index += tmp_bytes.length;
382         bytes[index++] = sep;
383 
384         System.arraycopy( cmd_bytes, 0, bytes, index, cmd_bytes.length );
385         index += cmd_bytes.length;
386         bytes[index++] = sep;
387 
388         signals.write( bytes, 0, bytes.length );
389     }
390     /**
391     * sends put url request
392     */
sendPutURLDataCmd( String jobid, String url )393     public void sendPutURLDataCmd( String jobid, String url )
394     {
395         Main.debug( "sendPutURLCmd(" + jobid + ") url = " + url );
396         //length  = length of args plus 1 for code, 2 for seps and 1 for end
397         byte [] url_bytes = url.getBytes();
398         int length = jobid.length() + url_bytes.length + 4;
399         byte [] bytes = new byte[ length + 8 ];
400         byte [] tmp_bytes = getPaddedLengthBytes( length );
401         int index = 0;
402 
403         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
404         index += tmp_bytes.length;
405         bytes[index++] = (byte) PutURLDataCode;
406         bytes[index++] = sep;
407 
408         tmp_bytes = jobid.getBytes();
409         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
410         index += tmp_bytes.length;
411         bytes[index++] = sep;
412 
413         System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
414         index += url_bytes.length;
415         bytes[index++] = sep;
416 
417         signals.write( bytes, 0, bytes.length );
418     }
419     /**
420     * sends put data
421     */
sendPutData( String jobid, byte [] b, int off, int len )422     public void sendPutData( String jobid, byte [] b, int off, int len )
423     {
424         Main.debug( "sendPutData(" + jobid + ") len = " + len );
425         //length  = length of args plus 1 for code, 2 for seps and 1 for end
426         int length = jobid.length() + len + 4;
427         byte [] bytes = new byte[ length + 8 ];
428         byte [] tmp_bytes = getPaddedLengthBytes( length );
429         int index = 0;
430 
431         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
432         index += tmp_bytes.length;
433         bytes[index++] = (byte) PutDataCode;
434         bytes[index++] = sep;
435 
436         tmp_bytes = jobid.getBytes();
437         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
438         index += tmp_bytes.length;
439         bytes[index++] = sep;
440 
441         System.arraycopy( b, off, bytes, index, len );
442         index += len;
443         bytes[index++] = sep;
444 
445         signals.write( bytes, 0, bytes.length );
446     }
447     /**
448     * sends notification about the state of the applet.
449     * @see org.kde.kjas.server.KJASAppletStub for valid states
450     */
sendAppletStateNotification( String contextID, String appletID, int state )451     public void sendAppletStateNotification( String contextID, String appletID, int state )
452     {
453         Main.debug( "sendAppletStateNotification, contextID = " + contextID + ", appletID = " +
454                     appletID + ", state=" + state );
455 
456         byte [] state_bytes = String.valueOf( state ).getBytes();
457 
458         int length = contextID.length() + appletID.length() + state_bytes.length + 5;
459         byte [] bytes = new byte[ length + 8 ]; //for length of message
460         byte [] tmp_bytes = getPaddedLengthBytes( length );
461         int index = 0;
462 
463         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
464         index += tmp_bytes.length;
465         bytes[index++] = (byte) AppletStateNotificationCode;
466         bytes[index++] = sep;
467 
468         tmp_bytes = contextID.getBytes();
469         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
470         index += tmp_bytes.length;
471         bytes[index++] = sep;
472 
473         tmp_bytes = appletID.getBytes();
474         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
475         index += tmp_bytes.length;
476         bytes[index++] = sep;
477 
478         System.arraycopy( state_bytes, 0, bytes, index, state_bytes.length );
479         index += state_bytes.length;
480         bytes[index++] = sep;
481 
482         signals.write( bytes, 0, bytes.length );
483     }
484 
485     /**
486     * sends notification about applet failure.
487     * This can happen in any state.
488     * @param contextID context ID of the applet's context
489     * @param appletID  ID of the applet
490     * @param errorMessage any message
491     */
sendAppletFailed( String contextID, String appletID, String errorMessage)492     public void sendAppletFailed ( String contextID, String appletID, String errorMessage)
493     {
494         Main.debug( "sendAppletFailed, contextID = " + contextID + ", appletID = " +
495                     appletID + ", errorMessage=" + errorMessage );
496         byte [] msg_bytes = errorMessage.getBytes();
497         int length = contextID.length() + appletID.length() + msg_bytes.length + 5;
498         byte [] bytes = new byte[ length + 8 ]; //for length of message
499         byte [] tmp_bytes = getPaddedLengthBytes( length );
500         int index = 0;
501 
502         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
503         index += tmp_bytes.length;
504         bytes[index++] = (byte) AppletFailedCode;
505         bytes[index++] = sep;
506 
507         tmp_bytes = contextID.getBytes();
508         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
509         index += tmp_bytes.length;
510         bytes[index++] = sep;
511 
512         tmp_bytes = appletID.getBytes();
513         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
514         index += tmp_bytes.length;
515         bytes[index++] = sep;
516 
517         System.arraycopy( msg_bytes, 0, bytes, index, msg_bytes.length );
518         index += msg_bytes.length;
519         bytes[index++] = sep;
520 
521         signals.write( bytes, 0, bytes.length );
522     }
523 
sendShowDocumentCmd( String loaderKey, String url )524     public void sendShowDocumentCmd( String loaderKey, String url )
525     {
526         Main.debug( "sendShowDocumentCmd from context#" + loaderKey + " url = " + url );
527 
528         //length = length of args + 2 for seps + 1 for end + 1 for code
529         byte [] url_bytes = url.getBytes();
530         byte [] key_bytes = loaderKey.getBytes();
531         int length = key_bytes.length + url_bytes.length + 4;
532         byte [] bytes = new byte[ length + 8 ]; //8 for the length of this message
533         byte [] tmp_bytes = getPaddedLengthBytes( length );
534         int index = 0;
535 
536         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
537         index += tmp_bytes.length;
538         bytes[index++] = (byte) ShowDocumentCode;
539         bytes[index++] = sep;
540 
541         System.arraycopy( key_bytes, 0, bytes, index, key_bytes.length );
542         index += key_bytes.length;
543         bytes[index++] = sep;
544 
545         System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
546         index += url_bytes.length;
547         bytes[index++] = sep;
548 
549         signals.write( bytes, 0, bytes.length );
550     }
551 
sendShowDocumentCmd( String contextID, String url, String frame)552     public void sendShowDocumentCmd( String contextID, String url, String frame)
553     {
554         Main.debug( "sendShowDocumentCmd from context#" + contextID +
555                          " url = " + url + ", frame = " + frame );
556 
557         //length = length of args plus code, 3 seps, end
558         byte [] url_bytes = url.getBytes();
559         byte [] frame_bytes = frame.getBytes();
560         int length = contextID.length() + url_bytes.length + frame_bytes.length + 5;
561         byte [] bytes = new byte[ length + 8 ]; //for length of message
562         byte [] tmp_bytes = getPaddedLengthBytes( length );
563         int index = 0;
564 
565         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
566         index += tmp_bytes.length;
567         bytes[index++] = (byte) ShowURLInFrameCode;
568         bytes[index++] = sep;
569 
570         tmp_bytes = contextID.getBytes();
571         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
572         index += tmp_bytes.length;
573         bytes[index++] = sep;
574 
575         System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
576         index += url_bytes.length;
577         bytes[index++] = sep;
578 
579         System.arraycopy( frame_bytes, 0, bytes, index, frame_bytes.length );
580         index += frame_bytes.length;
581         bytes[index++] = sep;
582 
583         signals.write( bytes, 0, bytes.length );
584     }
585 
sendShowStatusCmd( String contextID, String msg )586     public void sendShowStatusCmd( String contextID, String msg )
587     {
588         Main.debug( "sendShowStatusCmd, contextID = " + contextID + " msg = " + msg );
589 
590         byte [] msg_bytes = msg.getBytes();
591         int length = contextID.length() + msg_bytes.length + 4;
592         byte [] bytes = new byte[ length + 8 ]; //for length of message
593         int index = 0;
594 
595         byte [] tmp_bytes = getPaddedLengthBytes( length );
596         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
597         index += tmp_bytes.length;
598         bytes[index++] = (byte) ShowStatusCode;
599         bytes[index++] = sep;
600 
601         tmp_bytes = contextID.getBytes();
602         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
603         index += tmp_bytes.length;
604         bytes[index++] = sep;
605 
606         System.arraycopy( msg_bytes, 0, bytes, index, msg_bytes.length );
607         index += msg_bytes.length;
608         bytes[index++] = sep;
609 
610         signals.write( bytes, 0, bytes.length );
611     }
612 
sendResizeAppletCmd( String contextID, String appletID, int width, int height )613     public void sendResizeAppletCmd( String contextID, String appletID,
614                                      int width, int height )
615     {
616         Main.debug( "sendResizeAppletCmd, contextID = " + contextID + ", appletID = " +
617                     appletID + ", width = " + width + ", height = " + height );
618 
619         byte [] width_bytes = String.valueOf( width ).getBytes();
620         byte [] height_bytes = String.valueOf( height ).getBytes();
621 
622         //length = length of args plus code, 4 seps, end
623         int length = contextID.length() + appletID.length() + width_bytes.length +
624                      height_bytes.length + 6;
625         byte [] bytes = new byte[ length + 8 ]; //for length of message
626         byte [] tmp_bytes = getPaddedLengthBytes( length );
627         int index = 0;
628 
629         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
630         index += tmp_bytes.length;
631         bytes[index++] = (byte) ResizeAppletCode;
632         bytes[index++] = sep;
633 
634         tmp_bytes = contextID.getBytes();
635         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
636         index += tmp_bytes.length;
637         bytes[index++] = sep;
638 
639         tmp_bytes = appletID.getBytes();
640         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
641         index += tmp_bytes.length;
642         bytes[index++] = sep;
643 
644         System.arraycopy( width_bytes, 0, bytes, index, width_bytes.length );
645         index += width_bytes.length;
646         bytes[index++] = sep;
647 
648         System.arraycopy( height_bytes, 0, bytes, index, height_bytes.length );
649         index += height_bytes.length;
650         bytes[index++] = sep;
651 
652         signals.write( bytes, 0, bytes.length );
653     }
sendJavaScriptEventCmd( String contextID, String appletID, int objid, String event, int [] types, String [] args )654     public void sendJavaScriptEventCmd( String contextID, String appletID, int objid, String event, int [] types, String [] args )
655     {
656         Main.debug( "sendJavaScriptEventCmd, contextID = " + contextID + " event = " + event );
657         String objstr = new String("" + objid);
658         int length = contextID.length() + appletID.length() + event.length() + objstr.length() + 6;
659         byte [][][] arglist = null;
660         if (types != null) {
661             arglist = new byte[args.length][2][];
662             for (int i = 0; i < types.length; i++) {
663                 arglist[i][0] = (new String("" + types[i])).getBytes();
664                 arglist[i][1] = args[i].getBytes();
665                 length += 2 + arglist[i][0].length + arglist[i][1].length;
666             }
667         }
668         byte [] bytes = new byte[ length + 8 ]; //for length of message
669         int index = 0;
670 
671         byte [] tmp_bytes = getPaddedLengthBytes( length );
672         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
673         index += tmp_bytes.length;
674         bytes[index++] = (byte) JavaScriptEvent;
675         bytes[index++] = sep;
676 
677         tmp_bytes = contextID.getBytes();
678         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
679         index += tmp_bytes.length;
680         bytes[index++] = sep;
681 
682         tmp_bytes = appletID.getBytes();
683         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
684         index += tmp_bytes.length;
685         bytes[index++] = sep;
686 
687         tmp_bytes = objstr.getBytes();
688         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
689         index += tmp_bytes.length;
690         bytes[index++] = sep;
691 
692         tmp_bytes = event.getBytes();
693         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
694         index += tmp_bytes.length;
695         bytes[index++] = sep;
696 
697         if (types != null)
698             for (int i = 0; i < types.length; i++) {
699                 System.arraycopy( arglist[i][0], 0, bytes, index, arglist[i][0].length );
700                 index += arglist[i][0].length;
701                 bytes[index++] = sep;
702                 System.arraycopy( arglist[i][1], 0, bytes, index, arglist[i][1].length );
703                 index += arglist[i][1].length;
704                 bytes[index++] = sep;
705             }
706 
707         signals.write( bytes, 0, bytes.length );
708     }
sendMemberValue( String contextID, int cmd, int ticketnr, int type, int rid, String value )709     public void sendMemberValue( String contextID, int cmd, int ticketnr, int type, int rid, String value )
710     {
711         Main.debug( "sendMemberValue, contextID = " + contextID + " value = " + value + " type=" + type + " rid=" + rid );
712 
713         String strticket = String.valueOf( ticketnr );
714         String strtype = String.valueOf( type );
715         String strobj = String.valueOf( rid );
716         byte [] value_bytes = value.getBytes();
717         int length = contextID.length() + value_bytes.length + strtype.length() + strobj.length() + strticket.length() + 7;
718         byte [] bytes = new byte[ length + 8 ]; //for length of message
719         int index = 0;
720 
721         byte [] tmp_bytes = getPaddedLengthBytes( length );
722         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
723         index += tmp_bytes.length;
724         bytes[index++] = (byte) cmd;
725         bytes[index++] = sep;
726 
727         tmp_bytes = contextID.getBytes();
728         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
729         index += tmp_bytes.length;
730         bytes[index++] = sep;
731 
732         tmp_bytes = strticket.getBytes();
733         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
734         index += tmp_bytes.length;
735         bytes[index++] = sep;
736 
737         tmp_bytes = strtype.getBytes();
738         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
739         index += tmp_bytes.length;
740         bytes[index++] = sep;
741 
742         tmp_bytes = strobj.getBytes();
743         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
744         index += tmp_bytes.length;
745         bytes[index++] = sep;
746 
747         System.arraycopy( value_bytes, 0, bytes, index, value_bytes.length );
748         index += value_bytes.length;
749         bytes[index++] = sep;
750 
751         signals.write( bytes, 0, bytes.length );
752     }
753 
sendAudioClipCommand(String contextId, String url, int cmd)754     private void sendAudioClipCommand(String contextId, String url, int cmd) {
755         byte [] url_bytes = url.getBytes();
756         int length = contextId.length() + url_bytes.length + 4;
757         byte [] bytes = new byte[ length + 8 ];
758         byte [] tmp_bytes = getPaddedLengthBytes( length );
759         int index = 0;
760 
761         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
762         index += tmp_bytes.length;
763         bytes[index++] = (byte) cmd;
764         bytes[index++] = sep;
765 
766         tmp_bytes = contextId.getBytes();
767         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
768         index += tmp_bytes.length;
769         bytes[index++] = sep;
770 
771         System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
772         index += url_bytes.length;
773         bytes[index++] = sep;
774 
775         signals.write( bytes, 0, bytes.length );
776     }
777 
sendAudioClipPlayCommand(String contextId, String url)778     public void sendAudioClipPlayCommand(String contextId, String url) {
779         sendAudioClipCommand(contextId, url, AudioClipPlayCode);
780     }
sendAudioClipLoopCommand(String contextId, String url)781     public void sendAudioClipLoopCommand(String contextId, String url) {
782         sendAudioClipCommand(contextId, url, AudioClipLoopCode);
783     }
sendAudioClipStopCommand(String contextId, String url)784     public void sendAudioClipStopCommand(String contextId, String url) {
785         sendAudioClipCommand(contextId, url, AudioClipStopCode);
786     }
787 
sendPutMember( String contextID, int ticketnr, boolean success )788     public void sendPutMember( String contextID, int ticketnr, boolean success )
789     {
790         Main.debug("sendPutMember, contextID = " + contextID + " success = " + success);
791 
792         byte [] ticket_bytes = String.valueOf( ticketnr ).getBytes();
793         byte [] ret_bytes = String.valueOf( success ? "1" : "0" ).getBytes();
794         int length = contextID.length() + ret_bytes.length + ticket_bytes.length + 5;
795         byte [] bytes = new byte[ length + 8 ]; //for length of message
796         byte [] tmp_bytes = getPaddedLengthBytes( length );
797         int index = 0;
798 
799         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
800         index += tmp_bytes.length;
801         bytes[index++] = (byte) PutMember;
802         bytes[index++] = sep;
803 
804         tmp_bytes = contextID.getBytes();
805         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
806         index += tmp_bytes.length;
807         bytes[index++] = sep;
808 
809         System.arraycopy( ticket_bytes, 0, bytes, index, ticket_bytes.length );
810         index += ticket_bytes.length;
811         bytes[index++] = sep;
812 
813         System.arraycopy( ret_bytes, 0, bytes, index, ret_bytes.length );
814         index += ret_bytes.length;
815         bytes[index++] = sep;
816 
817         signals.write( bytes, 0, bytes.length );
818     }
sendSecurityConfirm( String [] certs, int certsnr, String perm, String id )819     public void sendSecurityConfirm( String [] certs, int certsnr, String perm, String id )
820     {
821         Main.debug("sendSecurityConfirm, ID = " + id + " certsnr = " + certsnr);
822 
823         byte [] id_bytes = id.getBytes();
824         byte [] perm_bytes = perm.getBytes();
825         byte [] certsnr_bytes = String.valueOf( certsnr ).getBytes();
826         int length = perm_bytes.length + id_bytes.length + certsnr_bytes.length + 5;
827         for (int i = 0; i < certsnr; i++)
828             length += certs[i].length() + 1;
829         byte [] bytes = new byte[ length + 8 ]; //for length of message
830         byte [] tmp_bytes = getPaddedLengthBytes( length );
831         int index = 0;
832 
833         System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
834         index += tmp_bytes.length;
835         bytes[index++] = (byte) SecurityConfirmCode;
836         bytes[index++] = sep;
837 
838         System.arraycopy( id_bytes, 0, bytes, index, id_bytes.length );
839         index += id_bytes.length;
840         bytes[index++] = sep;
841 
842         System.arraycopy( perm_bytes, 0, bytes, index, perm_bytes.length );
843         index += perm_bytes.length;
844         bytes[index++] = sep;
845 
846         System.arraycopy( certsnr_bytes, 0, bytes, index, certsnr_bytes.length );
847         index += certsnr_bytes.length;
848         bytes[index++] = sep;
849 
850         for (int i = 0; i < certsnr; i++) {
851             byte [] cert_bytes = certs[i].getBytes();
852             System.arraycopy( cert_bytes, 0, bytes, index, cert_bytes.length );
853             index += cert_bytes.length;
854             bytes[index++] = sep;
855         }
856 
857         signals.write( bytes, 0, bytes.length );
858     }
859     /**************************************************************
860      *****  Utility functions for parsing commands ****************
861      **************************************************************/
getArg( byte[] command )862     private String getArg( byte[] command )
863     {
864         int begin = cmd_index;
865         while( 0 != ((int) command[cmd_index++]) );
866 
867         if( cmd_index > (begin + 1) )
868         {
869             String rval = new String( command, begin, (cmd_index - begin - 1) );
870             return rval;
871         }
872         else
873             return null;
874     }
875 
getPaddedLengthBytes( int length )876     private byte[] getPaddedLengthBytes( int length )
877     {
878         byte[] length_bytes = String.valueOf( length ).getBytes();
879         if( length_bytes.length > 8 )
880            throw new IllegalArgumentException( "can't create string number of length = 8" );
881         byte [] bytes = { (byte) ' ', (byte) ' ', (byte) ' ', (byte) ' ',
882                           (byte) ' ', (byte) ' ', (byte) ' ', (byte) ' '};
883         System.arraycopy( length_bytes, 0, bytes, 0, length_bytes.length );
884         return bytes;
885     }
readPaddedLength( int string_size )886     private int readPaddedLength( int string_size )
887         throws IOException
888     {
889             //read in 8 bytes for command length- length will be sent as a padded string
890             byte[] length = new byte[string_size];
891             commands.read( length, 0, string_size );
892 
893             String length_str = new String( length );
894             return Integer.parseInt( length_str.trim() );
895     }
896 
897 }
898