KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SecureChannelPanel


1 import java.awt.*;
2 import java.awt.event.*;
3 import java.awt.image.ImageObserver JavaDoc;
4 import java.io.*;
5 import javax.swing.*;
6 import javax.accessibility.Accessible JavaDoc;
7 import java.util.*;
8 import org.jivesoftware.smack.*;
9 import org.jivesoftware.smack.packet.*;
10 import org.jivesoftware.smack.util.StringUtils;
11 import org.jivesoftware.smackx.muc.*;
12 import org.jivesoftware.smackx.packet.MUCUser;
13 import whisper.*;
14
15 /** Panel that appears as a tab in the main window for composing a one-off message.*/
16 public final class SecureChannelPanel extends JPanel implements Accessible JavaDoc, ImageObserver JavaDoc, MenuContainer, Serializable, WMP{
17     
18     private static final int GAP=10;
19     private final Vector occupants=new Vector(); //Strings of the occupants nicknames inc. own
20

21     final JPanel wherePanel=new JPanel(new GridLayout(2,1,0,0));
22         final JLabel whereLbl=new JLabel();
23         final JLabel statLbl=new JLabel(Lang.gs("chat encrypted"),Icons.PADLOCK,SwingConstants.LEFT);
24     
25     final JSplitPane splitpane=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,false);
26         final JEditorPane chatTextPane=new JEditorPane();
27         final JScrollPane chatTextPaneSP=new JScrollPane(chatTextPane);
28             final JScrollBar sb=chatTextPaneSP.getVerticalScrollBar();
29         final JList occupantsList=new JList(occupants);
30         final JScrollPane occupantsSP=new JScrollPane(occupantsList);
31     
32     final JPanel bottomPanel=new JPanel(new BorderLayout(0,0));
33         final Box writePanel=Box.createHorizontalBox();
34             final JTextField text=new JTextField(20);
35             final JButton sendBtn=new JButton(Lang.gs("send"),Icons.SEND);
36     
37         final JPanel btnPanel=new JPanel(new FlowLayout(FlowLayout.RIGHT,0,0));
38             final JButton closeBtn=new JButton(Lang.gs("close"),Icons.CLOSE);
39     
40     final BtnClick click=new BtnClick();
41     JPanel thisPanel=this;
42
43     private final String JavaDoc Me=Lang.gs("me");
44     private String JavaDoc ChatText="";
45     private String JavaDoc myNickname;
46     private String JavaDoc HEADER=GUI.getHeader();
47         
48     public boolean amProviding=false; //whether the user is providing the secure channel
49
private SessionKey encryptChannelKey=null;
50     private SessionKey decryptChannelKey=null;
51     private String JavaDoc providerJID=null; //the jid of the provider or null is amProviding
52
private Chat chat=null; //only if not amProviding
53
private PublicKey channelPublicKey=null;//only if not amProviding
54
private boolean hasJoined=false; //only if not amProviding
55
private SessionKey myKey=null; //only if not amProviding
56
private Hashtable occupantsChats=null; // key is jid value is Chat object. only if amProviding
57
private Hashtable jid2nick=null; // key is jid value is nickname . only if amProviding
58
private boolean autoallow=false;
59     private boolean autoallowcontacts=true;
60     private final ThreadGroup JavaDoc threads=new ThreadGroup JavaDoc("Secure Channel Threads");
61     public final MessageListener messageListener=new MessageListener();
62     private Hashtable listeners=null;//only if not amProviding
63
private final int SK_USE_LIMIT=17;
64     private int sk_use=0;
65     
66     private SecureChannelPanel(){
67         super(new BorderLayout(GAP,GAP));
68         wherePanel.add(whereLbl);
69         wherePanel.add(statLbl);
70         add(wherePanel,BorderLayout.NORTH);
71         // chat history
72
chatTextPane.setEditable(false);
73         chatTextPane.setMinimumSize(new Dimension(0,0));
74         chatTextPane.setContentType("text/html");
75         java.net.URL JavaDoc base=null;
76         try{
77             base=(new File(".")).toURL();
78             ((javax.swing.text.html.HTMLDocument JavaDoc)chatTextPane.getDocument()).setBase(base);
79         }
80         catch (Exception JavaDoc e){
81             // swallow
82
}
83         GUI.setScrollBars(chatTextPaneSP);
84         // occupants list
85
GUI.setScrollBars(occupantsSP);
86         occupantsList.setPrototypeCellValue("abcdefghij");
87         occupantsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
88         occupantsList.setLayoutOrientation(JList.VERTICAL);
89         occupantsList.setVisibleRowCount(8);
90         occupantsList.setMinimumSize(occupantsList.getPreferredSize());
91         //splitpane
92
if(WhisperIM.UserPref.getProperty("muc_list_location").equals("left")){
93             splitpane.setResizeWeight(0.0);
94             splitpane.setRightComponent(chatTextPaneSP);
95             splitpane.setLeftComponent(occupantsSP);
96             //splitpane.resetToPreferredSizes();
97
}
98         else{
99             splitpane.setResizeWeight(1.0);
100             splitpane.setRightComponent(occupantsSP);
101             splitpane.setLeftComponent(chatTextPaneSP);
102             //splitpane.resetToPreferredSizes();
103
}
104         add(splitpane,BorderLayout.CENTER);
105         //write part
106
sendBtn.setDefaultCapable(true);
107         sendBtn.addActionListener(click);
108         sendBtn.setMnemonic(Lang.s2k("send_mn"));
109         sendBtn.setToolTipText(Lang.gs("chat send_tt"));
110         writePanel.add(text);
111         writePanel.add(writePanel.createGlue());
112         writePanel.add(Box.createHorizontalStrut(GAP));
113         writePanel.add(sendBtn);
114         
115         closeBtn.addActionListener(click);
116         closeBtn.setMnemonic(Lang.s2k("leave_mn"));
117         closeBtn.setToolTipText(Lang.gs("leave_tt"));
118         btnPanel.add(closeBtn);
119         
120         bottomPanel.add(writePanel,BorderLayout.NORTH);
121         bottomPanel.add(Box.createVerticalStrut(GAP),BorderLayout.CENTER);
122         bottomPanel.add(btnPanel,BorderLayout.SOUTH);
123         add(bottomPanel,BorderLayout.SOUTH);
124         
125         //help key
126
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(WhisperIM.HELP_KEY,0),"help"); //put in help key for action help
127
getActionMap().put("help",new HelpAction(this,"schannel.html#using"));
128         // enter key
129
text.getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),"send_messge");
130         text.getActionMap().put("send_messge", new EnterAction());
131     }
132     
133     /** Creates a new joined secure channel.*/
134     public SecureChannelPanel(String JavaDoc jid,String JavaDoc providername,String JavaDoc nick){
135         this();
136         providerJID=jid;
137         myNickname=nick;
138         whereLbl.setText(Lang.gs("provided by")+" "+jid+" "+providername);
139         chat=new Chat(WhisperIM.MainWindow.Conn,providerJID);
140         chat.addMessageListener(messageListener);
141         myKey=new SessionKey(WhisperIM.SR);
142     }
143     
144     /** creates a new secure channel that is being provided by this user.*/
145     public SecureChannelPanel(String JavaDoc nick, boolean autoallowcontacts, boolean autoallow){
146         this();
147         amProviding=true;
148         myNickname=nick;
149         this.autoallowcontacts=autoallowcontacts;
150         this.autoallow=autoallow;
151         whereLbl.setText(Lang.gs("you are providing"));
152         encryptChannelKey=new SessionKey(WhisperIM.SR);
153         decryptChannelKey=Channel.createPair(encryptChannelKey,WhisperIM.SR);
154         occupantsChats=new Hashtable();
155         jid2nick=new Hashtable();
156         listeners=new Hashtable();
157     }
158     // methods
159

