/***************************************************************************
 ** $Id: torkview.cpp,v 1.125 2009/11/07 14:21:56 hoganrobert Exp $
 *   Copyright (C) 2006 - 2008 Robert Hogan                                *
 *   robert@roberthogan.net                                                *
 *                                                                         *
 *   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; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
 ***************************************************************************/

#include <sys/time.h>

#include "torkview.h"
#include "tork.h"
#include "torclient.h"
#include <tdelocale.h>
#include <ntqlabel.h>
#include <ntqlistview.h>
#include "dndlistview.h"
#include "portsandicons.h"
#include "torkconfig.h"
#include "chart.h"
#include "functions.h"
#include "mixminion.h"
#include "crypto.h"

#include "hitwidget.h"
#include "kwidgetlistbox.h"
#include "kerrylabel.h"


#ifndef EXTERNAL_GEOIP
# include "GeoIP-1.4.0/libGeoIP/GeoIP.h"
#else
# include <GeoIP.h>
#endif

#include "kdebug.h"
#include <kstandarddirs.h>
#include <kiconloader.h>
#include <kmimetype.h>
#include <ksystemtray.h>
#include <kprocio.h>
#include <tdemessagebox.h>
#include <krun.h>
#include <kurl.h>
#include <tdeio/netaccess.h>

#include <ntqregexp.h>
#include <ntqsplitter.h>
#include <ntqgroupbox.h>
#include <ntqfile.h>
#include <ntqdir.h>
#include <ntqpixmap.h>
/* Linux-specific includes */
#include <dirent.h>
#include <unistd.h>
#include "../config.h"

using namespace tk;


#define MAX_BW_RATE 2
#define MAX_CG_RATE 60*5
#define MAX_TN_RATE 60*20
#define MAX_CBWS_RATE 60

torkView::torkView(TQWidget *parent)
    : torkview_base(parent), m_pop(0L), m_tormon(TorkConfig::showTorMon()), torbtx(0), torbrx(0)
{

#ifndef EXTERNAL_GEOIP
    geoip_db = !locate("data", "tork/geoip/GeoIP.dat").isNull();
#else
    GeoIP * gi = 0;
    gi = GeoIP_new(GEOIP_STANDARD);
    if (gi)
        geoip_db = true;
    else
        geoip_db = false;
#endif

    greenonion << "green" << "up" << "built" << "good" << "connected" << "succeeded";
    redonion << "red" << "down" << "bad" << "failed";
    yellowonion << "yellow" << "sentconnect";
    orangeonion << "orange" << "sentresolve";
    littleonion << "little" << "launched" << "new" << "detached";
    todelete << "todelete" << "closed" << "failed" << "dropped";
    iconList << greenonion << redonion << yellowonion << orangeonion << littleonion;

    guard << "up" << "up" << "built" << "good" << "connected";
    redguard << "red" << "down" << "bad" << "dropped"  << "unusable" << "failed";
    detachedguard << "detached" << "never-connected" << "unlisted" << "succeeded";
    littleguard << "little" << "new" << "sentresolve" << "sentconnect";
    guardIconList << guard << redguard << detachedguard << littleguard;

    greenonion << "green" << "built";
    redonion << "red" << "failed";
    yellowonion << "yellow" << "extended";
    littleonion << "little" << "launched";
    circuitIconList << greenonion << redonion << yellowonion << littleonion;


    torType += i18n("running a Tor Client and Server With Default Settings");
    torType += i18n("running a Tor Client and Relay Server With Default Settings");
    torType += i18n("running a Tor Server With Default Settings");
    torType += i18n("running a Tor Relay Server With Default Settings");
    torType += i18n("running a Tor Client with Default Settings");
    torType += i18n("running an instance of Tor using all the settings in the configure dialog");
    torType += i18n("connected to a Remote Instance of Tor");
    torType += i18n("connected to a Local Instance of Tor");

    streamPurpose["DIR_FETCH"] = "Tor(Directory Fetch)";
    streamPurpose["DNS_REQUEST"] = "Tor(DNS)";
    streamPurpose["UPLOAD_DESC"] = "Tor(Upload Descriptor)";
    streamPurpose["DIRPORT_TEST"] = "Tor(Server Test)";


	mFirstUpdate = true;

    if (checkInterface())
        gotEth0 = true;
    else
        gotEth0 = false;

    if (!TorkConfig::showTorBar())
        frame4->hide();

	settingsChanged();

    populateMenu();

    menuItems << sshitem << gpgitem << telnetitem << kopeteitem << ksircitem;
    menuItems << allpurposeitem << konversationitem << pidginitem << gaimitem << operaitem << firefoxitem;
    menuItems << hiddenservicesitem << konqitem << mixminionitem;

    for ( TQValueList<HitWidget*>::Iterator it = menuItems.begin(); it != menuItems.end(); ++it ){
        if (*it)
            (*it)->setEnabled(false);
    }

    resetBWHistory();

    Chart* chart = new Chart(ChartFrame, speedHistoryTx(), speedHistoryRx(), 
                            historyBufferSize(), historyPointer(), maxSpeed(),
                            sys_speedHistoryTx(), sys_speedHistoryRx(), 
                            sys_historyBufferSize(), sys_historyPointer(), sys_maxSpeed(), gotEth0);
    chart->setMinimumWidth(ChartFrame->width());
    chart->setMinimumHeight(ChartFrame->height());

    connect(this, SIGNAL(updateStats()), chart, SLOT(update()));


    m_osd = new StreamOSD(this, true);
    m_osd->readSettings(TDEGlobal::config());

    m_nontorosd = new StreamOSD(this, false);
    m_nontorosd->readSettings(TDEGlobal::config());

    //Icons showing the status of the stream
    streamStatusIcon["SUCCEEDED"] = TQPixmap(SmallIcon("tork_green"));
    streamStatusIcon["FAILED"] = TQPixmap(SmallIcon("tork_red"));
    streamStatusIcon["SENTCONNECT"] = TQPixmap(SmallIcon("tork_yellow"));
    streamStatusIcon["SENTRESOLVE"] = TQPixmap(SmallIcon("tork_orange"));
    streamStatusIcon["NEW"] = TQPixmap(SmallIcon("tork_little"));
    streamStatusIcon["DETACHED"] = TQPixmap(SmallIcon("tork_little"));
    streamStatusIcon["CLOSED"] = TQPixmap(SmallIcon("tork_todelete"));
    progDisplayCounter = 0;
}

void torkView::resetBWHistory() {

	memset(mSpeedHistoryRx, 0, sizeof(double)*HISTORY_SIZE);
	memset(mSpeedHistoryTx, 0, sizeof(double)*HISTORY_SIZE);
	memset(mSpeedBufferRx, 0, sizeof(double)*SPEED_BUFFER_SIZE);
	memset(mSpeedBufferTx, 0, sizeof(double)*SPEED_BUFFER_SIZE);
	mMaxSpeedAge = 0;
	mMaxSpeed = 0.0;
	mSpeedBufferPtr = mSpeedHistoryPtr = 0;
	mBRx = mBTx = 0;

	memset(sys_mSpeedHistoryRx, 0, sizeof(double)*HISTORY_SIZE);
	memset(sys_mSpeedHistoryTx, 0, sizeof(double)*HISTORY_SIZE);
	memset(sys_mSpeedBufferRx, 0, sizeof(double)*SPEED_BUFFER_SIZE);
	memset(sys_mSpeedBufferTx, 0, sizeof(double)*SPEED_BUFFER_SIZE);
	sys_mMaxSpeedAge = 0;
	sys_mMaxSpeed = 0.0;
	sys_mSpeedBufferPtr = sys_mSpeedHistoryPtr = 0;
	sysmBRx = sysmBTx = 0;

    mFirstUpdate = true;
    torbtx = 0;
    torbrx = 0;
}

void torkView::updateChart() {

    emit updateStats();

}

void torkView::changeQuickConfigure(int no) {

/*    TQValueList<int> qconf;
    qconf << 4 << 2 << 3 << 5 << 6 << 7;*/
    TorkConfig::setQuickConfigure(no);
}

void torkView::clearStreamMaps() {

    streams.clear();
    osdstreams.clear();
    circuitExits.clear();
    streamBwIn.clear();
    streamBwOut.clear();
    logstreams.clear();
    cachedStreamIcon.clear();
    torservers.clear();
}

void torkView::downloadTorButton() {

    int result = KMessageBox::questionYesNo(0,
                 i18n( "<p>Once you install TorButton, restart Firefox from here "
                 "rather than letting Firefox restart automatically. This will"
                 " ensure you do not browse with your normal Firefox "
                 "profile.<br> <b>Continue?</b></p>")
                 ,i18n( "Be sure to restart Firefox from Tork!" ));

    switch (result) {
      case KMessageBox::Yes : 
        anonymizedFirefox( "http://www.torproject.org/torbutton/torbutton-current.xpi");
    }

}

void torkView::downloadMixminion() {


    TorkUpdate* updater = new TorkUpdate(this);
    updater->downloadMixminion();

}

void torkView::sendAnonymousEmail() {


    if (TorkConfig::availablePrograms().contains("mixminion")){
        TQString caption;
        TQString message;
        caption = i18n("Mixminion Not Installed!");
        message = i18n("<p>Mixminion does not appear to be installed on your system.<br>");
        message += i18n("<p><b>Try installing it from the main interface.</b><br>");
        KMessageBox::information (this, message, caption);
        return;
    }

    MixMinionClient* mixminion = new MixMinionClient();
    mixminion->show();

}

bool torkView::checkInterface() {

    bool gotone = false;
    //Would anyone have this many ethernet cards?
    TQStringList devices;
    devices << "eth" << "wlan";
	for ( TQStringList::Iterator it = devices.begin(); it != devices.end(); ++it ){
        for (int i=0; i < 5; i++){
            TQString devpath = TQString("/sys/class/net/%1%2").arg((*it)).arg(i);
            TQDir ethdir(devpath);
            if (ethdir.exists()){
                mSysDevPathList.append(devpath);
                gotone = true;
            }else
                continue;
        }
    }

    return gotone;
}

void torkView::torify(const TQString& text)
{

    TQString command = "usewithtor " + text;
    TQString icon = text.section(" ",0,0);
    KRun::runCommand( command, icon, icon );

}

void torkView::anonymousFirefox()
{
    anonymizedFirefox("http://healthcheck.anonymityanywhere.com/");
}

