KHTML
khtml_settings.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 1999 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "khtml_settings.h" 00021 #include "khtmldefaults.h" 00022 00023 #include <kconfig.h> 00024 #include <kconfiggroup.h> 00025 #include <kdebug.h> 00026 #include <kglobal.h> 00027 #include <kglobalsettings.h> 00028 #include <klocale.h> 00029 #include <kmessagebox.h> 00030 #include <khtml_filter_p.h> 00031 #include <kstandarddirs.h> 00032 #include <kjob.h> 00033 #include <kio/job.h> 00034 00035 #include <QFile> 00036 #include <QFileInfo> 00037 #include <QtGui/QFontDatabase> 00038 #include <QByteArray> 00039 00044 struct KPerDomainSettings { 00045 bool m_bEnableJava : 1; 00046 bool m_bEnableJavaScript : 1; 00047 bool m_bEnablePlugins : 1; 00048 // don't forget to maintain the bitfields as the enums grow 00049 KHTMLSettings::KJSWindowOpenPolicy m_windowOpenPolicy : 2; 00050 KHTMLSettings::KJSWindowStatusPolicy m_windowStatusPolicy : 1; 00051 KHTMLSettings::KJSWindowFocusPolicy m_windowFocusPolicy : 1; 00052 KHTMLSettings::KJSWindowMovePolicy m_windowMovePolicy : 1; 00053 KHTMLSettings::KJSWindowResizePolicy m_windowResizePolicy : 1; 00054 00055 #ifdef DEBUG_SETTINGS 00056 void dump(const QString &infix = QString()) const { 00057 kDebug() << "KPerDomainSettings " << infix << " @" << this << ":"; 00058 kDebug() << " m_bEnableJava: " << m_bEnableJava; 00059 kDebug() << " m_bEnableJavaScript: " << m_bEnableJavaScript; 00060 kDebug() << " m_bEnablePlugins: " << m_bEnablePlugins; 00061 kDebug() << " m_windowOpenPolicy: " << m_windowOpenPolicy; 00062 kDebug() << " m_windowStatusPolicy: " << m_windowStatusPolicy; 00063 kDebug() << " m_windowFocusPolicy: " << m_windowFocusPolicy; 00064 kDebug() << " m_windowMovePolicy: " << m_windowMovePolicy; 00065 kDebug() << " m_windowResizePolicy: " << m_windowResizePolicy; 00066 } 00067 #endif 00068 }; 00069 00070 QString *KHTMLSettings::avFamilies = 0; 00071 typedef QMap<QString,KPerDomainSettings> PolicyMap; 00072 00073 // The "struct" that contains all the data. Must be copiable (no pointers). 00074 class KHTMLSettingsData 00075 { 00076 public: 00077 bool m_bChangeCursor : 1; 00078 bool m_bOpenMiddleClick : 1; 00079 bool m_underlineLink : 1; 00080 bool m_hoverLink : 1; 00081 bool m_bEnableJavaScriptDebug : 1; 00082 bool m_bEnableJavaScriptErrorReporting : 1; 00083 bool enforceCharset : 1; 00084 bool m_bAutoLoadImages : 1; 00085 bool m_bUnfinishedImageFrame : 1; 00086 bool m_formCompletionEnabled : 1; 00087 bool m_autoDelayedActionsEnabled : 1; 00088 bool m_jsErrorsEnabled : 1; 00089 bool m_follow_system_colors : 1; 00090 bool m_allowTabulation : 1; 00091 bool m_autoSpellCheck : 1; 00092 bool m_adFilterEnabled : 1; 00093 bool m_hideAdsEnabled : 1; 00094 bool m_jsPopupBlockerPassivePopup : 1; 00095 bool m_accessKeysEnabled : 1; 00096 00097 // the virtual global "domain" 00098 KPerDomainSettings global; 00099 00100 int m_fontSize; 00101 int m_minFontSize; 00102 int m_maxFormCompletionItems; 00103 KHTMLSettings::KAnimationAdvice m_showAnimations; 00104 KHTMLSettings::KSmoothScrollingMode m_smoothScrolling; 00105 KHTMLSettings::KDNSPrefetch m_dnsPrefetch; 00106 00107 QString m_encoding; 00108 QString m_userSheet; 00109 00110 QColor m_textColor; 00111 QColor m_baseColor; 00112 QColor m_linkColor; 00113 QColor m_vLinkColor; 00114 00115 PolicyMap domainPolicy; 00116 QStringList fonts; 00117 QStringList defaultFonts; 00118 00119 khtml::FilterSet adBlackList; 00120 khtml::FilterSet adWhiteList; 00121 QList< QPair< QString, QChar > > m_fallbackAccessKeysAssignments; 00122 }; 00123 00124 class KHTMLSettingsPrivate : public QObject, public KHTMLSettingsData 00125 { 00126 Q_OBJECT 00127 public: 00128 00129 void adblockFilterLoadList(const QString& filename) 00130 { 00131 kDebug(6000) << "Loading filter list from" << filename; 00133 QFile file(filename); 00134 if (file.open(QIODevice::ReadOnly)) { 00135 QTextStream ts(&file); 00136 QString line = ts.readLine(); 00137 #ifndef NDEBUG /// only count when compiled for debugging 00138 int whiteCounter = 0, blackCounter = 0; 00139 #endif // NDEBUG 00140 while (!line.isEmpty()) { 00142 if (line.startsWith(QLatin1String("@@"))) 00143 { 00144 #ifndef NDEBUG 00145 ++whiteCounter; 00146 #endif // NDEBUG 00147 adWhiteList.addFilter(line); 00148 } 00149 else 00150 { 00151 #ifndef NDEBUG 00152 ++blackCounter; 00153 #endif // NDEBUG 00154 adBlackList.addFilter(line); 00155 } 00156 00157 line = ts.readLine(); 00158 } 00159 file.close(); 00160 00161 #ifndef NDEBUG 00162 kDebug(6000) << "Filter list loaded" << whiteCounter << "white list entries and" << blackCounter << "black list entries"; 00163 #endif // NDEBUG 00164 } 00165 } 00166 00167 public slots: 00168 void adblockFilterResult(KJob *job) 00169 { 00170 KIO::StoredTransferJob *tJob = qobject_cast<KIO::StoredTransferJob*>(job); 00171 Q_ASSERT(tJob); 00172 00173 if ( job->error() == KJob::NoError ) 00174 { 00175 const QByteArray byteArray = tJob->data(); 00176 const QString localFileName = tJob->property( "khtmlsettings_adBlock_filename" ).toString(); 00177 00178 QFile file(localFileName); 00179 if ( file.open(QFile::WriteOnly) ) 00180 { 00181 bool success = file.write(byteArray) == byteArray.size(); 00182 file.close(); 00183 if ( success ) 00184 adblockFilterLoadList(localFileName); 00185 else 00186 kDebug(6000) << "Could not write" << byteArray.size() << "to file" << localFileName; 00187 } 00188 else 00189 kDebug(6000) << "Cannot open file" << localFileName << "for filter list"; 00190 } 00191 else 00192 kDebug(6000) << "Downloading" << tJob->url() << "failed with message:" << job->errorText(); 00193 } 00194 }; 00195 00196 00200 static KPerDomainSettings &setup_per_domain_policy( 00201 KHTMLSettingsPrivate* const d, 00202 const QString &domain) { 00203 if (domain.isEmpty()) { 00204 kWarning(6000) << "setup_per_domain_policy: domain is empty"; 00205 } 00206 const QString ldomain = domain.toLower(); 00207 PolicyMap::iterator it = d->domainPolicy.find(ldomain); 00208 if (it == d->domainPolicy.end()) { 00209 // simply copy global domain settings (they should have been initialized 00210 // by this time) 00211 it = d->domainPolicy.insert(ldomain,d->global); 00212 } 00213 return *it; 00214 } 00215 00216 00217 KHTMLSettings::KJavaScriptAdvice KHTMLSettings::strToAdvice(const QString& _str) 00218 { 00219 KJavaScriptAdvice ret = KJavaScriptDunno; 00220 00221 if (_str.isNull()) 00222 ret = KJavaScriptDunno; 00223 00224 if (_str.toLower() == QLatin1String("accept")) 00225 ret = KJavaScriptAccept; 00226 else if (_str.toLower() == QLatin1String("reject")) 00227 ret = KJavaScriptReject; 00228 00229 return ret; 00230 } 00231 00232 const char* KHTMLSettings::adviceToStr(KJavaScriptAdvice _advice) 00233 { 00234 switch( _advice ) { 00235 case KJavaScriptAccept: return I18N_NOOP("Accept"); 00236 case KJavaScriptReject: return I18N_NOOP("Reject"); 00237 default: return 0; 00238 } 00239 return 0; 00240 } 00241 00242 00243 void KHTMLSettings::splitDomainAdvice(const QString& configStr, QString &domain, 00244 KJavaScriptAdvice &javaAdvice, KJavaScriptAdvice& javaScriptAdvice) 00245 { 00246 QString tmp(configStr); 00247 int splitIndex = tmp.indexOf(':'); 00248 if ( splitIndex == -1) 00249 { 00250 domain = configStr.toLower(); 00251 javaAdvice = KJavaScriptDunno; 00252 javaScriptAdvice = KJavaScriptDunno; 00253 } 00254 else 00255 { 00256 domain = tmp.left(splitIndex).toLower(); 00257 QString adviceString = tmp.mid( splitIndex+1, tmp.length() ); 00258 int splitIndex2 = adviceString.indexOf( ':' ); 00259 if( splitIndex2 == -1 ) { 00260 // Java advice only 00261 javaAdvice = strToAdvice( adviceString ); 00262 javaScriptAdvice = KJavaScriptDunno; 00263 } else { 00264 // Java and JavaScript advice 00265 javaAdvice = strToAdvice( adviceString.left( splitIndex2 ) ); 00266 javaScriptAdvice = strToAdvice( adviceString.mid( splitIndex2+1, 00267 adviceString.length() ) ); 00268 } 00269 } 00270 } 00271 00272 void KHTMLSettings::readDomainSettings(const KConfigGroup &config, bool reset, 00273 bool global, KPerDomainSettings &pd_settings) { 00274 QString jsPrefix = global ? QString() 00275 : QString::fromLatin1("javascript."); 00276 QString javaPrefix = global ? QString() 00277 : QString::fromLatin1("java."); 00278 QString pluginsPrefix = global ? QString() 00279 : QString::fromLatin1("plugins."); 00280 00281 // The setting for Java 00282 QString key = javaPrefix + QLatin1String("EnableJava"); 00283 if ( (global && reset) || config.hasKey( key ) ) 00284 pd_settings.m_bEnableJava = config.readEntry( key, false ); 00285 else if ( !global ) 00286 pd_settings.m_bEnableJava = d->global.m_bEnableJava; 00287 00288 // The setting for Plugins 00289 key = pluginsPrefix + QLatin1String("EnablePlugins"); 00290 if ( (global && reset) || config.hasKey( key ) ) 00291 pd_settings.m_bEnablePlugins = config.readEntry( key, true ); 00292 else if ( !global ) 00293 pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins; 00294 00295 // The setting for JavaScript 00296 key = jsPrefix + QLatin1String("EnableJavaScript"); 00297 if ( (global && reset) || config.hasKey( key ) ) 00298 pd_settings.m_bEnableJavaScript = config.readEntry( key, true ); 00299 else if ( !global ) 00300 pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript; 00301 00302 // window property policies 00303 key = jsPrefix + QLatin1String("WindowOpenPolicy"); 00304 if ( (global && reset) || config.hasKey( key ) ) 00305 pd_settings.m_windowOpenPolicy = (KJSWindowOpenPolicy) 00306 config.readEntry( key, uint(KJSWindowOpenSmart) ); 00307 else if ( !global ) 00308 pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy; 00309 00310 key = jsPrefix + QLatin1String("WindowMovePolicy"); 00311 if ( (global && reset) || config.hasKey( key ) ) 00312 pd_settings.m_windowMovePolicy = (KJSWindowMovePolicy) 00313 config.readEntry( key, uint(KJSWindowMoveAllow) ); 00314 else if ( !global ) 00315 pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy; 00316 00317 key = jsPrefix + QLatin1String("WindowResizePolicy"); 00318 if ( (global && reset) || config.hasKey( key ) ) 00319 pd_settings.m_windowResizePolicy = (KJSWindowResizePolicy) 00320 config.readEntry( key, uint(KJSWindowResizeAllow) ); 00321 else if ( !global ) 00322 pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy; 00323 00324 key = jsPrefix + QLatin1String("WindowStatusPolicy"); 00325 if ( (global && reset) || config.hasKey( key ) ) 00326 pd_settings.m_windowStatusPolicy = (KJSWindowStatusPolicy) 00327 config.readEntry( key, uint(KJSWindowStatusAllow) ); 00328 else if ( !global ) 00329 pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy; 00330 00331 key = jsPrefix + QLatin1String("WindowFocusPolicy"); 00332 if ( (global && reset) || config.hasKey( key ) ) 00333 pd_settings.m_windowFocusPolicy = (KJSWindowFocusPolicy) 00334 config.readEntry( key, uint(KJSWindowFocusAllow) ); 00335 else if ( !global ) 00336 pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy; 00337 00338 } 00339 00340 00341 KHTMLSettings::KHTMLSettings() 00342 :d (new KHTMLSettingsPrivate()) 00343 { 00344 init(); 00345 } 00346 00347 KHTMLSettings::KHTMLSettings(const KHTMLSettings &other) 00348 :d(new KHTMLSettingsPrivate()) 00349 { 00350 KHTMLSettingsData* data = d; 00351 *data = *other.d; 00352 } 00353 00354 KHTMLSettings::~KHTMLSettings() 00355 { 00356 delete d; 00357 } 00358 00359 bool KHTMLSettings::changeCursor() const 00360 { 00361 return d->m_bChangeCursor; 00362 } 00363 00364 bool KHTMLSettings::underlineLink() const 00365 { 00366 return d->m_underlineLink; 00367 } 00368 00369 bool KHTMLSettings::hoverLink() const 00370 { 00371 return d->m_hoverLink; 00372 } 00373 00374 void KHTMLSettings::init() 00375 { 00376 KConfig global( "khtmlrc", KConfig::NoGlobals ); 00377 init( &global, true ); 00378 00379 KSharedConfig::Ptr local = KGlobal::config(); 00380 if ( !local ) 00381 return; 00382 00383 init( local.data(), false ); 00384 } 00385 00386 void KHTMLSettings::init( KConfig * config, bool reset ) 00387 { 00388 KConfigGroup cg( config, "MainView Settings" ); 00389 if (reset || cg.exists() ) 00390 { 00391 if ( reset || cg.hasKey( "OpenMiddleClick" ) ) 00392 d->m_bOpenMiddleClick = cg.readEntry( "OpenMiddleClick", true ); 00393 } 00394 00395 KConfigGroup cgAccess(config,"Access Keys" ); 00396 if (reset || cgAccess.exists() ) { 00397 d->m_accessKeysEnabled = cgAccess.readEntry( "Enabled", true ); 00398 } 00399 00400 KConfigGroup cgFilter( config, "Filter Settings" ); 00401 00402 if (reset || cgFilter.exists() ) 00403 { 00404 d->m_adFilterEnabled = cgFilter.readEntry("Enabled", false); 00405 d->m_hideAdsEnabled = cgFilter.readEntry("Shrink", false); 00406 00407 d->adBlackList.clear(); 00408 d->adWhiteList.clear(); 00409 00411 int htmlFilterListMaxAgeDays = cgFilter.readEntry(QString("HTMLFilterListMaxAgeDays")).toInt(); 00412 if (htmlFilterListMaxAgeDays < 1) 00413 htmlFilterListMaxAgeDays = 1; 00414 00415 QMap<QString,QString> entryMap = cgFilter.entryMap(); 00416 QMap<QString,QString>::ConstIterator it; 00417 for( it = entryMap.constBegin(); it != entryMap.constEnd(); ++it ) 00418 { 00419 int id = -1; 00420 QString name = it.key(); 00421 QString url = it.value(); 00422 00423 if (name.startsWith("Filter")) 00424 { 00425 if (url.startsWith(QLatin1String("@@"))) 00426 d->adWhiteList.addFilter(url); 00427 else 00428 d->adBlackList.addFilter(url); 00429 } else if (name.startsWith("HTMLFilterListName-") && (id = name.mid(19).toInt()) > 0) 00430 { 00432 bool filterEnabled = cgFilter.readEntry(QString("HTMLFilterListEnabled-").append(QString::number(id))) != QLatin1String("false"); 00433 00435 KUrl url(cgFilter.readEntry(QString("HTMLFilterListURL-").append(QString::number(id)))); 00436 00437 if (filterEnabled && url.isValid()) { 00439 QString localFile = cgFilter.readEntry(QString("HTMLFilterListLocalFilename-").append(QString::number(id))); 00440 localFile = KStandardDirs::locateLocal("data", "khtml/" + localFile); 00441 00443 QFileInfo fileInfo(localFile); 00444 00446 if (fileInfo.exists()) 00447 d->adblockFilterLoadList( localFile ); 00448 00450 if (!fileInfo.exists() || fileInfo.lastModified().daysTo(QDateTime::currentDateTime()) > htmlFilterListMaxAgeDays) 00451 { 00453 kDebug(6000) << "Asynchronously fetching filter list from" << url << "to" << localFile; 00454 00455 KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo ); 00456 QObject::connect( job, SIGNAL( result(KJob *) ), d, SLOT( adblockFilterResult(KJob *) ) ); 00458 job->setProperty("khtmlsettings_adBlock_filename", localFile); 00459 } 00460 } 00461 } 00462 } 00463 } 00464 00465 KConfigGroup cgHtml( config, "HTML Settings" ); 00466 if (reset || cgHtml.exists() ) 00467 { 00468 // Fonts and colors 00469 if( reset ) { 00470 d->defaultFonts = QStringList(); 00471 d->defaultFonts.append( cgHtml.readEntry( "StandardFont", KGlobalSettings::generalFont().family() ) ); 00472 d->defaultFonts.append( cgHtml.readEntry( "FixedFont", KGlobalSettings::fixedFont().family() ) ); 00473 d->defaultFonts.append( cgHtml.readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) ); 00474 d->defaultFonts.append( cgHtml.readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) ); 00475 d->defaultFonts.append( cgHtml.readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) ); 00476 d->defaultFonts.append( cgHtml.readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) ); 00477 d->defaultFonts.append( QString( "0" ) ); // font size adjustment 00478 } 00479 00480 if ( reset || cgHtml.hasKey( "MinimumFontSize" ) ) 00481 d->m_minFontSize = cgHtml.readEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE ); 00482 00483 if ( reset || cgHtml.hasKey( "MediumFontSize" ) ) 00484 d->m_fontSize = cgHtml.readEntry( "MediumFontSize", 12 ); 00485 00486 d->fonts = cgHtml.readEntry( "Fonts", QStringList() ); 00487 00488 if ( reset || cgHtml.hasKey( "DefaultEncoding" ) ) 00489 d->m_encoding = cgHtml.readEntry( "DefaultEncoding", "" ); 00490 00491 if ( reset || cgHtml.hasKey( "EnforceDefaultCharset" ) ) 00492 d->enforceCharset = cgHtml.readEntry( "EnforceDefaultCharset", false ); 00493 00494 // Behavior 00495 if ( reset || cgHtml.hasKey( "ChangeCursor" ) ) 00496 d->m_bChangeCursor = cgHtml.readEntry( "ChangeCursor", KDE_DEFAULT_CHANGECURSOR ); 00497 00498 if ( reset || cgHtml.hasKey("UnderlineLinks") ) 00499 d->m_underlineLink = cgHtml.readEntry( "UnderlineLinks", true ); 00500 00501 if ( reset || cgHtml.hasKey( "HoverLinks" ) ) 00502 { 00503 if ( (d->m_hoverLink = cgHtml.readEntry( "HoverLinks", false ))) 00504 d->m_underlineLink = false; 00505 } 00506 00507 if ( reset || cgHtml.hasKey( "AllowTabulation" ) ) 00508 d->m_allowTabulation = cgHtml.readEntry( "AllowTabulation", false ); 00509 00510 if ( reset || cgHtml.hasKey( "AutoSpellCheck" ) ) 00511 d->m_autoSpellCheck = cgHtml.readEntry( "AutoSpellCheck", true ); 00512 00513 // Other 00514 if ( reset || cgHtml.hasKey( "AutoLoadImages" ) ) 00515 d->m_bAutoLoadImages = cgHtml.readEntry( "AutoLoadImages", true ); 00516 00517 if ( reset || cgHtml.hasKey( "UnfinishedImageFrame" ) ) 00518 d->m_bUnfinishedImageFrame = cgHtml.readEntry( "UnfinishedImageFrame", true ); 00519 00520 if ( reset || cgHtml.hasKey( "ShowAnimations" ) ) 00521 { 00522 QString value = cgHtml.readEntry( "ShowAnimations").toLower(); 00523 if (value == "disabled") 00524 d->m_showAnimations = KAnimationDisabled; 00525 else if (value == "looponce") 00526 d->m_showAnimations = KAnimationLoopOnce; 00527 else 00528 d->m_showAnimations = KAnimationEnabled; 00529 } 00530 00531 if ( reset || cgHtml.hasKey( "SmoothScrolling" ) ) 00532 { 00533 QString value = cgHtml.readEntry( "SmoothScrolling", "whenefficient" ).toLower(); 00534 if (value == "disabled") 00535 d->m_smoothScrolling = KSmoothScrollingDisabled; 00536 else if (value == "whenefficient") 00537 d->m_smoothScrolling = KSmoothScrollingWhenEfficient; 00538 else 00539 d->m_smoothScrolling = KSmoothScrollingEnabled; 00540 } 00541 00542 if ( reset || cgHtml.hasKey( "DNSPrefetch" ) ) 00543 { 00544 // Enabled, Disabled, OnlyWWWAndSLD 00545 QString value = cgHtml.readEntry( "DNSPrefetch", "Enabled" ).toLower(); 00546 if (value == "enabled") 00547 d->m_dnsPrefetch = KDNSPrefetchEnabled; 00548 else if (value == "onlywwwandsld") 00549 d->m_dnsPrefetch = KDNSPrefetchOnlyWWWAndSLD; 00550 else 00551 d->m_dnsPrefetch = KDNSPrefetchDisabled; 00552 } 00553 00554 if ( cgHtml.readEntry( "UserStyleSheetEnabled", false ) == true ) { 00555 if ( reset || cgHtml.hasKey( "UserStyleSheet" ) ) 00556 d->m_userSheet = cgHtml.readEntry( "UserStyleSheet", "" ); 00557 } 00558 00559 d->m_formCompletionEnabled = cgHtml.readEntry("FormCompletion", true); 00560 d->m_maxFormCompletionItems = cgHtml.readEntry("MaxFormCompletionItems", 10); 00561 d->m_autoDelayedActionsEnabled = cgHtml.readEntry ("AutoDelayedActions", true); 00562 d->m_jsErrorsEnabled = cgHtml.readEntry("ReportJSErrors", true); 00563 const QStringList accesskeys = cgHtml.readEntry("FallbackAccessKeysAssignments", QStringList()); 00564 d->m_fallbackAccessKeysAssignments.clear(); 00565 for( QStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it ) 00566 if( (*it).length() > 2 && (*it)[ 1 ] == ':' ) 00567 d->m_fallbackAccessKeysAssignments.append( qMakePair( (*it).mid( 2 ), (*it)[ 0 ] )); 00568 } 00569 00570 // Colors 00571 //In which group ????? 00572 if ( reset || cg.hasKey( "FollowSystemColors" ) ) 00573 d->m_follow_system_colors = cg.readEntry( "FollowSystemColors", false ); 00574 00575 KConfigGroup cgGeneral( config, "General" ); 00576 if ( reset || cgGeneral.exists( ) ) 00577 { 00578 if ( reset || cgGeneral.hasKey( "foreground" ) ) { 00579 QColor def(HTML_DEFAULT_TXT_COLOR); 00580 d->m_textColor = cgGeneral.readEntry( "foreground", def ); 00581 } 00582 00583 if ( reset || cgGeneral.hasKey( "linkColor" ) ) { 00584 QColor def(HTML_DEFAULT_LNK_COLOR); 00585 d->m_linkColor = cgGeneral.readEntry( "linkColor", def ); 00586 } 00587 00588 if ( reset || cgGeneral.hasKey( "visitedLinkColor" ) ) { 00589 QColor def(HTML_DEFAULT_VLNK_COLOR); 00590 d->m_vLinkColor = cgGeneral.readEntry( "visitedLinkColor", def); 00591 } 00592 00593 if ( reset || cgGeneral.hasKey( "background" ) ) { 00594 QColor def(HTML_DEFAULT_BASE_COLOR); 00595 d->m_baseColor = cgGeneral.readEntry( "background", def); 00596 } 00597 } 00598 00599 KConfigGroup cgJava( config, "Java/JavaScript Settings" ); 00600 if( reset || cgJava.exists() ) 00601 { 00602 // The global setting for JavaScript debugging 00603 // This is currently always enabled by default 00604 if ( reset || cgJava.hasKey( "EnableJavaScriptDebug" ) ) 00605 d->m_bEnableJavaScriptDebug = cgJava.readEntry( "EnableJavaScriptDebug", false ); 00606 00607 // The global setting for JavaScript error reporting 00608 if ( reset || cgJava.hasKey( "ReportJavaScriptErrors" ) ) 00609 d->m_bEnableJavaScriptErrorReporting = cgJava.readEntry( "ReportJavaScriptErrors", false ); 00610 00611 // The global setting for popup block passive popup 00612 if ( reset || cgJava.hasKey( "PopupBlockerPassivePopup" ) ) 00613 d->m_jsPopupBlockerPassivePopup = cgJava.readEntry("PopupBlockerPassivePopup", true ); 00614 00615 // Read options from the global "domain" 00616 readDomainSettings(cgJava,reset,true,d->global); 00617 #ifdef DEBUG_SETTINGS 00618 d->global.dump("init global"); 00619 #endif 00620 00621 // The domain-specific settings. 00622 00623 static const char *const domain_keys[] = { // always keep order of keys 00624 "ECMADomains", "JavaDomains", "PluginDomains" 00625 }; 00626 bool check_old_ecma_settings = true; 00627 bool check_old_java_settings = true; 00628 // merge all domains into one list 00629 QMap<QString,int> domainList; // why can't Qt have a QSet? 00630 for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) { 00631 if ( reset || cgJava.hasKey(domain_keys[i]) ) { 00632 if (i == 0) check_old_ecma_settings = false; 00633 else if (i == 1) check_old_java_settings = false; 00634 const QStringList dl = cgJava.readEntry( domain_keys[i], QStringList() ); 00635 const QMap<QString,int>::Iterator notfound = domainList.end(); 00636 QStringList::ConstIterator it = dl.begin(); 00637 const QStringList::ConstIterator itEnd = dl.end(); 00638 for (; it != itEnd; ++it) { 00639 const QString domain = (*it).toLower(); 00640 QMap<QString,int>::Iterator pos = domainList.find(domain); 00641 if (pos == notfound) domainList.insert(domain,0); 00642 }/*next it*/ 00643 } 00644 }/*next i*/ 00645 00646 if (reset) 00647 d->domainPolicy.clear(); 00648 00649 { 00650 QMap<QString,int>::ConstIterator it = domainList.constBegin(); 00651 const QMap<QString,int>::ConstIterator itEnd = domainList.constEnd(); 00652 for ( ; it != itEnd; ++it) 00653 { 00654 const QString domain = it.key(); 00655 KConfigGroup cg( config, domain ); 00656 readDomainSettings(cg,reset,false,d->domainPolicy[domain]); 00657 #ifdef DEBUG_SETTINGS 00658 d->domainPolicy[domain].dump("init "+domain); 00659 #endif 00660 } 00661 } 00662 00663 bool check_old_java = true; 00664 if( ( reset || cgJava.hasKey( "JavaDomainSettings" ) ) 00665 && check_old_java_settings ) 00666 { 00667 check_old_java = false; 00668 const QStringList domainList = cgJava.readEntry( "JavaDomainSettings", QStringList() ); 00669 QStringList::ConstIterator it = domainList.constBegin(); 00670 const QStringList::ConstIterator itEnd = domainList.constEnd(); 00671 for ( ; it != itEnd; ++it) 00672 { 00673 QString domain; 00674 KJavaScriptAdvice javaAdvice; 00675 KJavaScriptAdvice javaScriptAdvice; 00676 splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); 00677 setup_per_domain_policy(d,domain).m_bEnableJava = 00678 javaAdvice == KJavaScriptAccept; 00679 #ifdef DEBUG_SETTINGS 00680 setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain); 00681 #endif 00682 } 00683 } 00684 00685 bool check_old_ecma = true; 00686 if( ( reset || cgJava.hasKey( "ECMADomainSettings" ) ) 00687 && check_old_ecma_settings ) 00688 { 00689 check_old_ecma = false; 00690 const QStringList domainList = cgJava.readEntry( "ECMADomainSettings", QStringList() ); 00691 QStringList::ConstIterator it = domainList.constBegin(); 00692 const QStringList::ConstIterator itEnd = domainList.constEnd(); 00693 for ( ; it != itEnd; ++it) 00694 { 00695 QString domain; 00696 KJavaScriptAdvice javaAdvice; 00697 KJavaScriptAdvice javaScriptAdvice; 00698 splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); 00699 setup_per_domain_policy(d,domain).m_bEnableJavaScript = 00700 javaScriptAdvice == KJavaScriptAccept; 00701 #ifdef DEBUG_SETTINGS 00702 setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain); 00703 #endif 00704 } 00705 } 00706 00707 if( ( reset || cgJava.hasKey( "JavaScriptDomainAdvice" ) ) 00708 && ( check_old_java || check_old_ecma ) 00709 && ( check_old_ecma_settings || check_old_java_settings ) ) 00710 { 00711 const QStringList domainList = cgJava.readEntry( "JavaScriptDomainAdvice", QStringList() ); 00712 QStringList::ConstIterator it = domainList.constBegin(); 00713 const QStringList::ConstIterator itEnd = domainList.constEnd(); 00714 for ( ; it != itEnd; ++it) 00715 { 00716 QString domain; 00717 KJavaScriptAdvice javaAdvice; 00718 KJavaScriptAdvice javaScriptAdvice; 00719 splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); 00720 if( check_old_java ) 00721 setup_per_domain_policy(d,domain).m_bEnableJava = 00722 javaAdvice == KJavaScriptAccept; 00723 if( check_old_ecma ) 00724 setup_per_domain_policy(d,domain).m_bEnableJavaScript = 00725 javaScriptAdvice == KJavaScriptAccept; 00726 #ifdef DEBUG_SETTINGS 00727 setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain); 00728 #endif 00729 } 00730 00731 //save all the settings into the new keywords if they don't exist 00732 #if 0 00733 if( check_old_java ) 00734 { 00735 QStringList domainConfig; 00736 PolicyMap::Iterator it; 00737 for( it = d->javaDomainPolicy.begin(); it != d->javaDomainPolicy.end(); ++it ) 00738 { 00739 QByteArray javaPolicy = adviceToStr( it.value() ); 00740 QByteArray javaScriptPolicy = adviceToStr( KJavaScriptDunno ); 00741 domainConfig.append(QString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy)); 00742 } 00743 cg.writeEntry( "JavaDomainSettings", domainConfig ); 00744 } 00745 00746 if( check_old_ecma ) 00747 { 00748 QStringList domainConfig; 00749 PolicyMap::Iterator it; 00750 for( it = d->javaScriptDomainPolicy.begin(); it != d->javaScriptDomainPolicy.end(); ++it ) 00751 { 00752 QByteArray javaPolicy = adviceToStr( KJavaScriptDunno ); 00753 QByteArray javaScriptPolicy = adviceToStr( it.value() ); 00754 domainConfig.append(QString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy)); 00755 } 00756 cg.writeEntry( "ECMADomainSettings", domainConfig ); 00757 } 00758 #endif 00759 } 00760 } 00761 } 00762 00763 00768 static const KPerDomainSettings &lookup_hostname_policy( 00769 const KHTMLSettingsPrivate* const d, 00770 const QString& hostname) 00771 { 00772 #ifdef DEBUG_SETTINGS 00773 kDebug() << "lookup_hostname_policy(" << hostname << ")"; 00774 #endif 00775 if (hostname.isEmpty()) { 00776 #ifdef DEBUG_SETTINGS 00777 d->global.dump("global"); 00778 #endif 00779 return d->global; 00780 } 00781 00782 const PolicyMap::const_iterator notfound = d->domainPolicy.constEnd(); 00783 00784 // First check whether there is a perfect match. 00785 PolicyMap::const_iterator it = d->domainPolicy.find(hostname); 00786 if( it != notfound ) { 00787 #ifdef DEBUG_SETTINGS 00788 kDebug() << "perfect match"; 00789 (*it).dump(hostname); 00790 #endif 00791 // yes, use it (unless dunno) 00792 return *it; 00793 } 00794 00795 // Now, check for partial match. Chop host from the left until 00796 // there's no dots left. 00797 QString host_part = hostname; 00798 int dot_idx = -1; 00799 while( (dot_idx = host_part.indexOf(QChar('.'))) >= 0 ) { 00800 host_part.remove(0,dot_idx); 00801 it = d->domainPolicy.find(host_part); 00802 Q_ASSERT(notfound == d->domainPolicy.end()); 00803 if( it != notfound ) { 00804 #ifdef DEBUG_SETTINGS 00805 kDebug() << "partial match"; 00806 (*it).dump(host_part); 00807 #endif 00808 return *it; 00809 } 00810 // assert(host_part[0] == QChar('.')); 00811 host_part.remove(0,1); // Chop off the dot. 00812 } 00813 00814 // No domain-specific entry: use global domain 00815 #ifdef DEBUG_SETTINGS 00816 kDebug() << "no match"; 00817 d->global.dump("global"); 00818 #endif 00819 return d->global; 00820 } 00821 00822 bool KHTMLSettings::isOpenMiddleClickEnabled() 00823 { 00824 return d->m_bOpenMiddleClick; 00825 } 00826 00827 bool KHTMLSettings::isBackRightClickEnabled() 00828 { 00829 return false; // ## the feature moved to konqueror 00830 } 00831 00832 bool KHTMLSettings::accessKeysEnabled() const 00833 { 00834 return d->m_accessKeysEnabled; 00835 } 00836 00837 bool KHTMLSettings::isAdFilterEnabled() const 00838 { 00839 return d->m_adFilterEnabled; 00840 } 00841 00842 bool KHTMLSettings::isHideAdsEnabled() const 00843 { 00844 return d->m_hideAdsEnabled; 00845 } 00846 00847 bool KHTMLSettings::isAdFiltered( const QString &url ) const 00848 { 00849 if (d->m_adFilterEnabled) 00850 { 00851 if (!url.startsWith("data:")) 00852 { 00853 // Check the blacklist, and only if that matches, the whitelist 00854 return d->adBlackList.isUrlMatched(url) && !d->adWhiteList.isUrlMatched(url); 00855 } 00856 } 00857 return false; 00858 } 00859 00860 QString KHTMLSettings::adFilteredBy( const QString &url, bool *isWhiteListed ) const 00861 { 00862 QString m = d->adWhiteList.urlMatchedBy(url); 00863 if (!m.isEmpty()) 00864 { 00865 if (isWhiteListed != 0) 00866 *isWhiteListed = true; 00867 return (m); 00868 } 00869 00870 m = d->adBlackList.urlMatchedBy(url); 00871 if (!m.isEmpty()) 00872 { 00873 if (isWhiteListed != 0) 00874 *isWhiteListed = false; 00875 return (m); 00876 } 00877 00878 return (QString()); 00879 } 00880 00881 void KHTMLSettings::addAdFilter( const QString &url ) 00882 { 00883 KConfigGroup config = KSharedConfig::openConfig( "khtmlrc", KConfig::NoGlobals )->group( "Filter Settings" ); 00884 00885 QRegExp rx; 00886 00887 // Try compiling to avoid invalid stuff. Only support the basic syntax here... 00888 // ### refactor somewhat 00889 if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/') 00890 { 00891 QString inside = url.mid(1, url.length()-2); 00892 rx.setPattern(inside); 00893 } 00894 else 00895 { 00896 rx.setPatternSyntax(QRegExp::Wildcard); 00897 rx.setPattern(url); 00898 } 00899 00900 if (rx.isValid()) 00901 { 00902 int last=config.readEntry("Count", 0); 00903 QString key = "Filter-" + QString::number(last); 00904 config.writeEntry(key, url); 00905 config.writeEntry("Count",last+1); 00906 config.sync(); 00907 if (url.startsWith(QLatin1String("@@"))) 00908 d->adWhiteList.addFilter(url); 00909 else 00910 d->adBlackList.addFilter(url); 00911 } 00912 else 00913 { 00914 KMessageBox::error(0, 00915 rx.errorString(), 00916 i18n("Filter error")); 00917 } 00918 } 00919 00920 bool KHTMLSettings::isJavaEnabled( const QString& hostname ) const 00921 { 00922 return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJava; 00923 } 00924 00925 bool KHTMLSettings::isJavaScriptEnabled( const QString& hostname ) const 00926 { 00927 return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJavaScript; 00928 } 00929 00930 bool KHTMLSettings::isJavaScriptDebugEnabled( const QString& /*hostname*/ ) const 00931 { 00932 // debug setting is global for now, but could change in the future 00933 return d->m_bEnableJavaScriptDebug; 00934 } 00935 00936 bool KHTMLSettings::isJavaScriptErrorReportingEnabled( const QString& /*hostname*/ ) const 00937 { 00938 // error reporting setting is global for now, but could change in the future 00939 return d->m_bEnableJavaScriptErrorReporting; 00940 } 00941 00942 bool KHTMLSettings::isPluginsEnabled( const QString& hostname ) const 00943 { 00944 return lookup_hostname_policy(d,hostname.toLower()).m_bEnablePlugins; 00945 } 00946 00947 KHTMLSettings::KJSWindowOpenPolicy KHTMLSettings::windowOpenPolicy( 00948 const QString& hostname) const { 00949 return lookup_hostname_policy(d,hostname.toLower()).m_windowOpenPolicy; 00950 } 00951 00952 KHTMLSettings::KJSWindowMovePolicy KHTMLSettings::windowMovePolicy( 00953 const QString& hostname) const { 00954 return lookup_hostname_policy(d,hostname.toLower()).m_windowMovePolicy; 00955 } 00956 00957 KHTMLSettings::KJSWindowResizePolicy KHTMLSettings::windowResizePolicy( 00958 const QString& hostname) const { 00959 return lookup_hostname_policy(d,hostname.toLower()).m_windowResizePolicy; 00960 } 00961 00962 KHTMLSettings::KJSWindowStatusPolicy KHTMLSettings::windowStatusPolicy( 00963 const QString& hostname) const { 00964 return lookup_hostname_policy(d,hostname.toLower()).m_windowStatusPolicy; 00965 } 00966 00967 KHTMLSettings::KJSWindowFocusPolicy KHTMLSettings::windowFocusPolicy( 00968 const QString& hostname) const { 00969 return lookup_hostname_policy(d,hostname.toLower()).m_windowFocusPolicy; 00970 } 00971 00972 int KHTMLSettings::mediumFontSize() const 00973 { 00974 return d->m_fontSize; 00975 } 00976 00977 int KHTMLSettings::minFontSize() const 00978 { 00979 return d->m_minFontSize; 00980 } 00981 00982 QString KHTMLSettings::settingsToCSS() const 00983 { 00984 // lets start with the link properties 00985 QString str = "a:link {\ncolor: "; 00986 str += d->m_linkColor.name(); 00987 str += ';'; 00988 if(d->m_underlineLink) 00989 str += "\ntext-decoration: underline;"; 00990 00991 if( d->m_bChangeCursor ) 00992 { 00993 str += "\ncursor: pointer;"; 00994 str += "\n}\ninput[type=image] { cursor: pointer;"; 00995 } 00996 str += "\n}\n"; 00997 str += "a:visited {\ncolor: "; 00998 str += d->m_vLinkColor.name(); 00999 str += ';'; 01000 if(d->m_underlineLink) 01001 str += "\ntext-decoration: underline;"; 01002 01003 if( d->m_bChangeCursor ) 01004 str += "\ncursor: pointer;"; 01005 str += "\n}\n"; 01006 01007 if(d->m_hoverLink) 01008 str += "a:link:hover, a:visited:hover { text-decoration: underline; }\n"; 01009 01010 return str; 01011 } 01012 01013 const QString &KHTMLSettings::availableFamilies() 01014 { 01015 if ( !avFamilies ) { 01016 avFamilies = new QString; 01017 QFontDatabase db; 01018 QStringList families = db.families(); 01019 QStringList s; 01020 QRegExp foundryExp(" \\[.+\\]"); 01021 01022 //remove foundry info 01023 QStringList::Iterator f = families.begin(); 01024 const QStringList::Iterator fEnd = families.end(); 01025 01026 for ( ; f != fEnd; ++f ) { 01027 (*f).replace( foundryExp, ""); 01028 if (!s.contains(*f)) 01029 s << *f; 01030 } 01031 s.sort(); 01032 01033 *avFamilies = ',' + s.join(",") + ','; 01034 } 01035 01036 return *avFamilies; 01037 } 01038 01039 QString KHTMLSettings::lookupFont(int i) const 01040 { 01041 QString font; 01042 if (d->fonts.count() > i) 01043 font = d->fonts[i]; 01044 if (font.isEmpty()) 01045 font = d->defaultFonts[i]; 01046 return font; 01047 } 01048 01049 QString KHTMLSettings::stdFontName() const 01050 { 01051 return lookupFont(0); 01052 } 01053 01054 QString KHTMLSettings::fixedFontName() const 01055 { 01056 return lookupFont(1); 01057 } 01058 01059 QString KHTMLSettings::serifFontName() const 01060 { 01061 return lookupFont(2); 01062 } 01063 01064 QString KHTMLSettings::sansSerifFontName() const 01065 { 01066 return lookupFont(3); 01067 } 01068 01069 QString KHTMLSettings::cursiveFontName() const 01070 { 01071 return lookupFont(4); 01072 } 01073 01074 QString KHTMLSettings::fantasyFontName() const 01075 { 01076 return lookupFont(5); 01077 } 01078 01079 void KHTMLSettings::setStdFontName(const QString &n) 01080 { 01081 while(d->fonts.count() <= 0) 01082 d->fonts.append(QString()); 01083 d->fonts[0] = n; 01084 } 01085 01086 void KHTMLSettings::setFixedFontName(const QString &n) 01087 { 01088 while(d->fonts.count() <= 1) 01089 d->fonts.append(QString()); 01090 d->fonts[1] = n; 01091 } 01092 01093 QString KHTMLSettings::userStyleSheet() const 01094 { 01095 return d->m_userSheet; 01096 } 01097 01098 bool KHTMLSettings::isFormCompletionEnabled() const 01099 { 01100 return d->m_formCompletionEnabled; 01101 } 01102 01103 int KHTMLSettings::maxFormCompletionItems() const 01104 { 01105 return d->m_maxFormCompletionItems; 01106 } 01107 01108 const QString &KHTMLSettings::encoding() const 01109 { 01110 return d->m_encoding; 01111 } 01112 01113 bool KHTMLSettings::followSystemColors() const 01114 { 01115 return d->m_follow_system_colors; 01116 } 01117 01118 const QColor& KHTMLSettings::textColor() const 01119 { 01120 return d->m_textColor; 01121 } 01122 01123 const QColor& KHTMLSettings::baseColor() const 01124 { 01125 return d->m_baseColor; 01126 } 01127 01128 const QColor& KHTMLSettings::linkColor() const 01129 { 01130 return d->m_linkColor; 01131 } 01132 01133 const QColor& KHTMLSettings::vLinkColor() const 01134 { 01135 return d->m_vLinkColor; 01136 } 01137 01138 bool KHTMLSettings::autoLoadImages() const 01139 { 01140 return d->m_bAutoLoadImages; 01141 } 01142 01143 bool KHTMLSettings::unfinishedImageFrame() const 01144 { 01145 return d->m_bUnfinishedImageFrame; 01146 } 01147 01148 KHTMLSettings::KAnimationAdvice KHTMLSettings::showAnimations() const 01149 { 01150 return d->m_showAnimations; 01151 } 01152 01153 KHTMLSettings::KSmoothScrollingMode KHTMLSettings::smoothScrolling() const 01154 { 01155 return d->m_smoothScrolling; 01156 } 01157 01158 KHTMLSettings::KDNSPrefetch KHTMLSettings::dnsPrefetch() const 01159 { 01160 return d->m_dnsPrefetch; 01161 } 01162 01163 bool KHTMLSettings::isAutoDelayedActionsEnabled() const 01164 { 01165 return d->m_autoDelayedActionsEnabled; 01166 } 01167 01168 bool KHTMLSettings::jsErrorsEnabled() const 01169 { 01170 return d->m_jsErrorsEnabled; 01171 } 01172 01173 void KHTMLSettings::setJSErrorsEnabled(bool enabled) 01174 { 01175 d->m_jsErrorsEnabled = enabled; 01176 // save it 01177 KConfigGroup cg( KGlobal::config(), "HTML Settings"); 01178 cg.writeEntry("ReportJSErrors", enabled); 01179 cg.sync(); 01180 } 01181 01182 bool KHTMLSettings::allowTabulation() const 01183 { 01184 return d->m_allowTabulation; 01185 } 01186 01187 bool KHTMLSettings::autoSpellCheck() const 01188 { 01189 return d->m_autoSpellCheck; 01190 } 01191 01192 QList< QPair< QString, QChar > > KHTMLSettings::fallbackAccessKeysAssignments() const 01193 { 01194 return d->m_fallbackAccessKeysAssignments; 01195 } 01196 01197 void KHTMLSettings::setJSPopupBlockerPassivePopup(bool enabled) 01198 { 01199 d->m_jsPopupBlockerPassivePopup = enabled; 01200 // save it 01201 KConfigGroup cg( KGlobal::config(), "Java/JavaScript Settings"); 01202 cg.writeEntry("PopupBlockerPassivePopup", enabled); 01203 cg.sync(); 01204 } 01205 01206 bool KHTMLSettings::jsPopupBlockerPassivePopup() const 01207 { 01208 return d->m_jsPopupBlockerPassivePopup; 01209 } 01210 01211 #include "khtml_settings.moc"
KDE 4.6 API Reference