/* * Created on Apr 2, 2008 * Created by Paul Gardner * * Copyright 2008 Vuze, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.aelitis.azureus.plugins.net.buddy.swt; import java.net.InetAddress; import java.text.SimpleDateFormat; import java.util.*; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginConfig; import org.gudy.azureus2.plugins.ui.UIInputReceiver; import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; import org.gudy.azureus2.plugins.ui.UIInstance; import org.gudy.azureus2.plugins.utils.LocaleUtilities; import org.gudy.azureus2.ui.swt.Messages; import org.gudy.azureus2.ui.swt.mainwindow.Colors; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import com.aelitis.azureus.core.security.*; import com.aelitis.azureus.core.util.AZ3Functions; import com.aelitis.azureus.plugins.net.buddy.*; public class BuddyPluginViewInstance implements BuddyPluginListener, BuddyPluginBuddyRequestListener { private static final int LOG_NORMAL = 1; private static final int LOG_SUCCESS = 2; private static final int LOG_ERROR = 3; private BuddyPlugin plugin; private UIInstance ui_instance; private Composite composite; private Table buddy_table; private StyledText log; private List buddies = new ArrayList(); private boolean init_complete; protected BuddyPluginViewInstance( BuddyPlugin _plugin, UIInstance _ui_instance, Composite _composite ) { plugin = _plugin; ui_instance = _ui_instance; composite = _composite; final LocaleUtilities lu = plugin.getPluginInterface().getUtilities().getLocaleUtilities(); Composite main = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; main.setLayout(layout); GridData grid_data = new GridData(GridData.FILL_BOTH ); main.setLayoutData(grid_data); if ( !plugin.isEnabled()){ Label control_label = new Label( main, SWT.NULL ); control_label.setText( lu.getLocalisedMessageText( "azbuddy.disabled" )); return; } // control area final Composite controls = new Composite(main, SWT.NONE); layout = new GridLayout(); layout.numColumns = 6; layout.marginHeight = 0; layout.marginWidth = 0; controls.setLayout(layout); grid_data = new GridData(GridData.FILL_HORIZONTAL ); controls.setLayoutData(grid_data); Label control_label = new Label( controls, SWT.NULL ); control_label.setText( lu.getLocalisedMessageText( "azbuddy.ui.new_buddy" ) + " " ); final Text control_text = new Text( controls, SWT.BORDER ); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); control_text.setLayoutData(gridData); final Button control_button = new Button( controls, SWT.NULL ); control_button.setText( lu.getLocalisedMessageText( "azbuddy.ui.add" )); control_button.setEnabled( false ); control_text.addModifyListener( new ModifyListener() { public void modifyText( ModifyEvent e ) { control_button.setEnabled( plugin.verifyPublicKey( control_text.getText().trim())); } }); control_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { plugin.addBuddy( control_text.getText().trim(), BuddyPlugin.SUBSYSTEM_AZ2 ); control_text.setText( "" ); } }); final Label control_lab_pk = new Label( controls, SWT.NULL ); control_lab_pk.setText( lu.getLocalisedMessageText( "azbuddy.ui.mykey" ) + " "); final Text control_val_pk = new Text( controls, SWT.NULL ); gridData = new GridData(); gridData.widthHint = 400; control_val_pk.setLayoutData(gridData); control_val_pk.setEditable( false ); control_val_pk.setBackground( control_lab_pk.getBackground()); control_val_pk.addKeyListener( new KeyListener() { public void keyPressed( KeyEvent event) { int key = event.character; if (key <= 26 && key > 0){ key += 'a' - 1; } if ( event.stateMask == SWT.MOD1 && key == 'a' ){ control_val_pk.setSelection( 0, control_val_pk.getText().length()); } } public void keyReleased( KeyEvent event) { } }); final CryptoManager crypt_man = CryptoManagerFactory.getSingleton(); byte[] public_key = crypt_man.getECCHandler().peekPublicKey(); if ( public_key == null ){ Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef"); }else{ control_val_pk.setText( Base32.encode( public_key )); } Messages.setLanguageText(control_val_pk, "ConfigView.copy.to.clipboard.tooltip", true); control_val_pk.setCursor(main.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); control_val_pk.setForeground(Colors.blue); control_val_pk.addMouseListener(new MouseAdapter() { public void mouseDoubleClick(MouseEvent arg0) { copyToClipboard(); } public void mouseDown(MouseEvent arg0) { copyToClipboard(); } protected void copyToClipboard() { new Clipboard(control_val_pk.getDisplay()).setContents(new Object[] {control_val_pk.getText()}, new Transfer[] {TextTransfer.getInstance()}); } }); crypt_man.addKeyListener( new CryptoManagerKeyListener() { public void keyChanged( final CryptoHandler handler ) { if ( control_val_pk.isDisposed()){ crypt_man.removeKeyListener( this ); }else if ( handler.getType() == CryptoManager.HANDLER_ECC ){ control_val_pk.getDisplay().asyncExec( new Runnable() { public void run() { byte[] public_key = handler.peekPublicKey(); if ( public_key == null ){ Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef"); }else{ control_val_pk.setText( Base32.encode( public_key )); } controls.layout(); } }); } } public void keyLockStatusChanged( CryptoHandler handler ) { } }); final Button config_button = new Button( controls, SWT.NULL ); config_button.setText( lu.getLocalisedMessageText( "plugins.basicview.config" )); config_button.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { plugin.showConfig(); } }); // table and log final Composite form = new Composite(main, SWT.NONE); FormLayout flayout = new FormLayout(); flayout.marginHeight = 0; flayout.marginWidth = 0; form.setLayout(flayout); gridData = new GridData(GridData.FILL_BOTH); form.setLayoutData(gridData); final Composite child1 = new Composite(form,SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; child1.setLayout(layout); final Sash sash = new Sash(form, SWT.HORIZONTAL); final Composite child2 = new Composite(form,SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; child2.setLayout(layout); FormData formData; // child1 formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.top = new FormAttachment(0, 0); child1.setLayoutData(formData); final FormData child1Data = formData; final int SASH_WIDTH = 4; // sash formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.top = new FormAttachment(child1); formData.height = SASH_WIDTH; sash.setLayoutData(formData); // child2 formData = new FormData(); formData.left = new FormAttachment(0, 0); formData.right = new FormAttachment(100, 0); formData.bottom = new FormAttachment(100, 0); formData.top = new FormAttachment(sash); child2.setLayoutData(formData); final PluginConfig pc = plugin.getPluginInterface().getPluginconfig(); sash.setData( "PCT", new Float( pc.getPluginFloatParameter( "swt.sash.position", 0.7f ))); sash.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { if (e.detail == SWT.DRAG){ return; } child1Data.height = e.y + e.height - SASH_WIDTH; form.layout(); Float l = new Float((double)child1.getBounds().height / form.getBounds().height); sash.setData( "PCT", l ); pc.setPluginParameter( "swt.sash.position", l.floatValue()); } }); form.addListener( SWT.Resize, new Listener() { public void handleEvent(Event e) { Float l = (Float) sash.getData( "PCT" ); if ( l != null ){ child1Data.height = (int) (form.getBounds().height * l.doubleValue()); form.layout(); } } }); // table buddy_table = new Table(child1, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL); final String[] headers = { "azbuddy.ui.table.name", "azbuddy.ui.table.online", "azbuddy.ui.table.lastseen", "azbuddy.ui.table.last_ygm", "azbuddy.ui.table.last_msg", "azbuddy.ui.table.loc_cat", "azbuddy.ui.table.rem_cat", "azbuddy.ui.table.read_cat", "azbuddy.ui.table.con", "azbuddy.ui.table.msg_in", "azbuddy.ui.table.msg_out", "azbuddy.ui.table.msg_queued", "MyTrackerView.bytesin", "MyTrackerView.bytesout", "azbuddy.ui.table.ss" }; int[] sizes = { 250, 100, 100, 100, 200, 100, 100, 100, 75, 75, 75, 75, 75, 75, 40 }; int[] aligns = { SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER }; for (int i = 0; i < headers.length; i++){ TableColumn tc = new TableColumn(buddy_table, aligns[i]); tc.setWidth(sizes[i]); Messages.setLanguageText(tc, headers[i]); } buddy_table.setHeaderVisible(true); TableColumn[] columns = buddy_table.getColumns(); columns[0].setData(new Integer(FilterComparator.FIELD_NAME)); columns[1].setData(new Integer(FilterComparator.FIELD_ONLINE)); columns[2].setData(new Integer(FilterComparator.FIELD_LAST_SEEN)); columns[3].setData(new Integer(FilterComparator.FIELD_YGM)); columns[4].setData(new Integer(FilterComparator.FIELD_LAST_MSG)); columns[5].setData(new Integer(FilterComparator.FIELD_LOC_CAT)); columns[6].setData(new Integer(FilterComparator.FIELD_REM_CAT)); columns[7].setData(new Integer(FilterComparator.FIELD_READ_CAT)); columns[8].setData(new Integer(FilterComparator.FIELD_CON)); columns[9].setData(new Integer(FilterComparator.FIELD_MSG_IN)); columns[10].setData(new Integer(FilterComparator.FIELD_MSG_OUT)); columns[11].setData(new Integer(FilterComparator.FIELD_QUEUED)); columns[12].setData(new Integer(FilterComparator.FIELD_BYTES_IN)); columns[13].setData(new Integer(FilterComparator.FIELD_BYTES_OUT)); columns[14].setData(new Integer(FilterComparator.FIELD_SS)); final FilterComparator comparator = new FilterComparator(); Listener sort_listener = new Listener() { public void handleEvent( Event e ) { TableColumn tc = (TableColumn) e.widget; int field = ((Integer) tc.getData()).intValue(); comparator.setField( field ); Collections.sort( buddies,comparator); updateTable(); } }; for (int i=0;i<columns.length;i++){ columns[i].addListener(SWT.Selection,sort_listener); } gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = buddy_table.getHeaderHeight() * 3; buddy_table.setLayoutData(gridData); buddy_table.addListener( SWT.SetData, new Listener() { public void handleEvent( Event event) { TableItem item = (TableItem)event.item; int index = buddy_table.indexOf(item); if ( index < 0 || index >= buddies.size()){ return; } BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(index); item.setText(0, buddy.getName()); int os; if ( buddy.isOnline( false )){ os = buddy.getOnlineStatus(); }else{ os = BuddyPlugin.STATUS_APPEAR_OFFLINE; } if ( os == BuddyPlugin.STATUS_APPEAR_OFFLINE ){ item.setText( 1, "" ); }else{ item.setText(1, plugin.getOnlineStatus( os )); } long lo = buddy.getLastTimeOnline(); item.setText(2, lo==0?"":new SimpleDateFormat().format(new Date( lo ))); long last_ygm = buddy.getLastMessagePending();; item.setText(3, last_ygm==0?"":new SimpleDateFormat().format(new Date( last_ygm ))); String lm = buddy.getLastMessageReceived(); item.setText(4, lm==null?"":lm); String loc_cat = buddy.getLocalAuthorisedRSSTagsOrCategoriesAsString(); if ( loc_cat == null ){ loc_cat = ""; } item.setText(5, "" + loc_cat); String rem_cat = buddy.getRemoteAuthorisedRSSTagsOrCategoriesAsString(); if ( rem_cat == null ){ rem_cat = ""; } item.setText(6, "" + rem_cat); String read_cat = buddy.getLocalReadTagsOrCategoriesAsString(); if ( read_cat == null ){ read_cat = ""; } item.setText(7, "" + read_cat); item.setText(8, "" + buddy.getConnectionsString()); String in_frag = buddy.getMessageInFragmentDetails(); item.setText(9, "" + buddy.getMessageInCount() + (in_frag.length()==0?"":("+" + in_frag ))); item.setText(10, "" + buddy.getMessageOutCount()); item.setText(11, "" + buddy.getMessageHandler().getMessageCount()); item.setText(12, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesInCount())); item.setText(13, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesOutCount())); item.setText(14, "" + buddy.getSubsystem() + " v" + buddy.getVersion()); item.setData( buddy ); } }); final Listener tt_label_listener = new Listener() { public void handleEvent(Event event) { Label label = (Label) event.widget; Shell shell = label.getShell(); switch (event.type) { case SWT.MouseDown: Event e = new Event(); e.item = (TableItem) label.getData("_TABLEITEM"); buddy_table.setSelection(new TableItem[] { (TableItem) e.item }); buddy_table.notifyListeners(SWT.Selection, e); // fall through case SWT.MouseExit: shell.dispose(); break; } } }; Listener tt_table_listener = new Listener() { private Shell tip = null; private Label label = null; public void handleEvent( Event event ) { switch (event.type){ case SWT.Dispose: case SWT.KeyDown: case SWT.MouseMove: { if (tip == null) break; tip.dispose(); tip = null; label = null; break; } case SWT.MouseHover: { Point mouse_position = new Point(event.x, event.y); TableItem item = buddy_table.getItem( mouse_position ); if (item != null) { if (tip != null && !tip.isDisposed()){ tip.dispose(); tip = null; } int index = buddy_table.indexOf(item); if ( index < 0 || index >= buddies.size()){ return; } BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(index); int item_index = 0; for (int i=0;i<headers.length;i++){ Rectangle bounds = item.getBounds(i); if ( bounds.contains( mouse_position )){ item_index = i; break; } } if( item_index != 0 ){ return; } tip = new Shell(buddy_table.getShell(), SWT.ON_TOP | SWT.TOOL); tip.setLayout(new FillLayout()); label = new Label(tip, SWT.NONE); label.setForeground(buddy_table.getDisplay() .getSystemColor(SWT.COLOR_INFO_FOREGROUND)); label.setBackground(buddy_table.getDisplay() .getSystemColor(SWT.COLOR_INFO_BACKGROUND)); label.setData("_TABLEITEM", item); label.setText( getToolTip( buddy )); label.addListener(SWT.MouseExit, tt_label_listener); label.addListener(SWT.MouseDown, tt_label_listener); Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT); Rectangle rect = item.getBounds(item_index); Point pt = buddy_table.toDisplay(rect.x, rect.y); tip.setBounds(pt.x, pt.y, size.x, size.y); tip.setVisible(true); } } } } protected String getToolTip( BuddyPluginBuddy buddy ) { List addresses = buddy.getAdjustedIPs(); InetAddress ip = buddy.getIP(); InetAddress adj = buddy.getAdjustedIP(); String str = ""; if ( ip == null ){ str = "<none>"; }else if ( ip == adj ){ str = ip.getHostAddress(); }else{ str = ip.getHostAddress() + "{"; for (int i=0;i<addresses.size();i++){ str += (i==0?"":"/") + ((InetAddress)addresses.get(i)).getHostAddress(); } str += "}"; } return( "ip=" + str + ",tcp=" + buddy.getTCPPort() + ",udp=" + buddy.getUDPPort()); } }; buddy_table.addListener(SWT.Dispose, tt_table_listener); buddy_table.addListener(SWT.KeyDown, tt_table_listener); buddy_table.addListener(SWT.MouseMove, tt_table_listener); buddy_table.addListener(SWT.MouseHover, tt_table_listener); final Menu menu = new Menu(buddy_table); final MenuItem remove_item = new MenuItem(menu, SWT.PUSH); remove_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.remove" )); remove_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e) { TableItem[] selection = buddy_table.getSelection(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); buddy.remove(); } }; }); // get public key final MenuItem get_pk_item = new MenuItem(menu, SWT.PUSH); get_pk_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.copypk" ) ); get_pk_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { TableItem[] selection = buddy_table.getSelection(); StringBuffer sb = new StringBuffer(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); sb.append( buddy.getPublicKey() + "\r\n" ); } if ( sb.length() > 0 ){ writeToClipboard( sb.toString()); } }; }); // disconnect message if ( Constants.isCVSVersion()){ final MenuItem send_msg_item = new MenuItem(menu, SWT.PUSH); send_msg_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.disconnect" ) ); send_msg_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { TableItem[] selection = buddy_table.getSelection(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); buddy.disconnect(); } } }); } // send message final MenuItem send_msg_item = new MenuItem(menu, SWT.PUSH); send_msg_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.send" ) ); send_msg_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { final TableItem[] selection = buddy_table.getSelection(); UIInputReceiver prompter = ui_instance.getInputReceiver(); prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.send" )); prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.send_msg" ) ); try{ prompter.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver prompter) { String text = prompter.getSubmittedInput(); if ( text != null ){ for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); plugin.getAZ2Handler().sendAZ2Message( buddy, text ); } } } }); }catch( Throwable e ){ } }; }); // chat final MenuItem chat_item = new MenuItem(menu, SWT.PUSH); chat_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.chat" ) ); chat_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { TableItem[] selection = buddy_table.getSelection(); BuddyPluginBuddy[] buddies = new BuddyPluginBuddy[selection.length]; for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); buddies[i] = buddy; } plugin.getAZ2Handler().createChat( buddies ); }; }); // ping final MenuItem ping_item = new MenuItem(menu, SWT.PUSH); ping_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.ping" ) ); ping_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { TableItem[] selection = buddy_table.getSelection(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); try{ buddy.ping(); }catch( Throwable e ){ print( "Ping failed", e ); } } }; }); // ygm final MenuItem ygm_item = new MenuItem(menu, SWT.PUSH); ygm_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.ygm" ) ); ygm_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { TableItem[] selection = buddy_table.getSelection(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); try{ buddy.setMessagePending(); }catch( Throwable e ){ print( "YGM failed", e ); } } }; }); // encrypt final MenuItem encrypt_item = new MenuItem(menu, SWT.PUSH); encrypt_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.enc" ) ); encrypt_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { TableItem[] selection = buddy_table.getSelection(); String str = readFromClipboard(); if( str != null ){ StringBuffer sb = new StringBuffer(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); try{ byte[] contents = str.getBytes( "UTF-8" ); BuddyPlugin.cryptoResult result = buddy.encrypt( contents ); sb.append( "key: " ); sb.append( plugin.getPublicKey()); sb.append( "\r\n" ); sb.append( "hash: " ); sb.append( Base32.encode( result.getChallenge())); sb.append( "\r\n" ); sb.append( "payload: " ); sb.append( Base32.encode( result.getPayload())); sb.append( "\r\n\r\n" ); }catch( Throwable e ){ print( "YGM failed", e ); } } writeToClipboard( sb.toString()); } }; }); // decrypt final MenuItem decrypt_item = new MenuItem(menu, SWT.PUSH); decrypt_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.dec" ) ); decrypt_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { String str = readFromClipboard(); if ( str != null ){ String[] bits = str.split( "\n" ); StringBuffer sb = new StringBuffer(); BuddyPluginBuddy buddy = null; byte[] hash = null; for (int i=0;i<bits.length;i++){ String bit = bits[i].trim(); if ( bit.length() > 0 ){ int pos = bit.indexOf( ':' ); if ( pos == -1 ){ continue; } String lhs = bit.substring( 0, pos ).trim(); String rhs = bit.substring( pos+1 ).trim(); if ( lhs.equals( "key" )){ buddy = plugin.getBuddyFromPublicKey( rhs ); }else if ( lhs.equals( "hash" )){ hash = Base32.decode( rhs ); }else if ( lhs.equals( "payload" )){ byte[] payload = Base32.decode( rhs ); if ( buddy != null ){ try{ BuddyPlugin.cryptoResult result = buddy.decrypt( payload ); byte[] sha1 = new SHA1Simple().calculateHash( result.getChallenge()); sb.append( "key: " ); sb.append( buddy.getPublicKey()); sb.append( "\r\n" ); sb.append( "hash_ok: " + Arrays.equals( hash, sha1 )); sb.append( "\r\n" ); sb.append( "payload: " ); sb.append( new String( result.getPayload(), "UTF-8" )); sb.append( "\r\n\r\n" ); }catch( Throwable e ){ print( "decrypt failed", e ); } } } } } if ( sb.length() > 0 ){ writeToClipboard( sb.toString()); } } }; }); // sign final MenuItem sign_item = new MenuItem(menu, SWT.PUSH); sign_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.sign" ) ); sign_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { String str = readFromClipboard(); if ( str != null ){ StringBuffer sb = new StringBuffer(); try{ sb.append( "key: " ); sb.append( plugin.getPublicKey()); sb.append( "\r\n" ); byte[] payload = str.getBytes( "UTF-8" ); sb.append( "data: " ); sb.append( Base32.encode( payload )); sb.append( "\r\n" ); byte[] sig = plugin.sign( payload ); sb.append( "sig: " ); sb.append( Base32.encode( sig )); sb.append( "\r\n" ); }catch( Throwable e ){ print( "sign failed", e ); } if ( sb.length() > 0 ){ writeToClipboard( sb.toString()); } } }; }); // verify final MenuItem verify_item = new MenuItem(menu, SWT.PUSH); verify_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.verify" ) ); verify_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { String str = readFromClipboard(); if ( str != null ){ String[] bits = str.split( "\n" ); StringBuffer sb = new StringBuffer(); String pk = null; byte[] data = null; for (int i=0;i<bits.length;i++){ String bit = bits[i].trim(); if ( bit.length() > 0 ){ int pos = bit.indexOf( ':' ); if ( pos == -1 ){ continue; } String lhs = bit.substring( 0, pos ).trim(); String rhs = bit.substring( pos+1 ).trim(); if ( lhs.equals( "key" )){ pk = rhs; }else if ( lhs.equals( "data" )){ data = Base32.decode( rhs ); }else if ( lhs.equals( "sig" )){ byte[] sig = Base32.decode( rhs ); if ( pk != null && data != null ){ try{ sb.append( "key: " ); sb.append( pk ); sb.append( "\r\n" ); boolean ok = plugin.verify( pk, data, sig ); sb.append( "sig_ok: " + ok ); sb.append( "\r\n" ); sb.append( "data: " ); sb.append( new String( data, "UTF-8" )); sb.append( "\r\n\r\n" ); }catch( Throwable e ){ print( "decrypt failed", e ); } } } } } if ( sb.length() > 0 ){ writeToClipboard( sb.toString()); } } }; }); // cats Menu cat_menu = new Menu(menu.getShell(), SWT.DROP_DOWN); MenuItem cat_item = new MenuItem(menu, SWT.CASCADE); Messages.setLanguageText(cat_item, "azbuddy.ui.menu.cat" ); cat_item.setMenu(cat_menu); // cats - share final MenuItem cat_share_item = new MenuItem(cat_menu, SWT.PUSH); cat_share_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.share" ) ); cat_share_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { UIInputReceiver prompter = ui_instance.getInputReceiver(); prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set" )); prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set_msg" )); prompter.prompt(new UIInputReceiverListener() { public void UIInputReceiverClosed(UIInputReceiver prompter) { String cats = prompter.getSubmittedInput(); if ( cats != null ){ cats = cats.trim(); if ( cats.equalsIgnoreCase( "None" )){ cats = ""; } TableItem[] selection = buddy_table.getSelection(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); buddy.setLocalAuthorisedRSSTagsOrCategories( cats ); } } } }); }; }); // cats - subscribe final Menu cat_subs_menu = new Menu(cat_menu.getShell(), SWT.DROP_DOWN); final MenuItem cat_subs_item = new MenuItem(cat_menu, SWT.CASCADE); Messages.setLanguageText(cat_subs_item, "azbuddy.ui.menu.cat_subs" ); cat_subs_item.setMenu(cat_subs_menu); cat_subs_menu.addMenuListener( new MenuListener() { public void menuShown( MenuEvent arg0 ) { MenuItem[] items = cat_subs_menu.getItems(); for (int i = 0; i < items.length; i++){ items[i].dispose(); } final AZ3Functions.provider az3 = AZ3Functions.getProvider(); if ( az3 != null ){ final TableItem[] selection = buddy_table.getSelection(); Set<String> avail_cats = new TreeSet<String>(); for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); Set<String> cats = buddy.getRemoteAuthorisedRSSTagsOrCategories(); if ( cats != null ){ avail_cats.addAll( cats ); } } for ( final String cat: avail_cats ){ final MenuItem subs_item = new MenuItem( cat_subs_menu, SWT.PUSH ); subs_item.setText( cat ); subs_item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent event ) { for (int i=0;i<selection.length;i++){ BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData(); if ( buddy.isRemoteRSSTagOrCategoryAuthorised( cat )){ try{ buddy.subscribeToCategory( cat ); }catch( Throwable e ){ print( "Failed", e ); } } } } }); } } } public void menuHidden( MenuEvent arg0 ) { } }); // done with menus buddy_table.setMenu( menu ); menu.addMenuListener( new MenuListener() { public void menuShown( MenuEvent arg0 ) { boolean available = plugin.isAvailable(); TableItem[] selection = buddy_table.getSelection(); remove_item.setEnabled( selection.length > 0 ); get_pk_item.setEnabled( available && selection.length > 0 ); send_msg_item.setEnabled(available && selection.length > 0); chat_item.setEnabled(available && selection.length > 0); ping_item.setEnabled(available && selection.length > 0); ygm_item.setEnabled(available && selection.length > 0); encrypt_item.setEnabled(selection.length > 0); decrypt_item.setEnabled(true); sign_item.setEnabled(true); verify_item.setEnabled(true); } public void menuHidden( MenuEvent arg0 ) { } }); // log area log = new StyledText(child2,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); grid_data = new GridData(GridData.FILL_BOTH); grid_data.horizontalSpan = 1; grid_data.horizontalIndent = 4; log.setLayoutData(grid_data); log.setIndent( 4 ); buddies = plugin.getBuddies(); for (int i=0;i<buddies.size();i++){ buddyAdded((BuddyPluginBuddy)buddies.get(i)); } Collections.sort( buddies, comparator ); plugin.addListener( this ); plugin.addRequestListener( this ); init_complete = true; updateTable(); } protected String readFromClipboard() { Object o = new Clipboard(SWTThread.getInstance().getDisplay()).getContents( TextTransfer.getInstance()); if ( o instanceof String ){ return((String)o); } return( null ); } protected void writeToClipboard( String str ) { new Clipboard(SWTThread.getInstance().getDisplay()).setContents( new Object[] {str }, new Transfer[] {TextTransfer.getInstance()}); } protected void updateTable() { if ( init_complete ){ buddy_table.setItemCount( buddies.size()); buddy_table.clearAll(); buddy_table.redraw(); } } public void initialised( boolean available ) { print( "Initialisation complete: available=" + available ); } public void buddyAdded( final BuddyPluginBuddy buddy ) { if ( buddy_table.isDisposed()){ return; } buddy.getMessageHandler().addListener( new BuddyPluginBuddyMessageListener() { public void messageQueued( BuddyPluginBuddyMessage message ) { print( message.getBuddy().getName() + ": message queued, id=" + message.getID()); update(); } public void messageDeleted( BuddyPluginBuddyMessage message ) { print( message.getBuddy().getName() + ": message deleted, id=" + message.getID()); update(); } public boolean deliverySucceeded( BuddyPluginBuddyMessage message, Map reply ) { print( message.getBuddy().getName() + ": message delivered, id=" + message.getID() + ", reply=" + reply ); update(); return( true ); } public void deliveryFailed( BuddyPluginBuddyMessage message, BuddyPluginException cause ) { print( message.getBuddy().getName() + ": message failed, id=" + message.getID(), cause ); update(); } protected void update() { if ( !buddy_table.isDisposed()){ buddy_table.getDisplay().asyncExec( new Runnable() { public void run() { if ( !buddy_table.isDisposed()){ updateTable(); } } }); } } }); if ( !buddies.contains( buddy )){ buddy_table.getDisplay().asyncExec( new Runnable() { public void run() { if ( !buddy_table.isDisposed()){ if ( !buddies.contains( buddy )){ buddies.add( buddy ); updateTable(); } } } }); } } public void buddyRemoved( final BuddyPluginBuddy buddy ) { if ( !buddy_table.isDisposed()){ buddy_table.getDisplay().asyncExec( new Runnable() { public void run() { if ( !buddy_table.isDisposed()){ if ( buddies.remove( buddy )){ updateTable(); } } } }); } } public void buddyChanged( final BuddyPluginBuddy buddy ) { if ( !buddy_table.isDisposed()){ buddy_table.getDisplay().asyncExec( new Runnable() { public void run() { if ( !buddy_table.isDisposed()){ updateTable(); } } }); } } public void messageLogged( String str, boolean error ) { print( str, error?LOG_ERROR:LOG_NORMAL, false, false ); } // @see com.aelitis.azureus.plugins.net.buddy.BuddyPluginListener#enabledStateChanged(boolean) public void enabledStateChanged( boolean enabled) { } public Map requestReceived( BuddyPluginBuddy from_buddy, int subsystem, Map request ) throws BuddyPluginException { return( null ); } public void pendingMessages( BuddyPluginBuddy[] from_buddies ) { String str = ""; for (int i=0;i<from_buddies.length;i++){ str += (str.length()==0?"":",") + from_buddies[i].getName(); } print( "YGM received: " + str ); } protected void print( String str, Throwable e ) { print( str + ": " + Debug.getNestedExceptionMessage( e )); } protected void print( String str ) { print( str, LOG_NORMAL, false, true ); } protected void print( final String str, final int log_type, final boolean clear_first, boolean log_to_plugin ) { if ( log_to_plugin ){ plugin.log( str ); } if ( !log.isDisposed()){ final int f_log_type = log_type; log.getDisplay().asyncExec( new Runnable() { public void run() { if ( log.isDisposed()){ return; } int start; if ( clear_first ){ start = 0; log.setText( str + "\n" ); }else{ String text = log.getText(); start = text.length(); if ( start > 32000 ){ log.replaceTextRange( 0, 1024, "" ); start = log.getText().length(); } log.append( str + "\n" ); } Color color; if ( f_log_type == LOG_NORMAL ){ color = Colors.black; }else if ( f_log_type == LOG_SUCCESS ){ color = Colors.green; }else{ color = Colors.red; } if ( color != Colors.black ){ StyleRange styleRange = new StyleRange(); styleRange.start = start; styleRange.length = str.length(); styleRange.foreground = color; log.setStyleRange(styleRange); } log.setSelection( log.getText().length()); } }); } } protected void destroy() { composite = null; plugin.removeListener( this ); plugin.removeRequestListener( this ); } protected class FilterComparator implements Comparator { boolean ascending = false; static final int FIELD_NAME = 0; static final int FIELD_ONLINE = 1; static final int FIELD_LAST_SEEN = 2; static final int FIELD_YGM = 3; static final int FIELD_LAST_MSG = 4; static final int FIELD_LOC_CAT = 5; static final int FIELD_REM_CAT = 6; static final int FIELD_READ_CAT = 7; static final int FIELD_CON = 8; static final int FIELD_MSG_IN = 9; static final int FIELD_MSG_OUT = 10; static final int FIELD_QUEUED = 11; static final int FIELD_BYTES_IN = 12; static final int FIELD_BYTES_OUT = 13; static final int FIELD_SS = 14; int field = FIELD_NAME; public int compare( Object arg0, Object arg1) { BuddyPluginBuddy b1 = (BuddyPluginBuddy) arg0; BuddyPluginBuddy b2 = (BuddyPluginBuddy) arg1; int res = 0; if(field == FIELD_NAME){ res = b1.getName().compareTo( b2.getName()); }else if(field == FIELD_ONLINE){ res = ( b1.isOnline( false )?1:0 ) - ( b2.isOnline( false )?1:0 ); }else if(field == FIELD_LAST_SEEN){ res = sortInt( b1.getLastTimeOnline() - b2.getLastTimeOnline()); }else if(field == FIELD_YGM){ res = sortInt( b1.getLastMessagePending() - b2.getLastMessagePending()); }else if(field == FIELD_LAST_MSG){ res = b1.getLastMessageReceived().compareTo( b2.getLastMessageReceived()); }else if(field == FIELD_LOC_CAT){ res = compareStrings( b1.getLocalAuthorisedRSSTagsOrCategoriesAsString(), b2.getLocalAuthorisedRSSTagsOrCategoriesAsString()); }else if(field == FIELD_REM_CAT){ res = compareStrings( b1.getRemoteAuthorisedRSSTagsOrCategoriesAsString(), b2.getRemoteAuthorisedRSSTagsOrCategoriesAsString()); }else if(field == FIELD_READ_CAT){ res = compareStrings( b1.getLocalReadTagsOrCategoriesAsString(), b2.getLocalReadTagsOrCategoriesAsString()); }else if(field == FIELD_CON){ res = b1.getConnectionsString().compareTo( b2.getConnectionsString()); }else if(field == FIELD_MSG_IN){ res = b1.getMessageInCount() - b2.getMessageInCount(); }else if(field == FIELD_MSG_OUT){ res = b1.getMessageOutCount() - b2.getMessageOutCount(); }else if(field == FIELD_QUEUED){ res = b1.getMessageHandler().getMessageCount() - b2.getMessageHandler().getMessageCount(); }else if(field == FIELD_BYTES_IN){ res = b1.getBytesInCount() - b2.getBytesInCount(); }else if(field == FIELD_BYTES_OUT){ res = b1.getBytesOutCount() - b2.getBytesOutCount(); }else if(field == FIELD_SS){ res = b1.getSubsystem() - b2.getSubsystem(); } return(( ascending ? 1 : -1) * res ); } protected int compareStrings( String s1, String s2 ) { if ( s1 == null && s2 == null ){ return(0); }else if ( s1 == null ){ return(-1); }else if ( s2 == null ){ return( 1 ); }else{ return( s1.compareTo(s2)); } } protected int sortInt( long l ) { if ( l < 0 ){ return( -1 ); }else if ( l > 0 ){ return( 1 ); }else{ return( 0 ); } } public void setField( int newField ) { if(field == newField) ascending = ! ascending; field = newField; } } }