void torkView::anonymizedFirefox(const TQString& url)
{
    TQString text = "firefox";
    TQString firefoxdir = TQString("%1/.mozilla/firefox").arg(getenv("HOME"));

    TQString torkfirefox = TQString("%1/tork.TorkAnonymous").arg(firefoxdir);
    TQDir torkdir(torkfirefox);
    if (!torkdir.exists()){

        TQFile inf(TQString("%1/profiles.ini").arg(firefoxdir));
        TQString line;
        int profileno=0;
        if ( inf.open(IO_ReadOnly) ) {
            TQTextStream stream( &inf );
    
            while ( !stream.atEnd() ) {
                line = stream.readLine(); // line of text excluding '\n'
                if (line.contains("[Profile")){
                    TQRegExp rx("([0-9]{1,4})");
                    rx.search(line);
                    profileno = rx.cap(0).toInt() + 1;
                }
                if (line.contains(".default"))
                    break;
            }
            inf.close();
        }else{
            emit processWarning("cantreadprofiles",i18n("Can't read %1")
                    .arg(TQString("%1/profiles.ini").arg(firefoxdir)));
            TDEIO::NetAccess::del(torkfirefox,0L);
            return;
        }
    
        TQString originalprofile = line.replace("Path=","");
        TQString originalfirefox = TQString("%1/%2").arg(firefoxdir).arg(originalprofile);
    
        if (!TDEIO::NetAccess::dircopy(originalfirefox,torkfirefox, 0L))
        {
            emit processWarning("cantcopyprofile",i18n("Can't copy %1").arg(originalfirefox));
            TDEIO::NetAccess::del(torkfirefox,0L);
            return;
        }


        //Update Profile
        TQFile inf2(TQString("%1/profiles.ini").arg(firefoxdir));
        if ( inf2.open(IO_WriteOnly | IO_Append) ) {
    
            TQTextStream ts( &inf2 );
            ts << "\n";
            ts << "[Profile" << profileno << "]" << "\n";
            ts << "Name=TorkAnonymous" << "\n";
            ts << "IsRelative=1" << "\n";
            ts << "Path=tork.TorkAnonymous" << "\n";
            ts << "\n";
            inf2.close();
        }else{
            emit processWarning("cantreadprofiles",i18n("Can't read %1")
                    .arg(TQString("%1/profiles.ini").arg(firefoxdir)));
            TDEIO::NetAccess::del(torkfirefox,0L);
            return;
        }

    }

    //Update Profile
    TQFile inf3(TQString("%1/prefs.js").arg(torkfirefox));
    if ( inf3.open(IO_WriteOnly | IO_Append) ) {

        TQTextStream ts( &inf3 );

        ts << "user_pref(\"network.proxy.ftp\", \"\");" << "\n";
        ts << "user_pref(\"network.proxy.ftp_port\", 0);" << "\n";
        ts << "user_pref(\"network.proxy.gopher\", \"\");" << "\n";
        ts << "user_pref(\"network.proxy.gopher_port\", 0);" << "\n";
        ts << "user_pref(\"network.proxy.http\", \"" << TorkConfig::konqHttpProxy().replace("http://","") << "\");" << "\n";
        ts << "user_pref(\"network.proxy.http_port\", " << TorkConfig::konqHttpProxyPort() << ");" << "\n";
        ts << "user_pref(\"network.proxy.share_proxy_settings\", true);" << "\n";
        ts << "user_pref(\"network.proxy.ssl\", \"" << TorkConfig::konqHttpsProxy().replace("http://","") << "\");" << "\n";
        ts << "user_pref(\"network.proxy.ssl_port\", " << TorkConfig::konqHttpsProxyPort() << ");" << "\n";
        ts << "user_pref(\"network.proxy.type\", 1);" << "\n";
        //Java/Javascript disabled
        ts << "user_pref(\"javascript.enabled\", false);" << "\n";
        ts << "user_pref(\"pref.advanced.javascript.disable_button.advanced\", false);" << "\n";
        ts << "user_pref(\"security.enable_java\", false);" << "\n";
        //Cookies Disabled
        ts << "user_pref(\"network.cookie.cookieBehavior\", 2);" << "\n";
        //Point SOCKS to Tor
        ts << "user_pref(\"network.proxy.socks\", \"" << TorkConfig::sOCKSBindAddressHost().replace("http://","") << "\");" << "\n";
        ts << "user_pref(\"network.proxy.socks_port\", " << TorkConfig::sOCKSBindAddressPort() << ");" << "\n";
        ts << "user_pref(\"network.proxy.socks_version\", 5);" << "\n";

        //Ensure dns requests go through proxy
        ts << "user_pref(\"network.proxy.socks_remote_dns\", true);" << "\n";
        //Tor doesn't do IPv6
        ts << "user_pref(\"network.dns.disableIPv6\", true);" << "\n";

        //Additional settings taken from TorToGo
        //

        //Disable Auto-Updating of Extensions
        ts << "user_pref(\"extensions.update.autoUpdateEnabled\", false);" << "\n";
        ts << "user_pref(\"extensions.update.autoUpdate\",false);" << "\n";
        ts << "user_pref(\"extensions.update.enabled\",false);" << "\n";

        //Disable Auto-Updating of Firefox
        ts << "user_pref(\"app.update.auto\",false);" << "\n";
        ts << "user_pref(\"app.update.enabled\",false);" << "\n";

        //Disable Updating of Searchbar
        ts << "user_pref(\"browser.search.update\",false);" << "\n";

        //No compression.  Compression can prevent munging of environmental variables
        ts << "user_pref(\"network.http.accept-encoding:gzip;q=0,deflate;q=0,compress;q=0\",false);" << "\n";
        // --Accept MIME type
        ts << "user_pref(\"network.http.accept.default:text/xml,application/xml, application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5);" << "\n";

        //--English non-localized
        ts << "user_pref(\"intl.accept_languages\",en);" << "\n";
        ts << "user_pref(\"intl.accept_charsets\",ISO-8859-1,*);" << "\n";

        //~User Agent/Anonymity Set (This will create a large anonymity set for Tor users):

        ts << "user_pref(\"general.useragent.override\",Mozilla/5.0 (Windows; U; Windows NT 5.1; en; rv:1.7.10) Gecko/20050716 Firefox/1.5.0.7);" << "\n";
        //  --Spoof the version of Firefox in use (real version is v.2.0.0.3rc)
        ts << "user_pref(\"general.useragent.extra.firefox\",Firefox/1.5.0.7);" << "\n";
        //--Required to match "intl.accept_languages" above
        ts << "user_pref(\"general.useragent.locale\",en);" << "\n";
        ts << "user_pref(\"extensions.torbutton.tor_enabled\", true);" << "\n";
        inf3.close();

    }else{
        emit processWarning("cantwritefirefoxsettings", i18n("Can't write to %1").arg(TQString("%1/prefs.js").arg(torkfirefox)));
        TDEIO::NetAccess::del(torkfirefox,0L);
        return;
    }

    KRun::runCommand( TQString("%1 -P TorkAnonymous %2").arg(text).arg(url), text, text );


}

void torkView::anonymousOpera()
{
    anonymizedOpera("http://healthcheck.anonymityanywhere.com/");
}

void torkView::anonymizedOpera(const TQString& url)
{

    TQString text = "opera";
    TQString originalopera = TQString("%1/.opera").arg(getenv("HOME"));
    TQString torkopera = TQString("%1/.opera-tork").arg(getenv("HOME"));
    TQDir torkdir(torkopera);
    if (!torkdir.exists())
        TDEIO::NetAccess::dircopy(originalopera,torkopera,0L);

    TQFile inf(TQString("%1/.opera-tork/opera6.ini").arg(getenv("HOME")));
    if ( inf.open(IO_WriteOnly | IO_Append) ) {

        TQTextStream ts( &inf );

        ts << "[Proxy]" << "\n";
        ts << "HTTPS server=" << TorkConfig::konqHttpsProxy() << ":" << TorkConfig::konqHttpsProxyPort() << "\n";
        ts << "HTTP server=" << TorkConfig::konqHttpProxy() << ":" << TorkConfig::konqHttpProxyPort() << "\n";
        ts << "Use HTTP=1" << "\n";
        ts << "Use HTTPS=1" << "\n";
        ts << "Use Automatic Proxy Configuration=0" << "\n";

        ts << "[Java]" << "\n";
        ts << "Enabled=0" << "\n";
        ts << "[Extensions]" << "\n";
        ts << "Scripting=0" << "\n";
        ts << "Plugins=0" << "\n";

        ts << "[User Prefs]" << "\n";
        ts << "Enable Cookies=0" << "\n";

        inf.close();
        KRun::runCommand( TQString("%1 -personaldir %2 -newpage %3").arg(text).arg(torkopera).arg(url), text, text );
    
    }


}

void torkView::privoxiedBash()
{

    TQString location = getenv("HOME");
    location += "/.tork";
    TQDir torkdir(location);
    if (!torkdir.exists() && !torkdir.mkdir(location))
        location = getenv("HOME");

    TQFile inf(TQString("%1/privoxy_konsole_session").arg(location));
    if (! inf.open(IO_WriteOnly) ) {
          inf.close();
          KMessageBox::information (this,"Couldn't create bash session file!");
          return ;
    }

    TQTextStream ts( &inf );
/*	TQTextStream &ts = *(inf.textStream());*/
    
    ts << TQString("http_proxy=%1:%2").arg(TorkConfig::konqHttpProxy()).arg(TorkConfig::konqHttpProxyPort()) << "\n";
    ts << TQString("https_proxy=%1:%2").arg(TorkConfig::konqHttpsProxy()).arg(TorkConfig::konqHttpsProxyPort()) << "\n";
    ts << "HTTP_PROXY=$http_proxy" << "\n";
    ts << "HTTPS_PROXY=$https_proxy" << "\n";
    ts << "export HTTP_PROXY HTTP_PROXY http_proxy https_proxy" << "\n";
    ts << "echo Using $http_proxy and $https_proxy as a privacy proxy in this bash session." << "\n";
    ts << "echo Using commands such as 'su' will cease use of the privacy proxy." << "\n";


    inf.close();

    KRun::runCommand( TQString("konsole --caption 'Shell Using Privoxy for Http requests - Launched From TorK' --noclose -e bash --init-file %1").arg(inf.name()), "konsole", "konsole" );

}