160     /** Called after the panel has been added to the main window.*/
161     public void go(){
162         if(amProviding){
163             announce(Lang.gs("opening channel"));
164             occupants.add(myNickname);
165             occupantsList.repaint();
166             sendBtn.requestFocusInWindow();
167             return;
168         }
169         sendBtn.setEnabled(false);
170         text.setEnabled(false);
171         announce(Lang.gs("joining channel"));
172         (new JoinChannelThread()).start();
173     }
174     
175     /** Sends a message.*/
176     public void doSend(){
177         if(text.getText().equals("")){
178             text.requestFocusInWindow();
179             return;
180         }
181         if(amProviding){
182             (new SendMessageThread(myNickname+":"+text.getText())).start();
183         }
184         else{
185             (new SendMessageThread(text.getText())).start();
186         }
187         text.setText("");
188         text.requestFocusInWindow();
189     }
190     
191     /** Adds text to the chat pane.*/
192     private void print(String JavaDoc txt){
193         ChatText=ChatText+txt+"<br>";
194         chatTextPane.setText(HEADER+ChatText+GUI.FOOTER);
195         sb.setValue(sb.getMaximum());
196     }
197     
198     /** Adds text to the chat pane as an announcement.*/
199     private void announce(String JavaDoc text){
200         print("<font color='"+MUCPanel.announceColour+"'>"+GUI.getTime()+" "+text+"</font>");
201     }
202     
203     /** Adds text to the chat pane as an announcement - called by threads outside the EDT.*/
204     private void announceFromThread(final String JavaDoc text){
205         javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
206             public void run(){
207                 print("<font color='"+MUCPanel.announceColour+"'>"+GUI.getTime()+" "+text+"</font>");
208             }
209         });
210     }
211     
212     /** Calls repaint on the occupantsList - called by threads outside the EDT.*/
213     private void updateListFromThread(){
214         SwingUtilities.invokeLater(new Runnable JavaDoc(){
215             public void run(){
216                 occupantsList.repaint();
217             }
218         });
219     }
220     
221     /** Decides if to allow a user to join the secure channel.
222     * Only used when this user is providing the channel.
223     * @param JID the bare jid of the requesting user.
224     *@param requestednickname The nickname they have requested.
225     * @param threadID the jabber chat thread id - may be null.
226     * @param time The time of the request as a localised string.*/

