File indexing completed on 2024-04-28 11:39:52

0001 /* This file is part of the KDE project
0002    Copyright (C) 1999 David Faure <faure@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "khtml_settings.h"
0021 #include "khtmldefaults.h"
0022 
0023 #include <kparts/htmlsettingsinterface.h>
0024 #include <kconfig.h>
0025 #include <kconfiggroup.h>
0026 #include "khtml_debug.h"
0027 #include <klocalizedstring.h>
0028 #include <kmessagebox.h>
0029 #include <khtml_filter_p.h>
0030 
0031 #include <kjob.h>
0032 #include <kio/job.h>
0033 
0034 #include <QFile>
0035 #include <QFileInfo>
0036 #include <QFontDatabase>
0037 #include <QByteArray>
0038 #include <QUrl>
0039 #include <qstandardpaths.h>
0040 #include <ksharedconfig.h>
0041 
0042 /**
0043  * @internal
0044  * Contains all settings which are both available globally and per-domain
0045  */
0046 struct KPerDomainSettings {
0047     bool m_bEnableJava : 1;
0048     bool m_bEnableJavaScript : 1;
0049     bool m_bEnablePlugins : 1;
0050     // don't forget to maintain the bitfields as the enums grow
0051     KHTMLSettings::KJSWindowOpenPolicy m_windowOpenPolicy : 2;
0052     KHTMLSettings::KJSWindowStatusPolicy m_windowStatusPolicy : 1;
0053     KHTMLSettings::KJSWindowFocusPolicy m_windowFocusPolicy : 1;
0054     KHTMLSettings::KJSWindowMovePolicy m_windowMovePolicy : 1;
0055     KHTMLSettings::KJSWindowResizePolicy m_windowResizePolicy : 1;
0056 
0057 #ifdef DEBUG_SETTINGS
0058     void dump(const QString &infix = QString()) const
0059     {
0060         // qCDebug(KHTML_LOG) << "KPerDomainSettings " << infix << " @" << this << ":";
0061         // qCDebug(KHTML_LOG) << "  m_bEnableJava: " << m_bEnableJava;
0062         // qCDebug(KHTML_LOG) << "  m_bEnableJavaScript: " << m_bEnableJavaScript;
0063         // qCDebug(KHTML_LOG) << "  m_bEnablePlugins: " << m_bEnablePlugins;
0064         // qCDebug(KHTML_LOG) << "  m_windowOpenPolicy: " << m_windowOpenPolicy;
0065         // qCDebug(KHTML_LOG) << "  m_windowStatusPolicy: " << m_windowStatusPolicy;
0066         // qCDebug(KHTML_LOG) << "  m_windowFocusPolicy: " << m_windowFocusPolicy;
0067         // qCDebug(KHTML_LOG) << "  m_windowMovePolicy: " << m_windowMovePolicy;
0068         // qCDebug(KHTML_LOG) << "  m_windowResizePolicy: " << m_windowResizePolicy;
0069     }
0070 #endif
0071 };
0072 
0073 QString *KHTMLSettings::avFamilies = nullptr;
0074 typedef QMap<QString, KPerDomainSettings> PolicyMap;
0075 
0076 // The "struct" that contains all the data. Must be copiable (no pointers).
0077 class KHTMLSettingsData
0078 {
0079 public:
0080     bool m_bChangeCursor : 1;
0081     bool m_bOpenMiddleClick : 1;
0082     bool m_underlineLink : 1;
0083     bool m_hoverLink : 1;
0084     bool m_bEnableJavaScriptDebug : 1;
0085     bool m_bEnableJavaScriptErrorReporting : 1;
0086     bool enforceCharset : 1;
0087     bool m_bAutoLoadImages : 1;
0088     bool m_bUnfinishedImageFrame : 1;
0089     bool m_formCompletionEnabled : 1;
0090     bool m_autoDelayedActionsEnabled : 1;
0091     bool m_jsErrorsEnabled : 1;
0092     bool m_follow_system_colors : 1;
0093     bool m_allowTabulation : 1;
0094     bool m_autoSpellCheck : 1;
0095     bool m_adFilterEnabled : 1;
0096     bool m_hideAdsEnabled : 1;
0097     bool m_jsPopupBlockerPassivePopup : 1;
0098     bool m_accessKeysEnabled : 1;
0099 
0100     // the virtual global "domain"
0101     KPerDomainSettings global;
0102 
0103     int m_fontSize;
0104     int m_minFontSize;
0105     int m_maxFormCompletionItems;
0106     KHTMLSettings::KAnimationAdvice m_showAnimations;
0107     KHTMLSettings::KSmoothScrollingMode m_smoothScrolling;
0108     KHTMLSettings::KDNSPrefetch m_dnsPrefetch;
0109 
0110     QString m_encoding;
0111     QString m_userSheet;
0112 
0113     QColor m_textColor;
0114     QColor m_baseColor;
0115     QColor m_linkColor;
0116     QColor m_vLinkColor;
0117 
0118     PolicyMap domainPolicy;
0119     QStringList fonts;
0120     QStringList defaultFonts;
0121 
0122     khtml::FilterSet adBlackList;
0123     khtml::FilterSet adWhiteList;
0124     QList< QPair< QString, QChar > > m_fallbackAccessKeysAssignments;
0125 };
0126 
0127 class KHTMLSettingsPrivate : public QObject, public KHTMLSettingsData
0128 {
0129     Q_OBJECT
0130 public:
0131 
0132     void adblockFilterLoadList(const QString &filename)
0133     {
0134         // qCDebug(KHTML_LOG) << "Loading filter list from" << filename;
0135         /** load list file and process each line */
0136         QFile file(filename);
0137         if (file.open(QIODevice::ReadOnly)) {
0138             QTextStream ts(&file);
0139             QString line = ts.readLine();
0140 #ifndef NDEBUG /// only count when compiled for debugging
0141             int whiteCounter = 0, blackCounter = 0;
0142 #endif // NDEBUG
0143             while (!line.isEmpty()) {
0144                 /** white list lines start with "@@" */
0145                 if (line.startsWith(QLatin1String("@@"))) {
0146 #ifndef NDEBUG
0147                     ++whiteCounter;
0148 #endif // NDEBUG
0149                     adWhiteList.addFilter(line);
0150                 } else {
0151 #ifndef NDEBUG
0152                     ++blackCounter;
0153 #endif // NDEBUG
0154                     adBlackList.addFilter(line);
0155                 }
0156 
0157                 line = ts.readLine();
0158             }
0159             file.close();
0160 
0161 #ifndef NDEBUG
0162             // qCDebug(KHTML_LOG) << "Filter list loaded" << whiteCounter << "white list entries and" << blackCounter << "black list entries";
0163 #endif // NDEBUG
0164         }
0165     }
0166 
0167 public Q_SLOTS:
0168     void adblockFilterResult(KJob *job)
0169     {
0170         KIO::StoredTransferJob *tJob = qobject_cast<KIO::StoredTransferJob *>(job);
0171         Q_ASSERT(tJob);
0172 
0173         if (tJob->error()) {
0174             // qCDebug(KHTML_LOG) << "Failed to download" << tJob->url() << "with message:" << tJob->errorText();
0175         } else if (tJob->isErrorPage()) { // 4XX error code
0176             // qCDebug(KHTML_LOG) << "Failed to fetch filter list" << tJob->url();
0177         } else {
0178             const QByteArray byteArray = tJob->data();
0179             const QString localFileName = tJob->property("khtmlsettings_adBlock_filename").toString();
0180 
0181             QFile file(localFileName);
0182             if (file.open(QFile::WriteOnly)) {
0183                 bool success = file.write(byteArray) == byteArray.size();
0184                 file.close();
0185                 if (success) {
0186                     adblockFilterLoadList(localFileName);
0187                 } else {
0188                     // qCDebug(KHTML_LOG) << "Could not write" << byteArray.size() << "to file" << localFileName;
0189                 }
0190             } else {
0191                 // qCDebug(KHTML_LOG) << "Cannot open file" << localFileName << "for filter list";
0192             }
0193         }
0194 
0195     }
0196 };
0197 
0198 /** Returns a writeable per-domains settings instance for the given domain
0199   * or a deep copy of the global settings if not existent.
0200   */
0201 static KPerDomainSettings &setup_per_domain_policy(
0202     KHTMLSettingsPrivate *const d,
0203     const QString &domain)
0204 {
0205     if (domain.isEmpty()) {
0206         qCWarning(KHTML_LOG) << "setup_per_domain_policy: domain is empty";
0207     }
0208     const QString ldomain = domain.toLower();
0209     PolicyMap::iterator it = d->domainPolicy.find(ldomain);
0210     if (it == d->domainPolicy.end()) {
0211         // simply copy global domain settings (they should have been initialized
0212         // by this time)
0213         it = d->domainPolicy.insert(ldomain, d->global);
0214     }
0215     return *it;
0216 }
0217 
0218 KHTMLSettings::KJavaScriptAdvice KHTMLSettings::strToAdvice(const QString &_str)
0219 {
0220     return static_cast<KJavaScriptAdvice>(KParts::HtmlSettingsInterface::textToJavascriptAdvice(_str));
0221 }
0222 
0223 const char *KHTMLSettings::adviceToStr(KJavaScriptAdvice _advice)
0224 {
0225     return KParts::HtmlSettingsInterface::javascriptAdviceToText(static_cast<KParts::HtmlSettingsInterface::JavaScriptAdvice>(_advice));
0226 }
0227 
0228 void KHTMLSettings::splitDomainAdvice(const QString &configStr, QString &domain,
0229                                       KJavaScriptAdvice &javaAdvice, KJavaScriptAdvice &javaScriptAdvice)
0230 {
0231     KParts::HtmlSettingsInterface::JavaScriptAdvice jAdvice, jsAdvice;
0232     KParts::HtmlSettingsInterface::splitDomainAdvice(configStr, domain, jAdvice, jsAdvice);
0233     javaAdvice = static_cast<KJavaScriptAdvice>(jAdvice);
0234     javaScriptAdvice = static_cast<KJavaScriptAdvice>(jsAdvice);
0235 }
0236 
0237 void KHTMLSettings::readDomainSettings(const KConfigGroup &config, bool reset,
0238                                        bool global, KPerDomainSettings &pd_settings)
0239 {
0240     QString jsPrefix = global ? QString()
0241                        : QString::fromLatin1("javascript.");
0242     QString javaPrefix = global ? QString()
0243                          : QString::fromLatin1("java.");
0244     QString pluginsPrefix = global ? QString()
0245                             : QString::fromLatin1("plugins.");
0246 
0247     // The setting for Java
0248     QString key = javaPrefix + QLatin1String("EnableJava");
0249     if ((global && reset) || config.hasKey(key)) {
0250         pd_settings.m_bEnableJava = config.readEntry(key, false);
0251     } else if (!global) {
0252         pd_settings.m_bEnableJava = d->global.m_bEnableJava;
0253     }
0254 
0255     // The setting for Plugins
0256     key = pluginsPrefix + QLatin1String("EnablePlugins");
0257     if ((global && reset) || config.hasKey(key)) {
0258         pd_settings.m_bEnablePlugins = config.readEntry(key, true);
0259     } else if (!global) {
0260         pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins;
0261     }
0262 
0263     // The setting for JavaScript
0264     key = jsPrefix + QLatin1String("EnableJavaScript");
0265     if ((global && reset) || config.hasKey(key)) {
0266         pd_settings.m_bEnableJavaScript = config.readEntry(key, true);
0267     } else if (!global) {
0268         pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript;
0269     }
0270 
0271     // window property policies
0272     key = jsPrefix + QLatin1String("WindowOpenPolicy");
0273     if ((global && reset) || config.hasKey(key))
0274         pd_settings.m_windowOpenPolicy = (KJSWindowOpenPolicy)
0275                                          config.readEntry(key, uint(KJSWindowOpenSmart));
0276     else if (!global) {
0277         pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy;
0278     }
0279 
0280     key = jsPrefix + QLatin1String("WindowMovePolicy");
0281     if ((global && reset) || config.hasKey(key))
0282         pd_settings.m_windowMovePolicy = (KJSWindowMovePolicy)
0283                                          config.readEntry(key, uint(KJSWindowMoveAllow));
0284     else if (!global) {
0285         pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy;
0286     }
0287 
0288     key = jsPrefix + QLatin1String("WindowResizePolicy");
0289     if ((global && reset) || config.hasKey(key))
0290         pd_settings.m_windowResizePolicy = (KJSWindowResizePolicy)
0291                                            config.readEntry(key, uint(KJSWindowResizeAllow));
0292     else if (!global) {
0293         pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy;
0294     }
0295 
0296     key = jsPrefix + QLatin1String("WindowStatusPolicy");
0297     if ((global && reset) || config.hasKey(key))
0298         pd_settings.m_windowStatusPolicy = (KJSWindowStatusPolicy)
0299                                            config.readEntry(key, uint(KJSWindowStatusAllow));
0300     else if (!global) {
0301         pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy;
0302     }
0303 
0304     key = jsPrefix + QLatin1String("WindowFocusPolicy");
0305     if ((global && reset) || config.hasKey(key))
0306         pd_settings.m_windowFocusPolicy = (KJSWindowFocusPolicy)
0307                                           config.readEntry(key, uint(KJSWindowFocusAllow));
0308     else if (!global) {
0309         pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy;
0310     }
0311 
0312 }
0313 
0314 KHTMLSettings::KHTMLSettings()
0315     : d(new KHTMLSettingsPrivate())
0316 {
0317     init();
0318 }
0319 
0320 KHTMLSettings::KHTMLSettings(const KHTMLSettings &other)
0321     : d(new KHTMLSettingsPrivate())
0322 {
0323     KHTMLSettingsData *data = d;
0324     *data = *other.d;
0325 }
0326 
0327 KHTMLSettings::~KHTMLSettings()
0328 {
0329     delete d;
0330 }
0331 
0332 bool KHTMLSettings::changeCursor() const
0333 {
0334     return d->m_bChangeCursor;
0335 }
0336 
0337 bool KHTMLSettings::underlineLink() const
0338 {
0339     return d->m_underlineLink;
0340 }
0341 
0342 bool KHTMLSettings::hoverLink() const
0343 {
0344     return d->m_hoverLink;
0345 }
0346 
0347 void KHTMLSettings::init()
0348 {
0349     KConfig global("khtmlrc", KConfig::NoGlobals);
0350     init(&global, true);
0351 
0352     KSharedConfig::Ptr local = KSharedConfig::openConfig();
0353     if (!local) {
0354         return;
0355     }
0356 
0357     init(local.data(), false);
0358 }
0359 
0360 void KHTMLSettings::init(KConfig *config, bool reset)
0361 {
0362     KConfigGroup cg(config, "MainView Settings");
0363     if (reset || cg.exists()) {
0364         if (reset || cg.hasKey("OpenMiddleClick")) {
0365             d->m_bOpenMiddleClick = cg.readEntry("OpenMiddleClick", true);
0366         }
0367     }
0368 
0369     KConfigGroup cgAccess(config, "Access Keys");
0370     if (reset || cgAccess.exists()) {
0371         d->m_accessKeysEnabled = cgAccess.readEntry("Enabled", true);
0372     }
0373 
0374     KConfigGroup cgFilter(config, "Filter Settings");
0375 
0376     if (reset || cgFilter.exists()) {
0377         d->m_adFilterEnabled = cgFilter.readEntry("Enabled", false);
0378         d->m_hideAdsEnabled = cgFilter.readEntry("Shrink", false);
0379 
0380         d->adBlackList.clear();
0381         d->adWhiteList.clear();
0382 
0383         if (d->m_adFilterEnabled) {
0384 
0385             /** read maximum age for filter list files, minimum is one day */
0386             int htmlFilterListMaxAgeDays = cgFilter.readEntry(QString("HTMLFilterListMaxAgeDays")).toInt();
0387             if (htmlFilterListMaxAgeDays < 1) {
0388                 htmlFilterListMaxAgeDays = 1;
0389             }
0390 
0391             QMap<QString, QString> entryMap = cgFilter.entryMap();
0392             QMap<QString, QString>::ConstIterator it;
0393             for (it = entryMap.constBegin(); it != entryMap.constEnd(); ++it) {
0394                 int id = -1;
0395                 QString name = it.key();
0396                 QString url = it.value();
0397 
0398                 if (name.startsWith("Filter")) {
0399                     if (url.startsWith(QLatin1String("@@"))) {
0400                         d->adWhiteList.addFilter(url);
0401                     } else {
0402                         d->adBlackList.addFilter(url);
0403                     }
0404                 } else if (name.startsWith("HTMLFilterListName-") && (id = name.mid(19).toInt()) > 0) {
0405                     /** check if entry is enabled */
0406                     bool filterEnabled = cgFilter.readEntry(QString("HTMLFilterListEnabled-").append(QString::number(id))) != QLatin1String("false");
0407 
0408                     /** get url for HTMLFilterList */
0409                     QUrl url(cgFilter.readEntry(QString("HTMLFilterListURL-").append(QString::number(id))));
0410 
0411                     if (filterEnabled && url.isValid()) {
0412                         /** determine where to cache HTMLFilterList file */
0413                         QString localFile = cgFilter.readEntry(QString("HTMLFilterListLocalFilename-").append(QString::number(id)));
0414                         localFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + "khtml/" + localFile;
0415 
0416                         /** determine existence and age of cache file */
0417                         QFileInfo fileInfo(localFile);
0418 
0419                         /** load cached file if it exists, irrespective of age */
0420                         if (fileInfo.exists()) {
0421                             d->adblockFilterLoadList(localFile);
0422                         }
0423 
0424                         /** if no cache list file exists or if it is too old ... */
0425                         if (!fileInfo.exists() || fileInfo.lastModified().daysTo(QDateTime::currentDateTime()) > htmlFilterListMaxAgeDays) {
0426                             /** ... in this case, refetch list asynchronously */
0427                             // qCDebug(KHTML_LOG) << "Asynchronously fetching filter list from" << url << "to" << localFile;
0428 
0429                             KIO::StoredTransferJob *job = KIO::storedGet(url, KIO::Reload, KIO::HideProgressInfo);
0430                             QObject::connect(job, SIGNAL(result(KJob*)), d, SLOT(adblockFilterResult(KJob*)));
0431                             /** for later reference, store name of cache file */
0432                             job->setProperty("khtmlsettings_adBlock_filename", localFile);
0433                         }
0434                     }
0435                 }
0436             }
0437         }
0438 
0439     }
0440 
0441     KConfigGroup cgHtml(config, "HTML Settings");
0442     if (reset || cgHtml.exists()) {
0443         // Fonts and colors
0444         if (reset) {
0445             d->defaultFonts = QStringList();
0446             d->defaultFonts.append(cgHtml.readEntry("StandardFont", QFontDatabase::systemFont(QFontDatabase::GeneralFont).family()));
0447             d->defaultFonts.append(cgHtml.readEntry("FixedFont", QFontDatabase::systemFont(QFontDatabase::FixedFont).family()));
0448             // Resolve generic font family names
0449             const QString serifFont = QFontInfo(QFont(QLatin1String(HTML_DEFAULT_VIEW_SERIF_FONT))).family();
0450             const QString sansSerifFont = QFontInfo(QFont(QLatin1String(HTML_DEFAULT_VIEW_SANSSERIF_FONT))).family();
0451             const QString cursiveFont = QFontInfo(QFont(QLatin1String(HTML_DEFAULT_VIEW_CURSIVE_FONT))).family();
0452             const QString fantasyFont = QFontInfo(QFont(QLatin1String(HTML_DEFAULT_VIEW_FANTASY_FONT))).family();
0453             d->defaultFonts.append(cgHtml.readEntry("SerifFont", serifFont));
0454             d->defaultFonts.append(cgHtml.readEntry("SansSerifFont", sansSerifFont));
0455             d->defaultFonts.append(cgHtml.readEntry("CursiveFont", cursiveFont));
0456             d->defaultFonts.append(cgHtml.readEntry("FantasyFont", fantasyFont));
0457             d->defaultFonts.append(QString("0"));     // font size adjustment
0458         }
0459 
0460         if (reset || cgHtml.hasKey("MinimumFontSize")) {
0461             d->m_minFontSize = cgHtml.readEntry("MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE);
0462         }
0463 
0464         if (reset || cgHtml.hasKey("MediumFontSize")) {
0465             d->m_fontSize = cgHtml.readEntry("MediumFontSize", 12);
0466         }
0467 
0468         d->fonts = cgHtml.readEntry("Fonts", QStringList());
0469         const int fontsListLength = d->fonts.length();
0470         // Resolve generic font family names
0471         for (int i = 0; i < fontsListLength; ++i) {
0472             const QString fontFamily = d->fonts.at(i);
0473             if (!fontFamily.isEmpty()) {
0474                 d->fonts[i] = QFontInfo(QFont(fontFamily)).family();
0475                 //qCWarning(KHTML_LOG) << "Font family name:" << fontFamily << "resolved to:" << d->fonts.at(i);
0476             }
0477         }
0478 
0479         if (reset || cgHtml.hasKey("DefaultEncoding")) {
0480             d->m_encoding = cgHtml.readEntry("DefaultEncoding", "");
0481         }
0482 
0483         if (reset || cgHtml.hasKey("EnforceDefaultCharset")) {
0484             d->enforceCharset = cgHtml.readEntry("EnforceDefaultCharset", false);
0485         }
0486 
0487         // Behavior
0488         if (reset || cgHtml.hasKey("ChangeCursor")) {
0489             d->m_bChangeCursor = cgHtml.readEntry("ChangeCursor", true);
0490         }
0491 
0492         if (reset || cgHtml.hasKey("UnderlineLinks")) {
0493             d->m_underlineLink = cgHtml.readEntry("UnderlineLinks", true);
0494         }
0495 
0496         if (reset || cgHtml.hasKey("HoverLinks")) {
0497             if ((d->m_hoverLink = cgHtml.readEntry("HoverLinks", false))) {
0498                 d->m_underlineLink = false;
0499             }
0500         }
0501 
0502         if (reset || cgHtml.hasKey("AllowTabulation")) {
0503             d->m_allowTabulation = cgHtml.readEntry("AllowTabulation", false);
0504         }
0505 
0506         if (reset || cgHtml.hasKey("AutoSpellCheck")) {
0507             d->m_autoSpellCheck = cgHtml.readEntry("AutoSpellCheck", true);
0508         }
0509 
0510         // Other
0511         if (reset || cgHtml.hasKey("AutoLoadImages")) {
0512             d->m_bAutoLoadImages = cgHtml.readEntry("AutoLoadImages", true);
0513         }
0514 
0515         if (reset || cgHtml.hasKey("UnfinishedImageFrame")) {
0516             d->m_bUnfinishedImageFrame = cgHtml.readEntry("UnfinishedImageFrame", true);
0517         }
0518 
0519         if (reset || cgHtml.hasKey("ShowAnimations")) {
0520             QString value = cgHtml.readEntry("ShowAnimations").toLower();
0521             if (value == "disabled") {
0522                 d->m_showAnimations = KAnimationDisabled;
0523             } else if (value == "looponce") {
0524                 d->m_showAnimations = KAnimationLoopOnce;
0525             } else {
0526                 d->m_showAnimations = KAnimationEnabled;
0527             }
0528         }
0529 
0530         if (reset || cgHtml.hasKey("SmoothScrolling")) {
0531             QString value = cgHtml.readEntry("SmoothScrolling", "whenefficient").toLower();
0532             if (value == "disabled") {
0533                 d->m_smoothScrolling = KSmoothScrollingDisabled;
0534             } else if (value == "whenefficient") {
0535                 d->m_smoothScrolling = KSmoothScrollingWhenEfficient;
0536             } else {
0537                 d->m_smoothScrolling = KSmoothScrollingEnabled;
0538             }
0539         }
0540 
0541         if (reset || cgHtml.hasKey("DNSPrefetch")) {
0542             // Enabled, Disabled, OnlyWWWAndSLD
0543             QString value = cgHtml.readEntry("DNSPrefetch", "Enabled").toLower();
0544             if (value == "enabled") {
0545                 d->m_dnsPrefetch = KDNSPrefetchEnabled;
0546             } else if (value == "onlywwwandsld") {
0547                 d->m_dnsPrefetch = KDNSPrefetchOnlyWWWAndSLD;
0548             } else {
0549                 d->m_dnsPrefetch = KDNSPrefetchDisabled;
0550             }
0551         }
0552 
0553         if (cgHtml.readEntry("UserStyleSheetEnabled", false) == true) {
0554             if (reset || cgHtml.hasKey("UserStyleSheet")) {
0555                 d->m_userSheet = cgHtml.readEntry("UserStyleSheet", "");
0556             }
0557         }
0558 
0559         d->m_formCompletionEnabled = cgHtml.readEntry("FormCompletion", true);
0560         d->m_maxFormCompletionItems = cgHtml.readEntry("MaxFormCompletionItems", 10);
0561         d->m_autoDelayedActionsEnabled = cgHtml.readEntry("AutoDelayedActions", true);
0562         d->m_jsErrorsEnabled = cgHtml.readEntry("ReportJSErrors", true);
0563         const QStringList accesskeys = cgHtml.readEntry("FallbackAccessKeysAssignments", QStringList());
0564         d->m_fallbackAccessKeysAssignments.clear();
0565         for (QStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it)
0566             if ((*it).length() > 2 && (*it)[ 1 ] == ':') {
0567                 d->m_fallbackAccessKeysAssignments.append(qMakePair((*it).mid(2), (*it)[ 0 ]));
0568             }
0569     }
0570 
0571     // Colors
0572     //In which group ?????
0573     if (reset || cg.hasKey("FollowSystemColors")) {
0574         d->m_follow_system_colors = cg.readEntry("FollowSystemColors", false);
0575     }
0576 
0577     KConfigGroup cgGeneral(config, "General");
0578     if (reset || cgGeneral.exists()) {
0579         if (reset || cgGeneral.hasKey("foreground")) {
0580             QColor def(HTML_DEFAULT_TXT_COLOR);
0581             d->m_textColor = cgGeneral.readEntry("foreground", def);
0582         }
0583 
0584         if (reset || cgGeneral.hasKey("linkColor")) {
0585             QColor def(HTML_DEFAULT_LNK_COLOR);
0586             d->m_linkColor = cgGeneral.readEntry("linkColor", def);
0587         }
0588 
0589         if (reset || cgGeneral.hasKey("visitedLinkColor")) {
0590             QColor def(HTML_DEFAULT_VLNK_COLOR);
0591             d->m_vLinkColor = cgGeneral.readEntry("visitedLinkColor", def);
0592         }
0593 
0594         if (reset || cgGeneral.hasKey("background")) {
0595             QColor def(HTML_DEFAULT_BASE_COLOR);
0596             d->m_baseColor = cgGeneral.readEntry("background", def);
0597         }
0598     }
0599 
0600     KConfigGroup cgJava(config, "Java/JavaScript Settings");
0601     if (reset || cgJava.exists()) {
0602         // The global setting for JavaScript debugging
0603         // This is currently always enabled by default
0604         if (reset || cgJava.hasKey("EnableJavaScriptDebug")) {
0605             d->m_bEnableJavaScriptDebug = cgJava.readEntry("EnableJavaScriptDebug", false);
0606         }
0607 
0608         // The global setting for JavaScript error reporting
0609         if (reset || cgJava.hasKey("ReportJavaScriptErrors")) {
0610             d->m_bEnableJavaScriptErrorReporting = cgJava.readEntry("ReportJavaScriptErrors", false);
0611         }
0612 
0613         // The global setting for popup block passive popup
0614         if (reset || cgJava.hasKey("PopupBlockerPassivePopup")) {
0615             d->m_jsPopupBlockerPassivePopup = cgJava.readEntry("PopupBlockerPassivePopup", true);
0616         }
0617 
0618         // Read options from the global "domain"
0619         readDomainSettings(cgJava, reset, true, d->global);
0620 #ifdef DEBUG_SETTINGS
0621         d->global.dump("init global");
0622 #endif
0623 
0624         // The domain-specific settings.
0625 
0626         static const char *const domain_keys[] = {  // always keep order of keys
0627             "ECMADomains", "JavaDomains", "PluginDomains"
0628         };
0629         bool check_old_ecma_settings = true;
0630         bool check_old_java_settings = true;
0631         // merge all domains into one list
0632         QMap<QString, int> domainList;  // why can't Qt have a QSet?
0633         for (unsigned i = 0; i < sizeof domain_keys / sizeof domain_keys[0]; ++i) {
0634             if (reset || cgJava.hasKey(domain_keys[i])) {
0635                 if (i == 0) {
0636                     check_old_ecma_settings = false;
0637                 } else if (i == 1) {
0638                     check_old_java_settings = false;
0639                 }
0640                 const QStringList dl = cgJava.readEntry(domain_keys[i], QStringList());
0641                 const QMap<QString, int>::Iterator notfound = domainList.end();
0642                 QStringList::ConstIterator it = dl.begin();
0643                 const QStringList::ConstIterator itEnd = dl.end();
0644                 for (; it != itEnd; ++it) {
0645                     const QString domain = (*it).toLower();
0646                     QMap<QString, int>::Iterator pos = domainList.find(domain);
0647                     if (pos == notfound) {
0648                         domainList.insert(domain, 0);
0649                     }
0650                 }/*next it*/
0651             }
0652         }/*next i*/
0653 
0654         if (reset) {
0655             d->domainPolicy.clear();
0656         }
0657 
0658         {
0659             QMap<QString, int>::ConstIterator it = domainList.constBegin();
0660             const QMap<QString, int>::ConstIterator itEnd = domainList.constEnd();
0661             for (; it != itEnd; ++it) {
0662                 const QString domain = it.key();
0663                 KConfigGroup cg(config, domain);
0664                 readDomainSettings(cg, reset, false, d->domainPolicy[domain]);
0665 #ifdef DEBUG_SETTINGS
0666                 d->domainPolicy[domain].dump("init " + domain);
0667 #endif
0668             }
0669         }
0670 
0671         bool check_old_java = true;
0672         if ((reset || cgJava.hasKey("JavaDomainSettings"))
0673                 && check_old_java_settings) {
0674             check_old_java = false;
0675             const QStringList domainList = cgJava.readEntry("JavaDomainSettings", QStringList());
0676             QStringList::ConstIterator it = domainList.constBegin();
0677             const QStringList::ConstIterator itEnd = domainList.constEnd();
0678             for (; it != itEnd; ++it) {
0679                 QString domain;
0680                 KJavaScriptAdvice javaAdvice;
0681                 KJavaScriptAdvice javaScriptAdvice;
0682                 splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
0683                 setup_per_domain_policy(d, domain).m_bEnableJava =
0684                     javaAdvice == KJavaScriptAccept;
0685 #ifdef DEBUG_SETTINGS
0686                 setup_per_domain_policy(d, domain).dump("JavaDomainSettings 4 " + domain);
0687 #endif
0688             }
0689         }
0690 
0691         bool check_old_ecma = true;
0692         if ((reset || cgJava.hasKey("ECMADomainSettings"))
0693                 && check_old_ecma_settings) {
0694             check_old_ecma = false;
0695             const QStringList domainList = cgJava.readEntry("ECMADomainSettings", QStringList());
0696             QStringList::ConstIterator it = domainList.constBegin();
0697             const QStringList::ConstIterator itEnd = domainList.constEnd();
0698             for (; it != itEnd; ++it) {
0699                 QString domain;
0700                 KJavaScriptAdvice javaAdvice;
0701                 KJavaScriptAdvice javaScriptAdvice;
0702                 splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
0703                 setup_per_domain_policy(d, domain).m_bEnableJavaScript =
0704                     javaScriptAdvice == KJavaScriptAccept;
0705 #ifdef DEBUG_SETTINGS
0706                 setup_per_domain_policy(d, domain).dump("ECMADomainSettings 4 " + domain);
0707 #endif
0708             }
0709         }
0710 
0711         if ((reset || cgJava.hasKey("JavaScriptDomainAdvice"))
0712                 && (check_old_java || check_old_ecma)
0713                 && (check_old_ecma_settings || check_old_java_settings)) {
0714             const QStringList domainList = cgJava.readEntry("JavaScriptDomainAdvice", QStringList());
0715             QStringList::ConstIterator it = domainList.constBegin();
0716             const QStringList::ConstIterator itEnd = domainList.constEnd();
0717             for (; it != itEnd; ++it) {
0718                 QString domain;
0719                 KJavaScriptAdvice javaAdvice;
0720                 KJavaScriptAdvice javaScriptAdvice;
0721                 splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
0722                 if (check_old_java)
0723                     setup_per_domain_policy(d, domain).m_bEnableJava =
0724                         javaAdvice == KJavaScriptAccept;
0725                 if (check_old_ecma)
0726                     setup_per_domain_policy(d, domain).m_bEnableJavaScript =
0727                         javaScriptAdvice == KJavaScriptAccept;
0728 #ifdef DEBUG_SETTINGS
0729                 setup_per_domain_policy(d, domain).dump("JavaScriptDomainAdvice 4 " + domain);
0730 #endif
0731             }
0732 
0733             //save all the settings into the new keywords if they don't exist
0734 #if 0
0735             if (check_old_java) {
0736                 QStringList domainConfig;
0737                 PolicyMap::Iterator it;
0738                 for (it = d->javaDomainPolicy.begin(); it != d->javaDomainPolicy.end(); ++it) {
0739                     QByteArray javaPolicy = adviceToStr(it.value());
0740                     QByteArray javaScriptPolicy = adviceToStr(KJavaScriptDunno);
0741                     domainConfig.append(QString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy));
0742                 }
0743                 cg.writeEntry("JavaDomainSettings", domainConfig);
0744             }
0745 
0746             if (check_old_ecma) {
0747                 QStringList domainConfig;
0748                 PolicyMap::Iterator it;
0749                 for (it = d->javaScriptDomainPolicy.begin(); it != d->javaScriptDomainPolicy.end(); ++it) {
0750                     QByteArray javaPolicy = adviceToStr(KJavaScriptDunno);
0751                     QByteArray javaScriptPolicy = adviceToStr(it.value());
0752                     domainConfig.append(QString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy));
0753                 }
0754                 cg.writeEntry("ECMADomainSettings", domainConfig);
0755             }
0756 #endif
0757         }
0758     }
0759 }
0760 
0761 /** Local helper for retrieving per-domain settings.
0762   *
0763   * In case of doubt, the global domain is returned.
0764   */
0765 static const KPerDomainSettings &lookup_hostname_policy(
0766     const KHTMLSettingsPrivate *const d,
0767     const QString &hostname)
0768 {
0769 #ifdef DEBUG_SETTINGS
0770     // qCDebug(KHTML_LOG) << "lookup_hostname_policy(" << hostname << ")";
0771 #endif
0772     if (hostname.isEmpty()) {
0773 #ifdef DEBUG_SETTINGS
0774         d->global.dump("global");
0775 #endif
0776         return d->global;
0777     }
0778 
0779     const PolicyMap::const_iterator notfound = d->domainPolicy.constEnd();
0780 
0781     // First check whether there is a perfect match.
0782     PolicyMap::const_iterator it = d->domainPolicy.find(hostname);
0783     if (it != notfound) {
0784 #ifdef DEBUG_SETTINGS
0785         // qCDebug(KHTML_LOG) << "perfect match";
0786         (*it).dump(hostname);
0787 #endif
0788         // yes, use it (unless dunno)
0789         return *it;
0790     }
0791 
0792     // Now, check for partial match.  Chop host from the left until
0793     // there's no dots left.
0794     QString host_part = hostname;
0795     int dot_idx = -1;
0796     while ((dot_idx = host_part.indexOf(QChar('.'))) >= 0) {
0797         host_part.remove(0, dot_idx);
0798         it = d->domainPolicy.find(host_part);
0799         Q_ASSERT(notfound == d->domainPolicy.end());
0800         if (it != notfound) {
0801 #ifdef DEBUG_SETTINGS
0802             // qCDebug(KHTML_LOG) << "partial match";
0803             (*it).dump(host_part);
0804 #endif
0805             return *it;
0806         }
0807         // assert(host_part[0] == QChar('.'));
0808         host_part.remove(0, 1); // Chop off the dot.
0809     }
0810 
0811     // No domain-specific entry: use global domain
0812 #ifdef DEBUG_SETTINGS
0813     // qCDebug(KHTML_LOG) << "no match";
0814     d->global.dump("global");
0815 #endif
0816     return d->global;
0817 }
0818 
0819 bool KHTMLSettings::isOpenMiddleClickEnabled()
0820 {
0821     return d->m_bOpenMiddleClick;
0822 }
0823 
0824 bool KHTMLSettings::isBackRightClickEnabled()
0825 {
0826     return false; // ## the feature moved to konqueror
0827 }
0828 
0829 bool KHTMLSettings::accessKeysEnabled() const
0830 {
0831     return d->m_accessKeysEnabled;
0832 }
0833 
0834 bool KHTMLSettings::isAdFilterEnabled() const
0835 {
0836     return d->m_adFilterEnabled;
0837 }
0838 
0839 bool KHTMLSettings::isHideAdsEnabled() const
0840 {
0841     return d->m_hideAdsEnabled;
0842 }
0843 
0844 bool KHTMLSettings::isAdFiltered(const QString &url) const
0845 {
0846     if (d->m_adFilterEnabled) {
0847         if (!url.startsWith("data:")) {
0848             // Check the blacklist, and only if that matches, the whitelist
0849             return d->adBlackList.isUrlMatched(url) && !d->adWhiteList.isUrlMatched(url);
0850         }
0851     }
0852     return false;
0853 }
0854 
0855 QString KHTMLSettings::adFilteredBy(const QString &url, bool *isWhiteListed) const
0856 {
0857     QString m = d->adWhiteList.urlMatchedBy(url);
0858     if (!m.isEmpty()) {
0859         if (isWhiteListed != nullptr) {
0860             *isWhiteListed = true;
0861         }
0862         return (m);
0863     }
0864 
0865     m = d->adBlackList.urlMatchedBy(url);
0866     if (!m.isEmpty()) {
0867         if (isWhiteListed != nullptr) {
0868             *isWhiteListed = false;
0869         }
0870         return (m);
0871     }
0872 
0873     return (QString());
0874 }
0875 
0876 void KHTMLSettings::addAdFilter(const QString &url)
0877 {
0878     KConfigGroup config = KSharedConfig::openConfig("khtmlrc", KConfig::NoGlobals)->group("Filter Settings");
0879 
0880     QRegExp rx;
0881 
0882     // Try compiling to avoid invalid stuff. Only support the basic syntax here...
0883     // ### refactor somewhat
0884     if (url.length() > 2 && url[0] == '/' && url[url.length() - 1] == '/') {
0885         QString inside = url.mid(1, url.length() - 2);
0886         rx.setPattern(inside);
0887     } else {
0888         rx.setPatternSyntax(QRegExp::Wildcard);
0889         rx.setPattern(url);
0890     }
0891 
0892     if (rx.isValid()) {
0893         int last = config.readEntry("Count", 0);
0894         QString key = "Filter-" + QString::number(last);
0895         config.writeEntry(key, url);
0896         config.writeEntry("Count", last + 1);
0897         config.sync();
0898         if (url.startsWith(QLatin1String("@@"))) {
0899             d->adWhiteList.addFilter(url);
0900         } else {
0901             d->adBlackList.addFilter(url);
0902         }
0903     } else {
0904         KMessageBox::error(nullptr,
0905                            rx.errorString(),
0906                            i18n("Filter error"));
0907     }
0908 }
0909 
0910 bool KHTMLSettings::isJavaEnabled(const QString &hostname) const
0911 {
0912     return lookup_hostname_policy(d, hostname.toLower()).m_bEnableJava;
0913 }
0914 
0915 bool KHTMLSettings::isJavaScriptEnabled(const QString &hostname) const
0916 {
0917     return lookup_hostname_policy(d, hostname.toLower()).m_bEnableJavaScript;
0918 }
0919 
0920 bool KHTMLSettings::isJavaScriptDebugEnabled(const QString & /*hostname*/) const
0921 {
0922     // debug setting is global for now, but could change in the future
0923     return d->m_bEnableJavaScriptDebug;
0924 }
0925 
0926 bool KHTMLSettings::isJavaScriptErrorReportingEnabled(const QString & /*hostname*/) const
0927 {
0928     // error reporting setting is global for now, but could change in the future
0929     return d->m_bEnableJavaScriptErrorReporting;
0930 }
0931 
0932 bool KHTMLSettings::isPluginsEnabled(const QString &hostname) const
0933 {
0934     return lookup_hostname_policy(d, hostname.toLower()).m_bEnablePlugins;
0935 }
0936 
0937 KHTMLSettings::KJSWindowOpenPolicy KHTMLSettings::windowOpenPolicy(
0938     const QString &hostname) const
0939 {
0940     return lookup_hostname_policy(d, hostname.toLower()).m_windowOpenPolicy;
0941 }
0942 
0943 KHTMLSettings::KJSWindowMovePolicy KHTMLSettings::windowMovePolicy(
0944     const QString &hostname) const
0945 {
0946     return lookup_hostname_policy(d, hostname.toLower()).m_windowMovePolicy;
0947 }
0948 
0949 KHTMLSettings::KJSWindowResizePolicy KHTMLSettings::windowResizePolicy(
0950     const QString &hostname) const
0951 {
0952     return lookup_hostname_policy(d, hostname.toLower()).m_windowResizePolicy;
0953 }
0954 
0955 KHTMLSettings::KJSWindowStatusPolicy KHTMLSettings::windowStatusPolicy(
0956     const QString &hostname) const
0957 {
0958     return lookup_hostname_policy(d, hostname.toLower()).m_windowStatusPolicy;
0959 }
0960 
0961 KHTMLSettings::KJSWindowFocusPolicy KHTMLSettings::windowFocusPolicy(
0962     const QString &hostname) const
0963 {
0964     return lookup_hostname_policy(d, hostname.toLower()).m_windowFocusPolicy;
0965 }
0966 
0967 int KHTMLSettings::mediumFontSize() const
0968 {
0969     return d->m_fontSize;
0970 }
0971 
0972 int KHTMLSettings::minFontSize() const
0973 {
0974     return d->m_minFontSize;
0975 }
0976 
0977 QString KHTMLSettings::settingsToCSS() const
0978 {
0979     // lets start with the link properties
0980     QString str = "a:link {\ncolor: ";
0981     str += d->m_linkColor.name();
0982     str += ';';
0983     if (d->m_underlineLink) {
0984         str += "\ntext-decoration: underline;";
0985     }
0986 
0987     if (d->m_bChangeCursor) {
0988         str += "\ncursor: pointer;";
0989         str += "\n}\ninput[type=image] { cursor: pointer;";
0990     }
0991     str += "\n}\n";
0992     str += "a:visited {\ncolor: ";
0993     str += d->m_vLinkColor.name();
0994     str += ';';
0995     if (d->m_underlineLink) {
0996         str += "\ntext-decoration: underline;";
0997     }
0998 
0999     if (d->m_bChangeCursor) {
1000         str += "\ncursor: pointer;";
1001     }
1002     str += "\n}\n";
1003 
1004     if (d->m_hoverLink) {
1005         str += "a:link:hover, a:visited:hover { text-decoration: underline; }\n";
1006     }
1007 
1008     return str;
1009 }
1010 
1011 const QString &KHTMLSettings::availableFamilies()
1012 {
1013     if (!avFamilies) {
1014         avFamilies = new QString;
1015         QFontDatabase db;
1016         QStringList families = db.families();
1017         QStringList s;
1018         QRegExp foundryExp(" \\[.+\\]");
1019 
1020         //remove foundry info
1021         QStringList::Iterator f = families.begin();
1022         const QStringList::Iterator fEnd = families.end();
1023 
1024         for (; f != fEnd; ++f) {
1025             (*f).replace(foundryExp, "");
1026             if (!s.contains(*f)) {
1027                 s << *f;
1028             }
1029         }
1030         s.sort();
1031 
1032         *avFamilies = ',' + s.join(",") + ',';
1033     }
1034 
1035     return *avFamilies;
1036 }
1037 
1038 QString KHTMLSettings::lookupFont(int i) const
1039 {
1040     QString font;
1041     if (d->fonts.count() > i) {
1042         font = d->fonts[i];
1043     }
1044     if (font.isEmpty()) {
1045         font = d->defaultFonts[i];
1046     }
1047     return font;
1048 }
1049 
1050 QString KHTMLSettings::stdFontName() const
1051 {
1052     return lookupFont(0);
1053 }
1054 
1055 QString KHTMLSettings::fixedFontName() const
1056 {
1057     return lookupFont(1);
1058 }
1059 
1060 QString KHTMLSettings::serifFontName() const
1061 {
1062     return lookupFont(2);
1063 }
1064 
1065 QString KHTMLSettings::sansSerifFontName() const
1066 {
1067     return lookupFont(3);
1068 }
1069 
1070 QString KHTMLSettings::cursiveFontName() const
1071 {
1072     return lookupFont(4);
1073 }
1074 
1075 QString KHTMLSettings::fantasyFontName() const
1076 {
1077     return lookupFont(5);
1078 }
1079 
1080 void KHTMLSettings::setStdFontName(const QString &n)
1081 {
1082     while (d->fonts.count() <= 0) {
1083         d->fonts.append(QString());
1084     }
1085     d->fonts[0] = n;
1086 }
1087 
1088 void KHTMLSettings::setFixedFontName(const QString &n)
1089 {
1090     while (d->fonts.count() <= 1) {
1091         d->fonts.append(QString());
1092     }
1093     d->fonts[1] = n;
1094 }
1095 
1096 QString KHTMLSettings::userStyleSheet() const
1097 {
1098     return d->m_userSheet;
1099 }
1100 
1101 bool KHTMLSettings::isFormCompletionEnabled() const
1102 {
1103     return d->m_formCompletionEnabled;
1104 }
1105 
1106 int KHTMLSettings::maxFormCompletionItems() const
1107 {
1108     return d->m_maxFormCompletionItems;
1109 }
1110 
1111 const QString &KHTMLSettings::encoding() const
1112 {
1113     return d->m_encoding;
1114 }
1115 
1116 bool KHTMLSettings::followSystemColors() const
1117 {
1118     return d->m_follow_system_colors;
1119 }
1120 
1121 const QColor &KHTMLSettings::textColor() const
1122 {
1123     return d->m_textColor;
1124 }
1125 
1126 const QColor &KHTMLSettings::baseColor() const
1127 {
1128     return d->m_baseColor;
1129 }
1130 
1131 const QColor &KHTMLSettings::linkColor() const
1132 {
1133     return d->m_linkColor;
1134 }
1135 
1136 const QColor &KHTMLSettings::vLinkColor() const
1137 {
1138     return d->m_vLinkColor;
1139 }
1140 
1141 bool KHTMLSettings::autoLoadImages() const
1142 {
1143     return d->m_bAutoLoadImages;
1144 }
1145 
1146 bool KHTMLSettings::unfinishedImageFrame() const
1147 {
1148     return d->m_bUnfinishedImageFrame;
1149 }
1150 
1151 KHTMLSettings::KAnimationAdvice KHTMLSettings::showAnimations() const
1152 {
1153     return d->m_showAnimations;
1154 }
1155 
1156 KHTMLSettings::KSmoothScrollingMode KHTMLSettings::smoothScrolling() const
1157 {
1158     return d->m_smoothScrolling;
1159 }
1160 
1161 KHTMLSettings::KDNSPrefetch KHTMLSettings::dnsPrefetch() const
1162 {
1163     return d->m_dnsPrefetch;
1164 }
1165 
1166 bool KHTMLSettings::isAutoDelayedActionsEnabled() const
1167 {
1168     return d->m_autoDelayedActionsEnabled;
1169 }
1170 
1171 bool KHTMLSettings::jsErrorsEnabled() const
1172 {
1173     return d->m_jsErrorsEnabled;
1174 }
1175 
1176 void KHTMLSettings::setJSErrorsEnabled(bool enabled)
1177 {
1178     d->m_jsErrorsEnabled = enabled;
1179     // save it
1180     KConfigGroup cg(KSharedConfig::openConfig(), "HTML Settings");
1181     cg.writeEntry("ReportJSErrors", enabled);
1182     cg.sync();
1183 }
1184 
1185 bool KHTMLSettings::allowTabulation() const
1186 {
1187     return d->m_allowTabulation;
1188 }
1189 
1190 bool KHTMLSettings::autoSpellCheck() const
1191 {
1192     return d->m_autoSpellCheck;
1193 }
1194 
1195 QList< QPair< QString, QChar > > KHTMLSettings::fallbackAccessKeysAssignments() const
1196 {
1197     return d->m_fallbackAccessKeysAssignments;
1198 }
1199 
1200 void KHTMLSettings::setJSPopupBlockerPassivePopup(bool enabled)
1201 {
1202     d->m_jsPopupBlockerPassivePopup = enabled;
1203     // save it
1204     KConfigGroup cg(KSharedConfig::openConfig(), "Java/JavaScript Settings");
1205     cg.writeEntry("PopupBlockerPassivePopup", enabled);
1206     cg.sync();
1207 }
1208 
1209 bool KHTMLSettings::jsPopupBlockerPassivePopup() const
1210 {
1211     return d->m_jsPopupBlockerPassivePopup;
1212 }
1213 
1214 #include "khtml_settings.moc"