void torkView::toggleParanoidMode(int id)
{

    switch(id)
    {
    case 0:
        paranoidmodeicon->setPixmap(SmallIcon("tork_penguin"));
        paranoidmodetext->setText(i18n("In Normal mode!"));
        break;
    case 1:
        paranoidmodeicon->setPixmap(SmallIcon("tork_agent"));
        paranoidmodetext->setText(i18n("In DNS FailSafe mode!"));
        break;
    case 2:
        paranoidmodeicon->setPixmap(SmallIcon("gv"));
        paranoidmodetext->setText(i18n("In System FailSafe mode!"));
        break;
    default:
        return;
    }

    TorkConfig::setParanoidMode(id);

}

void torkView::toggleAnonymizerTork(bool state)
{

    welcomeitem->setEnabled(true);

    disconnect(welcomeitem->icon, SIGNAL(leftClickedURL()), this, SIGNAL(startEverything()));
    disconnect(welcomeitem->icon, SIGNAL(leftClickedURL()), this, SIGNAL(stopEverything()));

    if (state){
        connect(welcomeitem->icon, SIGNAL(leftClickedURL()), SIGNAL(stopEverything()));
        welcomeheaderLabel->setText(i18n("Welcome to the Tor Network!"));
        welcomeitem->setIcon("tork_stop");
        welcomeitem->setDescriptionText("<qt>"+i18n("- <b>You are %1.</b><br>"
                            ).arg(torType[TorkConfig::quickConfigure()])+"</qt>");
        welcomeitem->setPropertiesText("<qt>"+i18n(
                            "- The 'Tor Network' tab shows you the state of the Tor network, including your Tor Traffic. <br> "
                            "- You can use the 'Traffic Log' tab to view Tor and Non-Tor Traffic on your system.<br> "
                            "- You can use the 'Tor Log' tab to view warning messages from Tor itself. <br> "
                            "- Try out the services listed below. <br> "
                            )+"</qt>");


        setHiddenServicesText();

        welcomeitem->score->setEnabled(false);
        for ( TQValueList<HitWidget*>::Iterator it = menuItems.begin(); it != menuItems.end(); ++it ){
            if (*it)
                (*it)->setEnabled(true);
        }

    }else{
        connect(welcomeitem->icon, SIGNAL(leftClickedURL()), SIGNAL(startEverything()));
        welcomeitem->setIcon("tork_pressplay");
        welcomeheaderLabel->setText(i18n("Press 'Play' to get started!"));
        welcomeitem->setDescriptionText("<qt>"+i18n("- <b>Press 'Play' to connect to Tor. (You can also use the toolbar icons.)</b><br>"
                            )+"</qt>");
        welcomeitem->setPropertiesText("<qt>"+i18n(
                            "- The 'Tor Network' tab shows you the state of the Tor network, including your Tor Traffic. <br> "
                            "- You can use the 'Traffic Log' tab to view Tor and Non-Tor Traffic on your system.<br> "
                            "- You can use the 'Tor Log' tab to view warning messages from Tor itself. <br> "
                            "- Once Tor is up and running you can use the services listed below. <br> "
                            )+"</qt>");

        welcomeitem->score->setEnabled(true);
        setHiddenServicesText();

        for ( TQValueList<HitWidget*>::Iterator it = menuItems.begin(); it != menuItems.end(); ++it ){
            if (*it)
                (*it)->setEnabled(false);
        }


    }
}

void torkView::setHiddenServicesText()
{

    TQString activeHiddenServices;
    TQStringList hiddenServices = TorkConfig::hiddenServices();
    for ( TQStringList::Iterator it = hiddenServices.begin(); it != hiddenServices.end(); ++it )
    {
        if ((*it).isEmpty())
            continue;
        if (!(*it).section("\n",-2,-2).isEmpty())
            activeHiddenServices.append(i18n("<b>%1</b> (serving files from <i>%2</i>)").arg((*it).section("\n",-6,-6)).arg((*it).section("\n",-2,-2)));
        else
            activeHiddenServices.append(i18n("<b>%1</b> (redirecting to <i>%2</i>)").arg((*it).section("\n",-6,-6)).arg((*it).section("\n",-3,-3)));

    }

    if (!activeHiddenServices.isEmpty()){
        hiddenservicesitem->setPropertiesText("<qt>"+i18n(
                        "- You are running the following hidden services:<br>&nbsp;&nbsp;&nbsp;&nbsp;%1<br>"
                        ).arg(activeHiddenServices)+"</qt>");
    }else{
        hiddenservicesitem->setPropertiesText("<qt>"+i18n(
                                "- Anonymous web sites/web services are known as 'hidden services'. <br>"
                                "- Their location and ownership are  concealed by the operation of the Tor network.<br>"
                                )+"</qt>");
    }

}

torkView::~torkView()
{

}

#define MAXPROGDISPLAY 5

void torkView::streamStatusUpdated(const TQString &streamID, const TQString &status,
        const TQString &circID, const TQString &Target, const TQString &info)
{


  TQString tmpstatus = status.stripWhiteSpace();

  streamItem* streamline;
  TQListViewItem* osdstreamline;
  TQListViewItem* torTrafficLine;

  torTrafficLine=0L;

  if (!(streamline = streams[streamID])){
    if (!(tmpstatus == "CLOSED") && !(tmpstatus == "FAILED")){
      m_osd->setShown(m_tormon);
      m_osd->infoList->adjustColumn(1);
      infoList->adjustColumn(2);

      timeLastTorUse = TQTime::currentTime();

      TQString cleanedFullTarget = Target;
      cleanedFullTarget.replace(TQRegExp("(\\.\\$[A-Z0-9]{40})\\."),".");
      TQString cleanedTarget = cleanedFullTarget.section(":",0,0);
      TQString cleanedPort = cleanedFullTarget.section(":",1,1);
      addrLastTorUse = cleanedFullTarget;

      if (TorkConfig::paranoidMode() > 0)
          emit newIdentity();

      // Find the program associated with the stream
      TQString program = "..";
      TQPixmap programicon;

      if ((tmpstatus == "NEW")){
          if (info.contains("PURPOSE=USER")){
              TQRegExp rx("(SOURCE_ADDR=127.0.0.1:[0-9]+ )");
              rx.search(info);
              TQString port = rx.cap(0).section("SOURCE_ADDR=127.0.0.1:",-1)
                                 .stripWhiteSpace();
              portStream[streamID] = port;
          }else{
              TQString purpose = info.section("PURPOSE=",-1,-1);
              program = streamPurpose[purpose];
              programicon = TQPixmap(SmallIcon("tork_tor"));
          }
      }

      // Assign the circuit and exit server to the stream
      circuitItem* circuitline;
      TQString circuit = "Pending..";
      TQString exitserver;
      TQPixmap exitserverflag;
      // Don't look for circuit if one hasn't been assigned yet
      if (circID != "0") {
        if ((circuitline = (circuitItem*)
                           circuitList->findItem(circID,0)) != 0){
          TQListViewItem* serverline;
          if ((serverline = (TQListViewItem*) circuitExits[circID]) != 0){
              exitserver = serverline->text(1);
              exitserverflag = *serverline->pixmap(1);
          }
          circuit = circuitline->text(2);
        }
      }

      //Assign an icon to illustrate the type of stream
      TQPixmap icon = cachedStreamIcon[cleanedFullTarget];
      if (icon.isNull()){

        TQString iconPath = locate("cache",
                          KMimeType::favIconForURL("http://"+cleanedTarget)
                          +".png");

        if (!iconPath.isEmpty()){

            icon.load( iconPath );
            if (cleanedPort == "443"){
                TQPixmap overlay = KSystemTray::loadIcon( "tork_ssl" );

                if ( !overlay.isNull() )
                {
                  int x = icon.width() - overlay.width();
                  int y = icon.height() - overlay.height();
                  if ( icon.mask() )
                  {
                    TQBitmap mask = *icon.mask();
                    bitBlt( &mask, x, y,
                            overlay.mask() ?
                            const_cast<TQBitmap*>(overlay.mask()) : &overlay,
                            0, 0, overlay.width(), overlay.height(),
                            overlay.mask() ? OrROP : SetROP );
                    icon.setMask(mask);
                  }
                  bitBlt( &icon, x, y, &overlay );
                }
            }

        }else{
            int i;
            for (i = 0; _port_icon[i].port; ++i) {
                portsandicons_t *pics = &_port_icon[i];
                if (cleanedPort == pics->port){
                    icon = SmallIcon(pics->icon);
                    if ((!pics->secure) && (!pics->display)){
                        pics->display = DONT_DISPLAY_AGAIN;
                        if (pics->screaminglyinsecure)
                            emit showScreamingNotice(cleanedPort);
                        else
                            emit showSecurityNotice(cleanedPort);
                    }
                }
            }
        }
        cachedStreamIcon[cleanedFullTarget] = icon;
      }

      //Assign an icon to illustrate the stream status
      TQPixmap statusicon = streamStatusIcon[tmpstatus];

      //Display the entries in the UI

      //Add to the traffic log if necessary
      if (TorkConfig::logTorTraffic()){
        torTrafficLine = new TQListViewItem(TorTraffic, streamID,
                                           TQDateTime::currentDateTime().
                                            toString(TQt::ISODate).
                                            replace("T"," "),
                                           cleanedFullTarget,
                                           circuit);
        torTrafficLine->setPixmap( 2, icon );
      }

      // The stream in the 'Connections' Pane
      streamline = new streamItem(streamList, streamID, program,
                                  cleanedFullTarget, "",
                                  "0 B/s", exitserver,
                                  circuit);
      streamline->setPixmap(1,programicon);
      streamline->setPixmap(2,icon);
      streamline->setPixmap(3,statusicon);
      streamline->setPixmap(5,exitserverflag);
      streamline->setDragEnabled(true);
      streamline->setDropEnabled(true);

      //The stream in the OSD display
      osdstreamline = new TQListViewItem(m_osd->infoList,streamID,
                                        cleanedTarget,"","0 B/s", circuit);
      osdstreamline->setPixmap(2,statusicon);
      osdstreamline->setPixmap(1,icon);

      // Cache for quick reference
      streams[streamID] = streamline;
      osdstreams[streamID] = osdstreamline;
      logstreams[streamID] = torTrafficLine;


    }

  }else{

      osdstreamline = osdstreams[streamID];

      if (tmpstatus == "CLOSED"){
          kdDebug() << "progcnt: " << progDisplayCounter << endl;
          if ((streamline->text(1) != "..") &&
             (progDisplayCounter > 0))
              progDisplayCounter--;
          streams.erase(streamID);
          streamBwIn.erase(streamID);
          streamBwOut.erase(streamID);
          osdstreams.erase(streamID);
          portStream.erase(streamID);
          logstreams.erase(streamID);
          if (osdstreamline) delete osdstreamline;
          delete streamline;
          return;
      }

      TQPixmap statusicon = streamStatusIcon[status.stripWhiteSpace()];
      streamline->setPixmap(3,statusicon);
      osdstreamline->setPixmap(2,statusicon);


      // If the stream does not have a verbose circuit description, add one
      if ((streamline->text(6) == "Pending..")){

          TQString circuit = "Pending..";
          TQString exitserver;
          TQPixmap exitserverflag;

          circuitItem* circuitline;
          // Don't look for circuit if one hasn't been assigned yet
          if (circID != "0") {
            if ((circuitline = (circuitItem*) circuitList->findItem(circID,0)) != 0){
                TQListViewItem* serverline;
                if ((serverline = (TQListViewItem*) circuitExits[circID]) != 0){
                    exitserver = serverline->text(1);
                    exitserverflag = *serverline->pixmap(1);
                }
                circuit = circuitline->text(2);
            }

            if ((torTrafficLine = logstreams[streamID])){
                torTrafficLine->setText(3,circuit);
            }

            streamline->setText(6, circuit);
            streamline->setPixmap(5,exitserverflag);
            streamline->setText(5,exitserver);

            osdstreamline->setPixmap(4,exitserverflag);
            osdstreamline->setText(4,exitserver);
          }
      }

      if (tmpstatus == "SUCCEEDED"){
        //HACK: this is too process intensive if there are many short-lived
        //      streams so we only look for the program if we aren't
        //      already displaying it in MAXPROGDISPLAY streams and there's 
        //      less than MAXPROGDISPLAY * 3 streams active in total.
        //      There's also no point in looking up the program unless
        //      the connection is successful
        if (streamline->text(1) == ".."){
          if ((streamList->childCount() < (MAXPROGDISPLAY * 3))
             && (progDisplayCounter < MAXPROGDISPLAY)) {
            TQString program = parseStreamPort(portStream[streamID]);
            TQPixmap programicon = streamProgram(program);
            streamline->setText(1,program);
            streamline->setPixmap(1,programicon);
            progDisplayCounter++;
          }
        }
      }
  }


}

