File indexing completed on 2024-05-12 05:46:30

0001 /*
0002    Original Authors:
0003    Copyright (c) Kalle Dalheimer <kalle@kde.org> 1997
0004    Copyright (c) David Faure <faure@kde.org> 1998
0005    Copyright (c) Dirk Mueller <mueller@kde.org> 2000
0006 
0007    Completely re-written by:
0008    Copyright (C) 2000- Dawit Alemayehu <adawit@kde.org>
0009 
0010    This library is free software; you can redistribute it and/or
0011    modify it under the terms of the GNU General Public License (GPL)
0012    version 2 as published by the Free Software Foundation.
0013 
0014    This library is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017    Library General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this library; see the file COPYING.LIB.  If not, write to
0021    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022    Boston, MA 02110-1301, USA.
0023 */
0024 
0025 // Own
0026 #include "useragentdlg.h"
0027 
0028 // Local
0029 #include "ksaveioconfig.h"
0030 #include "useragentinfo.h"
0031 #include "useragentselectordlg.h"
0032 
0033 // Qt
0034 #include <QCheckBox>
0035 #include <QPushButton>
0036 #include <QTreeWidget>
0037 #include <QLoggingCategory>
0038 
0039 // KDE
0040 #include <kconfig.h>
0041 #include <KConfigGroup>
0042 #include <KLocalizedString>
0043 #include <kmessagebox.h>
0044 #include <http_slave_defaults.h>
0045 #include <kpluginfactory.h>
0046 
0047 Q_DECLARE_LOGGING_CATEGORY(KIO_USERAGENTDLG)
0048 Q_LOGGING_CATEGORY(KIO_USERAGENTDLG, "kf5.kio.useragentdlg")
0049 
0050 K_PLUGIN_FACTORY_DECLARATION (KioConfigFactory)
0051 
0052 typedef QList<QTreeWidgetItem*> SiteList;
0053 typedef SiteList::iterator SiteListIterator;
0054 
0055 UserAgentDlg::UserAgentDlg (QWidget* parent, const QVariantList&)
0056     : KCModule (parent),
0057       m_userAgentInfo (nullptr),
0058       m_config (nullptr)
0059 {
0060     ui.setupUi (this);
0061     ui.newButton->setIcon (QIcon::fromTheme(QStringLiteral("list-add")));
0062     ui.changeButton->setIcon (QIcon::fromTheme(QStringLiteral("edit-rename")));
0063     ui.deleteButton->setIcon (QIcon::fromTheme(QStringLiteral("list-remove")));
0064     ui.deleteAllButton->setIcon (QIcon::fromTheme(QStringLiteral("edit-delete")));
0065 }
0066 
0067 UserAgentDlg::~UserAgentDlg()
0068 {
0069     delete m_userAgentInfo;
0070     delete m_config;
0071 }
0072 
0073 void UserAgentDlg::on_sendUACheckBox_clicked()
0074 {
0075     configChanged();
0076 }
0077 
0078 void UserAgentDlg::on_newButton_clicked()
0079 {
0080     const QPointer<UserAgentSelectorDlg> pdlg (new UserAgentSelectorDlg (m_userAgentInfo, this));
0081     pdlg->setWindowTitle(i18nc ("@title:window", "Add Identification"));
0082 
0083     if (pdlg->exec() == QDialog::Accepted && pdlg) {
0084         if (!handleDuplicate (pdlg->siteName(), pdlg->identity(), pdlg->alias())) {
0085             QTreeWidgetItem* item = new QTreeWidgetItem (ui.sitePolicyTreeWidget);
0086             item->setText (0, pdlg->siteName());
0087             item->setText (1, pdlg->identity());
0088             item->setText (2, pdlg->alias());
0089             ui.sitePolicyTreeWidget->setCurrentItem (item);
0090             configChanged();
0091         }
0092     }
0093     delete pdlg;
0094 }
0095 
0096 void UserAgentDlg::on_changeButton_clicked()
0097 {
0098     on_sitePolicyTreeWidget_itemDoubleClicked (ui.sitePolicyTreeWidget->currentItem(), -1);
0099 }
0100 
0101 void UserAgentDlg::on_deleteButton_clicked()
0102 {
0103     SiteList selectedItems = ui.sitePolicyTreeWidget->selectedItems();
0104     SiteListIterator endIt = selectedItems.end();
0105 
0106     for (SiteListIterator it = selectedItems.begin(); it != endIt; ++it)
0107         delete (*it);
0108 
0109     updateButtons();
0110     configChanged();
0111 }
0112 
0113 void UserAgentDlg::on_deleteAllButton_clicked()
0114 {
0115     ui.sitePolicyTreeWidget->clear();
0116     updateButtons();
0117     configChanged();
0118 }
0119 
0120 void UserAgentDlg::on_osNameCheckBox_clicked()
0121 {
0122     changeDefaultUAModifiers();
0123 }
0124 
0125 void UserAgentDlg::on_osVersionCheckBox_clicked()
0126 {
0127     changeDefaultUAModifiers();
0128 }
0129 
0130 void UserAgentDlg::on_processorTypeCheckBox_clicked()
0131 {
0132     changeDefaultUAModifiers();
0133 }
0134 
0135 void UserAgentDlg::on_languageCheckBox_clicked()
0136 {
0137     changeDefaultUAModifiers();
0138 }
0139 
0140 void UserAgentDlg::on_sitePolicyTreeWidget_itemDoubleClicked (QTreeWidgetItem* item, int)
0141 {
0142     if (item) {
0143         // Store the current site name...
0144         const QString currentSiteName = item->text (0);
0145 
0146         UserAgentSelectorDlg pdlg (m_userAgentInfo, this);
0147         pdlg.setWindowTitle (i18nc ("@title:window", "Modify Identification"));
0148         pdlg.setSiteName (currentSiteName);
0149         pdlg.setIdentity (item->text (1));
0150 
0151         if (pdlg.exec() == QDialog::Accepted) {
0152             if (pdlg.siteName() == currentSiteName ||
0153                     !handleDuplicate (pdlg.siteName(), pdlg.identity(), pdlg.alias())) {
0154                 item->setText (0, pdlg.siteName());
0155                 item->setText (1, pdlg.identity());
0156                 item->setText (2, pdlg.alias());
0157                 configChanged();
0158             }
0159         }
0160     }
0161 }
0162 
0163 void UserAgentDlg::changeDefaultUAModifiers()
0164 {
0165     m_ua_keys = QLatin1Char(':'); // Make sure it's not empty
0166 
0167     if (ui.osNameCheckBox->isChecked())
0168         m_ua_keys += QLatin1Char('o');
0169 
0170     if (ui.osVersionCheckBox->isChecked())
0171         m_ua_keys += QLatin1Char('v');
0172 
0173     if (ui.processorTypeCheckBox->isChecked())
0174         m_ua_keys += QLatin1Char('m');
0175 
0176     if (ui.languageCheckBox->isChecked())
0177         m_ua_keys += QLatin1Char('l');
0178 
0179     ui.osVersionCheckBox->setEnabled(m_ua_keys.contains(QLatin1Char('o')));
0180 
0181     QString modVal = KProtocolManager::defaultUserAgent (m_ua_keys);
0182     if (ui.defaultIdLineEdit->text() != modVal) {
0183         ui.defaultIdLineEdit->setText (modVal);
0184         configChanged();
0185     }
0186 }
0187 
0188 bool UserAgentDlg::handleDuplicate (const QString& site,
0189                                     const QString& identity,
0190                                     const QString& alias)
0191 {
0192     SiteList list = ui.sitePolicyTreeWidget->findItems (site, Qt::MatchExactly, 0);
0193 
0194     if (!list.isEmpty()) {
0195         QString msg = i18n ("<qt><center>Found an existing identification for"
0196                             "<br/><b>%1</b><br/>"
0197                             "Do you want to replace it?</center>"
0198                             "</qt>", site);
0199         int res = KMessageBox::warningContinueCancel (this, msg,
0200                   i18nc ("@title:window", "Duplicate Identification"),
0201                   KGuiItem (i18n ("Replace")));
0202         if (res == KMessageBox::Continue) {
0203             list[0]->setText (0, site);
0204             list[0]->setText (1, identity);
0205             list[0]->setText (2, alias);
0206             configChanged();
0207         }
0208 
0209         return true;
0210     }
0211 
0212     return false;
0213 }
0214 
0215 void UserAgentDlg::configChanged (bool enable)
0216 {
0217     emit changed (enable);
0218 }
0219 
0220 void UserAgentDlg::updateButtons()
0221 {
0222     const int selectedItemCount = ui.sitePolicyTreeWidget->selectedItems().count();
0223     const bool hasItems = ui.sitePolicyTreeWidget->topLevelItemCount() > 0;
0224 
0225     ui.changeButton->setEnabled ( (hasItems && selectedItemCount == 1));
0226     ui.deleteButton->setEnabled ( (hasItems && selectedItemCount > 0));
0227     ui.deleteAllButton->setEnabled (hasItems);
0228 }
0229 
0230 void UserAgentDlg::on_sitePolicyTreeWidget_itemSelectionChanged()
0231 {
0232     updateButtons();
0233 }
0234 
0235 void UserAgentDlg::load()
0236 {
0237     ui.sitePolicyTreeWidget->clear();
0238 
0239     if (!m_config)
0240         m_config = new KConfig (QStringLiteral("kio_httprc"), KConfig::NoGlobals);
0241     else
0242         m_config->reparseConfiguration();
0243 
0244     if (!m_userAgentInfo)
0245         m_userAgentInfo = new UserAgentInfo();
0246 
0247     const QStringList list = m_config->groupList();
0248     QStringList::ConstIterator endIt = list.end();
0249     QString agentStr;
0250 
0251     for (QStringList::ConstIterator it = list.begin(); it != endIt; ++it) {
0252         if ( (*it) == QLatin1String("<default>"))
0253             continue;
0254 
0255         KConfigGroup cg (m_config, *it);
0256         agentStr = cg.readEntry ("UserAgent");
0257         if (!agentStr.isEmpty()) {
0258             QTreeWidgetItem* item = new QTreeWidgetItem (ui.sitePolicyTreeWidget);
0259             item->setText (0, (*it).toLower());
0260             item->setText (1, m_userAgentInfo->aliasStr (agentStr));
0261             item->setText (2, agentStr);
0262         }
0263     }
0264 
0265     // Update buttons and checkboxes...
0266     KConfigGroup cg2 (m_config, QString());
0267     bool b = cg2.readEntry ("SendUserAgent", true);
0268     ui.sendUACheckBox->setChecked (b);
0269     m_ua_keys = cg2.readEntry ("UserAgentKeys", DEFAULT_USER_AGENT_KEYS).toLower();
0270     ui.defaultIdLineEdit->setText (KProtocolManager::defaultUserAgent (m_ua_keys));
0271     ui.osNameCheckBox->setChecked (m_ua_keys.contains(QLatin1Char('o')));
0272     ui.osVersionCheckBox->setChecked (m_ua_keys.contains(QLatin1Char('v')));
0273     ui.processorTypeCheckBox->setChecked (m_ua_keys.contains(QLatin1Char('m')));
0274     ui.languageCheckBox->setChecked (m_ua_keys.contains(QLatin1Char('l')));
0275 
0276     updateButtons();
0277     configChanged (false);
0278 }
0279 
0280 void UserAgentDlg::defaults()
0281 {
0282     ui.sitePolicyTreeWidget->clear();
0283     m_ua_keys = QStringLiteral(DEFAULT_USER_AGENT_KEYS);
0284     ui.defaultIdLineEdit->setText (KProtocolManager::defaultUserAgent (m_ua_keys));
0285     ui.osNameCheckBox->setChecked (m_ua_keys.contains (QLatin1Char('o')));
0286     ui.osVersionCheckBox->setChecked (m_ua_keys.contains (QLatin1Char('v')));
0287     ui.processorTypeCheckBox->setChecked (m_ua_keys.contains (QLatin1Char('m')));
0288     ui.languageCheckBox->setChecked (m_ua_keys.contains(QLatin1Char('l')));
0289     ui.sendUACheckBox->setChecked (true);
0290 
0291     updateButtons();
0292     configChanged();
0293 }
0294 
0295 void UserAgentDlg::save()
0296 {
0297     Q_ASSERT (m_config);
0298 
0299     // Put all the groups except the default into the delete list.
0300     QStringList deleteList = m_config->groupList();
0301 
0302     //Remove all the groups that DO NOT contain a "UserAgent" entry...
0303     QStringList::ConstIterator endIt = deleteList.constEnd();
0304     for (QStringList::ConstIterator it = deleteList.constBegin(); it != endIt; ++it) {
0305         if ( (*it) == QLatin1String ("<default>"))
0306             continue;
0307 
0308         KConfigGroup cg (m_config, *it);
0309         if (!cg.hasKey ("UserAgent"))
0310             deleteList.removeAll (*it);
0311     }
0312 
0313     QString domain;
0314     QTreeWidgetItem* item;
0315     int itemCount = ui.sitePolicyTreeWidget->topLevelItemCount();
0316 
0317     // Save and remove from the delete list all the groups that were
0318     // not deleted by the end user.
0319     for (int i = 0; i < itemCount; i++) {
0320         item = ui.sitePolicyTreeWidget->topLevelItem (i);
0321         domain = item->text (0);
0322         KConfigGroup cg (m_config, domain);
0323         cg.writeEntry ("UserAgent", item->text (2));
0324         deleteList.removeAll (domain);
0325         qCDebug (KIO_USERAGENTDLG, "UserAgentDlg::save: Removed [%s] from delete list", domain.toLatin1().constData());
0326     }
0327 
0328     // Write the global configuration information...
0329     KConfigGroup cg (m_config, QString());
0330     cg.writeEntry ("SendUserAgent", ui.sendUACheckBox->isChecked());
0331     cg.writeEntry ("UserAgentKeys", m_ua_keys);
0332 
0333     // Sync up all the changes so far...
0334     m_config->sync();
0335 
0336     // If delete list is not empty, delete the specified domains.
0337     if (!deleteList.isEmpty()) {
0338         // Remove entries from local file.
0339         endIt = deleteList.constEnd();
0340         KConfig cfg (QStringLiteral("kio_httprc"), KConfig::SimpleConfig);
0341 
0342         for (QStringList::ConstIterator it = deleteList.constBegin(); it != endIt; ++it) {
0343             KConfigGroup cg (&cfg, *it);
0344             cg.deleteEntry ("UserAgent");
0345             qCDebug (KIO_USERAGENTDLG, "UserAgentDlg::save: Deleting UserAgent of group [%s]", (*it).toLatin1().constData());
0346             if (cg.keyList().count() < 1)
0347                 cg.deleteGroup();
0348         }
0349 
0350         // Sync up the configuration...
0351         cfg.sync();
0352 
0353         // Check everything is gone, reset to blank otherwise.
0354         m_config->reparseConfiguration();
0355         endIt = deleteList.constEnd();
0356         for (QStringList::ConstIterator it = deleteList.constBegin(); it != endIt; ++it) {
0357             KConfigGroup cg (m_config, *it);
0358             if (cg.hasKey ("UserAgent"))
0359                 cg.writeEntry ("UserAgent", QString());
0360         }
0361 
0362         // Sync up the configuration...
0363         m_config->sync();
0364     }
0365 
0366     KSaveIOConfig::updateRunningIOSlaves (this);
0367     configChanged (false);
0368 }
0369 
0370 QString UserAgentDlg::quickHelp() const
0371 {
0372     return i18n ("<h1>Browser Identification</h1>"
0373                  "<p>The browser-identification module allows you to have "
0374                  "full control over how KDE applications using the HTTP "
0375                  "protocol (like Konqueror) will identify itself to web sites "
0376                  "you browse.</p>"
0377                  "<p>This ability to fake identification is necessary because "
0378                  "some web sites do not display properly when they detect that "
0379                  "they are not talking to current versions of either Netscape "
0380                  "Navigator or Internet Explorer, even if the browser actually "
0381                  "supports all the necessary features to render those pages "
0382                  "properly. "
0383                  "For such sites, you can use this feature to try to browse "
0384                  "them. Please understand that this might not always work, since "
0385                  "such sites might be using non-standard web protocols and or "
0386                  "specifications.</p>"
0387                  "<p><u>NOTE:</u> To obtain specific help on a particular section "
0388                  "of the dialog box, simply click on the quick help button on "
0389                  "the window title bar, then click on the section "
0390                  "for which you are seeking help.</p>");
0391 }
0392 
0393