227     public void allow(String JavaDoc JID, String JavaDoc requestednickname, String JavaDoc threadID,String JavaDoc time){
228         //System.out.println("checking join request");
229
synchronized(occupantsChats){
230             if(occupantsChats.get(JID)!=null){
231                 // already listed as present
232
// The user may need to reconect (say after network disconnection)
233
// we ignore this call, other wise we get duplicate requests
234
//send a left message first
235
String JavaDoc nick=(String JavaDoc) jid2nick.get(JID);
236                 if(nick!=null){
237                     MessageListener ml=(MessageListener) listeners.get(JID);
238                     if(ml!=null){
239                         WhisperIM.MainWindow.Conn.removePacketListener(ml);
240                     }
241                     listeners.remove(JID);
242                     occupants.remove((String JavaDoc) jid2nick.get(JID));
243                     (new SendMessageThread(nick+":"+Channel.LEAVING)).start();
244                     jid2nick.remove(JID);
245                 }
246                 // and remove chat
247
occupantsChats.remove(JID);
248                 return;
249             }
250         }
251         Object JavaDoc o=WhisperIM.MainWindow.Contacts.get("jabber"+JID);
252         if(autoallow || (o!=null && autoallowcontacts)){
253             approved(JID,requestednickname,threadID,time);
254             return;
255         }
256         // ask the user first
257
String JavaDoc who="";
258         if(o!=null){
259             ContactListItem cli=(ContactListItem) o;
260             who=" ("+cli.toString()+")";
261         }
262         if(JOptionPane.showConfirmDialog(this,JID+who+"\r\n"+Lang.gs("is requesting join"),Lang.gs("secure channel"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE)==JOptionPane.YES_OPTION){
263             approved(JID,requestednickname,threadID,GUI.getTime());
264         }
265     }
266     
267     private synchronized void approved(String JavaDoc JID, String JavaDoc requestednickname, String JavaDoc threadID,String JavaDoc time){
268         //System.out.println("approving join request");
269
String JavaDoc nick=requestednickname.trim().toLowerCase();
270         Chat c;
271         //calculate nickname
272
nick=nick.replace(' ','_');
273         nick=nick.replace(':','_');
274         Random r=new Random();
275         while(occupants.contains(nick)){
276             nick=nick+r.nextInt(99);
277         }
278         if(threadID!=null){
279             c=new Chat(WhisperIM.MainWindow.Conn,JID,threadID);
280         }
281         else{
282             c=new Chat(WhisperIM.MainWindow.Conn,JID);
283         }
284         MessageListener ml=new MessageListener();
285         listeners.put(JID,ml);
286         c.addMessageListener(ml);
287         // send joined response
288
(new SendJoinedThread(c,nick)).start();
289         occupantsChats.put(JID,c);
290         // show jid
291
announce(nick+": "+JID);
292         // send entered message to others
293
(new SendMessageThread(nick+":"+Channel.ENTERED)).start();
294         occupants.add(nick);
295         occupantsList.repaint();
296         jid2nick.put(JID,nick);
297     }
298     
299     public void doClose(){
300         threads.interrupt();
301         if(!amProviding){
302             try{
303                 WhisperIM.MainWindow.Conn.removePacketListener(messageListener);
304                 (new SendMessageThread(Channel.LEAVING)).start();
305             }
306             catch(Exception JavaDoc e){
307                 //System.out.println(e.getMessage());
308
// swallow
309
}
310         }
311         else{
312             try{
313                 Enumeration mls=listeners.elements();
314                 MessageListener ml;
315                 while(mls.hasMoreElements()){
316                     ml=(MessageListener)mls.nextElement();
317                     WhisperIM.MainWindow.Conn.removePacketListener(ml);
318                 }
319                 Enumeration e=occupantsChats.elements();
320                 Chat c;
321                 Channel channel=new Channel(new whisper.Message(myNickname+":"+Channel.LEAVING,encryptChannelKey,WhisperIM.KEYPAIR,WhisperIM.SR));
322                 while(e.hasMoreElements()){
323                     c=(Chat) e.nextElement();
324                     if(WhisperIM.MainWindow.Conn.isConnected()){
325                         c.sendMessage(channel.getText());
326                     }
327                 }
328             }
329             catch(Exception JavaDoc e2){
330                 //System.out.println(e2.getMessage());
331
// swallow
332
}
333         }
334         if(decryptChannelKey!=null){
335             decryptChannelKey.wipe();
336             decryptChannelKey=null;
337         }
338         text.setText("");
339         chatTextPane.setText("<html></html>");
340         ChatText="";
341         ChatText=null;
342         WhisperIM.MainWindow.secureChannelPanel=null;
343         WhisperIM.MainWindow.chatPane.remove(thisPanel);
344     }
345     
346     // wmp interface
347
public void goneOffline(){
348         threads.interrupt();
349         announce(" * "+Lang.gs("disconnected")+" *");
350         sendBtn.setEnabled(false);
351         text.setEnabled(false);
352     }
353     
354     public void goneOnline(){
355         // do nothing
356
}
357     
358     public void doFocus(){
359         sendBtn.requestFocusInWindow();
360     }
361     
362     public JButton getDefaultButton(){
363         if(sendBtn.isEnabled()){
364             return sendBtn;
365         }
366         return closeBtn;
367     }
368     
369     // inner classes
370

371     final class BtnClick implements ActionListener{
372         public void actionPerformed(ActionEvent ae){
373             //get button
374
String JavaDoc b=ae.getActionCommand();
375             // call method depending on button clicked
376
if(b.equals(closeBtn.getText())){
377                 doClose();
378                 return;
379             }
380             if(b.equals(sendBtn.getText())){
381                 if(text.getText().equals("")){
382                     text.requestFocus();
383                     return;
384                 }
385                 doSend();
386                 return;
387             }
388         }
389     }
390     
391     final class MessageListener implements PacketListener{
392         public void processPacket(Packet packet){
393             final org.jivesoftware.smack.packet.Message m;
394             //System.out.println("packet recieved by message listener");
395
try{
396                 m=(org.jivesoftware.smack.packet.Message) packet;
397             }
398             catch(ClassCastException JavaDoc cce){
399                 //System.out.println("class cast exception in message listener");
400
cce.printStackTrace();
401                 return;
402             }
403             String JavaDoc from=StringUtils.parseBareAddress(m.getFrom());
404             if(!amProviding){
405                 if(!from.equals(providerJID)){
406                     return;//ignore
407
}
408             }
409             Channel c;
410             try{
411                 c=new Channel(m.getBody());
412             }
413             catch(WhisperException we){
414                 //System.out.println("not a channel message - messageListener");
415
return; //ignore bad channel objects
416
}
417             if(!amProviding){
418                 (new ProcessMessageThread(c)).start();
419                 return;
420             }
421             if(c.getChannelMsgType()==Channel.JOIN_REQUEST){
422                 (new JoinRequestThread(c,StringUtils.parseBareAddress(m.getFrom()),m.getThread())).start();
423                 return;
424             }
425             if(c.getChannelMsgType()==Channel.MESSAGE){
426                 String JavaDoc nick=(String JavaDoc) jid2nick.get(from);
427                 if(nick==null){return;} // shouldn't happen
428
(new RelayMessageThread(c.getMessage(),nick,from)).start();
429                 return;
430             }
431             //System.out.println("weird message");
432
//System.out.println(c.getChannelMsgType());
433
//System.out.println(c.getText());
434
}
435         
436         /** Called by incoming chat listener.
437         * Onlu used when this user is providing and its a JOIN_REQUEST.*/

438         public void incoming(org.jivesoftware.smack.packet.Message m){
439             if(!amProviding){
440                 return;
441             }
442             Channel c;
443             try{
444                 c=new Channel(m.getBody());
445             }
446             catch(WhisperException we){
447                 //System.out.println("not a channel message - messageListener");
448
return; //ignore bad channel objects
449
}
450             if(c.getChannelMsgType()==Channel.JOIN_REQUEST){
451                 (new JoinRequestThread(c,StringUtils.parseBareAddress(m.getFrom()),m.getThread())).start();
452             }
453         }
454     }
455     
456     final class EnterAction extends AbstractAction{
457         public void actionPerformed(ActionEvent e) {
458             if(text.getText().equals("")){
459                     text.requestFocus();
460                     return;
461             }
462             doSend();
463         }
464     }
465     // thread classes
466
final class JoinChannelThread extends Thread JavaDoc{
467         public JoinChannelThread(){
468             super(threads,"Join Channel Thread");
469             setDaemon(true);
470             setPriority(Thread.MIN_PRIORITY);
471         }
472         public void run(){
473             try{
474                 //get public key
475
PublicKey pk=(PublicKey)WhisperIM.MainWindow.Keys.get("jabber"+providerJID);
476                 if(isInterrupted()){return;}
477                 if(pk==null){
478                     try{
479                         pk=WhisperIM.MainWindow.getKey("jabber",providerJID);
480                     }
481                     catch(Exception JavaDoc e1){
482                         announceFromThread(Lang.gs("could not open channel")+Lang.gs("no public key")+e1.getMessage());
483                         return;
484                     }
485                 }
486                 if(pk==null){
487                     announceFromThread(Lang.gs("could not open channel")+Lang.gs("no public key"));
488                     return;
489                 }
490                 if(isInterrupted()){return;}
491                 channelPublicKey=pk;
492                 org.jivesoftware.smack.packet.Message m=chat.createMessage();
493                 m.setTo(providerJID);
494                 Channel c=new Channel(myNickname,channelPublicKey,myKey,WhisperIM.KEYPAIR,WhisperIM.SR);
495                 myKey.wipe();
496                 myKey=null;
497                 m.setBody(c.getText());
498                 if(isInterrupted()){return;}
499                 try{
500                     chat.sendMessage(m);
501                 }
502                 catch(XMPPException xe){
503                     announceFromThread(Lang.gs("could not open channel")+xe.getMessage());
504                     return;
505                 }
506                 //System.out.println("request sent");
507
}
508             catch(Exception JavaDoc e){
509                 e.printStackTrace();
510             }
511         }
512     }
513     
514     final class ProcessMessageThread extends Thread JavaDoc{
515         private final Channel c;
516         
517         public ProcessMessageThread(Channel c){
518             super(threads,"Process Message Thread");
519             this.c=c;
520             setDaemon(true);
521             setPriority(Thread.MIN_PRIORITY);
522         }
523         public void run(){
524             try{
525                 //System.out.println("processing message:"+c.getChannelMsgType());
526
whisper.Message m=c.getMessage();
527                 // verify
528
if(m!=null && (!m.isValid(channelPublicKey))){
529                     announceFromThread(Lang.gs("bad message received")+". "+Lang.gs("invalid signature"));
530                     return;
531                 }
532                 if(c.getChannelMsgType()==Channel.JOINED){
533                     //System.out.println("join recieved");
534
if(hasJoined){
535                         return; //ignore if already joined
536
}
537                     announceFromThread(Lang.gs("joining response"));
538                     if(isInterrupted()){return;}
539                     //synchronized(decryptChannelKey){
540
try{
541                             decryptChannelKey=m.getESK().decrypt(WhisperIM.KEYPAIR);
542                             encryptChannelKey=Channel.createPair(decryptChannelKey,WhisperIM.SR);
543                         }
544                         catch(Exception JavaDoc e1){
545                         
546                             announceFromThread(Lang.gs("could not open channel")+e1.getMessage());
547                             return;
548                         }
549                     //}
550
hasJoined=true;
551                     String JavaDoc occlist;
552                     if(isInterrupted()){return;}
553                     try{
554                         occlist=m.decrypt(decryptChannelKey);
555                     }
556                     catch(Exception JavaDoc e2){
557                         m.wipe();
558                         m=null;
559                         announceFromThread(Lang.gs("could not open channel")+e2.getMessage());
560                         return;
561                     }
562                     m.wipe();
563                     m=null;
564                     String JavaDoc occs[]=occlist.split(",");
565                     if(occs==null || occs.length<2){
566                         announceFromThread(Lang.gs("could not open channel"));
567                         return;
568                     }
569                     myNickname=occs[0];
570                     occupants.clear();
571                     for(int i=0;i<occs.length;i++){
572                         if(!occupants.contains(occs[i])){
573                             occupants.add(occs[i]);
574                         }
575                     }
576                     updateListFromThread();
577                     if(isInterrupted()){return;}
578                     announceFromThread(Lang.gs("joined as")+myNickname);
579                     SwingUtilities.invokeLater(new Runnable JavaDoc(){
580                         public void run(){
581                             sendBtn.setEnabled(true);
582                             text.setEnabled(true);
583                             text.requestFocusInWindow();
584                         }
585                     });
586                     //System.out.println("joined channel");
587
return;
588                 }//end joined message
589
if(c.getChannelMsgType()==Channel.NEW_SESSION_KEY){
590                     //System.out.println("Recieved new session key");
591
synchronized(decryptChannelKey){
592                         try{
593                             SessionKey newChannelKey=c.getNewSessionKey(decryptChannelKey);
594                             decryptChannelKey.wipe();
595                             synchronized(encryptChannelKey){
596                                 encryptChannelKey.wipe();
597                                 encryptChannelKey=Channel.createPair(newChannelKey,WhisperIM.SR);
598                             }
599                             decryptChannelKey=newChannelKey;
600                         }
601                         catch(Exception JavaDoc e4){
602                             //decryptChannelKey.notify();
603
//e4.printStackTrace();
604
announceFromThread("New Session Key: "+Lang.gs("bad message received")+". "+Lang.gs("could not decrypt")+e4.getMessage());
605                             return;
606                         }
607                         
608                     }
609                     
610                     //System.out.println("Processed new session key");
611
return;
612                 }
613                 if(c.getChannelMsgType()!=Channel.MESSAGE){return;}
614                 if(isInterrupted()){return;}
615                 if(decryptChannelKey==null){
616                     //System.out.println("null session key");
617
return;
618                 }
619                 String JavaDoc plaintext;
620                 synchronized(decryptChannelKey){
621                     try{
622                         plaintext=m.decrypt(decryptChannelKey);
623                     }
624                     catch(Exception JavaDoc e5){
625                         announceFromThread(Lang.gs("bad message received")+". "+Lang.gs("could not decrypt")+". "+e5.getMessage());
626                         decryptChannelKey.notify();
627                         //e5.printStackTrace();
628
return;
629                     }
630                     decryptChannelKey.notify();
631                 }
632                 final String JavaDoc time=GUI.getTime(m);
633                 m.wipe();
634                 m=null;
635                 final String JavaDoc parts[]=plaintext.split(":",2);
636                 plaintext=null;
637                 if(parts.length!=2){
638                     announceFromThread(Lang.gs("bad message received"));
639                     System.err.println("message format not name:message ");
640                     return;
641                 }
642                 if(isInterrupted()){return;}
643                 // do a little translation
644
if(parts[1].equals(Channel.ENTERED)){
645                     if(!occupants.contains(parts[0])){
646                         occupants.add(parts[0]);
647                         updateListFromThread();
648                     }
649                     announceFromThread(parts[0]+" "+Lang.gs("has entered room"));
650                     parts[0]=null;
651                     parts[1]=null;
652                     return;
653                 }
654                 if(parts[1].equals(Channel.LEAVING)){
655                     occupants.remove(parts[0]);
656                     updateListFromThread();
657                     announceFromThread(parts[0]+" "+Lang.gs("has left room"));
658                     parts[0]=null;
659                     parts[1]=null;
660                     return;
661                 }
662                 final String JavaDoc colour;
663                 if(parts[0].toLowerCase().equals(myNickname)){
664                     colour=MUCPanel.myColour;
665                 }
666                 else{
667                     colour=MUCPanel.theirColours[0];
668                 }
669                 SwingUtilities.invokeLater(new Runnable JavaDoc(){
670                     public void run(){
671                         print("<font color='"+colour+"'>"+time+" "+parts[0]+"</font>"+" "+parts[1]);
672                     }
673                 });
674             }
675             catch(Exception JavaDoc e){
676                 e.printStackTrace();
677             }
678         }
679     }
680     
681     final class JoinRequestThread extends Thread JavaDoc{
682         private final Channel c;
683         private final String JavaDoc fromJID;
684         private final String JavaDoc threadID;
685         public JoinRequestThread(Channel c,String JavaDoc fromJID,String JavaDoc threadID){
686             super(threads,"Join Request Thread");
687             this.c=c;
688             this.fromJID=fromJID;
689             this.threadID=threadID;
690             setDaemon(true);
691             setPriority(Thread.MIN_PRIORITY);
692         }
693         public void run(){
694             try{
695                 //System.out.println("join request recieved");
696
//get public key
697
PublicKey pk=(PublicKey)WhisperIM.MainWindow.Keys.get("jabber"+fromJID);
698                 if(isInterrupted()){return;}
699                 if(pk==null){
700                     try{
701                         pk=WhisperIM.MainWindow.getKey("jabber",fromJID);
702                     }
703                     catch(Exception JavaDoc e1){
704                         announceFromThread(fromJID+" "+Lang.gs("attempted to join")+". "+Lang.gs("no public key")+e1.getMessage());
705                         return;
706                     }
707                 }
708                 if(pk==null){
709                     announceFromThread(fromJID+" "+Lang.gs("attempted to join")+". "+Lang.gs("no public key"));
710                     return;
711                 }
712                 if(isInterrupted()){return;}
713                 final String JavaDoc requestedNick;
714                 SessionKey tmpKey;
715                 final whisper.Message m=c.getMessage();
716                 if(!m.isValid(pk)){
717                     announceFromThread(fromJID+" "+Lang.gs("attempted to join")+" ."+Lang.gs("invalid signature"));
718                     return;
719                 }
720                 if(isInterrupted()){return;}
721                 if(m.getESK()==null){
722                     announceFromThread(fromJID+" "+Lang.gs("attempted to join")+" ."+Lang.gs("could not decrypt"));
723                     return;
724                 }
725                 if(isInterrupted()){return;}
726                 try{
727                     tmpKey=m.getESK().decrypt(WhisperIM.KEYPAIR);
728                 }
729                 catch(Exception JavaDoc e2){
730                     announceFromThread(fromJID+" "+Lang.gs("attempted to join")+". "+Lang.gs("could not decrypt")+" ."+e2.getMessage());
731                     return;
732                 }
733                 if(isInterrupted()){return;}
734                 try{
735                     requestedNick=m.decrypt(tmpKey);
736                 }
737                 catch(Exception JavaDoc e3){
738                     announceFromThread(fromJID+" "+Lang.gs("attempted to join")+". "+Lang.gs("could not decrypt")+" ."+e3.getMessage());
739                     return;
740                 }
741                 tmpKey.wipe();
742                 tmpKey=null;
743                 SwingUtilities.invokeLater(new Runnable JavaDoc(){
744                     public void run(){
745                         allow(fromJID,requestedNick,threadID,GUI.getTime(m));
746                     }
747                 });
748                 m.wipe();
749             }
750             catch(Exception JavaDoc e){
751                 e.printStackTrace();
752             }
753         }
754     }
755     
756     final class BroadCastThread extends Thread JavaDoc{
757         private final whisper.Message m;
758
759         public BroadCastThread(whisper.Message m){
760             super(threads,"BroadCast Thread");
761             this.m=m;
762             setDaemon(true);
763             setPriority(Thread.MIN_PRIORITY);
764         }
765         
766         public void run(){
767             Enumeration e=occupantsChats.elements();
768             Chat c;
769             while(e.hasMoreElements()){
770                 if(isInterrupted()){return;}
771                 c=(Chat) e.nextElement();
772                 try{
773                     c.sendMessage((new Channel(m)).getText());
774                 }
775                 catch(Exception JavaDoc e1){
776                     announceFromThread(Lang.gs("message failed")+" "+e1.getMessage());
777                 }
778             }
779         }
780     }
781     
782     final class SendMessageThread extends Thread JavaDoc{
783         private final String JavaDoc text;
784             
785         public SendMessageThread(String JavaDoc text){
786             super(threads,"Send Message Thread");
787             this.text=text;
788             setDaemon(true);
789             setPriority(Thread.MIN_PRIORITY);
790         }
791         
792         public void run(){
793             try{
794                 if(amProviding){
795                     sk_use++;
796                 }
797                 whisper.Message m;
798                 synchronized(encryptChannelKey){
799                     m=new whisper.Message(text,encryptChannelKey,WhisperIM.KEYPAIR,WhisperIM.SR);
800                     encryptChannelKey.notify();
801                 }
802                 if(isInterrupted()){return;}
803                 if(amProviding){
804                     (new BroadCastThread(m)).start();
805                     final String JavaDoc parts[]=text.split(":",2);
806                     if(parts.length!=2){
807                         announceFromThread(text);
808                         return;
809                     }
810                     final String JavaDoc colour;
811                     if(parts[0].equals(myNickname)){
812                         colour=MUCPanel.myColour;
813                     }
814                     else{
815                         colour=MUCPanel.theirColours[0];
816                     }
817                     if(parts[1].equals(Channel.ENTERED)){
818                         announceFromThread(parts[0]+" "+Lang.gs("has entered room"));
819                         parts[0]=null;
820                         parts[1]=null;
821                         return;
822                     }
823                     if(parts[1].equals(Channel.LEAVING)){
824                         announceFromThread(parts[0]+" "+Lang.gs("has left room"));
825                         parts[0]=null;
826                         parts[1]=null;
827                         return;
828                     }
829                     SwingUtilities.invokeLater(new Runnable JavaDoc(){
830                         public void run(){
831                             print("<font color='"+colour+"'>"+GUI.getTime()+" "+parts[0]+"</font>"+" "+parts[1]);
832                         }
833                     });
834                     parts[0]=null;
835                     parts[1]=null;
836                     return;
837                 }
838                 else{
839                     chat.sendMessage( (new Channel(m)).getText());
840                     if(text.equals(Channel.LEAVING)){
841                         chat=null;
842                         if(encryptChannelKey!=null){
843                             encryptChannelKey.wipe();
844                             encryptChannelKey=null;
845                         }
846                     }
847                 }
848             }
849             catch(Exception JavaDoc e){
850                 announceFromThread(Lang.gs("message failed")+" "+e.getMessage());
851             }
852         }
853     }
854
855     
856     final class RelayMessageThread extends Thread JavaDoc{
857         private final whisper.Message m;
858         private final String JavaDoc nick;
859         private final String JavaDoc JID;
860
861         public RelayMessageThread(whisper.Message m, String JavaDoc nick, String JavaDoc JID){
862             super(threads,"Relay Message Thread");
863             this.m=m;
864             this.nick=nick;
865             this.JID=JID;
866             setDaemon(true);
867             setPriority(Thread.MIN_PRIORITY);
868         }
869         
870         public void run(){
871             try{
872                 //verify sig first
873
PublicKey pk=(PublicKey)WhisperIM.MainWindow.Keys.get("jabber"+JID);
874                 if(isInterrupted()){return;}
875                 if(pk==null){//shouldn't happen
876
announceFromThread(Lang.gs("error")+" "+Lang.gs("no public key"));
877                     return;
878                 }
879                 if(!m.isValid(pk)){
880                     announceFromThread(Lang.gs("message failed")+" "+Lang.gs("invalid signature"));
881                     return;
882                 }
883                 if(isInterrupted()){return;}
884                 String JavaDoc plaintext;
885                 synchronized(decryptChannelKey){
886                     try{
887                         plaintext=m.decrypt(decryptChannelKey);
888                     }
889                     catch(Exception JavaDoc e1){
890                         decryptChannelKey.notify();
891                         announceFromThread(Lang.gs("message failed")+" "+Lang.gs("could not decrypt")+" "+e1.getMessage());
892                         return;
893                     }
894                     decryptChannelKey.notify();
895                 }
896                 if(isInterrupted()){return;}
897                 String JavaDoc transmitplaintext=nick+":"+plaintext;
898                 
899                 if(amProviding){
900                     sk_use++;
901                     if(sk_use>=SK_USE_LIMIT){
902                         sk_use=1;
903                         // send new ESK first
904
(new SendNewSessionKeyThread()).run(); //i'm calling run() deliberately
905
}
906                 }
907                 synchronized(encryptChannelKey){
908                     whisper.Message mout=new whisper.Message(transmitplaintext,encryptChannelKey,WhisperIM.KEYPAIR,WhisperIM.SR);
909                     transmitplaintext=null;
910                     if(isInterrupted()){return;}
911                     (new BroadCastThread(mout)).start();
912                     encryptChannelKey.notify();
913                 }
914                 if(plaintext.equals(Channel.LEAVING)){
915                     occupants.remove(nick);
916                     WhisperIM.MainWindow.Conn.removePacketListener((MessageListener)listeners.get(JID) );
917                     jid2nick.remove(JID);
918                     occupantsChats.remove(JID);
919                     updateListFromThread();
920                     announceFromThread(nick+" "+Lang.gs("has left room"));
921                     plaintext=null;
922                     return;
923                 }
924                 final String JavaDoc finalplaintext=plaintext;
925                 SwingUtilities.invokeLater(new Runnable JavaDoc(){
926                     public void run(){
927                         print("<font color='"+MUCPanel.theirColours[0]+"'>"+GUI.getTime(m)+" "+nick+" </font>"+" "+finalplaintext);
928                     }
929                 });
930                 m.wipe();
931                 plaintext=null;
932             }
933             catch(Exception JavaDoc e){
934                 announceFromThread(Lang.gs("error")+" "+e.getMessage());
935             }
936         }
937     }
938     
939     final class SendJoinedThread extends Thread JavaDoc{
940         private final String JavaDoc nick;
941         private final Chat chat;
942             
943         public SendJoinedThread(Chat chat,String JavaDoc nick){
944             super(threads,"Send Joined Thread");
945             this.nick=nick;
946             this.chat=chat;
947             setDaemon(true);
948             setPriority(Thread.MIN_PRIORITY);
949         }
950         
951         public void run(){
952             try{
953                 String JavaDoc list=nick;
954                 String JavaDoc item;
955                 for(int i=0;i<occupants.size();i++){
956                     item=(String JavaDoc) occupants.elementAt(i);
957                     if(item.equals(nick)){
958                         // don't add
959
}
960                     else{
961                         list=list+","+item;
962                     }
963                 }
964                 PublicKey pk=(PublicKey)WhisperIM.MainWindow.Keys.get("jabber"+chat.getParticipant());
965                 if(isInterrupted()){return;}
966                 if(pk==null){//shouldn't happen
967
announceFromThread(Lang.gs("error")+" "+Lang.gs("no public key"));
968                     return;
969                 }
970                 Channel c;
971                 synchronized(encryptChannelKey){
972                     c=new Channel(WhisperIM.KEYPAIR,list,pk,encryptChannelKey,WhisperIM.SR);
973                     encryptChannelKey.notify();
974                 }
975                 if(isInterrupted()){return;}
976                 chat.sendMessage(c.getText());
977             }
978             catch(Exception JavaDoc e){
979                 announceFromThread(Lang.gs("error")+" "+e.getMessage());
980             }
981         }
982     }
983     
984     /** Sends a new session key.
985     * Only used if amProviding.*/

986     final class SendNewSessionKeyThread extends Thread JavaDoc{
987             
988         public SendNewSessionKeyThread(){
989             super(threads,"Send New SessionKey Thread");
990             setDaemon(true);
991             setPriority(Thread.MIN_PRIORITY);
992         }
993         
994         public void run(){
995             //System.out.println("Sending new session key");
996
try{
997                 synchronized(encryptChannelKey){
998                     SessionKey newChannelKey=new SessionKey(WhisperIM.SR);
999                     Enumeration e=occupantsChats.elements();
1000                    Chat c;
1001                    Channel channel;
1002                    try{
1003                        channel=new Channel(encryptChannelKey,newChannelKey,WhisperIM.SR);
1004                    }
1005                    catch(whisper.CryptoException ce){
1006                        announceFromThread("new session key:"+Lang.gs("message failed")+" "+ce.getMessage());
1007                        return;
1008                    }
1009                    while(e.hasMoreElements()){
1010                        if(isInterrupted()){return;}
1011                        c=(Chat) e.nextElement();
1012                        try{
1013                            c.sendMessage(channel.getText());
1014                        }
1015                        catch(Exception JavaDoc e1){
1016                            announceFromThread("new session key:"+Lang.gs("message failed")+" "+e1.getMessage());
1017                        }
1018                    }
1019                    encryptChannelKey.wipe();
1020                    encryptChannelKey=newChannelKey;
1021                    newChannelKey=null;
1022                    synchronized(decryptChannelKey){
1023                        decryptChannelKey.wipe();
1024                        decryptChannelKey=Channel.createPair(encryptChannelKey,WhisperIM.SR);
1025                        //decryptChannelKey.notify();
1026
}
1027                    //encryptChannelKey.notify();
1028
}
1029            }//end try
1030
catch (Exception JavaDoc e){
1031                e.printStackTrace();
1032            }
1033        //System.out.println("Finished sending new session key");
1034
}
1035    }
1036}
1037        
Popular Tags