TQString torkView::parseStreamPort(const TQString &str_port)
{

    int m_port = str_port.toInt();

    #define MAX_PROC_STR_LEN 32 /* /proc/1234/fd/1234 or socket:[12345] */
    #define PROC_NET_TCP_PATH "/proc/net/tcp"
    #define PROC_NET_UDP_PATH "/proc/net/udp"
    char fdpath[MAX_PROC_STR_LEN];
    char lbuf[MAX_PROC_STR_LEN];
    struct dirent *pde;
    DIR *pdir;

    TQString line;
    TQString inode;
    bool foundIt = false;


    TQFile tcp("/proc/net/tcp") ;
    tcp.open (IO_ReadOnly) ;
    TQTextStream input(&tcp) ;

    while (!input.eof())
    {
            TQString     line = input.readLine() ;
            TQStringList bits = TQStringList::split (TQRegExp("[ :]+"), line) ;
            int         port = bits[2].toLong(0, 16) ;

            if (port == m_port)
            {
                inode = bits[13];
                break;
            }
    }
    
    if (inode.isEmpty())
        return TQString();

    TQDir d = TQDir( "/proc" );
    TQStringList dirs = d.entryList( TQDir::Dirs );
    TQStringList::Iterator it;
    for ( it = dirs.begin(); it != dirs.end(); ++it )
    {

        TQDir fd = TQDir( "/proc/" +*it+"/fd" );
        if (!fd.exists()) 
            continue;

        TQString path = "/proc/" +*it+"/fd";

        if ((pdir = opendir((const char*)path)) == NULL)
            continue;

        while ((pde = readdir(pdir)) != NULL) {

            snprintf(fdpath, MAX_PROC_STR_LEN, "/proc/%s/fd/%s", (const char*)*it, pde->d_name);
            fdpath[MAX_PROC_STR_LEN - 1] = '\0';
            int len = readlink(fdpath, lbuf, MAX_PROC_STR_LEN);

            if (len < 0 || len > MAX_PROC_STR_LEN)
                continue;

            lbuf[len] = '\0';

            if (TQString(lbuf).contains(inode)){
                foundIt = true;
                TQFile file( "/proc/"+*it+"/cmdline" );
                file.open( IO_ReadOnly );
                if ( !file.isOpen() ) 
                    continue;
                TQTextStream t( &file );
                TQString program = t.readLine();
                program.replace('\0',' ');
                program = program.section(" ",0,0).section("/",-1);
                return program;

            }
        }
        closedir(pdir);

        if (foundIt) break;
    }
    return TQString();
}

void torkView::circuitStatusUpdated(const TQString &circuitID, const TQString &status, const TQString &server, const TQString &exit)
{

    TQString tmpstatus = status.lower().stripWhiteSpace();

    circuitItem* circuitline;
    if ((circuitline = (circuitItem*)circuitList->findItem(circuitID,0)) == 0){
        circuitline = new circuitItem(circuitList, circuitID, "",server);
        circuitline->setDragEnabled(true);
        circuitline->setDropEnabled(true);
    }else{
        circuitline->setText(2,server);
    }

    for( uint index = 0; index < circuitIconList.count(); index++ ) {
        if ( circuitIconList[index].contains(tmpstatus)) {
            circuitline->setPixmap(1,TQPixmap(SmallIcon("tork_"+circuitIconList[index].first())));
            continue;
        }
    }

    if (tmpstatus.contains("closed") || tmpstatus.contains("failed")){
        delete circuitline;
        circuitExits.erase(circuitID);
    }else if (!exit.isEmpty()){
        TQListViewItem* serverline;
        if ((serverline = (TQListViewItem*) serverList->findItem(exit,2)) != 0){
            circuitExits[circuitID] = serverline;
        }
    }
}


void torkView::ORStatusUpdated(const TQString &ORID, const TQString &status)
{


    TQString tmpstatus = status.lower().stripWhiteSpace();

    TQListViewItem* ORline = ORList->findItem(ORID,1);
    if (ORline == 0)
        ORline = new TQListViewItem(ORList, "", ORID);

    if (tmpstatus.contains("closed") || tmpstatus.contains("failed")){
        delete ORline;
        if (entryGuards[ORID])
            entryGuards.remove(ORID);
        return;
    }

    if (entryGuards[ORID]){
        guardStatusUpdated(ORID, status);
        return;
    }

    for( uint index = 0; index < iconList.count(); index++ ) {
        if ( iconList[index].contains(tmpstatus)) {
            ORline->setPixmap(0,TQPixmap(SmallIcon("tork_"+iconList[index].first())));
            return;
        }
    }

}

void torkView::guardStatusUpdated(const TQString &ORID, const TQString &status)
{

    entryGuards[ORID] = status;

    TQString tmpstatus = status.lower().stripWhiteSpace();

    TQListViewItem* ORline = ORList->findItem(ORID,1);
    if (ORline == 0)
        ORline = new TQListViewItem(ORList, "", ORID);

    for( uint index = 0; index < iconList.count(); index++ ) {
        if ( guardIconList[index].contains(tmpstatus)) {
            ORline->setPixmap(0,TQPixmap(SmallIcon("tork_guard_"+guardIconList[index].first())));
            return;
        }
    }

}

void torkView::infoUpdated(const TQString &type, const TQString &summary, const TQString &)
{
   static int id = 0;

   uint total = 0;
   for( uint index = 0; index < summary.length(); index += 120) {
        total++;
    }
   uint count = 1;
   TQString tmpid;
   for( uint index = 0; index < summary.length(); index += 120) {
        id++;
        tmpid = TQString("00000000000%1").arg(id).right(10);
        new TQListViewItem(infoList, TQDateTime::currentDateTime ().toString(TQt::ISODate).replace("T"," "), 
            tmpid, type, TQString("(%1 of %2) %3").arg(count)
                                              .arg(total)
                                              .arg(summary.mid(index,120)));
        count++;
    }


}
void torkView::bwUpdated(const TQString &in, const TQString &out)
{


    static time_t time_of_last_bw = time(NULL);
    static time_t time_of_last_cg = time(NULL);
    //static time_t time_of_last_tn = time(NULL);
    static time_t time_of_last_cbws = time(NULL);

    time_t now = time(NULL);


    //Tor Tx/Rx
    torbtx += out.toInt();
    torbrx += in.toInt();

    if (time_of_last_bw + MAX_BW_RATE <= now){
        int secs =  now - time_of_last_bw;
        time_of_last_bw = now;
        reportBW(secs);
    }


    if (time_of_last_cg + MAX_CG_RATE < now){
        emit signalCheckGuards();
        time_of_last_cg = now;
    }

//     if (time_of_last_tn + MAX_TN_RATE < now){
//         emit signalCheckTorNet();
//         time_of_last_tn = now;
//     }

    if (time_of_last_cbws + MAX_CBWS_RATE < now){
        emit signalCheckBWSettings();
        time_of_last_cbws = now;
    }

}

TQPixmap torkView::streamProgram(const TQString &program)
{

    
    TQString prog = TDEGlobal::iconLoader()->iconPath(program, TDEIcon::Small, true);
    if (prog.isEmpty())
        return SmallIcon( "exec" );
    else
        return SmallIcon( program );

}

void torkView::streamBwUpdated(const TQString &stream, const TQString &in, const TQString &out)
{

    //Tor Tx/Rx
    streamBwIn[stream] += in.toInt();
    streamBwOut[stream] += out.toInt();

}

