/******************************************************************************* * gui/NetworkDialog.cpp * * * * Copyright (c) 2006 Crypton * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * * * You should have received a copy of the GNU Affero General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "common/vmessagebox.h" #include "common/RSTreeWidgetItem.h" #include #include "gui/msgs/MessageComposer.h" #include "gui/profile/ProfileManager.h" #include "NetworkDialog.h" //#include "TrustView.h" #include "NetworkView.h" #include "GenCertDialog.h" #include "connect/PGPKeyDialog.h" #include "settings/rsharesettings.h" #include "RetroShareLink.h" #include "util/QtVersion.h" #include /* Images for context menu icons */ #define IMAGE_LOADCERT ":/images/loadcert16.png" #define IMAGE_PEERDETAILS ":/images/info16.png" #define IMAGE_AUTH ":/images/encrypted16.png" #define IMAGE_CLEAN_UNUSED ":/images/deletemail24.png" #define IMAGE_MAKEFRIEND ":/images/user/add_user16.png" #define IMAGE_EXPORT ":/images/exportpeers_16x16.png" #define IMAGE_COPYLINK ":/images/copyrslink.png" #define IMAGE_MESSAGE ":/images/mail_new.png" /****** * #define NET_DEBUG 1 *****/ /** Constructor */ NetworkDialog::NetworkDialog(QWidget */*parent*/) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); connect( ui.filterLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterItems(QString))); connect( ui.filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int))); //list data model float f = QFontMetricsF(font()).height()/14.0 ; PGPIdItemModel = new pgpid_item_model(neighs, f, this); PGPIdItemProxy = new pgpid_item_proxy(this); connect(ui.onlyTrustedKeys, SIGNAL(toggled(bool)), PGPIdItemProxy, SLOT(use_only_trusted_keys(bool))); PGPIdItemProxy->setSourceModel(PGPIdItemModel); PGPIdItemProxy->setFilterKeyColumn(COLUMN_PEERNAME); PGPIdItemProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); PGPIdItemProxy->setSortRole(Qt::EditRole); //use edit role to get raw data since we do not have edit for this model. ui.connectTreeWidget->setModel(PGPIdItemProxy); ui.connectTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); ui.connectTreeWidget->verticalHeader()->hide(); ui.connectTreeWidget->setShowGrid(false); ui.connectTreeWidget->setUpdatesEnabled(true); ui.connectTreeWidget->setSortingEnabled(true); ui.connectTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui.connectTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); connect(ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) ); connect(ui.connectTreeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(peerdetails())); ui.onlyTrustedKeys->setMinimumWidth(20*f); /* add filter actions */ ui.filterLineEdit->addFilter(QIcon(), tr("Name"), COLUMN_PEERNAME, tr("Search name")); ui.filterLineEdit->addFilter(QIcon(), tr("Peer ID"), COLUMN_PEERID, tr("Search peer ID")); ui.filterLineEdit->setCurrentFilter(COLUMN_PEERNAME); connect(ui.filterLineEdit, SIGNAL(textChanged(QString)), PGPIdItemProxy, SLOT(setFilterWildcard(QString))); } void NetworkDialog::changeEvent(QEvent *e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::StyleChange: securedUpdateDisplay(); break; default: // remove compiler warnings break; } } void NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint /*point*/ ) { QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); if(l.empty()) { return; } QMenu *contextMnu = new QMenu; RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; // That's what context menus are made for RsPeerDetails detail; if(!rsPeers->getGPGDetails(peer_id, detail)) // that is not suppose to fail. return ; if(peer_id == rsPeers->getGPGOwnId()) contextMnu->addAction(QIcon(IMAGE_EXPORT), tr("Export/create a new node"), this, SLOT(on_actionExportKey_activated())); contextMnu->addAction(QIcon(IMAGE_PEERDETAILS), tr("Profile details..."), this, SLOT(peerdetails())); contextMnu->addSeparator() ; contextMnu->addAction(QIcon(IMAGE_CLEAN_UNUSED), tr("Remove unused keys..."), this, SLOT(removeUnusedKeys())); contextMnu->exec(QCursor::pos()); } void NetworkDialog::removeUnusedKeys() { std::set pre_selected ; std::list ids ; rsPeers->getGPGAllList(ids) ; RsPeerDetails details ; time_t now = time(NULL) ; time_t THREE_MONTHS = 3*31*24*60*60 ;//3*DayPerMonth*HoursPerDay*MinPerHour*SecPerMin for(std::list::const_iterator it(ids.begin());it!=ids.end();++it) { rsPeers->getGPGDetails(*it,details) ; if(rsPeers->haveSecretKey(*it)) { std::cerr << "Skipping public/secret key pair " << *it << std::endl; continue ; } if(now > (time_t) (THREE_MONTHS + details.lastUsed) && !details.accept_connection) { std::cerr << "Adding " << *it << " to pre-selection." << std::endl; pre_selected.insert(*it) ; } } std::set selected = FriendSelectionDialog::selectFriends_PGP(NULL, tr("Clean keyring"), tr("The selected keys below haven't been used in the last 3 months. \nDo you want to delete them permanently ? \n\nNotes: Your old keyring will be backed up.\n The removal may fail when running multiple Retroshare instances on the same machine."),FriendSelectionWidget::MODUS_CHECK,FriendSelectionWidget::SHOW_GPG | FriendSelectionWidget::SHOW_NON_FRIEND_GPG, pre_selected) ; std::cerr << "Removing these keys from the keyring: " << std::endl; for(std::set::const_iterator it(selected.begin());it!=selected.end();++it) std::cerr << " " << *it << std::endl; std::string backup_file ; uint32_t error_code ; if(selected.empty()) return ; if( rsPeers->removeKeysFromPGPKeyring(selected,backup_file,error_code) ) QMessageBox::information(NULL,tr("Keyring info"),tr("%1 keys have been deleted from your keyring. \nFor security, your keyring was previously backed-up to file \n\n").arg(selected.size())+QString::fromStdString(backup_file) ) ; else { QString error_string ; switch(error_code) { default: case PGP_KEYRING_REMOVAL_ERROR_NO_ERROR: error_string = tr("Unknown error") ; break ; case PGP_KEYRING_REMOVAL_ERROR_CANT_REMOVE_SECRET_KEYS: error_string = tr("Cannot delete secret keys") ; break ; case PGP_KEYRING_REMOVAL_ERROR_CANNOT_WRITE_BACKUP: case PGP_KEYRING_REMOVAL_ERROR_CANNOT_CREATE_BACKUP: error_string = tr("Cannot create backup file. Check for permissions in pgp directory, disk space, etc.") ; break ; case PGP_KEYRING_REMOVAL_ERROR_DATA_INCONSISTENCY: error_string = tr("Data inconsistency in the keyring. This is most probably a bug. Please contact the developers.") ; break ; } QMessageBox::warning(NULL,tr("Keyring info"),tr("Key removal has failed. Your keyring remains intact.\n\nReported error:")+" "+error_string ) ; } updateDisplay(); // insertConnect() ; } void NetworkDialog::denyFriend() { QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); if(l.empty()) return; RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()); rsPeers->removeFriend(peer_id) ; securedUpdateDisplay(); } void NetworkDialog::makeFriend() { QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); if(l.empty()) return; PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); } /** Shows Peer Information/Auth Dialog */ void NetworkDialog::peerdetails() { QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); if(l.empty()) return; PGPKeyDialog::showIt(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()), PGPKeyDialog::PageDetails); } void NetworkDialog::copyLink() { QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); if(l.empty()) return; RsPgpId peer_id (ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), COLUMN_PEERID)).toString().toStdString()) ; QList urls; RetroShareLink link = RetroShareLink::createPerson(peer_id); if (link.valid()) { urls.push_back(link); } RSLinkClipboard::copyLinks(urls); } // void NetworkDialog::on_actionExportKey_activated() // { // ProfileManager prof ; // prof.exec() ; // } void NetworkDialog::filterColumnChanged(int col) { if(PGPIdItemProxy) PGPIdItemProxy->setFilterKeyColumn(col); //filterItems(ui.filterLineEdit->text()); } void NetworkDialog::updateDisplay() { if (!rsPeers) return; //update ids list std::list new_neighs; rsPeers->getGPGAllList(new_neighs); //refresh model PGPIdItemModel->data_updated(new_neighs); }