@ -101,7 +101,7 @@ WirelessAssistant::~WirelessAssistant()
void WirelessAssistant : : init ( )
void WirelessAssistant : : init ( )
{
{
statusLabel - > setText ( i18n ( " Initializing... " ) ) ;
statusLabel - > setText ( i18n ( " Initializing... " ) ) ;
statusLabel - > repaint( ) ;
statusLabel - > tq repaint( ) ;
////////////////////////////////////////
////////////////////////////////////////
///// CHECK FOR SYSFS (KERNEL 2.6) /////
///// CHECK FOR SYSFS (KERNEL 2.6) /////
@ -191,13 +191,13 @@ void WirelessAssistant::init()
timerGui = new TQTimer ( ) ;
timerGui = new TQTimer ( ) ;
timerConnectionCheck = new TQTimer ( ) ;
timerConnectionCheck = new TQTimer ( ) ;
connect ( timerGui , TQT_SIGNAL ( timeout ( ) ) , TQT_SLOT ( updateConnectedItem ( ) ) ) ;
connect ( timerGui , TQT_SIGNAL ( timeout ( ) ) , TQT_SLOT ( updateConnectedItem ( ) ) ) ;
connect ( timerConnectionCheck , TQT_SIGNAL ( timeout ( ) ) , TQT_SLOT ( checkConnection Status( ) ) ) ;
connect ( timerConnectionCheck , TQT_SIGNAL ( timeout ( ) ) , TQT_SLOT ( checkConnection tq Status( ) ) ) ;
////////////////////////
////////////////////////
///// DETECT & SET PATHS /////
///// DETECT & SET PATHS /////
if ( ! Commands . allFound ) { //all ok or ONLY dhcpcd not found (i.e. dhclient present).
if ( ! Commands . allFound ) { //all ok or ONLY dhcpcd not found (i.e. dhclient present).
std : : cout < < " Missing executables ( " < < Commands . notFound . join ( " ', ' " ) . ascii ( ) < < " ). Exiting. " < < std : : endl ;
std : : cout < < " Missing executables ( " < < Commands . notFound . join ( " ', ' " ) . ascii ( ) < < " ). Exiting. " < < std : : endl ;
KMessageBox : : error ( 0 , i18n ( " Executable(s) '%1' could not be found. \n Wireless Assistant will now quit. " ) . arg( Commands . notFound . join ( " ', ' " ) ) ) ;
KMessageBox : : error ( 0 , i18n ( " Executable(s) '%1' could not be found. \n Wireless Assistant will now quit. " ) . tq arg( Commands . notFound . join ( " ', ' " ) ) ) ;
close ( ) ;
close ( ) ;
return ;
return ;
}
}
@ -213,7 +213,7 @@ void WirelessAssistant::init()
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( netScan ( ) ) ) ;
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( netScan ( ) ) ) ;
}
}
void WirelessAssistant : : checkConnection Status( )
void WirelessAssistant : : checkConnection tq Status( )
{
{
TQListViewItem * lvi ;
TQListViewItem * lvi ;
if ( groupAPs ) lvi = getItemByEssid ( WATools : : essid ( NetParams . iface . ascii ( ) ) ) ;
if ( groupAPs ) lvi = getItemByEssid ( WATools : : essid ( NetParams . iface . ascii ( ) ) ) ;
@ -235,7 +235,7 @@ void WirelessAssistant::checkConnectionStatus()
} else if ( connectedItem ) { //connection LOST
} else if ( connectedItem ) { //connection LOST
setConnectedItem ( 0 ) ;
setConnectedItem ( 0 ) ;
timerConnectionCheck - > stop ( ) ;
timerConnectionCheck - > stop ( ) ;
if ( autoReconnect | | KMessageBox : : questionYesNo ( 0 , i18n ( " Connection to '%1' has been lost! \n Would you like to reconnect? " ) . arg( NetParams . essid ) , i18n ( " Connection Lost " ) , KStdGuiItem : : yes ( ) , KStdGuiItem : : no ( ) ) = = KMessageBox : : Yes ) {
if ( autoReconnect | | KMessageBox : : questionYesNo ( 0 , i18n ( " Connection to '%1' has been lost! \n Would you like to reconnect? " ) . tq arg( NetParams . essid ) , i18n ( " Connection Lost " ) , KStdGuiItem : : yes ( ) , KStdGuiItem : : no ( ) ) = = KMessageBox : : Yes ) {
netDisconnect ( true ) ;
netDisconnect ( true ) ;
netConnect ( ) ;
netConnect ( ) ;
}
}
@ -249,7 +249,7 @@ void WirelessAssistant::removeNetParams()
TQString ap = nvi - > ap ( ) ; TQString essid = nvi - > essid ( ) ;
TQString ap = nvi - > ap ( ) ; TQString essid = nvi - > essid ( ) ;
for ( TQStringList : : Iterator nps = NetParamsList . begin ( ) ; nps ! = NetParamsList . end ( ) ; nps + + ) {
for ( TQStringList : : Iterator nps = NetParamsList . begin ( ) ; nps ! = NetParamsList . end ( ) ; nps + + ) {
if ( ( * nps ) . section ( " , " , 2 , 2 ) = = ap & & ( * nps ) . section ( " , " , 1 , 1 ) = = essid ) {
if ( ( * nps ) . section ( " , " , 2 , 2 ) = = ap & & ( * nps ) . section ( " , " , 1 , 1 ) = = essid ) {
if ( KMessageBox : : warningContinueCancel ( 0 , i18n ( " <qt><p>Settings for network '<b>%1</b>' are about to be deleted.</p><p>Would you like to continue?</p></qt> " ) . arg( essid ) ) = = KMessageBox : : Continue ) {
if ( KMessageBox : : warningContinueCancel ( 0 , i18n ( " <qt><p>Settings for network '<b>%1</b>' are about to be deleted.</p><p>Would you like to continue?</p></qt> " ) . tq arg( essid ) ) = = KMessageBox : : Continue ) {
if ( nvi - > hidden ( ) ) // hiddenEssid = 1
if ( nvi - > hidden ( ) ) // hiddenEssid = 1
nvi - > setEssid ( " <hidden> " ) ;
nvi - > setEssid ( " <hidden> " ) ;
NetParamsList . remove ( nps ) ;
NetParamsList . remove ( nps ) ;
@ -282,7 +282,7 @@ void WirelessAssistant::setDNS( const WANetParams & np )
f . close ( ) ;
f . close ( ) ;
} else {
} else {
std : : cout < < " dns setup error: " < < f . name ( ) . ascii ( ) < < " is not writeable. " < < std : : endl ;
std : : cout < < " dns setup error: " < < f . name ( ) . ascii ( ) < < " is not writeable. " < < std : : endl ;
KMessageBox : : error ( 0 , i18n ( " <qt><p>File '<i>%1</i>' could not be opened for writing.</p><p>Nameserver(s) and/or domain are not set.</p></qt> " ) . arg( f . name ( ) ) ) ;
KMessageBox : : error ( 0 , i18n ( " <qt><p>File '<i>%1</i>' could not be opened for writing.</p><p>Nameserver(s) and/or domain are not set.</p></qt> " ) . tq arg( f . name ( ) ) ) ;
}
}
}
}
@ -291,7 +291,7 @@ void WirelessAssistant::netScan()
timerConnectionCheck - > stop ( ) ; //stop while scanning.
timerConnectionCheck - > stop ( ) ; //stop while scanning.
netScan ( NetParams ) ;
netScan ( NetParams ) ;
if ( netList - > childCount ( ) > 0 ) {
if ( netList - > childCount ( ) > 0 ) {
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( checkConnection Status( ) ) ) ;
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( checkConnection tq Status( ) ) ) ;
timerConnectionCheck - > start ( WA_CONNECTION_CHECK_INTERVAL ) ;
timerConnectionCheck - > start ( WA_CONNECTION_CHECK_INTERVAL ) ;
}
}
}
}
@ -314,19 +314,19 @@ void WirelessAssistant::netScan( const WANetParams & np )
}
}
if ( ! WATools : : isUp ( np . iface . ascii ( ) ) ) {
if ( ! WATools : : isUp ( np . iface . ascii ( ) ) ) {
statusLabel - > setText ( i18n ( " Bringing interface %1 up... " ) . arg( np . iface . ascii ( ) ) ) ;
statusLabel - > setText ( i18n ( " Bringing interface %1 up... " ) . tq arg( np . iface . ascii ( ) ) ) ;
//runCommand( Commands.cmd("ifup",np) );
//runCommand( Commands.cmd("ifup",np) );
WATools : : setUp ( true , np . iface . ascii ( ) ) ;
WATools : : setUp ( true , np . iface . ascii ( ) ) ;
if ( DelayBeforeScanning > 0 ) {
if ( DelayBeforeScanning > 0 ) {
statusLabel - > setText ( i18n ( " Waiting before scanning... " ) ) ;
statusLabel - > setText ( i18n ( " Waiting before scanning... " ) ) ;
statusLabel - > repaint( ) ;
statusLabel - > tq repaint( ) ;
KApplication : : eventLoop ( ) - > processEvents ( TQEventLoop : : ExcludeUserInput ) ;
KApplication : : eventLoop ( ) - > processEvents ( TQEventLoop : : ExcludeUserInput ) ;
usleep ( DelayBeforeScanning * 1000000 ) ; // delay * 1000ms
usleep ( DelayBeforeScanning * 1000000 ) ; // delay * 1000ms
}
}
}
}
statusLabel - > setText ( i18n ( " Scanning... " ) ) ;
statusLabel - > setText ( i18n ( " Scanning... " ) ) ;
statusLabel - > repaint( ) ;
statusLabel - > tq repaint( ) ;
netList - > clear ( ) ;
netList - > clear ( ) ;
@ -570,7 +570,7 @@ void WirelessAssistant::netConnect()
setNetParamsFromList ( netList - > selectedItem ( ) ) ;
setNetParamsFromList ( netList - > selectedItem ( ) ) ;
//can't connect if WPA needed, and wpa_supplicant and wpa_cli not available
//can't connect if WPA needed, and wpa_supplicant and wpa_cli not available
if ( NetParams . wpa & & ! wpaAvailable ) {
if ( NetParams . wpa & & ! wpaAvailable ) {
KMessageBox : : error ( 0 , i18n ( " <qt><p><b>Can not connect to network '%1'.<b></p><p>The network you are trying to connect to requires WPA authentication. The necessary executables <i>wpa_supplicant</i> and <i>wpa_cli</i> could not be found. Install <i>wpa_supplicant</i> and restart Wireless Assistant to connect.</p></qt> " ) . arg( NetParams . essid ) ) ;
KMessageBox : : error ( 0 , i18n ( " <qt><p><b>Can not connect to network '%1'.<b></p><p>The network you are trying to connect to requires WPA authentication. The necessary executables <i>wpa_supplicant</i> and <i>wpa_cli</i> could not be found. Install <i>wpa_supplicant</i> and restart Wireless Assistant to connect.</p></qt> " ) . tq arg( NetParams . essid ) ) ;
timerConnectionCheck - > start ( WA_CONNECTION_CHECK_INTERVAL ) ; //resume connection checking
timerConnectionCheck - > start ( WA_CONNECTION_CHECK_INTERVAL ) ; //resume connection checking
return ;
return ;
}
}
@ -579,7 +579,7 @@ void WirelessAssistant::netConnect()
if ( ( NetParams . essid = = " <hidden> " ) | | ( ! setNetParamsFromConfig ( search ) ) ) {
if ( ( NetParams . essid = = " <hidden> " ) | | ( ! setNetParamsFromConfig ( search ) ) ) {
ui_NetParamsWizard * netwiz = new ui_NetParamsWizard ;
ui_NetParamsWizard * netwiz = new ui_NetParamsWizard ;
if ( ! NetParams . hiddenEssid )
if ( ! NetParams . hiddenEssid )
netwiz - > setCaption ( i18n ( " %1 - First Connection Wizard " ) . arg( NetParams . essid ) ) ;
netwiz - > setCaption ( i18n ( " %1 - First Connection Wizard " ) . tq arg( NetParams . essid ) ) ;
netwiz - > setEssidEnabled ( NetParams . hiddenEssid ) ;
netwiz - > setEssidEnabled ( NetParams . hiddenEssid ) ;
netwiz - > setWepEnabled ( NetParams . wep ) ;
netwiz - > setWepEnabled ( NetParams . wep ) ;
netwiz - > setWpaEnabled ( NetParams . wpa , NetParams . wpaSettings ) ;
netwiz - > setWpaEnabled ( NetParams . wpa , NetParams . wpaSettings ) ;
@ -650,8 +650,8 @@ void WirelessAssistant::netConnect( const WANetParams & np )
std : : cout < < " No pre-connection command specified. " < < std : : endl ;
std : : cout < < " No pre-connection command specified. " < < std : : endl ;
statusLabel - > setText ( i18n ( " Connecting to '%1'... " ) . arg( np . essid ) ) ;
statusLabel - > setText ( i18n ( " Connecting to '%1'... " ) . tq arg( np . essid ) ) ;
statusLabel - > repaint( ) ;
statusLabel - > tq repaint( ) ;
if ( ! WATools : : isUp ( np . iface . ascii ( ) ) ) WATools : : setUp ( true , np . iface . ascii ( ) ) ;
if ( ! WATools : : isUp ( np . iface . ascii ( ) ) ) WATools : : setUp ( true , np . iface . ascii ( ) ) ;
//runCommand( Commands.cmd("ifup", np) );
//runCommand( Commands.cmd("ifup", np) );
if ( runCommand ( Commands . cmd ( " iwconfig_set " , np ) ) . find ( " 8B04 " ) > - 1 ) { // error 8B04 - Request 'Set Frequency' not supported.
if ( runCommand ( Commands . cmd ( " iwconfig_set " , np ) ) . find ( " 8B04 " ) > - 1 ) { // error 8B04 - Request 'Set Frequency' not supported.
@ -710,7 +710,7 @@ void WirelessAssistant::netConnect( const WANetParams & np )
if ( autoQuit )
if ( autoQuit )
this - > close ( ) ;
this - > close ( ) ;
groupAPs ? setConnectedItem ( np . essid ) : setConnectedItem ( np . ap ) ;
groupAPs ? setConnectedItem ( np . essid ) : setConnectedItem ( np . ap ) ;
statusLabel - > setText ( i18n ( " Successfully connected to '%1'. " ) . arg( np . essid ) ) ;
statusLabel - > setText ( i18n ( " Successfully connected to '%1'. " ) . tq arg( np . essid ) ) ;
setUi ( 1 ) ;
setUi ( 1 ) ;
} else {
} else {
std : : cout < < " CONNECTION FAILED. " < < std : : endl ;
std : : cout < < " CONNECTION FAILED. " < < std : : endl ;
@ -757,7 +757,7 @@ void WirelessAssistant::setConnectedItem( const TQString & netid )
void WirelessAssistant : : netDisconnect ( const bool & quiet )
void WirelessAssistant : : netDisconnect ( const bool & quiet )
{
{
if ( ( quiet ) | | ( KMessageBox : : warningContinueCancel ( 0 , i18n ( " <qt><p>You are about to disconnect from '<b>%1</b>'.</p><p>Would you like to continue?<p></qt> " ) . arg( connectedItem - > essid ( ) ) ) = = KMessageBox : : Continue ) ) {
if ( ( quiet ) | | ( KMessageBox : : warningContinueCancel ( 0 , i18n ( " <qt><p>You are about to disconnect from '<b>%1</b>'.</p><p>Would you like to continue?<p></qt> " ) . tq arg( connectedItem - > essid ( ) ) ) = = KMessageBox : : Continue ) ) {
timerConnectionCheck - > stop ( ) ; //stop while disconnecting.
timerConnectionCheck - > stop ( ) ; //stop while disconnecting.
if ( ! NetParams . preDisconnectionCommand . isEmpty ( ) ) {
if ( ! NetParams . preDisconnectionCommand . isEmpty ( ) ) {
@ -769,13 +769,13 @@ void WirelessAssistant::netDisconnect( const bool & quiet )
statusLabel - > setText ( i18n ( " Disconnecting... " ) ) ;
statusLabel - > setText ( i18n ( " Disconnecting... " ) ) ;
statusLabel - > repaint( ) ;
statusLabel - > tq repaint( ) ;
setConnectedItem ( 0 ) ;
setConnectedItem ( 0 ) ;
if ( NetParams . dhcp ) {
if ( NetParams . dhcp ) {
if ( dhcpClientRunning ( ) ) {
if ( dhcpClientRunning ( ) ) {
runCommand ( Commands . cmd ( " kill_dhcp " , NetParams ) ) ;
runCommand ( Commands . cmd ( " kill_dhcp " , NetParams ) ) ;
statusLabel - > setText ( i18n ( " Waiting for DHCP client to shut down... " ) ) ;
statusLabel - > setText ( i18n ( " Waiting for DHCP client to shut down... " ) ) ;
statusLabel - > repaint( ) ;
statusLabel - > tq repaint( ) ;
TQTimer * tmr = new TQTimer ( ) ;
TQTimer * tmr = new TQTimer ( ) ;
tmr - > start ( 1500 , true ) ; //wait 1.5sec for dhcp client to really shutdown, single shot.
tmr - > start ( 1500 , true ) ; //wait 1.5sec for dhcp client to really shutdown, single shot.
while ( tmr - > isActive ( ) ) {
while ( tmr - > isActive ( ) ) {
@ -960,7 +960,7 @@ TQString WirelessAssistant::runCommand( const TQStringList & cmd, int timeout, b
TQToolTip : : remove
TQToolTip : : remove
( buttonClose ) ;
( buttonClose ) ;
TQToolTip : : add
TQToolTip : : add
( buttonClose , i18n ( " Terminate current process \n (%1) " ) . arg( p - > arguments ( ) . join ( " " ) ) ) ;
( buttonClose , i18n ( " Terminate current process \n (%1) " ) . tq arg( p - > arguments ( ) . join ( " " ) ) ) ;
}
}
i + + ;
i + + ;
}
}
@ -1059,7 +1059,7 @@ void WirelessAssistant::editNetParams()
ui_NetParamsEdit * netedit = new ui_NetParamsEdit ( ) ;
ui_NetParamsEdit * netedit = new ui_NetParamsEdit ( ) ;
netedit - > setValues ( NetParams ) ;
netedit - > setValues ( NetParams ) ;
netedit - > setCaption ( i18n ( " %1 Settings " ) . arg( NetParams . essid ) ) ;
netedit - > setCaption ( i18n ( " %1 Settings " ) . tq arg( NetParams . essid ) ) ;
netedit - > exec ( ) ;
netedit - > exec ( ) ;
if ( netedit - > result ( ) = = TQDialog : : Rejected ) {
if ( netedit - > result ( ) = = TQDialog : : Rejected ) {
delete netedit ;
delete netedit ;
@ -1085,7 +1085,7 @@ bool WirelessAssistant::dhcpClientRunning()
TQString pidFile ;
TQString pidFile ;
pidPaths < < " /etc/ " < < " /etc/dhcpc/ " < < " /var/run/ " ;
pidPaths < < " /etc/ " < < " /etc/dhcpc/ " < < " /var/run/ " ;
if ( Commands . dhcpClient = = " dhcpcd " )
if ( Commands . dhcpClient = = " dhcpcd " )
pidFile = TQString ( " dhcpcd-%1.pid " ) . arg( NetParams . iface . ascii ( ) ) ;
pidFile = TQString ( " dhcpcd-%1.pid " ) . tq arg( NetParams . iface . ascii ( ) ) ;
else
else
pidFile = TQString ( " dhclient.pid " ) ;
pidFile = TQString ( " dhclient.pid " ) ;
@ -1185,14 +1185,14 @@ bool WirelessAssistant::generateWpaConfigFile( const TQString& essid, const TQSt
bool WirelessAssistant : : setWpaClientEnabled ( bool e , const TQString & iface , TQString driver )
bool WirelessAssistant : : setWpaClientEnabled ( bool e , const TQString & iface , TQString driver )
{
{
if ( ! e ) {
if ( ! e ) {
if ( runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . arg( NetParams . iface ) < < " terminate " ) . contains ( " OK " ) ) {
if ( runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . tq arg( NetParams . iface ) < < " terminate " ) . contains ( " OK " ) ) {
TQFile ( wpaConfigFile ) . remove ( ) ;
TQFile ( wpaConfigFile ) . remove ( ) ;
return 1 ;
return 1 ;
} else
} else
return 0 ; // wpa client was not running.
return 0 ; // wpa client was not running.
}
}
if ( ! runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . arg( NetParams . iface ) < < " status " ) . contains ( " Failed to connect " ) ) {
if ( ! runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . tq arg( NetParams . iface ) < < " status " ) . contains ( " Failed to connect " ) ) {
std : : cout < < " WPA client already running. Reconfiguring... " < < std : : endl ;
std : : cout < < " WPA client already running. Reconfiguring... " < < std : : endl ;
runCommand ( TQStringList ( Commands . wpa_cli ) < < " reconfigure " ) ;
runCommand ( TQStringList ( Commands . wpa_cli ) < < " reconfigure " ) ;
} else {
} else {
@ -1215,9 +1215,9 @@ bool WirelessAssistant::setWpaClientEnabled( bool e, const TQString& iface, TQSt
wp - > clearArguments ( ) ;
wp - > clearArguments ( ) ;
wp - > addArgument ( Commands . wpa_supplicant ) ;
wp - > addArgument ( Commands . wpa_supplicant ) ;
wp - > addArgument ( " -W " ) ; //wait for control interface
wp - > addArgument ( " -W " ) ; //wait for control interface
wp - > addArgument ( TQString ( " -D%1 " ) . arg( driver ) ) ;
wp - > addArgument ( TQString ( " -D%1 " ) . tq arg( driver ) ) ;
wp - > addArgument ( TQString ( " -i%1 " ) . arg( iface ) ) ;
wp - > addArgument ( TQString ( " -i%1 " ) . tq arg( iface ) ) ;
wp - > addArgument ( TQString ( " -c%1 " ) . arg( wpaConfigFile ) ) ;
wp - > addArgument ( TQString ( " -c%1 " ) . tq arg( wpaConfigFile ) ) ;
//std::cout << "Starting WPA client: " << wp->arguments().join(" ").ascii() << std::endl;
//std::cout << "Starting WPA client: " << wp->arguments().join(" ").ascii() << std::endl;
if ( ! wp - > start ( ) ) {
if ( ! wp - > start ( ) ) {
std : : cout < < " Failed to start WPA client. " < < std : : endl ;
std : : cout < < " Failed to start WPA client. " < < std : : endl ;
@ -1231,14 +1231,14 @@ bool WirelessAssistant::setWpaClientEnabled( bool e, const TQString& iface, TQSt
TQString o ;
TQString o ;
int i = 0 ;
int i = 0 ;
while ( ! ( o = runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . arg( NetParams . iface ) < < " status " ) ) . contains ( " Failed to connect " ) ) {
while ( ! ( o = runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . tq arg( NetParams . iface ) < < " status " ) ) . contains ( " Failed to connect " ) ) {
for ( int c = 0 ; c < 15 ; c + + ) {
for ( int c = 0 ; c < 15 ; c + + ) {
usleep ( 75 * 1000 ) ; //75msec
usleep ( 75 * 1000 ) ; //75msec
KApplication : : eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
KApplication : : eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
i + + ;
i + + ;
}
}
if ( i > 400 ) { //more than 30sec have passed
if ( i > 400 ) { //more than 30sec have passed
runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . arg( NetParams . iface ) < < " terminate " ) ;
runCommand ( TQStringList ( Commands . wpa_cli ) < < TQString ( " -i%1 " ) . tq arg( NetParams . iface ) < < " terminate " ) ;
return 0 ;
return 0 ;
}
}
if ( o . contains ( " wpa_state=COMPLETED " ) ) {
if ( o . contains ( " wpa_state=COMPLETED " ) ) {