void torkView::reportBW(int secs)
{

    if ((streamList->childCount() == 0) && m_osd->isShown())
        m_osd->hide();

    //Calculate Streams Tx/Rx

	for ( TQMap<TQString, streamItem*>::Iterator stream = streams.begin(); stream != streams.end(); ++stream )
	{

        if (stream.data()){
            stream.data()->calcBWRate(streamBwIn[stream.key().latin1()],
                                      streamBwOut[stream.key().latin1()], secs);
            TQString sbw =
                         BytesPerSecToString(
                         stream.data()->mSpeedHistoryRx[stream.data()->mSpeedHistoryPtr] +
                         stream.data()->mSpeedHistoryTx[stream.data()->mSpeedHistoryPtr],0);
            //Overlay here
//            TQPixmap icon = stream.data()->pixmap(3);
//             TQPixmap pm(*(stream.data()->pixmap(3)));
//             TQPainter p;
//             p.begin(&pm);
//            
//          p.drawText(stream.data()->pixmap(3)->rect(),TQt::AlignCenter,sbw);
//             p.end();
//             stream.data()->setPixmap(3,pm);

            stream.data()->setText(4,sbw);
            TQListViewItem* osdstreamline = osdstreams[stream.data()->text(0)];
            osdstreamline->setText(3,sbw);
        }
    }

    //Calculate System Tx/Rx
    unsigned int sysbrx = 0;
    unsigned int sysbtx = 0;
	for ( TQStringList::Iterator it = mSysDevPathList.begin(); it != mSysDevPathList.end(); ++it )
	{
		if ((*it).isEmpty())
			continue;
       	sysbrx += readInterfaceNumValue((*it),"rx_bytes");
    	sysbtx += readInterfaceNumValue((*it),"tx_bytes");

    }

    //Calculate Tor Tx/Rx
    unsigned int btx = (torbtx - mBTx);
    unsigned int brx = (torbrx - mBRx);
	mBRx = torbrx;
	mBTx = torbtx;



    //Calculate Tor Tx/Rx
    if (++mSpeedBufferPtr >= SPEED_BUFFER_SIZE)
        mSpeedBufferPtr = 0;


    mSpeedBufferTx[mSpeedBufferPtr] = ((btx )*(1000.0f/(secs * 1000)));
    mSpeedBufferRx[mSpeedBufferPtr] = ((brx )*(1000.0f/(secs * 1000)));


    if (++mSpeedHistoryPtr >= HISTORY_SIZE)
        mSpeedHistoryPtr = 0;
    mSpeedHistoryRx[mSpeedHistoryPtr] = calcSpeed(mSpeedBufferRx);
    mSpeedHistoryTx[mSpeedHistoryPtr] = calcSpeed(mSpeedBufferTx);

    mMaxSpeedAge--;

    if (mSpeedHistoryTx[mSpeedHistoryPtr] > mMaxSpeed) {
        mMaxSpeed = mSpeedHistoryTx[mSpeedHistoryPtr];
        mMaxSpeedAge = HISTORY_SIZE;
    }
    if (mSpeedHistoryRx[mSpeedHistoryPtr] > mMaxSpeed)  {
        mMaxSpeed = mSpeedHistoryRx[mSpeedHistoryPtr];
        mMaxSpeedAge = HISTORY_SIZE;
    }
    if (mMaxSpeedAge < 1)
        calcMaxSpeed();


    //Calculate Sys Tx/Rx

	if (!mFirstUpdate) { // a primeira velocidade sempre eh absurda, para evitar isso temos o mFirstUpdate
		if (++sys_mSpeedBufferPtr >= SPEED_BUFFER_SIZE)
			sys_mSpeedBufferPtr = 0;

		sys_mSpeedBufferTx[sys_mSpeedBufferPtr] = ((sysbtx - sysmBTx)*(1000.0f/(secs * 1000)));
		sys_mSpeedBufferRx[sys_mSpeedBufferPtr] = ((sysbrx - sysmBRx)*(1000.0f/(secs * 1000)));

		if (++sys_mSpeedHistoryPtr >= HISTORY_SIZE)
			sys_mSpeedHistoryPtr = 0;
		sys_mSpeedHistoryRx[sys_mSpeedHistoryPtr] = calcSpeed(sys_mSpeedBufferRx);
		sys_mSpeedHistoryTx[sys_mSpeedHistoryPtr] = calcSpeed(sys_mSpeedBufferTx);

		sys_mMaxSpeedAge--;

		if (sys_mSpeedHistoryTx[sys_mSpeedHistoryPtr] > sys_mMaxSpeed) {
			sys_mMaxSpeed = sys_mSpeedHistoryTx[sys_mSpeedHistoryPtr];
			sys_mMaxSpeedAge = HISTORY_SIZE;
		}
		if (sys_mSpeedHistoryRx[sys_mSpeedHistoryPtr] > sys_mMaxSpeed)  {
			sys_mMaxSpeed = sys_mSpeedHistoryRx[sys_mSpeedHistoryPtr];
			sys_mMaxSpeedAge = HISTORY_SIZE;
		}
		if (sys_mMaxSpeedAge < 1)
			sys_calcMaxSpeed();
	}

    mFirstUpdate = false;

	sysmBRx = sysbrx;
	sysmBTx = sysbtx;

    //Update Main Graphs
    emit updateStats();

    //Update ChartBar in OSD
    float bitRateIn = brx;// * 8.0 / (secondselapsed / 1000.0);
    float bitRateOut = btx;// * 8.0 / (secondselapsed / 1000.0);

    int8_t upperIn = (int8_t) (100.0 * bitRateIn /mMaxSpeed);
    if (upperIn < 0) upperIn = 0;
    else if (upperIn > 100) upperIn = 100;
    int8_t upperOut = (int8_t) (100.0 * bitRateOut / mMaxSpeed );
    if (upperOut < 0) upperOut = 0;
    else if (upperOut > 100) upperOut = 100;

    TQString kbsrx = BytesPerSecToString(mSpeedHistoryRx[mSpeedHistoryPtr]);
    TQString kbstx = BytesPerSecToString(mSpeedHistoryTx[mSpeedHistoryPtr]);

    m_osd->m_graphIn->addPercentReading(upperIn, false);
    m_osd->m_graphOut->addPercentReading(upperOut, false);
    m_osd->m_graphIn->setLabel(TQString("Dn: %1")
                               .arg(kbsrx));
    m_osd->m_graphOut->setLabel(TQString("Up: %1")
                               .arg(kbstx));

    // Update Tray and StatusBar
    emit updateTrayStats(BytesToString(mBRx),
                         BytesToString(mBTx),
                         kbsrx,
                         kbstx);
}

unsigned long torkView::readInterfaceNumValue(TQString interface,
                                              const char* name) {
	// stdio functions appear to be more fast than TQFile?
	FILE* fp = fopen((interface+"/statistics/"+name).latin1(), "r");
	if (!fp)
      return 0;
	long retval;
	fscanf(fp, "%lu", &retval);
	fclose(fp);
	return retval;
}


void torkView::activeServersUpdated( const TQStringList &servers)
{
    TQListViewItem* tm;
    TQStringList tmpservers = servers;
	for ( TQStringList::Iterator it = tmpservers.begin(); it != tmpservers.end(); ++it )
	{
		if ((*it).isEmpty())
			continue;
        if ( (tm = serverList->findItem((*it),1)) > 0){
            tm->setPixmap(0,TQPixmap(SmallIcon("tork_green")));
        }else{
            tm = new TQListViewItem(serverList, (*it));
            tm->setPixmap(0,TQPixmap(SmallIcon("tork_green")));
        }
	}

}

void torkView::serverStatusUpdated(const TQString &ip,const TQString &fp,
                                   const TQString &server, const TQString &statuses)
{
    TQListViewItem* tm;
    
    if (!(tm = torservers[fp])){
      tm = new TQListViewItem(serverList, "", (server), fp, statuses);
      torservers[fp] = tm;
    }

    TQString cc;
    int country_id = 0;
    GeoIP * gi = 0;
    if (geoip_db)
#ifndef EXTERNAL_GEOIP
       gi = GeoIP_open(locate("data", "tork/geoip/GeoIP.dat").ascii(),0);
#else
       gi = GeoIP_new(GEOIP_STANDARD);
#endif

    if (gi){
        country_id = GeoIP_id_by_name(gi, ip);
        cc = GeoIP_country_code[country_id];
        GeoIP_delete(gi);
    
        if (!m_countryList.contains(country_id))
            m_countryList << country_id;
    }else
        cc = "--";

    TQString ccode = TQString("%1").arg(country_id);
    tm->setText(4,ccode);
    tm->setText(5,ip);

/*
    TQRegExp rx("^[0-9]{1,3}\\.");
    rx.search(ip);
    TQString tmp = rx.cap(0);
    if (!m_subnet16List.contains(tmp))
        m_subnet16List << tmp;
*/
    if (cc == "--")
        tm->setPixmap(1,TQPixmap(SmallIcon("help")));
    else
        tm->setPixmap(1,TQPixmap(SmallIcon("tork_" + cc.lower())));

    TQString icontouse;
    if ((statuses.contains("Stable")) && (statuses.contains("Running")) && (statuses.contains("Fast")))
        icontouse = "tork_green";
    else if ((statuses.contains("Fast")) && (statuses.contains("Running")))
        icontouse = "tork_yellow";
    else if ((statuses.contains("Running")) && (statuses.contains("Stable")))
        icontouse = "tork_orange";
    else if ((statuses.contains("Running")))
        icontouse = "tork_little";
    else // if ((statuses.contains("Valid")))
        icontouse = "tork_red";

    if ((statuses.contains("Exit")))
        icontouse += "_exit";


    // Update Exclude Nodes if Country is Excluded and this server is new to us

    if (TorkConfig::excludeCountries().contains(ccode)){
        if (!TorkConfig::excludeServersHistory().contains(TQString("%1-%2-%3")
            .arg(ccode).arg(fp).arg(server))){

            TQStringList existingServers = TorkConfig::excludeServersHistory();
            existingServers.append(TQString("%1-%2-%3").arg(ccode).arg(fp).arg(server));
            TorkConfig::setExcludeServersHistory(existingServers);

            TQStringList permList;
            permList = TorkConfig::excludeNodes();
            TQString node = "$"+getFPFromFPDigest(fp);
            permList.append(node);

        }
    }


    tm->setPixmap(0,TQPixmap(SmallIcon(icontouse)));

}

void torkView::switchColors()
{
	// switch the foreground/background colors of the label
/*	TQColor color = Settings::col_background();
	Settings::setCol_background( Settings::col_foreground() );
	Settings::setCol_foreground( color );
*/
	settingsChanged();
}

void torkView::settingsChanged()
{
/*	sillyLabel->setPaletteBackgroundColor( Settings::col_background() );
	sillyLabel->setPaletteForegroundColor( Settings::col_foreground() );

	// i18n : internationalization
	sillyLabel->setText( i18n("This project is %1 days old").arg(Settings::val_time()) );
	emit signalChangeStatusbar( i18n("Settings changed") );*/
}

void torkView::displayError( const TQString &caption, const TQString &infol)
{

    if (!circuitList->recentDropEvent())
        return;
    TQString info = infol;;
    info.replace(TQRegExp("(\\$[A-Z0-9]{40})(~|=)"),"");

    delete m_pop;

    KPassivePopup* pop;

    TQPoint pnt;
    if (tdemain->isActiveWindow()){
        pop = new KPassivePopup( tdemain );
        pnt = tdemain->pos() += tdemain->m_view->pos() += tdemain->m_view->circuitList->pos() +=
                tdemain->m_view->circuitList->getMousePos() += tdemain->m_view->splitter3->pos() += 
                tdemain->m_view->splitter4->pos() += tdemain->m_view->groupBox1->pos();
    }else{
        pop = new KPassivePopup( tdemain->_tray );
        pnt = tdemain->_tray->pos();
    }
    pop->setView( caption,info );
    pop->show(TQPoint(pnt));

    m_pop = pop;
}

void torkView::displayServer( const TQString &caption, const TQString &info)
{


    KPassivePopup* pop;

    TQPoint pnt;
    if (tdemain->isActiveWindow()){
        pop = new KPassivePopup( serverList );
        //pnt = tdemain->pos()  -= tdemain->m_view->serverList->getMousePos() -= tdemain->m_view->serverList->getMousePos() -= tdemain->m_view->serverList->getMousePos();
    }else{
        pop = new KPassivePopup( tdemain->_tray );
        pnt = tdemain->_tray->pos();
    }
    pop->setView( caption,info );
    //pop->show(TQPoint(pnt));
    pop->show();


}

void torkView::showServerBW(const TQString &fp )
{

    TQString fl;
    TQString tmpFile;
    fl = TQString("http://www.noreply.org/tor-running-routers/%1/node-traf-%2.png")
                .arg(fp.left(2)).arg(fp);
    TDEIO::NetAccess::download( fl, tmpFile, 0L );
    kapp->processEvents();
    streamList-> setPaletteBackgroundPixmap( TQPixmap(tmpFile) );
}


void torkView::hidePopup( )
{

    delete m_pop;

}

void torkView::populateMenu()
{
    Anonymizer->clear();
    TQFont font;

    //Welcome
    welcomeitem = new HitWidget(TQString::null, TQString::null);
    welcomeheaderLabel = new TQLabel(welcomeitem);
    welcomeheaderLabel->setText(i18n("Press 'Play' to get started!"));
    font.setBold( true );
    welcomeheaderLabel->setFont( font );
    welcomeitem->insertHeaderWidget(0,welcomeheaderLabel);
    
    welcomeitem->setIcon("tork_pressplay");
    welcomeitem->setDescriptionText("<qt>"+i18n("- <b>Press 'Play' to connect to Tor. (You can also use the toolbar icons.)</b>")+"</qt>");
//    item->icon->setURL("konqueror");
    welcomeitem->setPropertiesText("<qt>"+i18n(
                            "- The 'Tor Network' tab shows you the state of the Tor network, including your Tor Traffic. <br> "
                            "- You can use the 'Traffic Log' tab to view Tor and Non-Tor Traffic on your system.<br> "
                            "- You can use the 'Tor Log' tab to view warning messages from Tor itself. <br> "
                            "- Once Tor is up and running you can use the services listed below. <br> "
                            )+"</qt>");

    KURLLabel *buttonStart = new KURLLabel(welcomeitem);
    buttonStart->setPixmap(SmallIcon("info"));
    welcomeitem->insertHitWidget(0,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(aboutTor()));

    buttonStart = new KURLLabel(welcomeitem);
    buttonStart->setText(i18n("What You Need To Know When Using TorK!"));
    welcomeitem->insertHitWidget(1,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(aboutTor()));

    paranoidmodeicon = new KURLLabel(welcomeitem);
    welcomeitem->insertHitWidget(2,paranoidmodeicon);
    connect(paranoidmodeicon, SIGNAL(leftClickedURL()), SIGNAL(aboutParanoidMode()));

    paranoidmodetext = new KURLLabel(welcomeitem);
    welcomeitem->insertHitWidget(3,paranoidmodetext);
    connect(paranoidmodetext, SIGNAL(leftClickedURL()), SIGNAL(aboutParanoidMode()));


    paranoidmodeicon->setPixmap(SmallIcon("tork_penguin"));
    paranoidmodetext->setText(i18n("In Normal mode!"));

    TQStringList qconf;
    qconf << "Clnt/Exit" << "Clnt/Relay" << "Exit" << "Relay" << "Client" << "Custom" << "Remote" << "Local";
    welcomeitem->score->setHidden(false);
    welcomeitem->score->insertStringList(qconf);
    welcomeitem->score->setPalette(TQPalette(TQt::white,TQt::white));

    welcomeitem->score->setCurrentItem(TorkConfig::quickConfigure());

    connect(welcomeitem->score, SIGNAL(activated(int)), SLOT(changeQuickConfigure(int)));

    Anonymizer->insertItem(welcomeitem);
    connect(welcomeitem->icon, SIGNAL(leftClickedURL()), SIGNAL(startEverything()));


    TQLabel *headerLabel;

    //Firefox
    firefoxitem = 0L;
#ifndef LIVECD
    if (TorkConfig::availablePrograms().contains("firefox")){

        firefoxitem = new HitWidget(TQString::null, TQString::null);

        headerLabel = new TQLabel(firefoxitem);
        headerLabel->setText(i18n("Anonymous Browsing (with Firefox)"));
        font.setBold( true );
        headerLabel->setFont( font );
        firefoxitem->insertHeaderWidget(0,headerLabel);
        
        firefoxitem->setIcon("tork_firefox");
        firefoxitem->setDescriptionText("<qt>"+i18n("<b>Click the icon to launch an anonymous browsing session in Firefox. </b><br>"
                                )+"</qt>");
        firefoxitem->setPropertiesText("<qt>"+i18n(
                                "- TorK will make a copy of your normal Firefox settings and modify them for anonymous browsing. <br>"
                                "- Firefox will use Privoxy in combination with Tor to anonymize your browsing. <br>"
                                "- No other Firefox sessions will be anonymous!<br>"
                                )+"</qt>");
        firefoxitem->icon->setURL("firefox");

        //TQComboBox* countries = new TQComboBox( FALSE, "this" );
        //firefoxitem->insertWidget(1,countries);

        buttonStart = new KURLLabel(firefoxitem);
        buttonStart->setPixmap(SmallIcon("info"));
        firefoxitem->insertHitWidget(0,buttonStart);
        connect(buttonStart, SIGNAL(leftClickedURL()), SLOT(downloadTorButton()));

        buttonStart = new KURLLabel(firefoxitem);
        buttonStart->setText(i18n("Install TorButton First (Recommended)"));
        firefoxitem->insertHitWidget(1,buttonStart);
        connect(buttonStart, SIGNAL(leftClickedURL()), SLOT(downloadTorButton()));

        Anonymizer->insertItem(firefoxitem);
        connect(firefoxitem->icon, SIGNAL(leftClickedURL()), SLOT(anonymousFirefox()));
    }
    //Kopete
#endif

    //Anonymous Mail
    mixminionitem = new HitWidget(TQString::null, TQString::null);
    headerLabel = new TQLabel(mixminionitem);
    headerLabel->setText(i18n("Anonymous Email"));
    font.setBold( true );
    headerLabel->setFont( font );
    mixminionitem->insertHeaderWidget(0,headerLabel);
    
    mixminionitem->setIcon("tork_mail");
    mixminionitem->setDescriptionText("<qt>"+i18n("<b>Click the icon to compose and send an anonymous email.</b><br>"
                            )+"</qt>");
    mixminionitem->setPropertiesText("<qt>"+i18n(
                            "- The email will be routed through the anonymizing mixminion network. <br>"
                            "- Delivery of anonymous email can take a while, sometimes up to 24 hours! <br>"
                            "- If you don't have mixminion already, click the link below to install it. <br>"
                            "- Visit the mixminion homepage to find out more. <br>"
                            )+"</qt>");


//     TQStringList qconf;
//     qconf << "Simple" << "KMail";
// 
//     TQFont f( sshitem->score->font().rawName(),
//               sshitem->score->font().pointSize() - 1 );
//     mixminionitem->score->setFont( f );
//     mixminionitem->score->setHidden(false);
//     mixminionitem->score->insertStringList(shellsAvailable);
//     mixminionitem->score->setPalette(TQPalette(TQt::white,TQt::white));
//     connect(mixminionitem->score, SIGNAL(activated(int)),mixminionitem,
//             SLOT(changeTerminalUrl(int)));


    buttonStart = new KURLLabel(mixminionitem);
    buttonStart->setPixmap(SmallIcon("info"));
    mixminionitem->insertHitWidget(0,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SLOT(downloadMixminion()));

    buttonStart = new KURLLabel(mixminionitem);
    buttonStart->setText(i18n("Install Mixminion"));
    mixminionitem->insertHitWidget(1,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SLOT(downloadMixminion()));

    buttonStart = new KURLLabel(mixminionitem);
    buttonStart->setPixmap(SmallIcon("konqueror"));
    mixminionitem->insertHitWidget(2,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(mixminionHome()));

    buttonStart = new KURLLabel(mixminionitem);
    buttonStart->setText(i18n("Visit the Mixminion Project page."));
    mixminionitem->insertHitWidget(3,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(mixminionHome()));

    Anonymizer->insertItem(mixminionitem);
    connect(mixminionitem->icon, SIGNAL(leftClickedURL()), SLOT(sendAnonymousEmail()));

    konqitem=0L;
    //Konqueror
#ifndef LIVECD
    if (TorkConfig::availablePrograms().contains("konqueror")){
      konqitem = new HitWidget(TQString::null, TQString::null);
      headerLabel = new TQLabel(konqitem);
      headerLabel->setText(i18n("Anonymous Browsing (with Konqueror)"));
      font.setBold( true );
      headerLabel->setFont( font );
      konqitem->insertHeaderWidget(0,headerLabel);
      
      konqitem->setIcon("tork_konqueror_play");

      if (TorkConfig::tDEUsesTor())
          konqitem->icon->pixmap()->fill(TQt::red);

      konqitem->setDescriptionText("<qt>"+i18n("<b>Click the icon to launch an anonymous browsing session. </b><br>"
                              )+"</qt>");
      konqitem->setPropertiesText("<qt>"+i18n(
                              "- This will also make any other Konqueror sessions you use anonymous. <br>"
                              "- Konqueror windows that have anonymous browsing enabled are a funny green colour.<br>"
                              "- Konqueror uses Privoxy in combination with Tor to anonymize your browsing. <br>"
                              "- You can toggle this setting at any time using the Konqueror icon in the toolbar or the miniview.<br>"
                              )+"</qt>");

      konqitem->icon->setURL("konqueror");

      buttonStart = new KURLLabel(konqitem);
      buttonStart->setPixmap(SmallIcon("configure"));
      konqitem->insertHitWidget(0,buttonStart);
      connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(showMyKonqueror()));

      buttonStart = new KURLLabel(konqitem);
      buttonStart->setText(i18n("Configure Anonymous Konqueror"));
      konqitem->insertHitWidget(1,buttonStart);
      connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(showMyKonqueror()));

      configurePriv = new KURLLabel(konqitem);
      configurePriv->setPixmap(SmallIcon("configure"));
      konqitem->insertHitWidget(2,configurePriv);
      connect(configurePriv, SIGNAL(leftClickedURL()), SIGNAL(configurePrivoxy()));

      configurePrivText = new KURLLabel(konqitem);
      configurePrivText->setText(i18n("Configure Privoxy"));
      konqitem->insertHitWidget(3,configurePrivText);
      connect(configurePrivText, SIGNAL(leftClickedURL()), SIGNAL(configurePrivoxy()));

      Anonymizer->insertItem(konqitem);
      connect(konqitem->icon, SIGNAL(leftClickedURL()), SIGNAL(konqWithTor()));
    }
    
#endif


    operaitem = 0L;
#ifndef LIVECD

    if (TorkConfig::availablePrograms().contains("opera")){

        operaitem = new HitWidget(TQString::null, TQString::null);
        headerLabel = new TQLabel(operaitem);
        headerLabel->setText(i18n("Anonymous Browsing (with Opera)"));
        font.setBold( true );
        headerLabel->setFont( font );
        operaitem->insertHeaderWidget(0,headerLabel);
        
        operaitem->setIcon("tork_opera");
        operaitem->setDescriptionText("<qt>"+i18n("<b>Click the icon to launch an anonymous browsing session in Opera. </b><br>"
                                )+"</qt>");
        operaitem->setPropertiesText("<qt>"+i18n(
                                "- TorK will make a copy of your normal Opera settings and modify them for anonymous browsing. <br>"
                                "- Opera will use Privoxy in combination with Tor to anonymize your browsing. <br>"
                                "- No other Opera sessions will be anonymous!<br>"
                                )+"</qt>");
        operaitem->icon->setURL("opera");
        Anonymizer->insertItem(operaitem);
        connect(operaitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(anonymizedOpera(const TQString&)));
    }
#endif


    hiddenservicesitem = 0L;
    //Hidden Services
    hiddenservicesitem = new HitWidget(TQString::null, TQString::null);

    headerLabel = new TQLabel(hiddenservicesitem);
    headerLabel->setText(i18n("Anonymous Websites and Web Services"));
    font.setBold( true );
    headerLabel->setFont( font );
    hiddenservicesitem->insertHeaderWidget(0,headerLabel);
    
    hiddenservicesitem->setIcon("tork_agent");
    hiddenservicesitem->setDescriptionText("<qt>"+i18n("<b>Click the icon to create an anonymous web site or manage existing ones.</b><br>"
                            )+"</qt>");

    setHiddenServicesText();

    buttonStart = new KURLLabel(hiddenservicesitem);
    buttonStart->setPixmap(SmallIcon("konqueror"));
    hiddenservicesitem->insertHitWidget(0,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(hiddenServices()));

    buttonStart = new KURLLabel(hiddenservicesitem);
    buttonStart->setText(i18n("Search Hidden Services"));
    hiddenservicesitem->insertHitWidget(1,buttonStart);
    connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(hiddenServices()));

    Anonymizer->insertItem(hiddenservicesitem);
    connect(hiddenservicesitem->icon, SIGNAL(leftClickedURL()), SIGNAL(showMyHiddenServices()));


    //Kopete

    kopeteitem = 0L;
#ifndef LIVECD

    if (TorkConfig::availablePrograms().contains("kopete")){
        kopeteitem = new HitWidget(TQString::null, TQString::null);

        headerLabel = new TQLabel(kopeteitem);
        headerLabel->setText(i18n("Anonymous Instant Messaging/IRC (with Kopete)"));
        font.setBold( true );
        headerLabel->setFont( font );
        kopeteitem->insertHeaderWidget(0,headerLabel);
        
        kopeteitem->setIcon("kopete");
        kopeteitem->setDescriptionText("<qt>"+i18n("<b> Click to start an anonymized Kopete session.</b><br>"
                                )+"</qt>");
        kopeteitem->setPropertiesText("<qt>"+i18n(
                                "- You won't be anonymous if you use your real name!<br>"
                                )+"</qt>");
        kopeteitem->icon->setURL("kopete  --caption 'Anonymous IM Session - Launched From TorK'");
        Anonymizer->insertItem(kopeteitem);
        connect(kopeteitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }
#endif
    //Gaim
    gaimitem = 0L;

#ifndef LIVECD

    if (TorkConfig::availablePrograms().contains("gaim")){
        gaimitem = new HitWidget(TQString::null, TQString::null);
        headerLabel = new TQLabel(gaimitem);
        headerLabel->setText(i18n("Anonymous Instant Messaging/IRC (with Gaim)"));
        font.setBold( true );
        headerLabel->setFont( font );
        gaimitem->insertHeaderWidget(0,headerLabel);
        
        gaimitem->setIcon("gaim");
        gaimitem->setDescriptionText("<qt>"+i18n("<b> Click to start an anonymized Gaim session.</b><br>"
                                )+"</qt>");
        gaimitem->setPropertiesText("<qt>"+i18n(
                                "- You won't be anonymous if you use your real name!<br>"
                                )+"</qt>");
        gaimitem->icon->setURL("gaim");
        Anonymizer->insertItem(gaimitem);
        connect(gaimitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }
#endif
    //Pidgin

    pidginitem = 0L;

#ifndef LIVECD

    if (TorkConfig::availablePrograms().contains("pidgin")){
        pidginitem = new HitWidget(TQString::null, TQString::null);
        headerLabel = new TQLabel(pidginitem);
        headerLabel->setText(i18n("Anonymous Instant Messaging/IRC (with Pidgin)"));
        font.setBold( true );
        headerLabel->setFont( font );
        pidginitem->insertHeaderWidget(0,headerLabel);
        
        pidginitem->setIcon("pidgin");
        pidginitem->setDescriptionText("<qt>"+i18n("<b> Click to start an anonymized Pidgin session.</b><br>"
                                )+"</qt>");
        pidginitem->setPropertiesText("<qt>"+i18n(
                                "- You won't be anonymous if you use your real name!<br>"
                                )+"</qt>");
        pidginitem->icon->setURL("pidgin");
        Anonymizer->insertItem(pidginitem);
        connect(pidginitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }
#endif
    //Gaim
    konversationitem = 0L;

#ifndef LIVECD

    if (TorkConfig::availablePrograms().contains("konversation")){

        konversationitem = new HitWidget(TQString::null, TQString::null);

        headerLabel = new TQLabel(konversationitem);
        headerLabel->setText(i18n("Anonymous Instant Messaging/IRC (with Konversation)"));
        font.setBold( true );
        headerLabel->setFont( font );
        konversationitem->insertHeaderWidget(0,headerLabel);
        
        konversationitem->setIcon("konversation");
        konversationitem->setDescriptionText("<qt>"+i18n("<b> Click to start an anonymized Konversation  session.</b><br>"
                                )+"</qt>");
        konversationitem->setPropertiesText("<qt>"+i18n(
                                "- You won't be anonymous if you use your real name!<br>"
                                )+"</qt>");
        konversationitem->icon->setURL("konversation");
        Anonymizer->insertItem(konversationitem);
        connect(konversationitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }
#endif
    //KSIRC
    ksircitem =0L;

#ifndef LIVECD
    if (TorkConfig::availablePrograms().contains("ksirc")){

        ksircitem = new HitWidget(TQString::null, TQString::null);

        headerLabel = new TQLabel(ksircitem);
        headerLabel->setText(i18n("Anonymous IRC (with KSirc)"));
        font.setBold( true );
        headerLabel->setFont( font );
        ksircitem->insertHeaderWidget(0,headerLabel);
        
        ksircitem->setIcon("ksirc");
        ksircitem->setDescriptionText("<qt>"+i18n("<b> Click to start an anonymous KSirc IRC session.</b><br>"
                                )+"</qt>");
        ksircitem->setPropertiesText("<qt>"+i18n(
                                "- Leaking DNS requests is not fatal but something to keep an eye on. Use the traffic-log.<br>"
                                )+"</qt>");

        ksircitem->icon->setURL("ksirc  --caption 'Anonymous IRC Shell - Launched From TorK'");
        Anonymizer->insertItem(ksircitem);
        connect(ksircitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }

#endif
    //SSH

    TQStringList shellCandidates;
    TQStringList shellsAvailable;
    shellCandidates << "konsole" << "yakuake" << "xterm" << "rxvt" << "gnome-terminal";

    for ( TQStringList::Iterator it = shellCandidates.begin(); it != shellCandidates.end(); it++ )
    {
        if (TorkConfig::availablePrograms().contains(*it))
            shellsAvailable << (*it); 
    }

    TQStringList hkpShellsAvailable = shellsAvailable;

    if (TorkConfig::availablePrograms().contains("x3270"))
        shellsAvailable << "x3270";

    sshitem = 0L;

#ifndef LIVECD
    if (!shellsAvailable.isEmpty()){

        sshitem = new HitWidget(TQString::null, TQString::null);

        headerLabel = new TQLabel(sshitem);
        headerLabel->setText(i18n("Anonymous SSH Session"));
        font.setBold( true );
        headerLabel->setFont( font );
        sshitem->insertHeaderWidget(0,headerLabel);

        sshitem->setIcon("tork_konsolessh");
        sshitem->setDescriptionText("<qt>"+i18n("<b>Click the icon to start a Konsole terminal session.</b><br>"
                                )+"</qt>");
        sshitem->setPropertiesText("<qt>"+i18n(
                                "- Use <b>ssh</b> within the session to connect securely and anonymously. "
                                "e.g. <b> ssh shell.sf.net</b><br>"
                                "- Use the traffic-log tab to ensure you are not leaking DNS requests.<br>"
                                )+"</qt>");

        sshitem->icon->setURL("konsole --caption 'Anonymous SSH Shell - Launched From TorK'");
    
        buttonStart = new KURLLabel(sshitem);
        buttonStart->setPixmap(SmallIcon("help"));
        sshitem->insertHitWidget(0,buttonStart);
        connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(aboutTorify()));
        
        buttonStart = new KURLLabel(sshitem);
        buttonStart->setText(i18n("How can I be sure this is working?"));
        sshitem->insertHitWidget(1,buttonStart);
        connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(aboutTorify()));

        sshitem->shellTitles["konsole"] = " --caption 'Anonymous SSH Shell - Launched From TorK'";
        sshitem->shellTitles["yakuake"] = " --caption 'Anonymous SSH Shell - Launched From TorK'";
        sshitem->shellTitles["xterm"] = " -title 'Anonymous SSH Shell - Launched From TorK'";
        sshitem->shellTitles["rxvt"] = " -title 'Anonymous SSH Shell - Launched From TorK'";
        sshitem->shellTitles["gnome-terminal"] = " --title 'Anonymous SSH Shell - Launched From TorK'";

        TQFont f( sshitem->score->font().rawName(), sshitem->score->font().pointSize() - 1 );
        sshitem->score->setFont( f );
        sshitem->score->setHidden(false);
        sshitem->score->insertStringList(shellsAvailable);
        sshitem->score->setPalette(TQPalette(TQt::white,TQt::white));
        connect(sshitem->score, SIGNAL(activated(int)),sshitem, SLOT(changeTerminalUrl(int)));

        Anonymizer->insertItem(sshitem);
        connect(sshitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }
#endif
    //Telnet
   telnetitem =0L;

#ifndef LIVECD
    if (!shellsAvailable.isEmpty()){

        telnetitem = new HitWidget(TQString::null, TQString::null);

        headerLabel = new TQLabel(telnetitem);
        headerLabel->setText(i18n("Anonymous Telnet Session"));
        font.setBold( true );
        headerLabel->setFont( font );
        telnetitem->insertHeaderWidget(0,headerLabel);
        
        telnetitem->setIcon("tork_konsole");
        telnetitem->setDescriptionText("<qt>"+i18n("<b> This will start a Konsole terminal session.</b><br>"
                                )+"</qt>");
        telnetitem->setPropertiesText("<qt>"+i18n(
                                "- Use <b>telnet</b> within the session to connect anonymously. "
                                "e.g. <b> telnet shell.sf.net 23</b><br>"
                                "- Telnet passwords are sent in clear-text - so do be careful 007!.<br>"
                                )+"</qt>");
        telnetitem->icon->setURL("konsole  --caption 'Anonymous Telnet Session - Launched From TorK'");
        buttonStart = new KURLLabel(telnetitem);
        buttonStart->setPixmap(SmallIcon("help"));
        telnetitem->insertHitWidget(0,buttonStart);
        connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(riskySession()));
        
        buttonStart = new KURLLabel(telnetitem);
        buttonStart->setText(i18n("Why is anonymous telnet risky?"));
        telnetitem->insertHitWidget(1,buttonStart);
        connect(buttonStart, SIGNAL(leftClickedURL()), SIGNAL(riskySession()));

        telnetitem->shellTitles["konsole"] = " --caption 'Anonymous Telnet Session - Launched From TorK'";
        telnetitem->shellTitles["yakuake"] = " --caption 'Anonymous Telnet Session - Launched From TorK'";
        telnetitem->shellTitles["xterm"] = " -title 'Anonymous Telnet Session - Launched From TorK'";
        telnetitem->shellTitles["rxvt"] = " -title 'Anonymous Telnet Session - Launched From TorK'";
        telnetitem->shellTitles["gnome-terminal"] = " --title 'Anonymous Telnet Session - Launched From TorK'";

        TQFont f( telnetitem->score->font().rawName(), telnetitem->score->font().pointSize() - 1 );
        telnetitem->score->setFont( f );
        telnetitem->score->setHidden(false);
        telnetitem->score->insertStringList(shellsAvailable);
        telnetitem->score->setPalette(TQPalette(TQt::white,TQt::white));
        connect(telnetitem->score, SIGNAL(activated(int)),telnetitem, SLOT(changeTerminalUrl(int)));

        Anonymizer->insertItem(telnetitem);
        connect(telnetitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }
    //GPG
#endif

    gpgitem = 0L;

#ifndef LIVECD
    if ((TorkConfig::availablePrograms().contains("gpg")) && !shellsAvailable.isEmpty()){

        gpgitem = new HitWidget(TQString::null, TQString::null);

        headerLabel = new TQLabel(gpgitem);
        headerLabel->setText(i18n("Anonymously Refresh GPG Keys"));
        font.setBold( true );
        headerLabel->setFont( font );
        gpgitem->insertHeaderWidget(0,headerLabel);
        
        gpgitem->setIcon("tork_kgpg");
        gpgitem->setDescriptionText("<qt>"+i18n("<b>This will refresh your GPG keys anonymously.</b><br>"
                                "</qt>"));
        gpgitem->setPropertiesText("<qt>"+i18n(
                                "- To use the hidden service for GPG keys, add these lines to  %1/.gnupg/gpg.conf:<br>" 
                                "&nbsp;&nbsp;&nbsp;&nbsp; keyserver x-hkp://yod73zr3y6wnm2sw.onion<br>"
                                "&nbsp;&nbsp;&nbsp;&nbsp; keyserver x-hkp://d3ettcpzlta6azsm.onion<br>"
                                "</qt>").arg(getenv("HOME")));
    
        gpgitem->icon->setURL("konsole  --caption 'Anonymous GPG Keys Refresh - Launched From TorK' --noclose -e gpg --refresh-keys");
        
        gpgitem->shellTitles["konsole"] = " --caption 'Anonymous GPG Keys Refresh - Launched From TorK' --noclose -e gpg --refresh-keys";
        gpgitem->shellTitles["yakuake"] = " --caption 'Anonymous GPG Keys Refresh - Launched From TorK' --noclose -e gpg --refresh-keys";
        gpgitem->shellTitles["xterm"] = " -title 'Anonymous GPG Keys Refresh - Launched From TorK' -e gpg --refresh-keys";
        gpgitem->shellTitles["rxvt"] = " -title 'Anonymous GPG Keys Refresh - Launched From TorK' -e gpg --refresh-keys";
        gpgitem->shellTitles["gnome-terminal"] = " --title 'Anonymous GPG Keys Refresh - Launched From TorK' -e gpg --refresh-keys";

        TQFont f( gpgitem->score->font().rawName(), gpgitem->score->font().pointSize() - 1 );
        gpgitem->score->setFont( f );

        gpgitem->score->setHidden(false);
        gpgitem->score->insertStringList(hkpShellsAvailable);
        gpgitem->score->setPalette(TQPalette(TQt::white,TQt::white));
        connect(gpgitem->score, SIGNAL(activated(int)),gpgitem, SLOT(changeTerminalUrl(int)));

        Anonymizer->insertItem(gpgitem);
        connect(gpgitem->icon, SIGNAL(leftClickedURL(const TQString&)), SLOT(torify(const TQString&)));
    }
#endif
    //All Purpose Shell
    allpurposeitem = 0L;

#ifndef LIVECD

    if (!shellsAvailable.isEmpty()){
        allpurposeitem = new HitWidget(TQString::null, TQString::null);
        headerLabel = new TQLabel(allpurposeitem);
        headerLabel->setText(i18n("Anonymous Shell for Command-Line Programs using HTTP/HTTPS"));
        font.setBold( true );
        headerLabel->setFont( font );
        allpurposeitem->insertHeaderWidget(0,headerLabel);
        
        allpurposeitem->setIcon("tork_konsole");
        allpurposeitem->setDescriptionText("<qt>"+i18n("<b>Click to start a Konsole session.</b><br>"
                                )+"</qt>");
        allpurposeitem->setDescriptionText("<qt>"+i18n("- Your http(s) requests will be routed through a privacy proxy and Tor.<br>"
                                "- Suitable for such programs as <b>wget</b>, <b>slapt-get</b> and <b>lynx</b>. <br>"
                                )+"</qt>");

//         TQFont f( allpurposeitem->score->font().rawName(), 8 );
//         allpurposeitem->score->setFont( f );
//         allpurposeitem->score->setHidden(false);
//         allpurposeitem->score->insertStringList(shellsAvailable);
//         allpurposeitem->score->setPalette(TQPalette(TQt::white,TQt::white));


        Anonymizer->insertItem(allpurposeitem);
        connect(allpurposeitem->icon, SIGNAL(leftClickedURL()), SLOT(privoxiedBash()));
    }
#endif

}

circuitItem::circuitItem( DndListView *parent, const TQString &id, const TQString &status, const TQString &server )
    : TQListViewItem(  parent, id, status, server)
{
}


streamItem::streamItem( DndListView *parent, const TQString &id, const TQString &program, const TQString &target, const TQString &status, const TQString &bw, const TQString &exit, const TQString &circuit )
    : TQListViewItem(  parent, id, program, target, status, bw, exit, circuit)
{
/*    setDragEnabled(true);
    setDropEnabled(true);*/
	memset(mSpeedHistoryRx, 0, sizeof(double)*HISTORY_SIZE);
	memset(mSpeedHistoryTx, 0, sizeof(double)*HISTORY_SIZE);
	memset(mSpeedBufferRx, 0, sizeof(double)*SPEED_BUFFER_SIZE);
	memset(mSpeedBufferTx, 0, sizeof(double)*SPEED_BUFFER_SIZE);
	mMaxSpeedAge = 0;
	mMaxSpeed = 0.0;
	mSpeedBufferPtr = mSpeedHistoryPtr = 0;
	mBRx = mBTx = 0;

}


#include "torkview.moc"

