khtml_part.cpp
00001 // -*- c-basic-offset: 2 -*- 00002 /* This file is part of the KDE project 00003 * 00004 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 00005 * 1999 Lars Knoll <knoll@kde.org> 00006 * 1999 Antti Koivisto <koivisto@kde.org> 00007 * 2000 Simon Hausmann <hausmann@kde.org> 00008 * 2000 Stefan Schimanski <1Stein@gmx.de> 00009 * 2001-2003 George Staikos <staikos@kde.org> 00010 * 2001-2003 Dirk Mueller <mueller@kde.org> 00011 * 2000-2005 David Faure <faure@kde.org> 00012 * 2002 Apple Computer, Inc. 00013 * 00014 * This library is free software; you can redistribute it and/or 00015 * modify it under the terms of the GNU Library General Public 00016 * License as published by the Free Software Foundation; either 00017 * version 2 of the License, or (at your option) any later version. 00018 * 00019 * This library is distributed in the hope that it will be useful, 00020 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00022 * Library General Public License for more details. 00023 * 00024 * You should have received a copy of the GNU Library General Public License 00025 * along with this library; see the file COPYING.LIB. If not, write to 00026 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00027 * Boston, MA 02110-1301, USA. 00028 */ 00029 00030 //#define SPEED_DEBUG 00031 #include "khtml_part.h" 00032 00033 #include "khtml_pagecache.h" 00034 00035 #include "dom/dom_string.h" 00036 #include "dom/dom_element.h" 00037 #include "dom/dom_exception.h" 00038 #include "html/html_documentimpl.h" 00039 #include "html/html_baseimpl.h" 00040 #include "html/html_objectimpl.h" 00041 #include "html/html_miscimpl.h" 00042 #include "html/html_imageimpl.h" 00043 #include "html/html_objectimpl.h" 00044 #include "rendering/render_text.h" 00045 #include "rendering/render_frames.h" 00046 #include "rendering/render_layer.h" 00047 #include "misc/htmlhashes.h" 00048 #include "misc/loader.h" 00049 #include "xml/dom2_eventsimpl.h" 00050 #include "xml/dom2_rangeimpl.h" 00051 #include "xml/xml_tokenizer.h" 00052 #include "css/cssstyleselector.h" 00053 #include "css/csshelper.h" 00054 using namespace DOM; 00055 00056 #include "khtmlview.h" 00057 #include <kparts/partmanager.h> 00058 #include "ecma/kjs_proxy.h" 00059 #include "ecma/kjs_window.h" 00060 #include "khtml_settings.h" 00061 #include "kjserrordlg.h" 00062 00063 #include <kjs/function.h> 00064 #include <kjs/interpreter.h> 00065 00066 #include "htmlpageinfo.h" 00067 00068 #include <sys/types.h> 00069 #include <assert.h> 00070 #include <unistd.h> 00071 00072 #include <config.h> 00073 00074 #include <dcopclient.h> 00075 #include <dcopref.h> 00076 #include <kstandarddirs.h> 00077 #include <kstringhandler.h> 00078 #include <kio/job.h> 00079 #include <kio/global.h> 00080 #include <kio/netaccess.h> 00081 #include <kprotocolmanager.h> 00082 #include <kdebug.h> 00083 #include <kiconloader.h> 00084 #include <klocale.h> 00085 #include <kcharsets.h> 00086 #include <kmessagebox.h> 00087 #include <kstdaction.h> 00088 #include <kfiledialog.h> 00089 #include <ktrader.h> 00090 #include <kdatastream.h> 00091 #include <ktempfile.h> 00092 #include <kglobalsettings.h> 00093 #include <kurldrag.h> 00094 #include <kapplication.h> 00095 #include <kparts/browserinterface.h> 00096 #if !defined(QT_NO_DRAGANDDROP) 00097 #include <kmultipledrag.h> 00098 #endif 00099 #include "../kutils/kfinddialog.h" 00100 #include "../kutils/kfind.h" 00101 00102 #include <ksslcertchain.h> 00103 #include <ksslinfodlg.h> 00104 00105 #include <kfileitem.h> 00106 #include <kurifilter.h> 00107 #include <kstatusbar.h> 00108 #include <kurllabel.h> 00109 00110 #include <qclipboard.h> 00111 #include <qfile.h> 00112 #include <qtooltip.h> 00113 #include <qmetaobject.h> 00114 #include <private/qucomextra_p.h> 00115 00116 #include "khtmlpart_p.h" 00117 #include "kpassivepopup.h" 00118 #include "kpopupmenu.h" 00119 #include "rendering/render_form.h" 00120 #include <kwin.h> 00121 00122 #define HINT_UTF8 106 00123 00124 namespace khtml { 00125 class PartStyleSheetLoader : public CachedObjectClient 00126 { 00127 public: 00128 PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl) 00129 { 00130 m_part = part; 00131 m_cachedSheet = dl->requestStyleSheet(url, QString::null, "text/css", 00132 true /* "user sheet" */); 00133 if (m_cachedSheet) 00134 m_cachedSheet->ref( this ); 00135 } 00136 virtual ~PartStyleSheetLoader() 00137 { 00138 if ( m_cachedSheet ) m_cachedSheet->deref(this); 00139 } 00140 virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet, const DOM::DOMString &) 00141 { 00142 if ( m_part ) 00143 m_part->setUserStyleSheet( sheet.string() ); 00144 00145 delete this; 00146 } 00147 virtual void error( int, const QString& ) { 00148 delete this; 00149 } 00150 QGuardedPtr<KHTMLPart> m_part; 00151 khtml::CachedCSSStyleSheet *m_cachedSheet; 00152 }; 00153 } 00154 00155 void khtml::ChildFrame::liveConnectEvent(const unsigned long, const QString & event, const KParts::LiveConnectExtension::ArgList & args) 00156 { 00157 if (!m_part || !m_frame || !m_liveconnect) 00158 // hmmm 00159 return; 00160 00161 QString script; 00162 script.sprintf("%s(", event.latin1()); 00163 00164 KParts::LiveConnectExtension::ArgList::const_iterator i = args.begin(); 00165 const KParts::LiveConnectExtension::ArgList::const_iterator argsBegin = i; 00166 const KParts::LiveConnectExtension::ArgList::const_iterator argsEnd = args.end(); 00167 00168 for ( ; i != argsEnd; ++i) { 00169 if (i != argsBegin) 00170 script += ","; 00171 if ((*i).first == KParts::LiveConnectExtension::TypeString) { 00172 script += "\""; 00173 script += QString((*i).second).replace('\\', "\\\\").replace('"', "\\\""); 00174 script += "\""; 00175 } else 00176 script += (*i).second; 00177 } 00178 script += ")"; 00179 kdDebug(6050) << "khtml::ChildFrame::liveConnectEvent " << script << endl; 00180 00181 KHTMLPart * part = ::qt_cast<KHTMLPart *>(m_part->parent()); 00182 if (!part) 00183 return; 00184 if (!m_jscript) 00185 part->framejScript(m_part); 00186 if (m_jscript) { 00187 // we have a jscript => a part in an iframe 00188 KJS::Completion cmp; 00189 m_jscript->evaluate(QString::null, 1, script, 0L, &cmp); 00190 } else 00191 part->executeScript(m_frame->element(), script); 00192 } 00193 00194 KHTMLFrameList::Iterator KHTMLFrameList::find( const QString &name ) 00195 { 00196 Iterator it = begin(); 00197 const Iterator e = end(); 00198 00199 for (; it!=e; ++it ) 00200 if ( (*it)->m_name==name ) 00201 break; 00202 00203 return it; 00204 } 00205 00206 KHTMLPart::KHTMLPart( QWidget *parentWidget, const char *widgetname, QObject *parent, const char *name, GUIProfile prof ) 00207 : KParts::ReadOnlyPart( parent, name ) 00208 { 00209 d = 0; 00210 KHTMLFactory::registerPart( this ); 00211 setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() ); 00212 // TODO KDE4 - don't load plugins yet 00213 //setInstance( KHTMLFactory::instance(), false ); 00214 init( new KHTMLView( this, parentWidget, widgetname ), prof ); 00215 } 00216 00217 KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, const char *name, GUIProfile prof ) 00218 : KParts::ReadOnlyPart( parent, name ) 00219 { 00220 d = 0; 00221 KHTMLFactory::registerPart( this ); 00222 setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() ); 00223 // TODO KDE4 - don't load plugins yet 00224 //setInstance( KHTMLFactory::instance(), false ); 00225 assert( view ); 00226 init( view, prof ); 00227 } 00228 00229 void KHTMLPart::init( KHTMLView *view, GUIProfile prof ) 00230 { 00231 if ( prof == DefaultGUI ) 00232 setXMLFile( "khtml.rc" ); 00233 else if ( prof == BrowserViewGUI ) 00234 setXMLFile( "khtml_browser.rc" ); 00235 00236 d = new KHTMLPartPrivate(parent()); 00237 00238 d->m_view = view; 00239 setWidget( d->m_view ); 00240 00241 d->m_guiProfile = prof; 00242 d->m_extension = new KHTMLPartBrowserExtension( this, "KHTMLBrowserExtension" ); 00243 d->m_hostExtension = new KHTMLPartBrowserHostExtension( this ); 00244 d->m_statusBarExtension = new KParts::StatusBarExtension( this ); 00245 d->m_statusBarIconLabel = 0L; 00246 d->m_statusBarPopupLabel = 0L; 00247 d->m_openableSuppressedPopups = 0; 00248 00249 d->m_bSecurityInQuestion = false; 00250 d->m_paLoadImages = 0; 00251 d->m_paDebugScript = 0; 00252 d->m_bMousePressed = false; 00253 d->m_bRightMousePressed = false; 00254 d->m_bCleared = false; 00255 d->m_paViewDocument = new KAction( i18n( "View Do&cument Source" ), CTRL + Key_U, this, SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" ); 00256 d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" ); 00257 d->m_paViewInfo = new KAction( i18n( "View Document Information" ), CTRL+Key_I, this, SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" ); 00258 d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" ); 00259 d->m_paSaveDocument = KStdAction::saveAs( this, SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" ); 00260 if ( parentPart() ) 00261 d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes 00262 d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" ); 00263 d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, SLOT( slotSecurity() ), actionCollection(), "security" ); 00264 d->m_paSecurity->setWhatsThis( i18n( "Security Settings<p>" 00265 "Shows the certificate of the displayed page. Only " 00266 "pages that have been transmitted using a secure, encrypted connection have a " 00267 "certificate.<p> " 00268 "Hint: If the image shows a closed lock, the page has been transmitted over a " 00269 "secure connection.") ); 00270 d->m_paDebugRenderTree = new KAction( i18n( "Print Rendering Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_A, this, SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" ); 00271 d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_D, this, SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" ); 00272 d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), 0, this, SLOT( slotStopAnimations() ), actionCollection(), "stopAnimations" ); 00273 00274 d->m_paSetEncoding = new KActionMenu( i18n( "Set &Encoding" ), "charset", actionCollection(), "setEncoding" ); 00275 d->m_paSetEncoding->setDelayed( false ); 00276 00277 d->m_automaticDetection = new KPopupMenu( 0L ); 00278 00279 d->m_automaticDetection->insertItem( i18n( "Semi-Automatic" ), 0 ); 00280 d->m_automaticDetection->insertItem( i18n( "Arabic" ), 1 ); 00281 d->m_automaticDetection->insertItem( i18n( "Baltic" ), 2 ); 00282 d->m_automaticDetection->insertItem( i18n( "Central European" ), 3 ); 00283 //d->m_automaticDetection->insertItem( i18n( "Chinese" ), 4 ); 00284 d->m_automaticDetection->insertItem( i18n( "Greek" ), 5 ); 00285 d->m_automaticDetection->insertItem( i18n( "Hebrew" ), 6 ); 00286 d->m_automaticDetection->insertItem( i18n( "Japanese" ), 7 ); 00287 //d->m_automaticDetection->insertItem( i18n( "Korean" ), 8 ); 00288 d->m_automaticDetection->insertItem( i18n( "Russian" ), 9 ); 00289 //d->m_automaticDetection->insertItem( i18n( "Thai" ), 10 ); 00290 d->m_automaticDetection->insertItem( i18n( "Turkish" ), 11 ); 00291 d->m_automaticDetection->insertItem( i18n( "Ukrainian" ), 12 ); 00292 //d->m_automaticDetection->insertItem( i18n( "Unicode" ), 13 ); 00293 d->m_automaticDetection->insertItem( i18n( "Western European" ), 14 ); 00294 00295 connect( d->m_automaticDetection, SIGNAL( activated( int ) ), this, SLOT( slotAutomaticDetectionLanguage( int ) ) ); 00296 00297 d->m_paSetEncoding->popupMenu()->insertItem( i18n( "Automatic Detection" ), d->m_automaticDetection, 0 ); 00298 00299 d->m_paSetEncoding->insert( new KActionSeparator( actionCollection() ) ); 00300 00301 00302 d->m_manualDetection = new KSelectAction( i18n( "short for Manual Detection", "Manual" ), 0, this, SLOT( slotSetEncoding() ), actionCollection(), "manualDetection" ); 00303 QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames(); 00304 d->m_manualDetection->setItems( encodings ); 00305 d->m_manualDetection->setCurrentItem( -1 ); 00306 d->m_paSetEncoding->insert( d->m_manualDetection ); 00307 00308 00309 KConfig *config = KGlobal::config(); 00310 if ( config->hasGroup( "HTML Settings" ) ) { 00311 config->setGroup( "HTML Settings" ); 00312 khtml::Decoder::AutoDetectLanguage language; 00313 QCString name = QTextCodec::codecForLocale()->name(); 00314 name = name.lower(); 00315 00316 if ( name == "cp1256" || name == "iso-8859-6" ) { 00317 language = khtml::Decoder::Arabic; 00318 } 00319 else if ( name == "cp1257" || name == "iso-8859-13" || name == "iso-8859-4" ) { 00320 language = khtml::Decoder::Baltic; 00321 } 00322 else if ( name == "cp1250" || name == "ibm852" || name == "iso-8859-2" || name == "iso-8859-3" ) { 00323 language = khtml::Decoder::CentralEuropean; 00324 } 00325 else if ( name == "cp1251" || name == "koi8-r" || name == "iso-8859-5" ) { 00326 language = khtml::Decoder::Russian; 00327 } 00328 else if ( name == "koi8-u" ) { 00329 language = khtml::Decoder::Ukrainian; 00330 } 00331 else if ( name == "cp1253" || name == "iso-8859-7" ) { 00332 language = khtml::Decoder::Greek; 00333 } 00334 else if ( name == "cp1255" || name == "iso-8859-8" || name == "iso-8859-8-i" ) { 00335 language = khtml::Decoder::Hebrew; 00336 } 00337 else if ( name == "jis7" || name == "eucjp" || name == "sjis" ) { 00338 language = khtml::Decoder::Japanese; 00339 } 00340 else if ( name == "cp1254" || name == "iso-8859-9" ) { 00341 language = khtml::Decoder::Turkish; 00342 } 00343 else if ( name == "cp1252" || name == "iso-8859-1" || name == "iso-8859-15" ) { 00344 language = khtml::Decoder::WesternEuropean; 00345 } 00346 else 00347 language = khtml::Decoder::SemiautomaticDetection; 00348 00349 int _id = config->readNumEntry( "AutomaticDetectionLanguage", language ); 00350 d->m_automaticDetection->setItemChecked( _id, true ); 00351 d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true ); 00352 00353 d->m_autoDetectLanguage = static_cast< khtml::Decoder::AutoDetectLanguage >( _id ); 00354 } 00355 00356 00357 d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), 0, this, SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" ); 00358 00359 if ( prof == BrowserViewGUI ) { 00360 d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n( 00361 "Enlarge Font" ), "viewmag+", "CTRL++;CTRL+=", this, 00362 SLOT( slotIncZoomFast() ), actionCollection(), "incFontSizes" ); 00363 d->m_paIncZoomFactor->setWhatsThis( i18n( "Enlarge Font<p>" 00364 "Make the font in this window bigger. " 00365 "Click and hold down the mouse button for a menu with all available font sizes." ) ); 00366 d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n( 00367 "Shrink Font" ), "viewmag-", CTRL + Key_Minus, this, 00368 SLOT( slotDecZoomFast() ), actionCollection(), "decFontSizes" ); 00369 d->m_paDecZoomFactor->setWhatsThis( i18n( "Shrink Font<p>" 00370 "Make the font in this window smaller. " 00371 "Click and hold down the mouse button for a menu with all available font sizes." ) ); 00372 } 00373 00374 d->m_paFind = KStdAction::find( this, SLOT( slotFind() ), actionCollection(), "find" ); 00375 d->m_paFind->setWhatsThis( i18n( "Find text<p>" 00376 "Shows a dialog that allows you to find text on the displayed page." ) ); 00377 00378 d->m_paFindNext = KStdAction::findNext( this, SLOT( slotFindNext() ), actionCollection(), "findNext" ); 00379 d->m_paFindNext->setWhatsThis( i18n( "Find next<p>" 00380 "Find the next occurrence of the text that you " 00381 "have found using the <b>Find Text</b> function" ) ); 00382 00383 d->m_paFindPrev = KStdAction::findPrev( this, SLOT( slotFindPrev() ), actionCollection(), "findPrevious" ); 00384 d->m_paFindPrev->setWhatsThis( i18n( "Find previous<p>" 00385 "Find the previous occurrence of the text that you " 00386 "have found using the <b>Find Text</b> function" ) ); 00387 00388 d->m_paFindAheadText = new KAction( i18n("Find Text as You Type"), KShortcut( '/' ), this, SLOT( slotFindAheadText()), 00389 actionCollection(), "findAheadText"); 00390 d->m_paFindAheadLinks = new KAction( i18n("Find Links as You Type"), KShortcut( '\'' ), this, SLOT( slotFindAheadLink()), 00391 actionCollection(), "findAheadLink"); 00392 d->m_paFindAheadText->setEnabled( false ); 00393 d->m_paFindAheadLinks->setEnabled( false ); 00394 00395 if ( parentPart() ) 00396 { 00397 d->m_paFind->setShortcut( KShortcut() ); // avoid clashes 00398 d->m_paFindNext->setShortcut( KShortcut() ); // avoid clashes 00399 d->m_paFindPrev->setShortcut( KShortcut() ); // avoid clashes 00400 d->m_paFindAheadText->setShortcut( KShortcut()); 00401 d->m_paFindAheadLinks->setShortcut( KShortcut()); 00402 } 00403 00404 d->m_paPrintFrame = new KAction( i18n( "Print Frame..." ), "frameprint", 0, this, SLOT( slotPrintFrame() ), actionCollection(), "printFrame" ); 00405 d->m_paPrintFrame->setWhatsThis( i18n( "Print Frame<p>" 00406 "Some pages have several frames. To print only a single frame, click " 00407 "on it and then use this function." ) ); 00408 00409 d->m_paSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection(), "selectAll" ); 00410 if ( parentPart() ) 00411 d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes 00412 00413 d->m_paToggleCaretMode = new KToggleAction(i18n("Toggle Caret Mode"), 00414 Key_F7, this, SLOT(slotToggleCaretMode()), 00415 actionCollection(), "caretMode"); 00416 d->m_paToggleCaretMode->setChecked(isCaretMode()); 00417 if (parentPart()) 00418 d->m_paToggleCaretMode->setShortcut(KShortcut()); // avoid clashes 00419 00420 // set the default java(script) flags according to the current host. 00421 d->m_bOpenMiddleClick = d->m_settings->isOpenMiddleClickEnabled(); 00422 d->m_bBackRightClick = d->m_settings->isBackRightClickEnabled(); 00423 d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(); 00424 setDebugScript( d->m_settings->isJavaScriptDebugEnabled() ); 00425 d->m_bJavaEnabled = d->m_settings->isJavaEnabled(); 00426 d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(); 00427 00428 // Set the meta-refresh flag... 00429 d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled (); 00430 00431 connect( view, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) ); 00432 00433 connect( this, SIGNAL( completed() ), 00434 this, SLOT( updateActions() ) ); 00435 connect( this, SIGNAL( completed( bool ) ), 00436 this, SLOT( updateActions() ) ); 00437 connect( this, SIGNAL( started( KIO::Job * ) ), 00438 this, SLOT( updateActions() ) ); 00439 00440 d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) ); 00441 00442 connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ), 00443 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) ); 00444 connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ), 00445 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) ); 00446 connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ), 00447 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) ); 00448 00449 connect ( &d->m_progressUpdateTimer, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) ); 00450 00451 findTextBegin(); //reset find variables 00452 00453 connect( &d->m_redirectionTimer, SIGNAL( timeout() ), 00454 this, SLOT( slotRedirect() ) ); 00455 00456 d->m_dcopobject = new KHTMLPartIface(this); 00457 00458 // TODO KDE4 - load plugins now (see also the constructors) 00459 //if ( prof == BrowserViewGUI && !parentPart() ) 00460 // loadPlugins( partObject(), this, instance() ); 00461 00462 // "khtml" catalog does not exist, our translations are in kdelibs. 00463 // removing this catalog from KGlobal::locale() prevents problems 00464 // with changing the language in applications at runtime -Thomas Reitelbach 00465 KGlobal::locale()->removeCatalogue("khtml"); 00466 } 00467 00468 KHTMLPart::~KHTMLPart() 00469 { 00470 //kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl; 00471 00472 KConfig *config = KGlobal::config(); 00473 config->setGroup( "HTML Settings" ); 00474 config->writeEntry( "AutomaticDetectionLanguage", d->m_autoDetectLanguage ); 00475 00476 delete d->m_automaticDetection; 00477 delete d->m_manualDetection; 00478 00479 slotWalletClosed(); 00480 if (!parentPart()) { // only delete it if the top khtml_part closes 00481 removeJSErrorExtension(); 00482 delete d->m_statusBarPopupLabel; 00483 } 00484 00485 d->m_find = 0; // deleted by its parent, the view. 00486 00487 if ( d->m_manager ) 00488 { 00489 d->m_manager->setActivePart( 0 ); 00490 // We specify "this" as parent qobject for d->manager, so no need to delete it. 00491 } 00492 00493 stopAutoScroll(); 00494 d->m_redirectionTimer.stop(); 00495 00496 if (!d->m_bComplete) 00497 closeURL(); 00498 00499 disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ), 00500 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) ); 00501 disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ), 00502 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) ); 00503 disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ), 00504 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) ); 00505 00506 clear(); 00507 00508 if ( d->m_view ) 00509 { 00510 d->m_view->hide(); 00511 d->m_view->viewport()->hide(); 00512 d->m_view->m_part = 0; 00513 } 00514 00515 // Have to delete this here since we forward declare it in khtmlpart_p and 00516 // at least some compilers won't call the destructor in this case. 00517 delete d->m_jsedlg; 00518 d->m_jsedlg = 0; 00519 00520 if (!parentPart()) // only delete d->m_frame if the top khtml_part closes 00521 delete d->m_frame; 00522 delete d; d = 0; 00523 KHTMLFactory::deregisterPart( this ); 00524 } 00525 00526 bool KHTMLPart::restoreURL( const KURL &url ) 00527 { 00528 kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl; 00529 00530 d->m_redirectionTimer.stop(); 00531 00532 /* 00533 * That's not a good idea as it will call closeURL() on all 00534 * child frames, preventing them from further loading. This 00535 * method gets called from restoreState() in case of a full frameset 00536 * restoral, and restoreState() calls closeURL() before restoring 00537 * anyway. 00538 kdDebug( 6050 ) << "closing old URL" << endl; 00539 closeURL(); 00540 */ 00541 00542 d->m_bComplete = false; 00543 d->m_bLoadEventEmitted = false; 00544 d->m_workingURL = url; 00545 00546 // set the java(script) flags according to the current host. 00547 d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host()); 00548 setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() ); 00549 d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host()); 00550 d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host()); 00551 00552 m_url = url; 00553 00554 d->m_restoreScrollPosition = true; 00555 disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition())); 00556 connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition())); 00557 00558 KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &))); 00559 00560 emit started( 0L ); 00561 00562 return true; 00563 } 00564 00565 00566 bool KHTMLPart::openURL( const KURL &url ) 00567 { 00568 kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl; 00569 00570 d->m_redirectionTimer.stop(); 00571 00572 // check to see if this is an "error://" URL. This is caused when an error 00573 // occurs before this part was loaded (e.g. KonqRun), and is passed to 00574 // khtmlpart so that it can display the error. 00575 if ( url.protocol() == "error" && url.hasSubURL() ) { 00576 closeURL(); 00577 00578 if( d->m_bJScriptEnabled ) 00579 d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null; 00580 00586 KURL::List urls = KURL::split( url ); 00587 //kdDebug(6050) << "Handling error URL. URL count:" << urls.count() << endl; 00588 00589 if ( urls.count() > 1 ) { 00590 KURL mainURL = urls.first(); 00591 int error = mainURL.queryItem( "error" ).toInt(); 00592 // error=0 isn't a valid error code, so 0 means it's missing from the URL 00593 if ( error == 0 ) error = KIO::ERR_UNKNOWN; 00594 QString errorText = mainURL.queryItem( "errText", HINT_UTF8 ); 00595 urls.pop_front(); 00596 d->m_workingURL = KURL::join( urls ); 00597 //kdDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl; 00598 emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() ); 00599 htmlError( error, errorText, d->m_workingURL ); 00600 return true; 00601 } 00602 } 00603 00604 if (!parentPart()) { // only do it for toplevel part 00605 QString host = url.isLocalFile() ? "localhost" : url.host(); 00606 QString userAgent = KProtocolManager::userAgentForHost(host); 00607 if (userAgent != KProtocolManager::userAgentForHost(QString::null)) { 00608 if (!d->m_statusBarUALabel) { 00609 d->m_statusBarUALabel = new KURLLabel(d->m_statusBarExtension->statusBar()); 00610 d->m_statusBarUALabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small)); 00611 d->m_statusBarUALabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); 00612 d->m_statusBarUALabel->setUseCursor(false); 00613 d->m_statusBarExtension->addStatusBarItem(d->m_statusBarUALabel, 0, false); 00614 d->m_statusBarUALabel->setPixmap(SmallIcon("agent", instance())); 00615 } else { 00616 QToolTip::remove(d->m_statusBarUALabel); 00617 } 00618 QToolTip::add(d->m_statusBarUALabel, i18n("The fake user-agent '%1' is in use.").arg(userAgent)); 00619 } else if (d->m_statusBarUALabel) { 00620 d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarUALabel); 00621 delete d->m_statusBarUALabel; 00622 d->m_statusBarUALabel = 0L; 00623 } 00624 } 00625 00626 KParts::URLArgs args( d->m_extension->urlArgs() ); 00627 00628 // in case 00629 // a) we have no frameset (don't test m_frames.count(), iframes get in there) 00630 // b) the url is identical with the currently displayed one (except for the htmlref!) 00631 // c) the url request is not a POST operation and 00632 // d) the caller did not request to reload the page 00633 // e) there was no HTTP redirection meanwhile (testcase: webmin's software/tree.cgi) 00634 // => we don't reload the whole document and 00635 // we just jump to the requested html anchor 00636 bool isFrameSet = false; 00637 if ( d->m_doc && d->m_doc->isHTMLDocument() ) { 00638 HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc); 00639 isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET); 00640 } 00641 00642 if ( url.hasRef() && !isFrameSet ) 00643 { 00644 bool noReloadForced = !args.reload && !args.redirectedRequest() && !args.doPost(); 00645 if (noReloadForced && urlcmp( url.url(), m_url.url(), true, true )) 00646 { 00647 kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl; 00648 m_url = url; 00649 emit started( 0L ); 00650 00651 if ( !gotoAnchor( url.encodedHtmlRef()) ) 00652 gotoAnchor( url.htmlRef() ); 00653 00654 d->m_bComplete = true; 00655 if (d->m_doc) 00656 d->m_doc->setParsing(false); 00657 00658 kdDebug( 6050 ) << "completed..." << endl; 00659 emit completed(); 00660 return true; 00661 } 00662 } 00663 00664 // Save offset of viewport when page is reloaded to be compliant 00665 // to every other capable browser out there. 00666 if (args.reload) { 00667 args.xOffset = d->m_view->contentsX(); 00668 args.yOffset = d->m_view->contentsY(); 00669 d->m_extension->setURLArgs(args); 00670 } 00671 00672 if (!d->m_restored) 00673 closeURL(); 00674 00675 d->m_restoreScrollPosition = d->m_restored; 00676 disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition())); 00677 connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition())); 00678 00679 // initializing m_url to the new url breaks relative links when opening such a link after this call and _before_ begin() is called (when the first 00680 // data arrives) (Simon) 00681 m_url = url; 00682 if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() && 00683 m_url.path().isEmpty()) { 00684 m_url.setPath("/"); 00685 emit d->m_extension->setLocationBarURL( m_url.prettyURL() ); 00686 } 00687 // copy to m_workingURL after fixing m_url above 00688 d->m_workingURL = m_url; 00689 00690 args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" ); 00691 args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip); 00692 args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert); 00693 args.metaData().insert("PropagateHttpHeader", "true"); 00694 args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" ); 00695 args.metaData().insert("ssl_activate_warnings", "TRUE" ); 00696 args.metaData().insert("cross-domain", toplevelURL().url()); 00697 00698 if (d->m_restored) 00699 { 00700 args.metaData().insert("referrer", d->m_pageReferrer); 00701 d->m_cachePolicy = KIO::CC_Cache; 00702 } 00703 else if (args.reload) 00704 d->m_cachePolicy = KIO::CC_Reload; 00705 else 00706 d->m_cachePolicy = KProtocolManager::cacheControl(); 00707 00708 if ( args.doPost() && (m_url.protocol().startsWith("http")) ) 00709 { 00710 d->m_job = KIO::http_post( m_url, args.postData, false ); 00711 d->m_job->addMetaData("content-type", args.contentType() ); 00712 } 00713 else 00714 { 00715 d->m_job = KIO::get( m_url, false, false ); 00716 d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy)); 00717 } 00718 00719 if (widget()) 00720 d->m_job->setWindow(widget()->topLevelWidget()); 00721 d->m_job->addMetaData(args.metaData()); 00722 00723 connect( d->m_job, SIGNAL( result( KIO::Job* ) ), 00724 SLOT( slotFinished( KIO::Job* ) ) ); 00725 connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray& ) ), 00726 SLOT( slotData( KIO::Job*, const QByteArray& ) ) ); 00727 connect ( d->m_job, SIGNAL( infoMessage( KIO::Job*, const QString& ) ), 00728 SLOT( slotInfoMessage(KIO::Job*, const QString& ) ) ); 00729 connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KURL& ) ), 00730 SLOT( slotRedirection(KIO::Job*, const KURL&) ) ); 00731 00732 d->m_bComplete = false; 00733 d->m_bLoadEventEmitted = false; 00734 00735 // delete old status bar msg's from kjs (if it _was_ activated on last URL) 00736 if( d->m_bJScriptEnabled ) 00737 d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null; 00738 00739 // set the javascript flags according to the current url 00740 d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host()); 00741 setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() ); 00742 d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host()); 00743 d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host()); 00744 00745 00746 connect( d->m_job, SIGNAL( speed( KIO::Job*, unsigned long ) ), 00747 this, SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) ); 00748 00749 connect( d->m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ), 00750 this, SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) ); 00751 00752 connect( d->m_job, SIGNAL( result( KIO::Job* ) ), 00753 this, SLOT( slotJobDone( KIO::Job* ) ) ); 00754 00755 d->m_jobspeed = 0; 00756 00757 // If this was an explicit reload and the user style sheet should be used, 00758 // do a stat to see whether the stylesheet was changed in the meanwhile. 00759 if ( args.reload && !settings()->userStyleSheet().isEmpty() ) { 00760 KURL url( settings()->userStyleSheet() ); 00761 KIO::StatJob *job = KIO::stat( url, false /* don't show progress */ ); 00762 connect( job, SIGNAL( result( KIO::Job * ) ), 00763 this, SLOT( slotUserSheetStatDone( KIO::Job * ) ) ); 00764 } 00765 emit started( 0L ); 00766 00767 return true; 00768 } 00769 00770 bool KHTMLPart::closeURL() 00771 { 00772 if ( d->m_job ) 00773 { 00774 KHTMLPageCache::self()->cancelEntry(d->m_cacheId); 00775 d->m_job->kill(); 00776 d->m_job = 0; 00777 } 00778 00779 if ( d->m_doc && d->m_doc->isHTMLDocument() ) { 00780 HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc ); 00781 00782 if ( hdoc->body() && d->m_bLoadEventEmitted ) { 00783 hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false ); 00784 if ( d->m_doc ) 00785 d->m_doc->updateRendering(); 00786 d->m_bLoadEventEmitted = false; 00787 } 00788 } 00789 00790 d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David) 00791 d->m_bLoadEventEmitted = true; // don't want that one either 00792 d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy 00793 00794 disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition())); 00795 00796 KHTMLPageCache::self()->cancelFetch(this); 00797 if ( d->m_doc && d->m_doc->parsing() ) 00798 { 00799 kdDebug( 6050 ) << " was still parsing... calling end " << endl; 00800 slotFinishedParsing(); 00801 d->m_doc->setParsing(false); 00802 } 00803 00804 if ( !d->m_workingURL.isEmpty() ) 00805 { 00806 // Aborted before starting to render 00807 kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl; 00808 emit d->m_extension->setLocationBarURL( m_url.prettyURL() ); 00809 } 00810 00811 d->m_workingURL = KURL(); 00812 00813 if ( d->m_doc && d->m_doc->docLoader() ) 00814 khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() ); 00815 00816 // tell all subframes to stop as well 00817 { 00818 ConstFrameIt it = d->m_frames.begin(); 00819 const ConstFrameIt end = d->m_frames.end(); 00820 for (; it != end; ++it ) 00821 { 00822 if ( (*it)->m_run ) 00823 (*it)->m_run->abort(); 00824 if ( !( *it )->m_part.isNull() ) 00825 ( *it )->m_part->closeURL(); 00826 } 00827 } 00828 // tell all objects to stop as well 00829 { 00830 ConstFrameIt it = d->m_objects.begin(); 00831 const ConstFrameIt end = d->m_objects.end(); 00832 for (; it != end; ++it) 00833 { 00834 if ( !( *it )->m_part.isNull() ) 00835 ( *it )->m_part->closeURL(); 00836 } 00837 } 00838 // Stop any started redirections as well!! (DA) 00839 if ( d && d->m_redirectionTimer.isActive() ) 00840 d->m_redirectionTimer.stop(); 00841 00842 // null node activated. 00843 emit nodeActivated(Node()); 00844 00845 // make sure before clear() runs, we pop out of a dialog's message loop 00846 if ( d->m_view ) 00847 d->m_view->closeChildDialogs(); 00848 00849 return true; 00850 } 00851 00852 DOM::HTMLDocument KHTMLPart::htmlDocument() const 00853 { 00854 if (d->m_doc && d->m_doc->isHTMLDocument()) 00855 return static_cast<HTMLDocumentImpl*>(d->m_doc); 00856 else 00857 return static_cast<HTMLDocumentImpl*>(0); 00858 } 00859 00860 DOM::Document KHTMLPart::document() const 00861 { 00862 return d->m_doc; 00863 } 00864 00865 QString KHTMLPart::documentSource() const 00866 { 00867 QString sourceStr; 00868 if ( !( m_url.isLocalFile() ) && KHTMLPageCache::self()->isComplete( d->m_cacheId ) ) 00869 { 00870 QByteArray sourceArray; 00871 QDataStream dataStream( sourceArray, IO_WriteOnly ); 00872 KHTMLPageCache::self()->saveData( d->m_cacheId, &dataStream ); 00873 QTextStream stream( sourceArray, IO_ReadOnly ); 00874 stream.setCodec( QTextCodec::codecForName( encoding().latin1() ) ); 00875 sourceStr = stream.read(); 00876 } else 00877 { 00878 QString tmpFile; 00879 if( KIO::NetAccess::download( m_url, tmpFile, NULL ) ) 00880 { 00881 QFile f( tmpFile ); 00882 if ( f.open( IO_ReadOnly ) ) 00883 { 00884 QTextStream stream( &f ); 00885 stream.setCodec( QTextCodec::codecForName( encoding().latin1() ) ); 00886 sourceStr = stream.read(); 00887 f.close(); 00888 } 00889 KIO::NetAccess::removeTempFile( tmpFile ); 00890 } 00891 } 00892 00893 return sourceStr; 00894 } 00895 00896 00897 KParts::BrowserExtension *KHTMLPart::browserExtension() const 00898 { 00899 return d->m_extension; 00900 } 00901 00902 KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const 00903 { 00904 return d->m_hostExtension; 00905 } 00906 00907 KHTMLView *KHTMLPart::view() const 00908 { 00909 return d->m_view; 00910 } 00911 00912 void KHTMLPart::setStatusMessagesEnabled( bool enable ) 00913 { 00914 d->m_statusMessagesEnabled = enable; 00915 } 00916 00917 KJS::Interpreter *KHTMLPart::jScriptInterpreter() 00918 { 00919 KJSProxy *proxy = jScript(); 00920 if (!proxy || proxy->paused()) 00921 return 0; 00922 00923 return proxy->interpreter(); 00924 } 00925 00926 bool KHTMLPart::statusMessagesEnabled() const 00927 { 00928 return d->m_statusMessagesEnabled; 00929 } 00930 00931 void KHTMLPart::setJScriptEnabled( bool enable ) 00932 { 00933 if ( !enable && jScriptEnabled() && d->m_frame && d->m_frame->m_jscript ) { 00934 d->m_frame->m_jscript->clear(); 00935 } 00936 d->m_bJScriptForce = enable; 00937 d->m_bJScriptOverride = true; 00938 } 00939 00940 bool KHTMLPart::jScriptEnabled() const 00941 { 00942 if(onlyLocalReferences()) return false; 00943 00944 if ( d->m_bJScriptOverride ) 00945 return d->m_bJScriptForce; 00946 return d->m_bJScriptEnabled; 00947 } 00948 00949 void KHTMLPart::setMetaRefreshEnabled( bool enable ) 00950 { 00951 d->m_metaRefreshEnabled = enable; 00952 } 00953 00954 bool KHTMLPart::metaRefreshEnabled() const 00955 { 00956 return d->m_metaRefreshEnabled; 00957 } 00958 00959 // Define this to disable dlopening kjs_html, when directly linking to it. 00960 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD 00961 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD, 00962 // remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static) 00963 // Also, change the order of "ecma" and "." in khtml's SUBDIRS line. 00964 // OK - that's the default now, use the opposite of the above instructions to go back 00965 // to "dlopening it" - but it breaks exception catching in kjs_binding.cpp 00966 #define DIRECT_LINKAGE_TO_ECMA 00967 00968 #ifdef DIRECT_LINKAGE_TO_ECMA 00969 extern "C" { KJSProxy *kjs_html_init(khtml::ChildFrame * childframe); } 00970 #endif 00971 00972 static bool createJScript(khtml::ChildFrame *frame) 00973 { 00974 #ifndef DIRECT_LINKAGE_TO_ECMA 00975 KLibrary *lib = KLibLoader::self()->library("kjs_html"); 00976 if ( !lib ) { 00977 setJScriptEnabled( false ); 00978 return false; 00979 } 00980 // look for plain C init function 00981 void *sym = lib->symbol("kjs_html_init"); 00982 if ( !sym ) { 00983 lib->unload(); 00984 setJScriptEnabled( false ); 00985 return false; 00986 } 00987 typedef KJSProxy* (*initFunction)(khtml::ChildFrame *); 00988 initFunction initSym = (initFunction) sym; 00989 frame->m_jscript = (*initSym)(d->m_frame); 00990 frame->m_kjs_lib = lib; 00991 #else 00992 frame->m_jscript = kjs_html_init(frame); 00993 // frame->m_kjs_lib remains 0L. 00994 #endif 00995 return true; 00996 } 00997 00998 KJSProxy *KHTMLPart::jScript() 00999 { 01000 if (!jScriptEnabled()) return 0; 01001 01002 if ( !d->m_frame ) { 01003 KHTMLPart * p = parentPart(); 01004 if (!p) { 01005 d->m_frame = new khtml::ChildFrame; 01006 d->m_frame->m_part = this; 01007 } else { 01008 ConstFrameIt it = p->d->m_frames.begin(); 01009 const ConstFrameIt end = p->d->m_frames.end(); 01010 for (; it != end; ++it) 01011 if ((*it)->m_part.operator->() == this) { 01012 d->m_frame = *it; 01013 break; 01014 } 01015 } 01016 if ( !d->m_frame ) 01017 return 0; 01018 } 01019 if ( !d->m_frame->m_jscript ) 01020 if (!createJScript(d->m_frame)) 01021 return 0; 01022 if (d->m_bJScriptDebugEnabled) 01023 d->m_frame->m_jscript->setDebugEnabled(true); 01024 01025 return d->m_frame->m_jscript; 01026 } 01027 01028 QVariant KHTMLPart::crossFrameExecuteScript(const QString& target, const QString& script) 01029 { 01030 KHTMLPart* destpart = this; 01031 01032 QString trg = target.lower(); 01033 01034 if (target == "_top") { 01035 while (destpart->parentPart()) 01036 destpart = destpart->parentPart(); 01037 } 01038 else if (target == "_parent") { 01039 if (parentPart()) 01040 destpart = parentPart(); 01041 } 01042 else if (target == "_self" || target == "_blank") { 01043 // we always allow these 01044 } 01045 else { 01046 destpart = findFrame(target); 01047 if (!destpart) 01048 destpart = this; 01049 } 01050 01051 // easy way out? 01052 if (destpart == this) 01053 return executeScript(DOM::Node(), script); 01054 01055 // now compare the domains 01056 if (destpart->checkFrameAccess(this)) 01057 return destpart->executeScript(DOM::Node(), script); 01058 01059 // eww, something went wrong. better execute it in our frame 01060 return executeScript(DOM::Node(), script); 01061 } 01062 01063 //Enable this to see all JS scripts being executed 01064 //#define KJS_VERBOSE 01065 01066 KJSErrorDlg *KHTMLPart::jsErrorExtension() { 01067 if (!d->m_settings->jsErrorsEnabled()) { 01068 return 0L; 01069 } 01070 01071 if (parentPart()) { 01072 return parentPart()->jsErrorExtension(); 01073 } 01074 01075 if (!d->m_statusBarJSErrorLabel) { 01076 d->m_statusBarJSErrorLabel = new KURLLabel(d->m_statusBarExtension->statusBar()); 01077 d->m_statusBarJSErrorLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small)); 01078 d->m_statusBarJSErrorLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); 01079 d->m_statusBarJSErrorLabel->setUseCursor(false); 01080 d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false); 01081 QToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors.")); 01082 d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance())); 01083 connect(d->m_statusBarJSErrorLabel, SIGNAL(leftClickedURL()), SLOT(launchJSErrorDialog())); 01084 connect(d->m_statusBarJSErrorLabel, SIGNAL(rightClickedURL()), SLOT(jsErrorDialogContextMenu())); 01085 } 01086 if (!d->m_jsedlg) { 01087 d->m_jsedlg = new KJSErrorDlg; 01088 d->m_jsedlg->setURL(m_url.prettyURL()); 01089 if (KGlobalSettings::showIconsOnPushButtons()) { 01090 d->m_jsedlg->_clear->setIconSet(SmallIconSet("locationbar_erase")); 01091 d->m_jsedlg->_close->setIconSet(SmallIconSet("fileclose")); 01092 } 01093 } 01094 return d->m_jsedlg; 01095 } 01096 01097 void KHTMLPart::removeJSErrorExtension() { 01098 if (parentPart()) { 01099 parentPart()->removeJSErrorExtension(); 01100 return; 01101 } 01102 if (d->m_statusBarJSErrorLabel != 0) { 01103 d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel ); 01104 delete d->m_statusBarJSErrorLabel; 01105 d->m_statusBarJSErrorLabel = 0; 01106 } 01107 delete d->m_jsedlg; 01108 d->m_jsedlg = 0; 01109 } 01110 01111 void KHTMLPart::disableJSErrorExtension() { 01112 removeJSErrorExtension(); 01113 // These two lines are really kind of hacky, and it sucks to do this inside 01114 // KHTML but I don't know of anything that's reasonably easy as an alternative 01115 // right now. It makes me wonder if there should be a more clean way to 01116 // contact all running "KHTML" instance as opposed to Konqueror instances too. 01117 d->m_settings->setJSErrorsEnabled(false); 01118 DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray()); 01119 } 01120 01121 void KHTMLPart::jsErrorDialogContextMenu() { 01122 KPopupMenu *m = new KPopupMenu(0L); 01123 m->insertItem(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension())); 01124 m->insertItem(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension())); 01125 m->popup(QCursor::pos()); 01126 } 01127 01128 void KHTMLPart::launchJSErrorDialog() { 01129 KJSErrorDlg *dlg = jsErrorExtension(); 01130 if (dlg) { 01131 dlg->show(); 01132 dlg->raise(); 01133 } 01134 } 01135 01136 void KHTMLPart::launchJSConfigDialog() { 01137 QStringList args; 01138 args << "khtml_java_js"; 01139 KApplication::kdeinitExec( "kcmshell", args ); 01140 } 01141 01142 QVariant KHTMLPart::executeScript(const QString& filename, int baseLine, const DOM::Node& n, const QString& script) 01143 { 01144 #ifdef KJS_VERBOSE 01145 // The script is now printed by KJS's Parser::parse 01146 kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine /*<< " script=" << script*/ << endl; 01147 #endif 01148 KJSProxy *proxy = jScript(); 01149 01150 if (!proxy || proxy->paused()) 01151 return QVariant(); 01152 01153 KJS::Completion comp; 01154 01155 QVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp); 01156 01157 /* 01158 * Error handling 01159 */ 01160 if (comp.complType() == KJS::Throw && !comp.value().isNull()) { 01161 KJSErrorDlg *dlg = jsErrorExtension(); 01162 if (dlg) { 01163 KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec()); 01164 dlg->addError(i18n("<b>Error</b>: %1: %2").arg(filename, msg.qstring())); 01165 } 01166 } 01167 01168 // Handle immediate redirects now (e.g. location='foo') 01169 if ( !d->m_redirectURL.isEmpty() && d->m_delayRedirect == -1 ) 01170 { 01171 kdDebug(6070) << "executeScript done, handling immediate redirection NOW" << endl; 01172 // Must abort tokenizer, no further script must execute. 01173 khtml::Tokenizer* t = d->m_doc->tokenizer(); 01174 if(t) 01175 t->abort(); 01176 d->m_redirectionTimer.start( 0, true ); 01177 } 01178 01179 return ret; 01180 } 01181 01182 QVariant KHTMLPart::executeScript( const QString &script ) 01183 { 01184 return executeScript( DOM::Node(), script ); 01185 } 01186 01187 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script ) 01188 { 01189 #ifdef KJS_VERBOSE 01190 kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " /* << script */ << endl; 01191 #endif 01192 KJSProxy *proxy = jScript(); 01193 01194 if (!proxy || proxy->paused()) 01195 return QVariant(); 01196 ++(d->m_runningScripts); 01197 KJS::Completion comp; 01198 const QVariant ret = proxy->evaluate( QString::null, 1, script, n, &comp ); 01199 --(d->m_runningScripts); 01200 01201 /* 01202 * Error handling 01203 */ 01204 if (comp.complType() == KJS::Throw && !comp.value().isNull()) { 01205 KJSErrorDlg *dlg = jsErrorExtension(); 01206 if (dlg) { 01207 KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec()); 01208 dlg->addError(i18n("<b>Error</b>: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring())); 01209 } 01210 } 01211 01212 if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm ) 01213 submitFormAgain(); 01214 01215 #ifdef KJS_VERBOSE 01216 kdDebug(6070) << "KHTMLPart::executeScript - done" << endl; 01217 #endif 01218 return ret; 01219 } 01220 01221 bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script) 01222 { 01223 //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl; 01224 01225 d->scheduledScript = script; 01226 d->scheduledScriptNode = n; 01227 01228 return true; 01229 } 01230 01231 QVariant KHTMLPart::executeScheduledScript() 01232 { 01233 if( d->scheduledScript.isEmpty() ) 01234 return QVariant(); 01235 01236 //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl; 01237 01238 QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript ); 01239 d->scheduledScript = QString(); 01240 d->scheduledScriptNode = DOM::Node(); 01241 01242 return ret; 01243 } 01244 01245 void KHTMLPart::setJavaEnabled( bool enable ) 01246 { 01247 d->m_bJavaForce = enable; 01248 d->m_bJavaOverride = true; 01249 } 01250 01251 bool KHTMLPart::javaEnabled() const 01252 { 01253 if (onlyLocalReferences()) return false; 01254 01255 #ifndef Q_WS_QWS 01256 if( d->m_bJavaOverride ) 01257 return d->m_bJavaForce; 01258 return d->m_bJavaEnabled; 01259 #else 01260 return false; 01261 #endif 01262 } 01263 01264 KJavaAppletContext *KHTMLPart::javaContext() 01265 { 01266 return 0; 01267 } 01268 01269 KJavaAppletContext *KHTMLPart::createJavaContext() 01270 { 01271 return 0; 01272 } 01273 01274 void KHTMLPart::setPluginsEnabled( bool enable ) 01275 { 01276 d->m_bPluginsForce = enable; 01277 d->m_bPluginsOverride = true; 01278 } 01279 01280 bool KHTMLPart::pluginsEnabled() const 01281 { 01282 if (onlyLocalReferences()) return false; 01283 01284 if ( d->m_bPluginsOverride ) 01285 return d->m_bPluginsForce; 01286 return d->m_bPluginsEnabled; 01287 } 01288 01289 static int s_DOMTreeIndentLevel = 0; 01290 01291 void KHTMLPart::slotDebugDOMTree() 01292 { 01293 if ( d->m_doc && d->m_doc->firstChild() ) 01294 qDebug("%s", d->m_doc->firstChild()->toString().string().latin1()); 01295 01296 // Now print the contents of the frames that contain HTML 01297 01298 const int indentLevel = s_DOMTreeIndentLevel++; 01299 01300 ConstFrameIt it = d->m_frames.begin(); 01301 const ConstFrameIt end = d->m_frames.end(); 01302 for (; it != end; ++it ) 01303 if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) { 01304 KParts::ReadOnlyPart* const p = ( *it )->m_part; 01305 kdDebug(6050) << QString().leftJustify(s_DOMTreeIndentLevel*4,' ') << "FRAME " << p->name() << " " << endl; 01306 static_cast<KHTMLPart*>( p )->slotDebugDOMTree(); 01307 } 01308 s_DOMTreeIndentLevel = indentLevel; 01309 } 01310 01311 void KHTMLPart::slotDebugScript() 01312 { 01313 if (jScript()) 01314 jScript()->showDebugWindow(); 01315 } 01316 01317 void KHTMLPart::slotDebugRenderTree() 01318 { 01319 #ifndef NDEBUG 01320 if ( d->m_doc ) { 01321 d->m_doc->renderer()->printTree(); 01322 // dump out the contents of the rendering & DOM trees 01323 // QString dumps; 01324 // QTextStream outputStream(dumps,IO_WriteOnly); 01325 // d->m_doc->renderer()->layer()->dump( outputStream ); 01326 // kdDebug() << "dump output:" << "\n" + dumps; 01327 } 01328 #endif 01329 } 01330 01331 void KHTMLPart::slotStopAnimations() 01332 { 01333 stopAnimations(); 01334 } 01335 01336 void KHTMLPart::setAutoloadImages( bool enable ) 01337 { 01338 if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable ) 01339 return; 01340 01341 if ( d->m_doc ) 01342 d->m_doc->docLoader()->setAutoloadImages( enable ); 01343 01344 unplugActionList( "loadImages" ); 01345 01346 if ( enable ) { 01347 delete d->m_paLoadImages; 01348 d->m_paLoadImages = 0; 01349 } 01350 else if ( !d->m_paLoadImages ) 01351 d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" ); 01352 01353 if ( d->m_paLoadImages ) { 01354 QPtrList<KAction> lst; 01355 lst.append( d->m_paLoadImages ); 01356 plugActionList( "loadImages", lst ); 01357 } 01358 } 01359 01360 bool KHTMLPart::autoloadImages() const 01361 { 01362 if ( d->m_doc ) 01363 return d->m_doc->docLoader()->autoloadImages(); 01364 01365 return true; 01366 } 01367 01368 void KHTMLPart::clear() 01369 { 01370 if ( d->m_bCleared ) 01371 return; 01372 01373 d->m_bCleared = true; 01374 01375 d->m_bClearing = true; 01376 01377 { 01378 ConstFrameIt it = d->m_frames.begin(); 01379 const ConstFrameIt end = d->m_frames.end(); 01380 for(; it != end; ++it ) 01381 { 01382 // Stop HTMLRun jobs for frames 01383 if ( (*it)->m_run ) 01384 (*it)->m_run->abort(); 01385 } 01386 } 01387 01388 { 01389 ConstFrameIt it = d->m_objects.begin(); 01390 const ConstFrameIt end = d->m_objects.end(); 01391 for(; it != end; ++it ) 01392 { 01393 // Stop HTMLRun jobs for objects 01394 if ( (*it)->m_run ) 01395 (*it)->m_run->abort(); 01396 } 01397 } 01398 01399 01400 findTextBegin(); // resets d->m_findNode and d->m_findPos 01401 d->m_mousePressNode = DOM::Node(); 01402 01403 01404 if ( d->m_doc ) 01405 { 01406 if (d->m_doc->attached()) //the view may have detached it already 01407 d->m_doc->detach(); 01408 } 01409 01410 // Moving past doc so that onUnload works. 01411 if ( d->m_frame && d->m_frame->m_jscript ) 01412 d->m_frame->m_jscript->clear(); 01413 01414 // stopping marquees 01415 if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer()) 01416 d->m_doc->renderer()->layer()->suspendMarquees(); 01417 01418 if ( d->m_view ) 01419 d->m_view->clear(); 01420 01421 // do not dereference the document before the jscript and view are cleared, as some destructors 01422 // might still try to access the document. 01423 if ( d->m_doc ) { 01424 d->m_doc->deref(); 01425 } 01426 d->m_doc = 0; 01427 01428 delete d->m_decoder; 01429 d->m_decoder = 0; 01430 01431 // We don't want to change between parts if we are going to delete all of them anyway 01432 disconnect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ), 01433 this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) ); 01434 01435 if (d->m_frames.count()) 01436 { 01437 KHTMLFrameList frames = d->m_frames; 01438 d->m_frames.clear(); 01439 ConstFrameIt it = frames.begin(); 01440 const ConstFrameIt end = frames.end(); 01441 for(; it != end; ++it ) 01442 { 01443 if ( (*it)->m_part ) 01444 { 01445 partManager()->removePart( (*it)->m_part ); 01446 delete (KParts::ReadOnlyPart *)(*it)->m_part; 01447 } 01448 delete *it; 01449 } 01450 } 01451 d->m_suppressedPopupOriginParts.clear(); 01452 01453 if (d->m_objects.count()) 01454 { 01455 KHTMLFrameList objects = d->m_objects; 01456 d->m_objects.clear(); 01457 ConstFrameIt oi = objects.begin(); 01458 const ConstFrameIt oiEnd = objects.end(); 01459 01460 for (; oi != oiEnd; ++oi ) 01461 delete *oi; 01462 } 01463 01464 // Listen to part changes again 01465 connect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ), 01466 this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) ); 01467 01468 d->m_delayRedirect = 0; 01469 d->m_redirectURL = QString::null; 01470 d->m_redirectionTimer.stop(); 01471 d->m_redirectLockHistory = true; 01472 d->m_bClearing = false; 01473 d->m_frameNameId = 1; 01474 d->m_bFirstData = true; 01475 01476 d->m_bMousePressed = false; 01477 01478 d->m_selectionStart = DOM::Node(); 01479 d->m_selectionEnd = DOM::Node(); 01480 d->m_startOffset = 0; 01481 d->m_endOffset = 0; 01482 #ifndef QT_NO_CLIPBOARD 01483 connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection())); 01484 #endif 01485 01486 d->m_jobPercent = 0; 01487 01488 if ( !d->m_haveEncoding ) 01489 d->m_encoding = QString::null; 01490 #ifdef SPEED_DEBUG 01491 d->m_parsetime.restart(); 01492 #endif 01493 } 01494 01495 bool KHTMLPart::openFile() 01496 { 01497 return true; 01498 } 01499 01500 DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const 01501 { 01502 if ( d && d->m_doc && d->m_doc->isHTMLDocument() ) 01503 return static_cast<HTMLDocumentImpl*>(d->m_doc); 01504 return 0; 01505 } 01506 01507 DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const 01508 { 01509 if ( d ) 01510 return d->m_doc; 01511 return 0; 01512 } 01513 01514 void KHTMLPart::slotInfoMessage(KIO::Job* kio_job, const QString& msg) 01515 { 01516 assert(d->m_job == kio_job); 01517 01518 if (!parentPart()) 01519 setStatusBarText(msg, BarDefaultText); 01520 } 01521 01522 void KHTMLPart::setPageSecurity( PageSecurity sec ) 01523 { 01524 emit d->m_extension->setPageSecurity( sec ); 01525 if ( sec != NotCrypted && !d->m_statusBarIconLabel && !parentPart() ) { 01526 d->m_statusBarIconLabel = new KURLLabel( d->m_statusBarExtension->statusBar() ); 01527 d->m_statusBarIconLabel->setFixedHeight( instance()->iconLoader()->currentSize(KIcon::Small) ); 01528 d->m_statusBarIconLabel->setSizePolicy(QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed )); 01529 d->m_statusBarIconLabel->setUseCursor( false ); 01530 d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false ); 01531 connect( d->m_statusBarIconLabel, SIGNAL( leftClickedURL() ), SLOT( slotSecurity() ) ); 01532 } else if (d->m_statusBarIconLabel) { 01533 QToolTip::remove(d->m_statusBarIconLabel); 01534 } 01535 01536 if (d->m_statusBarIconLabel) { 01537 if (d->m_ssl_in_use) 01538 QToolTip::add(d->m_statusBarIconLabel, 01539 i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher)); 01540 else QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured.")); 01541 } 01542 01543 QString iconName; 01544 switch (sec) { 01545 case NotCrypted: 01546 iconName = "decrypted"; 01547 if ( d->m_statusBarIconLabel ) { 01548 d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarIconLabel ); 01549 delete d->m_statusBarIconLabel; 01550 d->m_statusBarIconLabel = 0L; 01551 } 01552 break; 01553 case Encrypted: 01554 iconName = "encrypted"; 01555 break; 01556 case Mixed: 01557 iconName = "halfencrypted"; 01558 break; 01559 } 01560 d->m_paSecurity->setIcon( iconName ); 01561 if ( d->m_statusBarIconLabel ) 01562 d->m_statusBarIconLabel->setPixmap( SmallIcon( iconName, instance() ) ); 01563 } 01564 01565 void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data ) 01566 { 01567 assert ( d->m_job == kio_job ); 01568 01569 //kdDebug( 6050 ) << "slotData: " << data.size() << endl; 01570 // The first data ? 01571 if ( !d->m_workingURL.isEmpty() ) 01572 { 01573 //kdDebug( 6050 ) << "begin!" << endl; 01574 01575 // We must suspend KIO while we're inside begin() because it can cause 01576 // crashes if a window (such as kjsdebugger) goes back into the event loop, 01577 // more data arrives, and begin() gets called again (re-entered). 01578 d->m_job->suspend(); 01579 begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset ); 01580 d->m_job->resume(); 01581 01582 if (d->m_cachePolicy == KIO::CC_Refresh) 01583 d->m_doc->docLoader()->setCachePolicy(KIO::CC_Verify); 01584 else 01585 d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy); 01586 01587 d->m_workingURL = KURL(); 01588 01589 d->m_cacheId = KHTMLPageCache::self()->createCacheEntry(); 01590 01591 // When the first data arrives, the metadata has just been made available 01592 d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers"); 01593 time_t cacheCreationDate = d->m_job->queryMetaData("cache-creation-date").toLong(); 01594 d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate); 01595 01596 d->m_pageServices = d->m_job->queryMetaData("PageServices"); 01597 d->m_pageReferrer = d->m_job->queryMetaData("referrer"); 01598 d->m_bSecurityInQuestion = false; 01599 d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE"); 01600 01601 { 01602 KHTMLPart *p = parentPart(); 01603 if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) { 01604 while (p->parentPart()) p = p->parentPart(); 01605 01606 p->setPageSecurity( Mixed ); 01607 p->d->m_bSecurityInQuestion = true; 01608 } 01609 } 01610 01611 setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted ); 01612 01613 // Shouldn't all of this be done only if ssl_in_use == true ? (DF) 01614 d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip"); 01615 d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert"); 01616 d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate"); 01617 d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain"); 01618 d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip"); 01619 d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher"); 01620 d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc"); 01621 d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version"); 01622 d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits"); 01623 d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits"); 01624 d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state"); 01625 01626 if (d->m_statusBarIconLabel) { 01627 QToolTip::remove(d->m_statusBarIconLabel); 01628 if (d->m_ssl_in_use) { 01629 QToolTip::add(d->m_statusBarIconLabel, i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher)); 01630 } else { 01631 QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured.")); 01632 } 01633 } 01634 01635 // Check for charset meta-data 01636 QString qData = d->m_job->queryMetaData("charset"); 01637 if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings 01638 d->m_encoding = qData; 01639 01640 01641 // Support for http-refresh 01642 qData = d->m_job->queryMetaData("http-refresh"); 01643 if( !qData.isEmpty()) 01644 d->m_doc->processHttpEquiv("refresh", qData); 01645 01646 // DISABLED: Support Content-Location per section 14.14 of RFC 2616. 01647 // See BR# 51185,BR# 82747 01648 /* 01649 QString baseURL = d->m_job->queryMetaData ("content-location"); 01650 if (!baseURL.isEmpty()) 01651 d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) )); 01652 */ 01653 01654 // Support for Content-Language 01655 QString language = d->m_job->queryMetaData("content-language"); 01656 if (!language.isEmpty()) 01657 d->m_doc->setContentLanguage(language); 01658 01659 if ( !m_url.isLocalFile() ) { 01660 // Support for http last-modified 01661 d->m_lastModified = d->m_job->queryMetaData("modified"); 01662 } else 01663 d->m_lastModified = QString::null; // done on-demand by lastModified() 01664 } 01665 01666 KHTMLPageCache::self()->addData(d->m_cacheId, data); 01667 write( data.data(), data.size() ); 01668 if (d->m_frame && d->m_frame->m_jscript) 01669 d->m_frame->m_jscript->dataReceived(); 01670 } 01671 01672 void KHTMLPart::slotRestoreData(const QByteArray &data ) 01673 { 01674 // The first data ? 01675 if ( !d->m_workingURL.isEmpty() ) 01676 { 01677 long saveCacheId = d->m_cacheId; 01678 QString savePageReferrer = d->m_pageReferrer; 01679 QString saveEncoding = d->m_encoding; 01680 begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset ); 01681 d->m_encoding = saveEncoding; 01682 d->m_pageReferrer = savePageReferrer; 01683 d->m_cacheId = saveCacheId; 01684 d->m_workingURL = KURL(); 01685 } 01686 01687 //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl; 01688 write( data.data(), data.size() ); 01689 01690 if (data.size() == 0) 01691 { 01692 //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl; 01693 // End of data. 01694 if (d->m_doc && d->m_doc->parsing()) 01695 end(); //will emit completed() 01696 } 01697 } 01698 01699 void KHTMLPart::showError( KIO::Job* job ) 01700 { 01701 kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete 01702 << " d->m_bCleared=" << d->m_bCleared << endl; 01703 01704 if (job->error() == KIO::ERR_NO_CONTENT) 01705 return; 01706 01707 if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already 01708 job->showErrorDialog( /*d->m_view*/ ); 01709 else 01710 { 01711 htmlError( job->error(), job->errorText(), d->m_workingURL ); 01712 } 01713 } 01714 01715 // This is a protected method, placed here because of it's relevance to showError 01716 void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl ) 01717 { 01718 kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl; 01719 // make sure we're not executing any embedded JS 01720 bool bJSFO = d->m_bJScriptForce; 01721 bool bJSOO = d->m_bJScriptOverride; 01722 d->m_bJScriptForce = false; 01723 d->m_bJScriptOverride = true; 01724 begin(); 01725 QString errText = QString::fromLatin1( "<HTML dir=%1><HEAD><TITLE>" ) 01726 .arg(QApplication::reverseLayout() ? "rtl" : "ltr"); 01727 errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() ); 01728 errText += QString::fromLatin1( "</TITLE></HEAD><BODY><P>" ); 01729 errText += i18n( "An error occurred while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() ); 01730 errText += QString::fromLatin1( "</P>" ); 01731 errText += QStyleSheet::convertFromPlainText( KIO::buildErrorString( errorCode, text ) ); 01732 errText += QString::fromLatin1( "</BODY></HTML>" ); 01733 write(errText); 01734 end(); 01735 01736 d->m_bJScriptForce = bJSFO; 01737 d->m_bJScriptOverride = bJSOO; 01738 01739 // make the working url the current url, so that reload works and 01740 // emit the progress signals to advance one step in the history 01741 // (so that 'back' works) 01742 m_url = reqUrl; // same as d->m_workingURL 01743 d->m_workingURL = KURL(); 01744 emit started( 0 ); 01745 emit completed(); 01746 return; 01747 // following disabled until 3.1 01748 01749 QString errorName, techName, description; 01750 QStringList causes, solutions; 01751 01752 QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl ); 01753 QDataStream stream(raw, IO_ReadOnly); 01754 01755 stream >> errorName >> techName >> description >> causes >> solutions; 01756 01757 QString url, protocol, datetime; 01758 url = reqUrl.prettyURL(); 01759 protocol = reqUrl.protocol(); 01760 datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(), 01761 false ); 01762 01763 QString doc = QString::fromLatin1( "<html><head><title>" ); 01764 doc += i18n( "Error: " ); 01765 doc += errorName; 01766 doc += QString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url ); 01767 doc += i18n( "The requested operation could not be completed" ); 01768 doc += QString::fromLatin1( "</h1><h2>" ); 01769 doc += errorName; 01770 doc += QString::fromLatin1( "</h2>" ); 01771 if ( !techName.isNull() ) { 01772 doc += QString::fromLatin1( "<h2>" ); 01773 doc += i18n( "Technical Reason: " ); 01774 doc += techName; 01775 doc += QString::fromLatin1( "</h2>" ); 01776 } 01777 doc += QString::fromLatin1( "<h3>" ); 01778 doc += i18n( "Details of the Request:" ); 01779 doc += QString::fromLatin1( "</h3><ul><li>" ); 01780 doc += i18n( "URL: %1" ).arg( url ); 01781 doc += QString::fromLatin1( "</li><li>" ); 01782 if ( !protocol.isNull() ) { 01783 // uncomment for 3.1... i18n change 01784 // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol ); 01785 doc += QString::fromLatin1( "</li><li>" ); 01786 } 01787 doc += i18n( "Date and Time: %1" ).arg( datetime ); 01788 doc += QString::fromLatin1( "</li><li>" ); 01789 doc += i18n( "Additional Information: %1" ).arg( text ); 01790 doc += QString::fromLatin1( "</li></ul><h3>" ); 01791 doc += i18n( "Description:" ); 01792 doc += QString::fromLatin1( "</h3><p>" ); 01793 doc += description; 01794 doc += QString::fromLatin1( "</p>" ); 01795 if ( causes.count() ) { 01796 doc += QString::fromLatin1( "<h3>" ); 01797 doc += i18n( "Possible Causes:" ); 01798 doc += QString::fromLatin1( "</h3><ul><li>" ); 01799 doc += causes.join( "</li><li>" ); 01800 doc += QString::fromLatin1( "</li></ul>" ); 01801 } 01802 if ( solutions.count() ) { 01803 doc += QString::fromLatin1( "<h3>" ); 01804 doc += i18n( "Possible Solutions:" ); 01805 doc += QString::fromLatin1( "</h3><ul><li>" ); 01806 doc += solutions.join( "</li><li>" ); 01807 doc += QString::fromLatin1( "</li></ul>" ); 01808 } 01809 doc += QString::fromLatin1( "</body></html>" ); 01810 01811 write( doc ); 01812 end(); 01813 } 01814 01815 void KHTMLPart::slotFinished( KIO::Job * job ) 01816 { 01817 d->m_job = 0L; 01818 d->m_jobspeed = 0L; 01819 01820 if (job->error()) 01821 { 01822 KHTMLPageCache::self()->cancelEntry(d->m_cacheId); 01823 01824 // The following catches errors that occur as a result of HTTP 01825 // to FTP redirections where the FTP URL is a directory. Since 01826 // KIO cannot change a redirection request from GET to LISTDIR, 01827 // we have to take care of it here once we know for sure it is 01828 // a directory... 01829 if (job->error() == KIO::ERR_IS_DIRECTORY) 01830 { 01831 KParts::URLArgs args; 01832 emit d->m_extension->openURLRequest( d->m_workingURL, args ); 01833 } 01834 else 01835 { 01836 emit canceled( job->errorString() ); 01837 // TODO: what else ? 01838 checkCompleted(); 01839 showError( job ); 01840 } 01841 01842 return; 01843 } 01844 KIO::TransferJob *tjob = ::qt_cast<KIO::TransferJob*>(job); 01845 if (tjob && tjob->isErrorPage()) { 01846 khtml::RenderPart *renderPart = d->m_frame ? static_cast<khtml::RenderPart *>(d->m_frame->m_frame) : 0; 01847 if (renderPart) { 01848 HTMLObjectElementImpl* elt = static_cast<HTMLObjectElementImpl *>(renderPart->element()); 01849 if (!elt) 01850 return; 01851 elt->renderAlternative(); 01852 checkCompleted(); 01853 } 01854 if (d->m_bComplete) return; 01855 } 01856 01857 //kdDebug( 6050 ) << "slotFinished" << endl; 01858 01859 KHTMLPageCache::self()->endData(d->m_cacheId); 01860 if (d->m_frame && d->m_frame->m_jscript) 01861 d->m_frame->m_jscript->dataReceived(); 01862 01863 if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http")) 01864 KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate()); 01865 01866 d->m_workingURL = KURL(); 01867 01868 if ( d->m_doc && d->m_doc->parsing()) 01869 end(); //will emit completed() 01870 } 01871 01872 void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset ) 01873 { 01874 // No need to show this for a new page until an error is triggered 01875 if (!parentPart()) { 01876 removeJSErrorExtension(); 01877 setSuppressedPopupIndicator( false ); 01878 d->m_openableSuppressedPopups = 0; 01879 for ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin(); 01880 i != d->m_suppressedPopupOriginParts.end(); ++i ) { 01881 01882 if (KHTMLPart* part = *i) { 01883 KJS::Window *w = KJS::Window::retrieveWindow( part ); 01884 if (w) 01885 w->forgetSuppressedWindows(); 01886 } 01887 } 01888 } 01889 01890 clear(); 01891 d->m_bCleared = false; 01892 d->m_cacheId = 0; 01893 d->m_bComplete = false; 01894 d->m_bLoadEventEmitted = false; 01895 01896 if(url.isValid()) { 01897 QString urlString = url.url(); 01898 KHTMLFactory::vLinks()->insert( urlString ); 01899 QString urlString2 = url.prettyURL(); 01900 if ( urlString != urlString2 ) { 01901 KHTMLFactory::vLinks()->insert( urlString2 ); 01902 } 01903 } 01904 01905 01906 // ### 01907 //stopParser(); 01908 01909 KParts::URLArgs args( d->m_extension->urlArgs() ); 01910 args.xOffset = xOffset; 01911 args.yOffset = yOffset; 01912 d->m_extension->setURLArgs( args ); 01913 01914 d->m_pageReferrer = QString::null; 01915 01916 KURL ref(url); 01917 d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : ""; 01918 01919 m_url = url; 01920 01921 bool servedAsXHTML = args.serviceType == "application/xhtml+xml"; 01922 bool servedAsXML = KMimeType::mimeType(args.serviceType)->is( "text/xml" ); 01923 // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl 01924 if ( servedAsXML && !servedAsXHTML ) { // any XML derivative, except XHTML 01925 d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view ); 01926 } else { 01927 d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view ); 01928 // HTML or XHTML? (#86446) 01929 static_cast<HTMLDocumentImpl *>(d->m_doc)->setHTMLRequested( !servedAsXHTML ); 01930 } 01931 #ifndef KHTML_NO_CARET 01932 // d->m_view->initCaret(); 01933 #endif 01934 01935 d->m_doc->ref(); 01936 d->m_doc->setURL( m_url.url() ); 01937 if (!d->m_doc->attached()) 01938 d->m_doc->attach( ); 01939 d->m_doc->setBaseURL( KURL() ); 01940 d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() ); 01941 emit docCreated(); 01942 01943 d->m_paUseStylesheet->setItems(QStringList()); 01944 d->m_paUseStylesheet->setEnabled( false ); 01945 01946 setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() ); 01947 QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet(); 01948 if ( !userStyleSheet.isEmpty() ) 01949 setUserStyleSheet( KURL( userStyleSheet ) ); 01950 01951 d->m_doc->setRestoreState(args.docState); 01952 d->m_doc->open(); 01953 connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing())); 01954 01955 emit d->m_extension->enableAction( "print", true ); 01956 01957 d->m_doc->setParsing(true); 01958 } 01959 01960 void KHTMLPart::write( const char *str, int len ) 01961 { 01962 if ( !d->m_decoder ) 01963 d->m_decoder = createDecoder(); 01964 01965 if ( len == -1 ) 01966 len = strlen( str ); 01967 01968 if ( len == 0 ) 01969 return; 01970 01971 QString decoded = d->m_decoder->decode( str, len ); 01972 01973 if(decoded.isEmpty()) return; 01974 01975 if(d->m_bFirstData) { 01976 // determine the parse mode 01977 d->m_doc->determineParseMode( decoded ); 01978 d->m_bFirstData = false; 01979 01980 //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl; 01981 // ### this is still quite hacky, but should work a lot better than the old solution 01982 if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered(); 01983 d->m_doc->setDecoderCodec(d->m_decoder->codec()); 01984 d->m_doc->recalcStyle( NodeImpl::Force ); 01985 } 01986 01987 khtml::Tokenizer* t = d->m_doc->tokenizer(); 01988 if(t) 01989 t->write( decoded, true ); 01990 } 01991 01992 void KHTMLPart::write( const QString &str ) 01993 { 01994 if ( str.isNull() ) 01995 return; 01996 01997 if(d->m_bFirstData) { 01998 // determine the parse mode 01999 d->m_doc->setParseMode( DocumentImpl::Strict ); 02000 d->m_bFirstData = false; 02001 } 02002 khtml::Tokenizer* t = d->m_doc->tokenizer(); 02003 if(t) 02004 t->write( str, true ); 02005 } 02006 02007 void KHTMLPart::end() 02008 { 02009 if (d->m_doc) { 02010 if (d->m_decoder) { 02011 QString decoded = d->m_decoder->flush(); 02012 if (d->m_bFirstData) { 02013 d->m_bFirstData = false; 02014 d->m_doc->determineParseMode(decoded); 02015 } 02016 write(decoded); 02017 } 02018 d->m_doc->finishParsing(); 02019 } 02020 } 02021 02022 bool KHTMLPart::doOpenStream( const QString& mimeType ) 02023 { 02024 KMimeType::Ptr mime = KMimeType::mimeType(mimeType); 02025 if ( mime->is( "text/html" ) || mime->is( "text/xml" ) ) 02026 { 02027 begin( url() ); 02028 return true; 02029 } 02030 return false; 02031 } 02032 02033 bool KHTMLPart::doWriteStream( const QByteArray& data ) 02034 { 02035 write( data.data(), data.size() ); 02036 return true; 02037 } 02038 02039 bool KHTMLPart::doCloseStream() 02040 { 02041 end(); 02042 return true; 02043 } 02044 02045 02046 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more) 02047 { 02048 if (!d->m_view) return; 02049 d->m_view->paint(p, rc, yOff, more); 02050 } 02051 02052 void KHTMLPart::stopAnimations() 02053 { 02054 if ( d->m_doc ) 02055 d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled ); 02056 02057 ConstFrameIt it = d->m_frames.begin(); 02058 const ConstFrameIt end = d->m_frames.end(); 02059 for (; it != end; ++it ) 02060 if ( !(*it)->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) { 02061 KParts::ReadOnlyPart* const p = ( *it )->m_part; 02062 static_cast<KHTMLPart*>( p )->stopAnimations(); 02063 } 02064 } 02065 02066 void KHTMLPart::resetFromScript() 02067 { 02068 closeURL(); 02069 d->m_bComplete = false; 02070 d->m_bLoadEventEmitted = false; 02071 disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing())); 02072 connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing())); 02073 d->m_doc->setParsing(true); 02074 02075 emit started( 0L ); 02076 } 02077 02078 void KHTMLPart::slotFinishedParsing() 02079 { 02080 d->m_doc->setParsing(false); 02081 checkEmitLoadEvent(); 02082 disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing())); 02083 02084 if (!d->m_view) 02085 return; // We are probably being destructed. 02086 02087 checkCompleted(); 02088 } 02089 02090 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj ) 02091 { 02092 if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) { 02093 KHTMLPart* p = this; 02094 while ( p ) { 02095 KHTMLPart* const op = p; 02096 ++(p->d->m_totalObjectCount); 02097 p = p->parentPart(); 02098 if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount 02099 && !op->d->m_progressUpdateTimer.isActive()) 02100 op->d->m_progressUpdateTimer.start( 200, true ); 02101 } 02102 } 02103 } 02104 02105 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj ) 02106 { 02107 if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) { 02108 KHTMLPart* p = this; 02109 while ( p ) { 02110 KHTMLPart* const op = p; 02111 ++(p->d->m_loadedObjects); 02112 p = p->parentPart(); 02113 if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100 02114 && !op->d->m_progressUpdateTimer.isActive()) 02115 op->d->m_progressUpdateTimer.start( 200, true ); 02116 } 02117 } 02118 02119 checkCompleted(); 02120 } 02121 02122 void KHTMLPart::slotProgressUpdate() 02123 { 02124 int percent; 02125 if ( d->m_loadedObjects < d->m_totalObjectCount ) 02126 percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount ); 02127 else 02128 percent = d->m_jobPercent; 02129 02130 if( d->m_bComplete ) 02131 percent = 100; 02132 02133 if (d->m_statusMessagesEnabled) { 02134 if( d->m_bComplete ) 02135 emit d->m_extension->infoMessage( i18n( "Page loaded." )); 02136 else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 ) 02137 emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) ); 02138 } 02139 02140 emit d->m_extension->loadingProgress( percent ); 02141 } 02142 02143 void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed ) 02144 { 02145 d->m_jobspeed = speed; 02146 if (!parentPart()) 02147 setStatusBarText(jsStatusBarText(), BarOverrideText); 02148 } 02149 02150 void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent ) 02151 { 02152 d->m_jobPercent = percent; 02153 02154 if ( !parentPart() ) 02155 d->m_progressUpdateTimer.start( 0, true ); 02156 } 02157 02158 void KHTMLPart::slotJobDone( KIO::Job* /*job*/ ) 02159 { 02160 d->m_jobPercent = 100; 02161 02162 if ( !parentPart() ) 02163 d->m_progressUpdateTimer.start( 0, true ); 02164 } 02165 02166 void KHTMLPart::slotUserSheetStatDone( KIO::Job *_job ) 02167 { 02168 using namespace KIO; 02169 02170 if ( _job->error() ) { 02171 showError( _job ); 02172 return; 02173 } 02174 02175 const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult(); 02176 UDSEntry::ConstIterator it = entry.begin(); 02177 const UDSEntry::ConstIterator end = entry.end(); 02178 for ( ; it != end; ++it ) { 02179 if ( ( *it ).m_uds == UDS_MODIFICATION_TIME ) { 02180 break; 02181 } 02182 } 02183 02184 // If the filesystem supports modification times, only reload the 02185 // user-defined stylesheet if necessary - otherwise always reload. 02186 if ( it != end ) { 02187 const time_t lastModified = static_cast<time_t>( ( *it ).m_long ); 02188 if ( d->m_userStyleSheetLastModified >= lastModified ) { 02189 return; 02190 } 02191 d->m_userStyleSheetLastModified = lastModified; 02192 } 02193 02194 setUserStyleSheet( KURL( settings()->userStyleSheet() ) ); 02195 } 02196 02197 void KHTMLPart::checkCompleted() 02198 { 02199 // kdDebug( 6050 ) << "KHTMLPart::checkCompleted() " << this << " " << name() << endl; 02200 // kdDebug( 6050 ) << " parsing: " << (d->m_doc && d->m_doc->parsing()) << endl; 02201 // kdDebug( 6050 ) << " complete: " << d->m_bComplete << endl; 02202 02203 // restore the cursor position 02204 if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored) 02205 { 02206 if (d->m_focusNodeNumber >= 0) 02207 d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber)); 02208 02209 d->m_focusNodeRestored = true; 02210 } 02211 02212 bool bPendingChildRedirection = false; 02213 // Any frame that hasn't completed yet ? 02214 ConstFrameIt it = d->m_frames.begin(); 02215 const ConstFrameIt end = d->m_frames.end(); 02216 for (; it != end; ++it ) { 02217 if ( !(*it)->m_bCompleted ) 02218 { 02219 //kdDebug( 6050 ) << this << " is waiting for " << (*it)->m_part << endl; 02220 return; 02221 } 02222 // Check for frames with pending redirections 02223 if ( (*it)->m_bPendingRedirection ) 02224 bPendingChildRedirection = true; 02225 } 02226 02227 // Any object that hasn't completed yet ? 02228 { 02229 ConstFrameIt oi = d->m_objects.begin(); 02230 const ConstFrameIt oiEnd = d->m_objects.end(); 02231 02232 for (; oi != oiEnd; ++oi ) 02233 if ( !(*oi)->m_bCompleted ) 02234 return; 02235 } 02236 // Are we still parsing - or have we done the completed stuff already ? 02237 if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) ) 02238 return; 02239 02240 // Still waiting for images/scripts from the loader ? 02241 int requests = 0; 02242 if ( d->m_doc && d->m_doc->docLoader() ) 02243 requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() ); 02244 02245 if ( requests > 0 ) 02246 { 02247 //kdDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests << endl; 02248 return; 02249 } 02250 02251 // OK, completed. 02252 // Now do what should be done when we are really completed. 02253 d->m_bComplete = true; 02254 d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy 02255 d->m_totalObjectCount = 0; 02256 d->m_loadedObjects = 0; 02257 02258 KHTMLPart* p = this; 02259 while ( p ) { 02260 KHTMLPart* op = p; 02261 p = p->parentPart(); 02262 if ( !p && !op->d->m_progressUpdateTimer.isActive()) 02263 op->d->m_progressUpdateTimer.start( 0, true ); 02264 } 02265 02266 checkEmitLoadEvent(); // if we didn't do it before 02267 02268 bool pendingAction = false; 02269 02270 if ( !d->m_redirectURL.isEmpty() ) 02271 { 02272 // DA: Do not start redirection for frames here! That action is 02273 // deferred until the parent emits a completed signal. 02274 if ( parentPart() == 0 ) { 02275 //kdDebug(6050) << this << " starting redirection timer" << endl; 02276 d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true ); 02277 } else { 02278 //kdDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted." << endl; 02279 } 02280 02281 pendingAction = true; 02282 } 02283 else if ( bPendingChildRedirection ) 02284 { 02285 pendingAction = true; 02286 } 02287 02288 // the view will emit completed on our behalf, 02289 // either now or at next repaint if one is pending 02290 02291 //kdDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction << endl; 02292 d->m_view->complete( pendingAction ); 02293 02294 // find the alternate stylesheets 02295 QStringList sheets; 02296 if (d->m_doc) 02297 sheets = d->m_doc->availableStyleSheets(); 02298 sheets.prepend( i18n( "Automatic Detection" ) ); 02299 d->m_paUseStylesheet->setItems( sheets ); 02300 02301 d->m_paUseStylesheet->setEnabled( sheets.count() > 2); 02302 if (sheets.count() > 2) 02303 { 02304 d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0)); 02305 slotUseStylesheet(); 02306 } 02307 02308 setJSDefaultStatusBarText(QString::null); 02309 02310 #ifdef SPEED_DEBUG 02311 kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl; 02312 #endif 02313 } 02314 02315 void KHTMLPart::checkEmitLoadEvent() 02316 { 02317 if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return; 02318 02319 ConstFrameIt it = d->m_frames.begin(); 02320 const ConstFrameIt end = d->m_frames.end(); 02321 for (; it != end; ++it ) 02322 if ( !(*it)->m_bCompleted ) // still got a frame running -> too early 02323 return; 02324 02325 ConstFrameIt oi = d->m_objects.begin(); 02326 const ConstFrameIt oiEnd = d->m_objects.end(); 02327 02328 for (; oi != oiEnd; ++oi ) 02329 if ( !(*oi)->m_bCompleted ) // still got a object running -> too early 02330 return; 02331 02332 // Still waiting for images/scripts from the loader ? 02333 // (onload must happen afterwards, #45607) 02334 // ## This makes this method very similar to checkCompleted. A brave soul should try merging them. 02335 int requests = 0; 02336 if ( d->m_doc && d->m_doc->docLoader() ) 02337 requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() ); 02338 02339 if ( requests > 0 ) 02340 return; 02341 02342 d->m_bLoadEventEmitted = true; 02343 if (d->m_doc) 02344 d->m_doc->close(); 02345 } 02346 02347 const KHTMLSettings *KHTMLPart::settings() const 02348 { 02349 return d->m_settings; 02350 } 02351 02352 #ifndef KDE_NO_COMPAT 02353 KURL KHTMLPart::baseURL() const 02354 { 02355 if ( !d->m_doc ) return KURL(); 02356 02357 return d->m_doc->baseURL(); 02358 } 02359 02360 QString KHTMLPart::baseTarget() const 02361 { 02362 if ( !d->m_doc ) return QString::null; 02363 02364 return d->m_doc->baseTarget(); 02365 } 02366 #endif 02367 02368 KURL KHTMLPart::completeURL( const QString &url ) 02369 { 02370 if ( !d->m_doc ) return KURL( url ); 02371 02372 if (d->m_decoder) 02373 return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum()); 02374 02375 return KURL( d->m_doc->completeURL( url ) ); 02376 } 02377 02378 // Called by ecma/kjs_window in case of redirections from Javascript, 02379 // and by xml/dom_docimpl.cpp in case of http-equiv meta refresh. 02380 void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory ) 02381 { 02382 kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl; 02383 kdDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect << endl; 02384 if( delay < 24*60*60 && 02385 ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) { 02386 d->m_delayRedirect = delay; 02387 d->m_redirectURL = url; 02388 d->m_redirectLockHistory = doLockHistory; 02389 kdDebug(6050) << " d->m_bComplete=" << d->m_bComplete << endl; 02390 if ( d->m_bComplete ) { 02391 d->m_redirectionTimer.stop(); 02392 d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true ); 02393 } 02394 } 02395 } 02396 02397 void KHTMLPart::slotRedirect() 02398 { 02399 kdDebug(6050) << this << " slotRedirect()" << endl; 02400 QString u = d->m_redirectURL; 02401 d->m_delayRedirect = 0; 02402 d->m_redirectURL = QString::null; 02403 02404 // SYNC check with ecma/kjs_window.cpp::goURL ! 02405 if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) 02406 { 02407 QString script = KURL::decode_string( u.right( u.length() - 11 ) ); 02408 kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl; 02409 QVariant res = executeScript( DOM::Node(), script ); 02410 if ( res.type() == QVariant::String ) { 02411 begin( url() ); 02412 write( res.asString() ); 02413 end(); 02414 } 02415 emit completed(); 02416 return; 02417 } 02418 KParts::URLArgs args; 02419 KURL cUrl( m_url ); 02420 KURL url( u ); 02421 02422 // handle windows opened by JS 02423 if ( openedByJS() && d->m_opener ) 02424 cUrl = d->m_opener->url(); 02425 02426 if (!kapp || !kapp->authorizeURLAction("redirect", cUrl, url)) 02427 { 02428 kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl << " to " << url << " REJECTED!" << endl; 02429 emit completed(); 02430 return; 02431 } 02432 02433 if ( urlcmp( u, m_url.url(), true, true ) ) 02434 { 02435 args.metaData().insert("referrer", d->m_pageReferrer); 02436 } 02437 02438 // For javascript and META-tag based redirections: 02439 // - We don't take cross-domain-ness in consideration if we are the 02440 // toplevel frame because the new URL may be in a different domain as the current URL 02441 // but that's ok. 02442 // - If we are not the toplevel frame then we check against the toplevelURL() 02443 if (parentPart()) 02444 args.metaData().insert("cross-domain", toplevelURL().url()); 02445 02446 args.setLockHistory( d->m_redirectLockHistory ); 02447 // _self: make sure we don't use any <base target=>'s 02448 02449 d->m_urlSelectedOpenedURL = true; // In case overriden, default to success 02450 urlSelected( u, 0, 0, "_self", args ); 02451 02452 if ( !d->m_urlSelectedOpenedURL ) // urlSelected didn't open a url, so emit completed ourselves 02453 emit completed(); 02454 } 02455 02456 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url) 02457 { 02458 // the slave told us that we got redirected 02459 //kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl; 02460 emit d->m_extension->setLocationBarURL( url.prettyURL() ); 02461 d->m_workingURL = url; 02462 } 02463 02464 bool KHTMLPart::setEncoding( const QString &name, bool override ) 02465 { 02466 d->m_encoding = name; 02467 d->m_haveEncoding = override; 02468 02469 if( !m_url.isEmpty() ) { 02470 // reload document 02471 closeURL(); 02472 KURL url = m_url; 02473 m_url = 0; 02474 d->m_restored = true; 02475 openURL(url); 02476 d->m_restored = false; 02477 } 02478 02479 return true; 02480 } 02481 02482 QString KHTMLPart::encoding() const 02483 { 02484 if(d->m_haveEncoding && !d->m_encoding.isEmpty()) 02485 return d->m_encoding; 02486 02487 if(d->m_decoder && d->m_decoder->encoding()) 02488 return QString(d->m_decoder->encoding()); 02489 02490 return defaultEncoding(); 02491 } 02492 02493 QString KHTMLPart::defaultEncoding() const 02494 { 02495 QString encoding = settings()->encoding(); 02496 if ( !encoding.isEmpty() ) 02497 return encoding; 02498 // HTTP requires the default encoding to be latin1, when neither 02499 // the user nor the page requested a particular encoding. 02500 if ( url().protocol().startsWith( "http" ) ) 02501 return "iso-8859-1"; 02502 else 02503 return KGlobal::locale()->encoding(); 02504 } 02505 02506 void KHTMLPart::setUserStyleSheet(const KURL &url) 02507 { 02508 if ( d->m_doc && d->m_doc->docLoader() ) 02509 (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader()); 02510 } 02511 02512 void KHTMLPart::setUserStyleSheet(const QString &styleSheet) 02513 { 02514 if ( d->m_doc ) 02515 d->m_doc->setUserStyleSheet( styleSheet ); 02516 } 02517 02518 bool KHTMLPart::gotoAnchor( const QString &name ) 02519 { 02520 if (!d->m_doc) 02521 return false; 02522 02523 HTMLCollectionImpl *anchors = 02524 new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS); 02525 anchors->ref(); 02526 NodeImpl *n = anchors->namedItem(name); 02527 anchors->deref(); 02528 02529 if(!n) { 02530 n = d->m_doc->getElementById( name ); 02531 } 02532 02533 d->m_doc->setCSSTarget(n); // Setting to null will clear the current target. 02534 02535 // Implement the rule that "" and "top" both mean top of page as in other browsers. 02536 bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.lower() == "top"); 02537 02538 if (quirkyName) { 02539 d->m_view->setContentsPos(0, 0); 02540 return true; 02541 } else if (!n) { 02542 kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl; 02543 return false; 02544 } 02545 02546 int x = 0, y = 0; 02547 int gox, dummy; 02548 HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n); 02549 02550 a->getUpperLeftCorner(x, y); 02551 if (x <= d->m_view->contentsX()) 02552 gox = x - 10; 02553 else { 02554 gox = d->m_view->contentsX(); 02555 if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) { 02556 a->getLowerRightCorner(x, dummy); 02557 gox = x - d->m_view->visibleWidth() + 10; 02558 } 02559 } 02560 02561 d->m_view->setContentsPos(gox, y); 02562 02563 return true; 02564 } 02565 02566 bool KHTMLPart::nextAnchor() 02567 { 02568 if (!d->m_doc) 02569 return false; 02570 d->m_view->focusNextPrevNode ( true ); 02571 02572 return true; 02573 } 02574 02575 bool KHTMLPart::prevAnchor() 02576 { 02577 if (!d->m_doc) 02578 return false; 02579 d->m_view->focusNextPrevNode ( false ); 02580 02581 return true; 02582 } 02583 02584 void KHTMLPart::setStandardFont( const QString &name ) 02585 { 02586 d->m_settings->setStdFontName(name); 02587 } 02588 02589 void KHTMLPart::setFixedFont( const QString &name ) 02590 { 02591 d->m_settings->setFixedFontName(name); 02592 } 02593 02594 void KHTMLPart::setURLCursor( const QCursor &c ) 02595 { 02596 d->m_linkCursor = c; 02597 } 02598 02599 QCursor KHTMLPart::urlCursor() const 02600 { 02601 return d->m_linkCursor; 02602 } 02603 02604 bool KHTMLPart::onlyLocalReferences() const 02605 { 02606 return d->m_onlyLocalReferences; 02607 } 02608 02609 void KHTMLPart::setOnlyLocalReferences(bool enable) 02610 { 02611 d->m_onlyLocalReferences = enable; 02612 } 02613 02614 void KHTMLPartPrivate::setFlagRecursively( 02615 bool KHTMLPartPrivate::*flag, bool value) 02616 { 02617 // first set it on the current one 02618 this->*flag = value; 02619 02620 // descend into child frames recursively 02621 { 02622 QValueList<khtml::ChildFrame*>::Iterator it = m_frames.begin(); 02623 const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_frames.end(); 02624 for (; it != itEnd; ++it) { 02625 KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part); 02626 if (part->inherits("KHTMLPart")) 02627 part->d->setFlagRecursively(flag, value); 02628 }/*next it*/ 02629 } 02630 // do the same again for objects 02631 { 02632 QValueList<khtml::ChildFrame*>::Iterator it = m_objects.begin(); 02633 const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_objects.end(); 02634 for (; it != itEnd; ++it) { 02635 KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part); 02636 if (part->inherits("KHTMLPart")) 02637 part->d->setFlagRecursively(flag, value); 02638 }/*next it*/ 02639 } 02640 } 02641 02642 void KHTMLPart::setCaretMode(bool enable) 02643 { 02644 #ifndef KHTML_NO_CARET 02645 kdDebug(6200) << "setCaretMode(" << enable << ")" << endl; 02646 if (isCaretMode() == enable) return; 02647 d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable); 02648 // FIXME: this won't work on frames as expected 02649 if (!isEditable()) { 02650 if (enable) { 02651 view()->initCaret(true); 02652 view()->ensureCaretVisible(); 02653 } else 02654 view()->caretOff(); 02655 }/*end if*/ 02656 #endif // KHTML_NO_CARET 02657 } 02658 02659 bool KHTMLPart::isCaretMode() const 02660 { 02661 return d->m_caretMode; 02662 } 02663 02664 void KHTMLPart::setEditable(bool enable) 02665 { 02666 #ifndef KHTML_NO_CARET 02667 if (isEditable() == enable) return; 02668 d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable); 02669 // FIXME: this won't work on frames as expected 02670 if (!isCaretMode()) { 02671 if (enable) { 02672 view()->initCaret(true); 02673 view()->ensureCaretVisible(); 02674 } else 02675 view()->caretOff(); 02676 }/*end if*/ 02677 #endif // KHTML_NO_CARET 02678 } 02679 02680 bool KHTMLPart::isEditable() const 02681 { 02682 return d->m_designMode; 02683 } 02684 02685 void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection) 02686 { 02687 #ifndef KHTML_NO_CARET 02688 #if 0 02689 kdDebug(6200) << k_funcinfo << "node: " << node.handle() << " nodeName: " 02690 << node.nodeName().string() << " offset: " << offset 02691 << " extendSelection " << extendSelection << endl; 02692 #endif 02693 if (view()->moveCaretTo(node.handle(), offset, !extendSelection)) 02694 emitSelectionChanged(); 02695 view()->ensureCaretVisible(); 02696 #endif // KHTML_NO_CARET 02697 } 02698 02699 KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const 02700 { 02701 #ifndef KHTML_NO_CARET 02702 return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused(); 02703 #else // KHTML_NO_CARET 02704 return CaretInvisible; 02705 #endif // KHTML_NO_CARET 02706 } 02707 02708 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy) 02709 { 02710 #ifndef KHTML_NO_CARET 02711 view()->setCaretDisplayPolicyNonFocused(policy); 02712 #endif // KHTML_NO_CARET 02713 } 02714 02715 void KHTMLPart::setCaretVisible(bool show) 02716 { 02717 #ifndef KHTML_NO_CARET 02718 if (show) { 02719 02720 NodeImpl *caretNode = xmlDocImpl()->focusNode(); 02721 if (isCaretMode() || isEditable() 02722 || (caretNode && caretNode->contentEditable())) { 02723 view()->caretOn(); 02724 }/*end if*/ 02725 02726 } else { 02727 02728 view()->caretOff(); 02729 02730 }/*end if*/ 02731 #endif // KHTML_NO_CARET 02732 } 02733 02734 void KHTMLPart::findTextBegin() 02735 { 02736 d->m_findPos = -1; 02737 d->m_findNode = 0; 02738 d->m_findPosEnd = -1; 02739 d->m_findNodeEnd= 0; 02740 d->m_findPosStart = -1; 02741 d->m_findNodeStart = 0; 02742 d->m_findNodePrevious = 0; 02743 delete d->m_find; 02744 d->m_find = 0L; 02745 } 02746 02747 bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor ) 02748 { 02749 if ( !d->m_doc ) 02750 return false; 02751 02752 DOM::NodeImpl* firstNode = 0L; 02753 if (d->m_doc->isHTMLDocument()) 02754 firstNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body(); 02755 else 02756 firstNode = d->m_doc; 02757 02758 if ( !firstNode ) 02759 { 02760 //kdDebug(6050) << k_funcinfo << "no first node (body or doc) -> return false" << endl; 02761 return false; 02762 } 02763 if ( firstNode->id() == ID_FRAMESET ) 02764 { 02765 //kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl; 02766 return false; 02767 } 02768 02769 if ( selection && hasSelection() ) 02770 { 02771 //kdDebug(6050) << k_funcinfo << "using selection" << endl; 02772 if ( !fromCursor ) 02773 { 02774 d->m_findNode = reverse ? d->m_selectionEnd.handle() : d->m_selectionStart.handle(); 02775 d->m_findPos = reverse ? d->m_endOffset : d->m_startOffset; 02776 } 02777 d->m_findNodeEnd = reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle(); 02778 d->m_findPosEnd = reverse ? d->m_startOffset : d->m_endOffset; 02779 d->m_findNodeStart = !reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle(); 02780 d->m_findPosStart = !reverse ? d->m_startOffset : d->m_endOffset; 02781 d->m_findNodePrevious = d->m_findNodeStart; 02782 } 02783 else // whole document 02784 { 02785 //kdDebug(6050) << k_funcinfo << "whole doc" << endl; 02786 if ( !fromCursor ) 02787 { 02788 d->m_findNode = firstNode; 02789 d->m_findPos = reverse ? -1 : 0; 02790 } 02791 d->m_findNodeEnd = reverse ? firstNode : 0; 02792 d->m_findPosEnd = reverse ? 0 : -1; 02793 d->m_findNodeStart = !reverse ? firstNode : 0; 02794 d->m_findPosStart = !reverse ? 0 : -1; 02795 d->m_findNodePrevious = d->m_findNodeStart; 02796 if ( reverse ) 02797 { 02798 // Need to find out the really last object, to start from it 02799 khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0; 02800 if ( obj ) 02801 { 02802 // find the last object in the render tree 02803 while ( obj->lastChild() ) 02804 { 02805 obj = obj->lastChild(); 02806 } 02807 // now get the last object with a NodeImpl associated 02808 while ( !obj->element() && obj->objectAbove() ) 02809 { 02810 obj = obj->objectAbove(); 02811 } 02812 d->m_findNode = obj->element(); 02813 } 02814 } 02815 } 02816 return true; 02817 } 02818 02819 // Old method (its API limits the available features - remove in KDE-4) 02820 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp ) 02821 { 02822 if ( !initFindNode( false, !forward, d->m_findNode ) ) 02823 return false; 02824 while(1) 02825 { 02826 if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() ) 02827 { 02828 DOMString nodeText = d->m_findNode->nodeValue(); 02829 DOMStringImpl *t = nodeText.implementation(); 02830 QConstString s(t->s, t->l); 02831 02832 int matchLen = 0; 02833 if ( isRegExp ) { 02834 QRegExp matcher( str ); 02835 matcher.setCaseSensitive( caseSensitive ); 02836 d->m_findPos = matcher.search(s.string(), d->m_findPos+1); 02837 if ( d->m_findPos != -1 ) 02838 matchLen = matcher.matchedLength(); 02839 } 02840 else { 02841 d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive); 02842 matchLen = str.length(); 02843 } 02844 02845 if(d->m_findPos != -1) 02846 { 02847 int x = 0, y = 0; 02848 if(static_cast<khtml::RenderText *>(d->m_findNode->renderer()) 02849 ->posOfChar(d->m_findPos, x, y)) 02850 d->m_view->setContentsPos(x-50, y-50); 02851 02852 d->m_selectionStart = d->m_findNode; 02853 d->m_startOffset = d->m_findPos; 02854 d->m_selectionEnd = d->m_findNode; 02855 d->m_endOffset = d->m_findPos + matchLen; 02856 d->m_startBeforeEnd = true; 02857 02858 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset, 02859 d->m_selectionEnd.handle(), d->m_endOffset ); 02860 emitSelectionChanged(); 02861 return true; 02862 } 02863 } 02864 d->m_findPos = -1; 02865 02866 NodeImpl *next; 02867 02868 if ( forward ) 02869 { 02870 next = d->m_findNode->firstChild(); 02871 02872 if(!next) next = d->m_findNode->nextSibling(); 02873 while(d->m_findNode && !next) { 02874 d->m_findNode = d->m_findNode->parentNode(); 02875 if( d->m_findNode ) { 02876 next = d->m_findNode->nextSibling(); 02877 } 02878 } 02879 } 02880 else 02881 { 02882 next = d->m_findNode->lastChild(); 02883 02884 if (!next ) next = d->m_findNode->previousSibling(); 02885 while ( d->m_findNode && !next ) 02886 { 02887 d->m_findNode = d->m_findNode->parentNode(); 02888 if( d->m_findNode ) 02889 { 02890 next = d->m_findNode->previousSibling(); 02891 } 02892 } 02893 } 02894 02895 d->m_findNode = next; 02896 if(!d->m_findNode) return false; 02897 } 02898 } 02899 02900 02901 void KHTMLPart::slotFind() 02902 { 02903 KParts::ReadOnlyPart *part = currentFrame(); 02904 if (!part) 02905 return; 02906 if (!part->inherits("KHTMLPart") ) 02907 { 02908 kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl; 02909 return; 02910 } 02911 static_cast<KHTMLPart *>( part )->findText(); 02912 } 02913 02914 void KHTMLPart::slotFindNext() 02915 { 02916 KParts::ReadOnlyPart *part = currentFrame(); 02917 if (!part) 02918 return; 02919 if (!part->inherits("KHTMLPart") ) 02920 { 02921 kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl; 02922 return; 02923 } 02924 static_cast<KHTMLPart *>( part )->findTextNext(); 02925 } 02926 02927 void KHTMLPart::slotFindPrev() 02928 { 02929 KParts::ReadOnlyPart *part = currentFrame(); 02930 if (!part) 02931 return; 02932 if (!part->inherits("KHTMLPart") ) 02933 { 02934 kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl; 02935 return; 02936 } 02937 static_cast<KHTMLPart *>( part )->findTextNext( true ); // reverse 02938 } 02939 02940 void KHTMLPart::slotFindDone() 02941 { 02942 // ### remove me 02943 } 02944 02945 void KHTMLPart::slotFindAheadText() 02946 { 02947 #ifndef KHTML_NO_TYPE_AHEAD_FIND 02948 KParts::ReadOnlyPart *part = currentFrame(); 02949 if (!part) 02950 return; 02951 if (!part->inherits("KHTMLPart") ) 02952 { 02953 kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl; 02954 return; 02955 } 02956 static_cast<KHTMLPart *>( part )->view()->startFindAhead( false ); 02957 #endif // KHTML_NO_TYPE_AHEAD_FIND 02958 } 02959 02960 void KHTMLPart::slotFindAheadLink() 02961 { 02962 #ifndef KHTML_NO_TYPE_AHEAD_FIND 02963 KParts::ReadOnlyPart *part = currentFrame(); 02964 if (!part) 02965 return; 02966 if (!part->inherits("KHTMLPart") ) 02967 { 02968 kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl; 02969 return; 02970 } 02971 static_cast<KHTMLPart *>( part )->view()->startFindAhead( true ); 02972 #endif // KHTML_NO_TYPE_AHEAD_FIND 02973 } 02974 02975 void KHTMLPart::enableFindAheadActions( bool enable ) 02976 { 02977 // only the topmost one has shortcuts 02978 KHTMLPart* p = this; 02979 while( p->parentPart()) 02980 p = p->parentPart(); 02981 p->d->m_paFindAheadText->setEnabled( enable ); 02982 p->d->m_paFindAheadLinks->setEnabled( enable ); 02983 } 02984 02985 void KHTMLPart::slotFindDialogDestroyed() 02986 { 02987 d->m_lastFindState.options = d->m_findDialog->options(); 02988 d->m_lastFindState.history = d->m_findDialog->findHistory(); 02989 d->m_findDialog->deleteLater(); 02990 d->m_findDialog = 0L; 02991 } 02992 02993 void KHTMLPart::findText() 02994 { 02995 // First do some init to make sure we can search in this frame 02996 if ( !d->m_doc ) 02997 return; 02998 02999 // Raise if already opened 03000 if ( d->m_findDialog ) 03001 { 03002 KWin::activateWindow( d->m_findDialog->winId() ); 03003 return; 03004 } 03005 03006 // The lineedit of the dialog would make khtml lose its selection, otherwise 03007 #ifndef QT_NO_CLIPBOARD 03008 disconnect( kapp->clipboard(), SIGNAL(selectionChanged()), this, SLOT(slotClearSelection()) ); 03009 #endif 03010 03011 // Now show the dialog in which the user can choose options. 03012 d->m_findDialog = new KFindDialog( false /*non-modal*/, widget(), "khtmlfind" ); 03013 d->m_findDialog->setHasSelection( hasSelection() ); 03014 d->m_findDialog->setHasCursor( d->m_findNode != 0 ); 03015 if ( d->m_findNode ) // has a cursor -> default to 'FromCursor' 03016 d->m_lastFindState.options |= KFindDialog::FromCursor; 03017 03018 // TODO? optionsDialog.setPattern( d->m_lastFindState.text ); 03019 d->m_findDialog->setFindHistory( d->m_lastFindState.history ); 03020 d->m_findDialog->setOptions( d->m_lastFindState.options ); 03021 03022 d->m_lastFindState.options = -1; // force update in findTextNext 03023 d->m_lastFindState.last_dir = -1; 03024 03025 d->m_findDialog->show(); 03026 connect( d->m_findDialog, SIGNAL(okClicked()), this, SLOT(slotFindNext()) ); 03027 connect( d->m_findDialog, SIGNAL(finished()), this, SLOT(slotFindDialogDestroyed()) ); 03028 03029 findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog ); 03030 } 03031 03032 void KHTMLPart::findText( const QString &str, long options, QWidget *parent, KFindDialog *findDialog ) 03033 { 03034 // First do some init to make sure we can search in this frame 03035 if ( !d->m_doc ) 03036 return; 03037 03038 #ifndef QT_NO_CLIPBOARD 03039 connect( kapp->clipboard(), SIGNAL(selectionChanged()), SLOT(slotClearSelection()) ); 03040 #endif 03041 03042 // Create the KFind object 03043 delete d->m_find; 03044 d->m_find = new KFind( str, options, parent, findDialog ); 03045 d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up 03046 connect( d->m_find, SIGNAL( highlight( const QString &, int, int ) ), 03047 this, SLOT( slotHighlight( const QString &, int, int ) ) ); 03048 //connect(d->m_find, SIGNAL( findNext() ), 03049 // this, SLOT( slotFindNext() ) ); 03050 03051 if ( !findDialog ) 03052 { 03053 d->m_lastFindState.options = options; 03054 initFindNode( options & KFindDialog::SelectedText, 03055 options & KFindDialog::FindBackwards, 03056 options & KFindDialog::FromCursor ); 03057 } 03058 } 03059 03060 bool KHTMLPart::findTextNext() 03061 { 03062 return findTextNext( false ); 03063 } 03064 03065 // New method 03066 bool KHTMLPart::findTextNext( bool reverse ) 03067 { 03068 if (!d->m_find) 03069 { 03070 // We didn't show the find dialog yet, let's do it then (#49442) 03071 findText(); 03072 return false; 03073 } 03074 03075 view()->updateFindAheadTimeout(); 03076 long options = 0; 03077 if ( d->m_findDialog ) // 0 when we close the dialog 03078 { 03079 if ( d->m_find->pattern() != d->m_findDialog->pattern() ) { 03080 d->m_find->setPattern( d->m_findDialog->pattern() ); 03081 d->m_find->resetCounts(); 03082 } 03083 options = d->m_findDialog->options(); 03084 if ( d->m_lastFindState.options != options ) 03085 { 03086 d->m_find->setOptions( options ); 03087 03088 if ( options & KFindDialog::SelectedText ) 03089 Q_ASSERT( hasSelection() ); 03090 03091 long difference = d->m_lastFindState.options ^ options; 03092 if ( difference & (KFindDialog::SelectedText | KFindDialog::FromCursor ) ) 03093 { 03094 // Important options changed -> reset search range 03095 (void) initFindNode( options & KFindDialog::SelectedText, 03096 options & KFindDialog::FindBackwards, 03097 options & KFindDialog::FromCursor ); 03098 } 03099 d->m_lastFindState.options = options; 03100 } 03101 } else 03102 options = d->m_lastFindState.options; 03103 if( reverse ) 03104 options = options ^ KFindDialog::FindBackwards; 03105 if( d->m_find->options() != options ) 03106 d->m_find->setOptions( options ); 03107 03108 // Changing find direction. Start and end nodes must be switched. 03109 // Additionally since d->m_findNode points after the last node 03110 // that was searched, it needs to be "after" it in the opposite direction. 03111 if( d->m_lastFindState.last_dir != -1 03112 && bool( d->m_lastFindState.last_dir ) != bool( options & KFindDialog::FindBackwards )) 03113 { 03114 qSwap( d->m_findNodeEnd, d->m_findNodeStart ); 03115 qSwap( d->m_findPosEnd, d->m_findPosStart ); 03116 qSwap( d->m_findNode, d->m_findNodePrevious ); 03117 // d->m_findNode now point at the end of the last searched line - advance one node 03118 khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0; 03119 khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0; 03120 if ( obj == end ) 03121 obj = 0L; 03122 else if ( obj ) 03123 { 03124 do { 03125 obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow(); 03126 } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) ); 03127 } 03128 if ( obj ) 03129 d->m_findNode = obj->element(); 03130 else 03131 d->m_findNode = 0; 03132 } 03133 d->m_lastFindState.last_dir = ( options & KFindDialog::FindBackwards ) ? 1 : 0; 03134 03135 KFind::Result res = KFind::NoMatch; 03136 khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0; 03137 khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0; 03138 khtml::RenderTextArea *tmpTextArea=0L; 03139 //kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl; 03140 while( res == KFind::NoMatch ) 03141 { 03142 if ( d->m_find->needData() ) 03143 { 03144 if ( !obj ) { 03145 //kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl; 03146 break; // we're done 03147 } 03148 //kdDebug(6050) << k_funcinfo << " gathering data" << endl; 03149 // First make up the QString for the current 'line' (i.e. up to \n) 03150 // We also want to remember the DOMNode for every portion of the string. 03151 // We store this in an index->node list. 03152 03153 d->m_stringPortions.clear(); 03154 bool newLine = false; 03155 QString str; 03156 DOM::NodeImpl* lastNode = d->m_findNode; 03157 while ( obj && !newLine ) 03158 { 03159 // Grab text from render object 03160 QString s; 03161 bool renderAreaText = obj->parent() && (QCString(obj->parent()->renderName())== "RenderTextArea"); 03162 bool renderLineText = (QCString(obj->renderName())== "RenderLineEdit"); 03163 if ( renderAreaText ) 03164 { 03165 khtml::RenderTextArea *parent= static_cast<khtml::RenderTextArea *>(obj->parent()); 03166 s = parent->text(); 03167 s = s.replace(0xa0, ' '); 03168 tmpTextArea = parent; 03169 } 03170 else if ( renderLineText ) 03171 { 03172 khtml::RenderLineEdit *parentLine= static_cast<khtml::RenderLineEdit *>(obj); 03173 if (parentLine->widget()->echoMode() == QLineEdit::Normal) 03174 s = parentLine->widget()->text(); 03175 s = s.replace(0xa0, ' '); 03176 } 03177 else if ( obj->isText() ) 03178 { 03179 bool isLink = false; 03180 03181 // checks whether the node has a <A> parent 03182 if ( options & FindLinksOnly ) 03183 { 03184 DOM::NodeImpl *parent = obj->element(); 03185 while ( parent ) 03186 { 03187 if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A ) 03188 { 03189 isLink = true; 03190 break; 03191 } 03192 parent = parent->parentNode(); 03193 } 03194 } 03195 else 03196 { 03197 isLink = true; 03198 } 03199 03200 if ( isLink && obj->parent()!=tmpTextArea ) 03201 { 03202 s = static_cast<khtml::RenderText *>(obj)->data().string(); 03203 s = s.replace(0xa0, ' '); 03204 } 03205 } 03206 else if ( obj->isBR() ) 03207 s = '\n'; 03208 else if ( !obj->isInline() && !str.isEmpty() ) 03209 s = '\n'; 03210 03211 if ( lastNode == d->m_findNodeEnd ) 03212 s.truncate( d->m_findPosEnd ); 03213 if ( !s.isEmpty() ) 03214 { 03215 newLine = s.find( '\n' ) != -1; // did we just get a newline? 03216 if( !( options & KFindDialog::FindBackwards )) 03217 { 03218 //kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode << endl; 03219 d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( str.length(), lastNode ) ); 03220 str += s; 03221 } 03222 else // KFind itself can search backwards, so str must not be built backwards 03223 { 03224 for( QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin(); 03225 it != d->m_stringPortions.end(); 03226 ++it ) 03227 (*it).index += s.length(); 03228 d->m_stringPortions.prepend( KHTMLPartPrivate::StringPortion( 0, lastNode ) ); 03229 str.prepend( s ); 03230 } 03231 } 03232 // Compare obj and end _after_ we processed the 'end' node itself 03233 if ( obj == end ) 03234 obj = 0L; 03235 else 03236 { 03237 // Move on to next object (note: if we found a \n already, then obj (and lastNode) 03238 // will point to the _next_ object, i.e. they are in advance. 03239 do { 03240 // We advance until the next RenderObject that has a NodeImpl as its element(). 03241 // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck 03242 // on that object forever... 03243 obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow(); 03244 } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) ); 03245 } 03246 if ( obj ) 03247 lastNode = obj->element(); 03248 else 03249 lastNode = 0; 03250 } // end while 03251 //kdDebug()<<" str : "<<str<<endl; 03252 if ( !str.isEmpty() ) 03253 { 03254 d->m_find->setData( str, d->m_findPos ); 03255 } 03256 03257 d->m_findPos = -1; // not used during the findnext loops. Only during init. 03258 d->m_findNodePrevious = d->m_findNode; 03259 d->m_findNode = lastNode; 03260 } 03261 if ( !d->m_find->needData() ) // happens if str was empty 03262 { 03263 // Let KFind inspect the text fragment, and emit highlighted if a match is found 03264 res = d->m_find->find(); 03265 } 03266 } // end while 03267 03268 if ( res == KFind::NoMatch ) // i.e. we're done 03269 { 03270 kdDebug() << "No more matches." << endl; 03271 if ( !(options & FindNoPopups) && d->m_find->shouldRestart() ) 03272 { 03273 //kdDebug(6050) << "Restarting" << endl; 03274 initFindNode( false, options & KFindDialog::FindBackwards, false ); 03275 d->m_find->resetCounts(); 03276 findTextNext( reverse ); 03277 } 03278 else // really done 03279 { 03280 //kdDebug(6050) << "Finishing" << endl; 03281 //delete d->m_find; 03282 //d->m_find = 0L; 03283 initFindNode( false, options & KFindDialog::FindBackwards, false ); 03284 d->m_find->resetCounts(); 03285 slotClearSelection(); 03286 } 03287 kdDebug() << "Dialog closed." << endl; 03288 } 03289 03290 return res == KFind::Match; 03291 } 03292 03293 void KHTMLPart::slotHighlight( const QString& /*text*/, int index, int length ) 03294 { 03295 //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl; 03296 QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin(); 03297 const QValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end(); 03298 QValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it; 03299 // We stop at the first portion whose index is 'greater than', and then use the previous one 03300 while ( it != itEnd && (*it).index <= index ) 03301 { 03302 prev = it; 03303 ++it; 03304 } 03305 Q_ASSERT ( prev != itEnd ); 03306 DOM::NodeImpl* node = (*prev).node; 03307 Q_ASSERT( node ); 03308 03309 d->m_selectionStart = node; 03310 d->m_startOffset = index - (*prev).index; 03311 03312 khtml::RenderObject* obj = node->renderer(); 03313 khtml::RenderTextArea *parent = 0L; 03314 khtml::RenderLineEdit *parentLine = 0L; 03315 bool renderLineText =false; 03316 03317 QRect highlightedRect; 03318 bool renderAreaText =false; 03319 Q_ASSERT( obj ); 03320 if ( obj ) 03321 { 03322 int x = 0, y = 0; 03323 renderAreaText = (QCString(obj->parent()->renderName())== "RenderTextArea"); 03324 renderLineText = (QCString(obj->renderName())== "RenderLineEdit"); 03325 03326 03327 if( renderAreaText ) 03328 parent= static_cast<khtml::RenderTextArea *>(obj->parent()); 03329 if ( renderLineText ) 03330 parentLine= static_cast<khtml::RenderLineEdit *>(obj); 03331 if ( !renderLineText ) 03332 //if (static_cast<khtml::RenderText *>(node->renderer()) 03333 // ->posOfChar(d->m_startOffset, x, y)) 03334 { 03335 int dummy; 03336 static_cast<khtml::RenderText *>(node->renderer()) 03337 ->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar 03338 //kdDebug(6050) << "topleft: " << x << "," << y << endl; 03339 if ( x != -1 || y != -1 ) 03340 { 03341 int gox = d->m_view->contentsX(); 03342 if (x+50 > d->m_view->contentsX() + d->m_view->visibleWidth()) 03343 gox = x - d->m_view->visibleWidth() + 50; 03344 if (x-10 < d->m_view->contentsX()) 03345 gox = x - d->m_view->visibleWidth() - 10; 03346 if (gox < 0) gox = 0; 03347 d->m_view->setContentsPos(gox, y-50); 03348 highlightedRect.setTopLeft( d->m_view->mapToGlobal(QPoint(x, y)) ); 03349 } 03350 } 03351 } 03352 // Now look for end node 03353 it = prev; // no need to start from beginning again 03354 while ( it != itEnd && (*it).index < index + length ) 03355 { 03356 prev = it; 03357 ++it; 03358 } 03359 Q_ASSERT ( prev != itEnd ); 03360 03361 d->m_selectionEnd = (*prev).node; 03362 d->m_endOffset = index + length - (*prev).index; 03363 d->m_startBeforeEnd = true; 03364 03365 // if the selection is limited to a single link, that link gets focus 03366 if(d->m_selectionStart == d->m_selectionEnd) 03367 { 03368 bool isLink = false; 03369 03370 // checks whether the node has a <A> parent 03371 DOM::NodeImpl *parent = d->m_selectionStart.handle(); 03372 while ( parent ) 03373 { 03374 if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A ) 03375 { 03376 isLink = true; 03377 break; 03378 } 03379 parent = parent->parentNode(); 03380 } 03381 03382 if(isLink == true) 03383 { 03384 d->m_doc->setFocusNode( parent ); 03385 } 03386 } 03387 03388 #if 0 03389 kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " << 03390 d->m_selectionEnd.handle() << "," << d->m_endOffset << endl; 03391 it = d->m_stringPortions.begin(); 03392 for ( ; it != d->m_stringPortions.end() ; ++it ) 03393 kdDebug(6050) << " StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl; 03394 #endif 03395 if( renderAreaText ) 03396 { 03397 if( parent ) 03398 parent->highLightWord( length, d->m_endOffset-length ); 03399 } 03400 else if ( renderLineText ) 03401 { 03402 if( parentLine ) 03403 parentLine->highLightWord( length, d->m_endOffset-length ); 03404 } 03405 else 03406 { 03407 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset, 03408 d->m_selectionEnd.handle(), d->m_endOffset ); 03409 if (d->m_selectionEnd.handle()->renderer() ) 03410 { 03411 int x, y, height, dummy; 03412 static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer()) 03413 ->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar 03414 //kdDebug(6050) << "bottomright: " << x << "," << y+height << endl; 03415 if ( x != -1 || y != -1 ) 03416 { 03417 // if ( static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer()) 03418 // ->posOfChar(d->m_endOffset-1, x, y)) 03419 highlightedRect.setBottomRight( d->m_view->mapToGlobal( QPoint(x, y+height) ) ); 03420 } 03421 } 03422 } 03423 emitSelectionChanged(); 03424 03425 // make the finddialog move away from the selected area 03426 if ( d->m_findDialog && !highlightedRect.isNull() ) 03427 { 03428 highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() ); 03429 //kdDebug(6050) << "avoiding " << highlightedRect << endl; 03430 KDialog::avoidArea( d->m_findDialog, highlightedRect ); 03431 } 03432 } 03433 03434 QString KHTMLPart::selectedTextAsHTML() const 03435 { 03436 if(!hasSelection()) { 03437 kdDebug() << "selectedTextAsHTML(): selection is not valid. Returning empty selection" << endl; 03438 return QString::null; 03439 } 03440 if(d->m_startOffset < 0 || d->m_endOffset <0) { 03441 kdDebug() << "invalid values for end/startOffset " << d->m_startOffset << " " << d->m_endOffset << endl; 03442 return QString::null; 03443 } 03444 DOM::Range r = selection(); 03445 if(r.isNull() || r.isDetached()) 03446 return QString::null; 03447 int exceptioncode = 0; //ignore the result 03448 return r.handle()->toHTML(exceptioncode).string(); 03449 } 03450 03451 QString KHTMLPart::selectedText() const 03452 { 03453 bool hasNewLine = true; 03454 bool seenTDTag = false; 03455 QString text; 03456 DOM::Node n = d->m_selectionStart; 03457 while(!n.isNull()) { 03458 if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) { 03459 DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString(); 03460 QString str(dstr->s, dstr->l); 03461 if(!str.isEmpty()) { 03462 if(seenTDTag) { 03463 text += " "; 03464 seenTDTag = false; 03465 } 03466 hasNewLine = false; 03467 if(n == d->m_selectionStart && n == d->m_selectionEnd) 03468 text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset); 03469 else if(n == d->m_selectionStart) 03470 text = str.mid(d->m_startOffset); 03471 else if(n == d->m_selectionEnd) 03472 text += str.left(d->m_endOffset); 03473 else 03474 text += str; 03475 } 03476 } 03477 else { 03478 // This is our simple HTML -> ASCII transformation: 03479 unsigned short id = n.elementId(); 03480 switch(id) { 03481 case ID_TEXTAREA: 03482 text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string(); 03483 break; 03484 case ID_INPUT: 03485 if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD) 03486 text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string(); 03487 break; 03488 case ID_SELECT: 03489 text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string(); 03490 break; 03491 case ID_BR: 03492 text += "\n"; 03493 hasNewLine = true; 03494 break; 03495 case ID_IMG: 03496 text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string(); 03497 break; 03498 case ID_TD: 03499 break; 03500 case ID_TH: 03501 case ID_HR: 03502 case ID_OL: 03503 case ID_UL: 03504 case ID_LI: 03505 case ID_DD: 03506 case ID_DL: 03507 case ID_DT: 03508 case ID_PRE: 03509 case ID_BLOCKQUOTE: 03510 case ID_DIV: 03511 if (!hasNewLine) 03512 text += "\n"; 03513 hasNewLine = true; 03514 break; 03515 case ID_P: 03516 case ID_TR: 03517 case ID_H1: 03518 case ID_H2: 03519 case ID_H3: 03520 case ID_H4: 03521 case ID_H5: 03522 case ID_H6: 03523 if (!hasNewLine) 03524 text += "\n"; 03525 // text += "\n"; 03526 hasNewLine = true; 03527 break; 03528 } 03529 } 03530 if(n == d->m_selectionEnd) break; 03531 DOM::Node next = n.firstChild(); 03532 if(next.isNull()) next = n.nextSibling(); 03533 while( next.isNull() && !n.parentNode().isNull() ) { 03534 n = n.parentNode(); 03535 next = n.nextSibling(); 03536 unsigned short id = n.elementId(); 03537 switch(id) { 03538 case ID_TD: 03539 seenTDTag = true; //Add two spaces after a td if then followed by text. 03540 break; 03541 case ID_TH: 03542 case ID_HR: 03543 case ID_OL: 03544 case ID_UL: 03545 case ID_LI: 03546 case ID_DD: 03547 case ID_DL: 03548 case ID_DT: 03549 case ID_PRE: 03550 case ID_BLOCKQUOTE: 03551 case ID_DIV: 03552 seenTDTag = false; 03553 if (!hasNewLine) 03554 text += "\n"; 03555 hasNewLine = true; 03556 break; 03557 case ID_P: 03558 case ID_TR: 03559 case ID_H1: 03560 case ID_H2: 03561 case ID_H3: 03562 case ID_H4: 03563 case ID_H5: 03564 case ID_H6: 03565 if (!hasNewLine) 03566 text += "\n"; 03567 // text += "\n"; 03568 hasNewLine = true; 03569 break; 03570 } 03571 } 03572 03573 n = next; 03574 } 03575 03576 if(text.isEmpty()) 03577 return QString::null; 03578 03579 int start = 0; 03580 int end = text.length(); 03581 03582 // Strip leading LFs 03583 while ((start < end) && (text[start] == '\n')) 03584 ++start; 03585 03586 // Strip excessive trailing LFs 03587 while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n')) 03588 --end; 03589 03590 return text.mid(start, end-start); 03591 } 03592 03593 bool KHTMLPart::hasSelection() const 03594 { 03595 if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ) 03596 return false; 03597 if ( d->m_selectionStart == d->m_selectionEnd && 03598 d->m_startOffset == d->m_endOffset ) 03599 return false; // empty 03600 return true; 03601 } 03602 03603 DOM::Range KHTMLPart::selection() const 03604 { 03605 if( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ) 03606 return DOM::Range(); 03607 DOM::Range r = document().createRange(); 03608 RangeImpl *rng = r.handle(); 03609 int exception = 0; 03610 NodeImpl *n = d->m_selectionStart.handle(); 03611 if(!n->parentNode() || 03612 !n->renderer() || 03613 (!n->renderer()->isReplaced() && !n->renderer()->isBR())) { 03614 rng->setStart( n, d->m_startOffset, exception ); 03615 if(exception) { 03616 kdDebug(6000) << "1 -selection() threw the exception " << exception << ". Returning empty range." << endl; 03617 return DOM::Range(); 03618 } 03619 } else { 03620 int o_start = 0; 03621 while ((n = n->previousSibling())) 03622 o_start++; 03623 rng->setStart( d->m_selectionStart.parentNode().handle(), o_start + d->m_startOffset, exception ); 03624 if(exception) { 03625 kdDebug(6000) << "2 - selection() threw the exception " << exception << ". Returning empty range." << endl; 03626 return DOM::Range(); 03627 } 03628 03629 } 03630 03631 n = d->m_selectionEnd.handle(); 03632 if(!n->parentNode() || 03633 !n->renderer() || 03634 (!n->renderer()->isReplaced() && !n->renderer()->isBR())) { 03635 03636 rng->setEnd( n, d->m_endOffset, exception ); 03637 if(exception) { 03638 kdDebug(6000) << "3 - selection() threw the exception " << exception << ". Returning empty range." << endl; 03639 return DOM::Range(); 03640 } 03641 03642 } else { 03643 int o_end = 0; 03644 while ((n = n->previousSibling())) 03645 o_end++; 03646 rng->setEnd( d->m_selectionEnd.parentNode().handle(), o_end + d->m_endOffset, exception); 03647 if(exception) { 03648 kdDebug(6000) << "4 - selection() threw the exception " << exception << ". Returning empty range." << endl; 03649 return DOM::Range(); 03650 } 03651 03652 } 03653 03654 return r; 03655 } 03656 03657 void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const 03658 { 03659 s = d->m_selectionStart; 03660 so = d->m_startOffset; 03661 e = d->m_selectionEnd; 03662 eo = d->m_endOffset; 03663 } 03664 03665 void KHTMLPart::setSelection( const DOM::Range &r ) 03666 { 03667 // Quick-fix: a collapsed range shouldn't select the whole node. 03668 // The real problem is in RenderCanvas::setSelection though (when index==0 the whole node is selected). 03669 if ( r.collapsed() ) 03670 slotClearSelection(); 03671 else { 03672 d->m_selectionStart = r.startContainer(); 03673 d->m_startOffset = r.startOffset(); 03674 d->m_selectionEnd = r.endContainer(); 03675 d->m_endOffset = r.endOffset(); 03676 d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset, 03677 d->m_selectionEnd.handle(),d->m_endOffset); 03678 #ifndef KHTML_NO_CARET 03679 bool v = d->m_view->placeCaret(); 03680 emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset()); 03681 #endif 03682 } 03683 } 03684 03685 void KHTMLPart::slotClearSelection() 03686 { 03687 bool hadSelection = hasSelection(); 03688 #ifndef KHTML_NO_CARET 03689 //kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle() 03690 // << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl; 03691 // nothing, leave selection parameters as is 03692 #else 03693 d->m_selectionStart = 0; 03694 d->m_startOffset = 0; 03695 d->m_selectionEnd = 0; 03696 d->m_endOffset = 0; 03697 #endif 03698 if ( d->m_doc ) d->m_doc->clearSelection(); 03699 if ( hadSelection ) 03700 emitSelectionChanged(); 03701 #ifndef KHTML_NO_CARET 03702 bool v = d->m_view->placeCaret(); 03703 emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset()); 03704 #endif 03705 } 03706 03707 void KHTMLPart::resetHoverText() 03708 { 03709 if( !d->m_overURL.isEmpty() ) // Only if we were showing a link 03710 { 03711 d->m_overURL = d->m_overURLTarget = QString::null; 03712 emit onURL( QString::null ); 03713 // revert to default statusbar text 03714 setStatusBarText(QString::null, BarHoverText); 03715 emit d->m_extension->mouseOverInfo(0); 03716 } 03717 } 03718 03719 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ ) 03720 { 03721 KURL u = completeURL(url); 03722 03723 // special case for <a href=""> 03724 if ( url.isEmpty() ) 03725 u.setFileName( url ); 03726 03727 emit onURL( url ); 03728 03729 if ( url.isEmpty() ) { 03730 setStatusBarText(u.htmlURL(), BarHoverText); 03731 return; 03732 } 03733 03734 if (url.find( QString::fromLatin1( "javascript:" ),0, false ) == 0 ) { 03735 QString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) ); 03736 jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long 03737 if (url.startsWith("javascript:window.open")) 03738 jscode += i18n(" (In new window)"); 03739 setStatusBarText( QStyleSheet::escape( jscode ), BarHoverText ); 03740 return; 03741 } 03742 03743 KFileItem item(u, QString::null, KFileItem::Unknown); 03744 emit d->m_extension->mouseOverInfo(&item); 03745 03746 QString com; 03747 03748 KMimeType::Ptr typ = KMimeType::findByURL( u ); 03749 03750 if ( typ ) 03751 com = typ->comment( u, false ); 03752 03753 if ( !u.isValid() ) { 03754 setStatusBarText(u.htmlURL(), BarHoverText); 03755 return; 03756 } 03757 03758 if ( u.isLocalFile() ) 03759 { 03760 // TODO : use KIO::stat() and create a KFileItem out of its result, 03761 // to use KFileItem::statusBarText() 03762 QCString path = QFile::encodeName( u.path() ); 03763 03764 struct stat buff; 03765 bool ok = !stat( path.data(), &buff ); 03766 03767 struct stat lbuff; 03768 if (ok) ok = !lstat( path.data(), &lbuff ); 03769 03770 QString text = u.htmlURL(); 03771 QString text2 = text; 03772 03773 if (ok && S_ISLNK( lbuff.st_mode ) ) 03774 { 03775 QString tmp; 03776 if ( com.isNull() ) 03777 tmp = i18n( "Symbolic Link"); 03778 else 03779 tmp = i18n("%1 (Link)").arg(com); 03780 char buff_two[1024]; 03781 text += " -> "; 03782 int n = readlink ( path.data(), buff_two, 1022); 03783 if (n == -1) 03784 { 03785 text2 += " "; 03786 text2 += tmp; 03787 setStatusBarText(text2, BarHoverText); 03788 return; 03789 } 03790 buff_two[n] = 0; 03791 03792 text += buff_two; 03793 text += " "; 03794 text += tmp; 03795 } 03796 else if ( ok && S_ISREG( buff.st_mode ) ) 03797 { 03798 if (buff.st_size < 1024) 03799 text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%' 03800 else 03801 { 03802 float d = (float) buff.st_size/1024.0; 03803 text = i18n("%2 (%1 K)").arg(KGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f 03804 } 03805 text += " "; 03806 text += com; 03807 } 03808 else if ( ok && S_ISDIR( buff.st_mode ) ) 03809 { 03810 text += " "; 03811 text += com; 03812 } 03813 else 03814 { 03815 text += " "; 03816 text += com; 03817 } 03818 setStatusBarText(text, BarHoverText); 03819 } 03820 else 03821 { 03822 QString extra; 03823 if (target.lower() == "_blank") 03824 { 03825 extra = i18n(" (In new window)"); 03826 } 03827 else if (!target.isEmpty() && 03828 (target.lower() != "_top") && 03829 (target.lower() != "_self") && 03830 (target.lower() != "_parent")) 03831 { 03832 KHTMLPart *p = this; 03833 while (p->parentPart()) 03834 p = p->parentPart(); 03835 if (!p->frameExists(target)) 03836 extra = i18n(" (In new window)"); 03837 else 03838 extra = i18n(" (In other frame)"); 03839 } 03840 03841 if (u.protocol() == QString::fromLatin1("mailto")) { 03842 QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/; 03843 mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path()); 03844 QStringList queries = QStringList::split('&', u.query().mid(1)); 03845 QStringList::Iterator it = queries.begin(); 03846 const QStringList::Iterator itEnd = queries.end(); 03847 for (; it != itEnd; ++it) 03848 if ((*it).startsWith(QString::fromLatin1("subject="))) 03849 mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8)); 03850 else if ((*it).startsWith(QString::fromLatin1("cc="))) 03851 mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3)); 03852 else if ((*it).startsWith(QString::fromLatin1("bcc="))) 03853 mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4)); 03854 mailtoMsg = QStyleSheet::escape(mailtoMsg); 03855 mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString::null); 03856 setStatusBarText("<qt>"+mailtoMsg, BarHoverText); 03857 return; 03858 } 03859 // Is this check necessary at all? (Frerich) 03860 #if 0 03861 else if (u.protocol() == QString::fromLatin1("http")) { 03862 DOM::Node hrefNode = nodeUnderMouse().parentNode(); 03863 while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull()) 03864 hrefNode = hrefNode.parentNode(); 03865 03866 if (!hrefNode.isNull()) { 03867 DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG"); 03868 if (!hreflangNode.isNull()) { 03869 QString countryCode = hreflangNode.nodeValue().string().lower(); 03870 // Map the language code to an appropriate country code. 03871 if (countryCode == QString::fromLatin1("en")) 03872 countryCode = QString::fromLatin1("gb"); 03873 QString flagImg = QString::fromLatin1("<img src=%1>").arg( 03874 locate("locale", QString::fromLatin1("l10n/") 03875 + countryCode 03876 + QString::fromLatin1("/flag.png"))); 03877 emit setStatusBarText(flagImg + u.prettyURL() + extra); 03878 } 03879 } 03880 } 03881 #endif 03882 setStatusBarText(u.htmlURL() + extra, BarHoverText); 03883 } 03884 } 03885 03886 // 03887 // This executes in the active part on a click or other url selection action in 03888 // that active part. 03889 // 03890 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args ) 03891 { 03892 // The member var is so that slotRedirection still calls the virtual urlSelected 03893 // but is able to know if is opened a url. KDE4: just make urlSelected return a bool 03894 // and move the urlSelectedIntern code back here. 03895 d->m_urlSelectedOpenedURL = urlSelectedIntern( url, button, state, _target, args ); 03896 } 03897 03898 // Return value: true if an url was opened, false if not (e.g. error, or jumping to anchor) 03899 bool KHTMLPart::urlSelectedIntern( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args ) 03900 { 03901 bool hasTarget = false; 03902 03903 QString target = _target; 03904 if ( target.isEmpty() && d->m_doc ) 03905 target = d->m_doc->baseTarget(); 03906 if ( !target.isEmpty() ) 03907 hasTarget = true; 03908 03909 if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) 03910 { 03911 crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) ); 03912 return false; 03913 } 03914 03915 KURL cURL = completeURL(url); 03916 // special case for <a href=""> (IE removes filename, mozilla doesn't) 03917 if ( url.isEmpty() ) 03918 cURL.setFileName( url ); // removes filename 03919 03920 if ( !cURL.isValid() ) 03921 // ### ERROR HANDLING 03922 return false; 03923 03924 kdDebug(6050) << this << " urlSelected: complete URL:" << cURL.url() << " target=" << target << endl; 03925 03926 if ( state & ControlButton ) 03927 { 03928 args.setNewTab(true); 03929 emit d->m_extension->createNewWindow( cURL, args ); 03930 return true; 03931 } 03932 03933 if ( button == LeftButton && ( state & ShiftButton ) ) 03934 { 03935 KIO::MetaData metaData; 03936 metaData["referrer"] = d->m_referrer; 03937 KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData ); 03938 return false; 03939 } 03940 03941 if (!checkLinkSecurity(cURL, 03942 i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ), 03943 i18n( "Follow" ))) 03944 return false; 03945 03946 args.frameName = target; 03947 03948 args.metaData().insert("main_frame_request", 03949 parentPart() == 0 ? "TRUE":"FALSE"); 03950 args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip); 03951 args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert); 03952 args.metaData().insert("PropagateHttpHeader", "true"); 03953 args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE"); 03954 args.metaData().insert("ssl_activate_warnings", "TRUE"); 03955 03956 if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" ) 03957 { 03958 // unknown frame names should open in a new window. 03959 khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false ); 03960 if ( frame ) 03961 { 03962 args.metaData()["referrer"] = d->m_referrer; 03963 requestObject( frame, cURL, args ); 03964 return true; 03965 } 03966 } 03967 03968 if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer")) 03969 args.metaData()["referrer"] = d->m_referrer; 03970 03971 03972 if ( button == NoButton && (state & ShiftButton) && (state & ControlButton) ) 03973 { 03974 emit d->m_extension->createNewWindow( cURL, args ); 03975 return true; 03976 } 03977 03978 if ( state & ShiftButton) 03979 { 03980 KParts::WindowArgs winArgs; 03981 winArgs.lowerWindow = true; 03982 KParts::ReadOnlyPart *newPart = 0; 03983 emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart ); 03984 return true; 03985 } 03986 03987 //If we're asked to open up an anchor in the current URL, in current window, 03988 //merely gotoanchor, and do not reload the new page. Note that this does 03989 //not apply if the URL is the same page, but without a ref 03990 if (cURL.hasRef() && (!hasTarget || target == "_self")) 03991 { 03992 KURL curUrl = this->url(); 03993 if (urlcmp(cURL.url(), curUrl.url(), 03994 false, // ignore trailing / diff, IE does, even if FFox doesn't 03995 true)) // don't care if the ref changes! 03996 { 03997 m_url = cURL; 03998 emit d->m_extension->openURLNotify(); 03999 if ( !gotoAnchor( m_url.encodedHtmlRef()) ) 04000 gotoAnchor( m_url.htmlRef() ); 04001 emit d->m_extension->setLocationBarURL( m_url.prettyURL() ); 04002 return false; // we jumped, but we didn't open a URL 04003 } 04004 } 04005 04006 if ( !d->m_bComplete && !hasTarget ) 04007 closeURL(); 04008 04009 view()->viewport()->unsetCursor(); 04010 emit d->m_extension->openURLRequest( cURL, args ); 04011 return true; 04012 } 04013 04014 void KHTMLPart::slotViewDocumentSource() 04015 { 04016 KURL url(m_url); 04017 bool isTempFile = false; 04018 if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId)) 04019 { 04020 KTempFile sourceFile(QString::null, defaultExtension()); 04021 if (sourceFile.status() == 0) 04022 { 04023 KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream()); 04024 url = KURL(); 04025 url.setPath(sourceFile.name()); 04026 isTempFile = true; 04027 } 04028 } 04029 04030 (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile ); 04031 } 04032 04033 void KHTMLPart::slotViewPageInfo() 04034 { 04035 KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, WDestructiveClose); 04036 dlg->_close->setGuiItem(KStdGuiItem::close()); 04037 04038 if (d->m_doc) 04039 dlg->_title->setText(d->m_doc->title().string()); 04040 04041 // If it's a frame, set the caption to "Frame Information" 04042 if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) { 04043 dlg->setCaption(i18n("Frame Information")); 04044 } 04045 04046 QString editStr = QString::null; 04047 04048 if (!d->m_pageServices.isEmpty()) 04049 editStr = i18n(" <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices); 04050 04051 QString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 ); 04052 dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr); 04053 if (lastModified().isEmpty()) 04054 { 04055 dlg->_lastModified->hide(); 04056 dlg->_lmLabel->hide(); 04057 } 04058 else 04059 dlg->_lastModified->setText(lastModified()); 04060 04061 const QString& enc = encoding(); 04062 if (enc.isEmpty()) { 04063 dlg->_eLabel->hide(); 04064 dlg->_encoding->hide(); 04065 } else { 04066 dlg->_encoding->setText(enc); 04067 } 04068 /* populate the list view now */ 04069 const QStringList headers = QStringList::split("\n", d->m_httpHeaders); 04070 04071 QStringList::ConstIterator it = headers.begin(); 04072 const QStringList::ConstIterator itEnd = headers.end(); 04073 04074 for (; it != itEnd; ++it) { 04075 const QStringList header = QStringList::split(QRegExp(":[ ]+"), *it); 04076 if (header.count() != 2) 04077 continue; 04078 new QListViewItem(dlg->_headers, header[0], header[1]); 04079 } 04080 04081 dlg->show(); 04082 /* put no code here */ 04083 } 04084 04085 04086 void KHTMLPart::slotViewFrameSource() 04087 { 04088 KParts::ReadOnlyPart *frame = currentFrame(); 04089 if ( !frame ) 04090 return; 04091 04092 KURL url = frame->url(); 04093 bool isTempFile = false; 04094 if (!(url.isLocalFile()) && frame->inherits("KHTMLPart")) 04095 { 04096 long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId; 04097 04098 if (KHTMLPageCache::self()->isComplete(cacheId)) 04099 { 04100 KTempFile sourceFile(QString::null, defaultExtension()); 04101 if (sourceFile.status() == 0) 04102 { 04103 KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream()); 04104 url = KURL(); 04105 url.setPath(sourceFile.name()); 04106 isTempFile = true; 04107 } 04108 } 04109 } 04110 04111 (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile ); 04112 } 04113 04114 KURL KHTMLPart::backgroundURL() const 04115 { 04116 // ### what about XML documents? get from CSS? 04117 if (!d->m_doc || !d->m_doc->isHTMLDocument()) 04118 return KURL(); 04119 04120 QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string(); 04121 04122 return KURL( m_url, relURL ); 04123 } 04124 04125 void KHTMLPart::slotSaveBackground() 04126 { 04127 KIO::MetaData metaData; 04128 metaData["referrer"] = d->m_referrer; 04129 KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData ); 04130 } 04131 04132 void KHTMLPart::slotSaveDocument() 04133 { 04134 KURL srcURL( m_url ); 04135 04136 if ( srcURL.fileName(false).isEmpty() ) 04137 srcURL.setFileName( "index" + defaultExtension() ); 04138 04139 KIO::MetaData metaData; 04140 // Referre unknown? 04141 KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId ); 04142 } 04143 04144 void KHTMLPart::slotSecurity() 04145 { 04146 // kdDebug( 6050 ) << "Meta Data:" << endl 04147 // << d->m_ssl_peer_cert_subject 04148 // << endl 04149 // << d->m_ssl_peer_cert_issuer 04150 // << endl 04151 // << d->m_ssl_cipher 04152 // << endl 04153 // << d->m_ssl_cipher_desc 04154 // << endl 04155 // << d->m_ssl_cipher_version 04156 // << endl 04157 // << d->m_ssl_good_from 04158 // << endl 04159 // << d->m_ssl_good_until 04160 // << endl 04161 // << d->m_ssl_cert_state 04162 // << endl; 04163 04164 KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true ); 04165 04166 if (d->m_bSecurityInQuestion) 04167 kid->setSecurityInQuestion(true); 04168 04169 if (d->m_ssl_in_use) { 04170 KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit()); 04171 if (x) { 04172 // Set the chain back onto the certificate 04173 const QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain); 04174 QPtrList<KSSLCertificate> ncl; 04175 04176 ncl.setAutoDelete(true); 04177 QStringList::ConstIterator it = cl.begin(); 04178 const QStringList::ConstIterator itEnd = cl.end(); 04179 for (; it != itEnd; ++it) { 04180 KSSLCertificate* const y = KSSLCertificate::fromString((*it).local8Bit()); 04181 if (y) ncl.append(y); 04182 } 04183 04184 if (ncl.count() > 0) 04185 x->chain().setChain(ncl); 04186 04187 kid->setup(x, 04188 d->m_ssl_peer_ip, 04189 m_url.url(), 04190 d->m_ssl_cipher, 04191 d->m_ssl_cipher_desc, 04192 d->m_ssl_cipher_version, 04193 d->m_ssl_cipher_used_bits.toInt(), 04194 d->m_ssl_cipher_bits.toInt(), 04195 (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt() 04196 ); 04197 kid->exec(); 04198 delete x; 04199 } else kid->exec(); 04200 } else kid->exec(); 04201 } 04202 04203 void KHTMLPart::slotSaveFrame() 04204 { 04205 KParts::ReadOnlyPart *frame = currentFrame(); 04206 if ( !frame ) 04207 return; 04208 04209 KURL srcURL( frame->url() ); 04210 04211 if ( srcURL.fileName(false).isEmpty() ) 04212 srcURL.setFileName( "index" + defaultExtension() ); 04213 04214 KIO::MetaData metaData; 04215 // Referrer unknown? 04216 KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" ); 04217 } 04218 04219 void KHTMLPart::slotSetEncoding() 04220 { 04221 d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false ); 04222 d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false ); 04223 d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true ); 04224 04225 QString enc = KGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() ); 04226 setEncoding( enc, true ); 04227 } 04228 04229 void KHTMLPart::slotUseStylesheet() 04230 { 04231 if (d->m_doc) 04232 { 04233 bool autoselect = (d->m_paUseStylesheet->currentItem() == 0); 04234 d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText(); 04235 d->m_doc->updateStyleSelector(); 04236 } 04237 } 04238 04239 void KHTMLPart::updateActions() 04240 { 04241 bool frames = false; 04242 04243 QValueList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.begin(); 04244 const QValueList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.end(); 04245 for (; it != end; ++it ) 04246 if ( (*it)->m_type == khtml::ChildFrame::Frame ) 04247 { 04248 frames = true; 04249 break; 04250 } 04251 04252 d->m_paViewFrame->setEnabled( frames ); 04253 d->m_paSaveFrame->setEnabled( frames ); 04254 04255 if ( frames ) 04256 d->m_paFind->setText( i18n( "&Find in Frame..." ) ); 04257 else 04258 d->m_paFind->setText( i18n( "&Find..." ) ); 04259 04260 KParts::Part *frame = 0; 04261 04262 if ( frames ) 04263 frame = currentFrame(); 04264 04265 bool enableFindAndSelectAll = true; 04266 04267 if ( frame ) 04268 enableFindAndSelectAll = frame->inherits( "KHTMLPart" ); 04269 04270 d->m_paFind->setEnabled( enableFindAndSelectAll ); 04271 d->m_paSelectAll->setEnabled( enableFindAndSelectAll ); 04272 04273 bool enablePrintFrame = false; 04274 04275 if ( frame ) 04276 { 04277 QObject *ext = KParts::BrowserExtension::childObject( frame ); 04278 if ( ext ) 04279 enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" ); 04280 } 04281 04282 d->m_paPrintFrame->setEnabled( enablePrintFrame ); 04283 04284 QString bgURL; 04285 04286 // ### frames 04287 if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing ) 04288 bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string(); 04289 04290 d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() ); 04291 04292 if ( d->m_paDebugScript ) 04293 d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L ); 04294 } 04295 04296 KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const { 04297 const ConstFrameIt end = d->m_objects.end(); 04298 for(ConstFrameIt it = d->m_objects.begin(); it != end; ++it ) 04299 if ((*it)->m_frame == frame) 04300 return (*it)->m_liveconnect; 04301 return 0L; 04302 } 04303 04304 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName, 04305 const QStringList ¶ms, bool isIFrame ) 04306 { 04307 //kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl; 04308 FrameIt it = d->m_frames.find( frameName ); 04309 if ( it == d->m_frames.end() ) 04310 { 04311 khtml::ChildFrame * child = new khtml::ChildFrame; 04312 //kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl; 04313 child->m_name = frameName; 04314 it = d->m_frames.append( child ); 04315 } 04316 04317 (*it)->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame; 04318 (*it)->m_frame = frame; 04319 (*it)->m_params = params; 04320 04321 // Support for <frame src="javascript:string"> 04322 if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) 04323 { 04324 if ( processObjectRequest(*it, KURL("about:blank"), QString("text/html") ) ) { 04325 KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part)); 04326 04327 // See if we want to replace content with javascript: output.. 04328 QVariant res = p->executeScript( DOM::Node(), KURL::decode_string( url.right( url.length() - 11) ) ); 04329 if ( res.type() == QVariant::String ) { 04330 p->begin(); 04331 p->write( res.asString() ); 04332 p->end(); 04333 } 04334 return true; 04335 } 04336 return false; 04337 } 04338 KURL u = url.isEmpty() ? KURL() : completeURL( url ); 04339 return requestObject( *it, u ); 04340 } 04341 04342 QString KHTMLPart::requestFrameName() 04343 { 04344 return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++); 04345 } 04346 04347 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType, 04348 const QStringList ¶ms ) 04349 { 04350 //kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl; 04351 khtml::ChildFrame *child = new khtml::ChildFrame; 04352 FrameIt it = d->m_objects.append( child ); 04353 (*it)->m_frame = frame; 04354 (*it)->m_type = khtml::ChildFrame::Object; 04355 (*it)->m_params = params; 04356 04357 KParts::URLArgs args; 04358 args.serviceType = serviceType; 04359 if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) { 04360 (*it)->m_bCompleted = true; 04361 return false; 04362 } 04363 return true; 04364 } 04365 04366 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args ) 04367 { 04368 if (!checkLinkSecurity(url)) 04369 { 04370 kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl; 04371 return false; 04372 } 04373 if ( child->m_bPreloaded ) 04374 { 04375 kdDebug(6005) << "KHTMLPart::requestObject preload" << endl; 04376 if ( child->m_frame && child->m_part ) 04377 child->m_frame->setWidget( child->m_part->widget() ); 04378 04379 child->m_bPreloaded = false; 04380 return true; 04381 } 04382 04383 //kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl; 04384 04385 KParts::URLArgs args( _args ); 04386 04387 if ( child->m_run ) 04388 child->m_run->abort(); 04389 04390 if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) ) 04391 args.serviceType = child->m_serviceType; 04392 04393 child->m_args = args; 04394 child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload); 04395 child->m_serviceName = QString::null; 04396 if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" )) 04397 child->m_args.metaData()["referrer"] = d->m_referrer; 04398 04399 child->m_args.metaData().insert("PropagateHttpHeader", "true"); 04400 child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip); 04401 child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert); 04402 child->m_args.metaData().insert("main_frame_request", 04403 parentPart() == 0 ? "TRUE":"FALSE"); 04404 child->m_args.metaData().insert("ssl_was_in_use", 04405 d->m_ssl_in_use ? "TRUE":"FALSE"); 04406 child->m_args.metaData().insert("ssl_activate_warnings", "TRUE"); 04407 child->m_args.metaData().insert("cross-domain", toplevelURL().url()); 04408 04409 // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank"> 04410 if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty()) 04411 args.serviceType = QString::fromLatin1( "text/html" ); 04412 04413 if ( args.serviceType.isEmpty() ) { 04414 kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl; 04415 child->m_run = new KHTMLRun( this, child, url, child->m_args, true ); 04416 d->m_bComplete = false; // ensures we stop it in checkCompleted... 04417 return false; 04418 } else { 04419 return processObjectRequest( child, url, args.serviceType ); 04420 } 04421 } 04422 04423 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype ) 04424 { 04425 //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl; 04426 04427 // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given 04428 // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part 04429 // though -> the reference becomes invalid -> crash is likely 04430 KURL url( _url ); 04431 04432 // khtmlrun called us this way to indicate a loading error 04433 if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) ) 04434 { 04435 child->m_bCompleted = true; 04436 checkCompleted(); 04437 return true; 04438 } 04439 04440 if (child->m_bNotify) 04441 { 04442 child->m_bNotify = false; 04443 if ( !child->m_args.lockHistory() ) 04444 emit d->m_extension->openURLNotify(); 04445 } 04446 04447 if ( child->m_serviceType != mimetype || !child->m_part ) 04448 { 04449 // Before attempting to load a part, check if the user wants that. 04450 // Many don't like getting ZIP files embedded. 04451 // However we don't want to ask for flash and other plugin things.. 04452 if ( child->m_type != khtml::ChildFrame::Object ) 04453 { 04454 QString suggestedFilename; 04455 if ( child->m_run ) 04456 suggestedFilename = child->m_run->suggestedFilename(); 04457 04458 KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave( 04459 url, mimetype, suggestedFilename ); 04460 switch( res ) { 04461 case KParts::BrowserRun::Save: 04462 KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0, suggestedFilename); 04463 // fall-through 04464 case KParts::BrowserRun::Cancel: 04465 child->m_bCompleted = true; 04466 checkCompleted(); 04467 return true; // done 04468 default: // Open 04469 break; 04470 } 04471 } 04472 04473 QStringList dummy; // the list of servicetypes handled by the part is now unused. 04474 KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), child->m_name.ascii(), this, child->m_name.ascii(), mimetype, child->m_serviceName, dummy, child->m_params ); 04475 04476 if ( !part ) 04477 { 04478 if ( child->m_frame ) 04479 if (child->m_frame->partLoadingErrorNotify( child, url, mimetype )) 04480 return true; // we succeeded after all (a fallback was used) 04481 04482 checkEmitLoadEvent(); 04483 return false; 04484 } 04485 04486 //CRITICAL STUFF 04487 if ( child->m_part ) 04488 { 04489 if (!::qt_cast<KHTMLPart*>(child->m_part) && child->m_jscript) 04490 child->m_jscript->clear(); 04491 partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part ); 04492 delete (KParts::ReadOnlyPart *)child->m_part; 04493 if (child->m_liveconnect) { 04494 disconnect(child->m_liveconnect, SIGNAL(partEvent(const unsigned long, const QString &, const KParts::LiveConnectExtension::ArgList &)), child, SLOT(liveConnectEvent(const unsigned long, const QString&, const KParts::LiveConnectExtension::ArgList &))); 04495 child->m_liveconnect = 0L; 04496 } 04497 } 04498 04499 child->m_serviceType = mimetype; 04500 if ( child->m_frame && part->widget() ) 04501 child->m_frame->setWidget( part->widget() ); 04502 04503 if ( child->m_type != khtml::ChildFrame::Object ) 04504 partManager()->addPart( part, false ); 04505 // else 04506 // kdDebug(6005) << "AH! NO FRAME!!!!!" << endl; 04507 04508 child->m_part = part; 04509 04510 if (::qt_cast<KHTMLPart*>(part)) { 04511 static_cast<KHTMLPart*>(part)->d->m_frame = child; 04512 } else if (child->m_frame) { 04513 child->m_liveconnect = KParts::LiveConnectExtension::childObject(part); 04514 if (child->m_liveconnect) 04515 connect(child->m_liveconnect, SIGNAL(partEvent(const unsigned long, const QString &, const KParts::LiveConnectExtension::ArgList &)), child, SLOT(liveConnectEvent(const unsigned long, const QString&, const KParts::LiveConnectExtension::ArgList &))); 04516 } 04517 KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part); 04518 if (sb) 04519 sb->setStatusBar( d->m_statusBarExtension->statusBar() ); 04520 04521 connect( part, SIGNAL( started( KIO::Job *) ), 04522 this, SLOT( slotChildStarted( KIO::Job *) ) ); 04523 connect( part, SIGNAL( completed() ), 04524 this, SLOT( slotChildCompleted() ) ); 04525 connect( part, SIGNAL( completed(bool) ), 04526 this, SLOT( slotChildCompleted(bool) ) ); 04527 connect( part, SIGNAL( setStatusBarText( const QString & ) ), 04528 this, SIGNAL( setStatusBarText( const QString & ) ) ); 04529 if ( part->inherits( "KHTMLPart" ) ) 04530 { 04531 connect( this, SIGNAL( completed() ), 04532 part, SLOT( slotParentCompleted() ) ); 04533 connect( this, SIGNAL( completed(bool) ), 04534 part, SLOT( slotParentCompleted() ) ); 04535 // As soon as the child's document is created, we need to set its domain 04536 // (but we do so only once, so it can't be simply done in the child) 04537 connect( part, SIGNAL( docCreated() ), 04538 this, SLOT( slotChildDocCreated() ) ); 04539 } 04540 04541 child->m_extension = KParts::BrowserExtension::childObject( part ); 04542 04543 if ( child->m_extension ) 04544 { 04545 connect( child->m_extension, SIGNAL( openURLNotify() ), 04546 d->m_extension, SIGNAL( openURLNotify() ) ); 04547 04548 connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), 04549 this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) ); 04550 04551 connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ), 04552 d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) ); 04553 connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ), 04554 d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) ); 04555 04556 connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ), 04557 d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) ); 04558 connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ), 04559 d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) ); 04560 connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ), 04561 d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) ); 04562 connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ), 04563 d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) ); 04564 connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ), 04565 d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) ); 04566 connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ), 04567 d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) ); 04568 04569 connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ), 04570 d->m_extension, SIGNAL( infoMessage( const QString & ) ) ); 04571 04572 connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ), 04573 this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) ); 04574 04575 child->m_extension->setBrowserInterface( d->m_extension->browserInterface() ); 04576 } 04577 } 04578 else if ( child->m_frame && child->m_part && 04579 child->m_frame->widget() != child->m_part->widget() ) 04580 child->m_frame->setWidget( child->m_part->widget() ); 04581 04582 checkEmitLoadEvent(); 04583 // Some JS code in the load event may have destroyed the part 04584 // In that case, abort 04585 if ( !child->m_part ) 04586 return false; 04587 04588 if ( child->m_bPreloaded ) 04589 { 04590 if ( child->m_frame && child->m_part ) 04591 child->m_frame->setWidget( child->m_part->widget() ); 04592 04593 child->m_bPreloaded = false; 04594 return true; 04595 } 04596 04597 child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload); 04598 04599 // make sure the part has a way to find out about the mimetype. 04600 // we actually set it in child->m_args in requestObject already, 04601 // but it's useless if we had to use a KHTMLRun instance, as the 04602 // point the run object is to find out exactly the mimetype. 04603 child->m_args.serviceType = mimetype; 04604 04605 // if not a frame set child as completed 04606 child->m_bCompleted = child->m_type == khtml::ChildFrame::Object; 04607 04608 if ( child->m_extension ) 04609 child->m_extension->setURLArgs( child->m_args ); 04610 04611 if(url.protocol() == "javascript" || url.url() == "about:blank") { 04612 if (!child->m_part->inherits("KHTMLPart")) 04613 return false; 04614 04615 KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part)); 04616 04617 p->begin(); 04618 if (d->m_doc && p->d->m_doc) 04619 p->d->m_doc->setBaseURL(d->m_doc->baseURL()); 04620 if (!url.url().startsWith("about:")) { 04621 p->write(url.path()); 04622 } else { 04623 p->m_url = url; 04624 // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script> 04625 p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>"); 04626 } 04627 p->end(); 04628 return true; 04629 } 04630 else if ( !url.isEmpty() ) 04631 { 04632 //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl; 04633 bool b = child->m_part->openURL( url ); 04634 if (child->m_bCompleted) 04635 checkCompleted(); 04636 return b; 04637 } 04638 else 04639 { 04640 child->m_bCompleted = true; 04641 checkCompleted(); 04642 return true; 04643 } 04644 } 04645 04646 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName, 04647 QObject *parent, const char *name, const QString &mimetype, 04648 QString &serviceName, QStringList &serviceTypes, 04649 const QStringList ¶ms ) 04650 { 04651 QString constr; 04652 if ( !serviceName.isEmpty() ) 04653 constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) ); 04654 04655 KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null ); 04656 04657 if ( offers.isEmpty() ) { 04658 int pos = mimetype.find( "-plugin" ); 04659 if (pos < 0) 04660 return 0L; 04661 QString stripped_mime = mimetype.left( pos ); 04662 offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, QString::null ); 04663 if ( offers.isEmpty() ) 04664 return 0L; 04665 } 04666 04667 KTrader::OfferList::ConstIterator it = offers.begin(); 04668 const KTrader::OfferList::ConstIterator itEnd = offers.end(); 04669 for ( ; it != itEnd; ++it ) 04670 { 04671 KService::Ptr service = (*it); 04672 04673 KLibFactory* const factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) ); 04674 if ( factory ) { 04675 KParts::ReadOnlyPart *res = 0L; 04676 04677 const char *className = "KParts::ReadOnlyPart"; 04678 if ( service->serviceTypes().contains( "Browser/View" ) ) 04679 className = "Browser/View"; 04680 04681 if ( factory->inherits( "KParts::Factory" ) ) 04682 res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params )); 04683 else 04684 res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className )); 04685 04686 if ( res ) { 04687 serviceTypes = service->serviceTypes(); 04688 serviceName = service->name(); 04689 return res; 04690 } 04691 } else { 04692 // TODO KMessageBox::error and i18n, like in KonqFactory::createView? 04693 kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2") 04694 .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl; 04695 } 04696 } 04697 return 0; 04698 } 04699 04700 KParts::PartManager *KHTMLPart::partManager() 04701 { 04702 if ( !d->m_manager && d->m_view ) 04703 { 04704 d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" ); 04705 d->m_manager->setAllowNestedParts( true ); 04706 connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ), 04707 this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) ); 04708 connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ), 04709 this, SLOT( slotPartRemoved( KParts::Part * ) ) ); 04710 } 04711 04712 return d->m_manager; 04713 } 04714 04715 void KHTMLPart::submitFormAgain() 04716 { 04717 disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain())); 04718 if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm) 04719 KHTMLPart::submitForm( d->m_submitForm->submitAction, d->m_submitForm->submitUrl, d->m_submitForm->submitFormData, d->m_submitForm->target, d->m_submitForm->submitContentType, d->m_submitForm->submitBoundary ); 04720 04721 delete d->m_submitForm; 04722 d->m_submitForm = 0; 04723 } 04724 04725 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary ) 04726 { 04727 submitForm(action, url, formData, _target, contentType, boundary); 04728 } 04729 04730 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary ) 04731 { 04732 kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl; 04733 if (d->m_formNotification == KHTMLPart::Only) { 04734 emit formSubmitNotification(action, url, formData, _target, contentType, boundary); 04735 return; 04736 } else if (d->m_formNotification == KHTMLPart::Before) { 04737 emit formSubmitNotification(action, url, formData, _target, contentType, boundary); 04738 } 04739 04740 KURL u = completeURL( url ); 04741 04742 if ( !u.isValid() ) 04743 { 04744 // ### ERROR HANDLING! 04745 return; 04746 } 04747 04748 // Form security checks 04749 // 04750 /* 04751 * If these form security checks are still in this place in a month or two 04752 * I'm going to simply delete them. 04753 */ 04754 04755 /* This is separate for a reason. It has to be _before_ all script, etc, 04756 * AND I don't want to break anything that uses checkLinkSecurity() in 04757 * other places. 04758 */ 04759 04760 if (!d->m_submitForm) { 04761 if (u.protocol() != "https" && u.protocol() != "mailto") { 04762 if (d->m_ssl_in_use) { // Going from SSL -> nonSSL 04763 int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning: This is a secure form but it is attempting to send your data back unencrypted." 04764 "\nA third party may be able to intercept and view this information." 04765 "\nAre you sure you wish to continue?"), 04766 i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted"))); 04767 if (rc == KMessageBox::Cancel) 04768 return; 04769 } else { // Going from nonSSL -> nonSSL 04770 KSSLSettings kss(true); 04771 if (kss.warnOnUnencrypted()) { 04772 int rc = KMessageBox::warningContinueCancel(NULL, 04773 i18n("Warning: Your data is about to be transmitted across the network unencrypted." 04774 "\nAre you sure you wish to continue?"), 04775 i18n("Network Transmission"), 04776 KGuiItem(i18n("&Send Unencrypted")), 04777 "WarnOnUnencryptedForm"); 04778 // Move this setting into KSSL instead 04779 KConfig *config = kapp->config(); 04780 QString grpNotifMsgs = QString::fromLatin1("Notification Messages"); 04781 KConfigGroupSaver saver( config, grpNotifMsgs ); 04782 04783 if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) { 04784 config->deleteEntry("WarnOnUnencryptedForm"); 04785 config->sync(); 04786 kss.setWarnOnUnencrypted(false); 04787 kss.save(); 04788 } 04789 if (rc == KMessageBox::Cancel) 04790 return; 04791 } 04792 } 04793 } 04794 04795 if (u.protocol() == "mailto") { 04796 int rc = KMessageBox::warningContinueCancel(NULL, 04797 i18n("This site is attempting to submit form data via email.\n" 04798 "Do you want to continue?"), 04799 i18n("Network Transmission"), 04800 KGuiItem(i18n("&Send Email")), 04801 "WarnTriedEmailSubmit"); 04802 04803 if (rc == KMessageBox::Cancel) { 04804 return; 04805 } 04806 } 04807 } 04808 04809 // End form security checks 04810 // 04811 04812 QString urlstring = u.url(); 04813 04814 if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) { 04815 urlstring = KURL::decode_string(urlstring); 04816 crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) ); 04817 return; 04818 } 04819 04820 if (!checkLinkSecurity(u, 04821 i18n( "<qt>The form will be submitted to <BR><B>%1</B><BR>on your local filesystem.<BR>Do you want to submit the form?" ), 04822 i18n( "Submit" ))) 04823 return; 04824 04825 KParts::URLArgs args; 04826 04827 if (!d->m_referrer.isEmpty()) 04828 args.metaData()["referrer"] = d->m_referrer; 04829 04830 args.metaData().insert("PropagateHttpHeader", "true"); 04831 args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip); 04832 args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert); 04833 args.metaData().insert("main_frame_request", 04834 parentPart() == 0 ? "TRUE":"FALSE"); 04835 args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE"); 04836 args.metaData().insert("ssl_activate_warnings", "TRUE"); 04837 //WABA: When we post a form we should treat it as the main url 04838 //the request should never be considered cross-domain 04839 //args.metaData().insert("cross-domain", toplevelURL().url()); 04840 args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ; 04841 04842 // Handle mailto: forms 04843 if (u.protocol() == "mailto") { 04844 // 1) Check for attach= and strip it 04845 QString q = u.query().mid(1); 04846 QStringList nvps = QStringList::split("&", q); 04847 bool triedToAttach = false; 04848 04849 QStringList::Iterator nvp = nvps.begin(); 04850 const QStringList::Iterator nvpEnd = nvps.end(); 04851 04852 // cannot be a for loop as if something is removed we don't want to do ++nvp, as 04853 // remove returns an iterator pointing to the next item 04854 04855 while (nvp != nvpEnd) { 04856 const QStringList pair = QStringList::split("=", *nvp); 04857 if (pair.count() >= 2) { 04858 if (pair.first().lower() == "attach") { 04859 nvp = nvps.remove(nvp); 04860 triedToAttach = true; 04861 } else { 04862 ++nvp; 04863 } 04864 } else { 04865 ++nvp; 04866 } 04867 } 04868 04869 if (triedToAttach) 04870 KMessageBox::information(NULL, i18n("This site attempted to attach a file from your computer in the form submission. The attachment was removed for your protection."), i18n("KDE"), "WarnTriedAttach"); 04871 04872 // 2) Append body= 04873 QString bodyEnc; 04874 if (contentType.lower() == "multipart/form-data") { 04875 // FIXME: is this correct? I suspect not 04876 bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(), 04877 formData.size())); 04878 } else if (contentType.lower() == "text/plain") { 04879 // Convention seems to be to decode, and s/&/\n/ 04880 QString tmpbody = QString::fromLatin1(formData.data(), 04881 formData.size()); 04882 tmpbody.replace(QRegExp("[&]"), "\n"); 04883 tmpbody.replace(QRegExp("[+]"), " "); 04884 tmpbody = KURL::decode_string(tmpbody); // Decode the rest of it 04885 bodyEnc = KURL::encode_string(tmpbody); // Recode for the URL 04886 } else { 04887 bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(), 04888 formData.size())); 04889 } 04890 04891 nvps.append(QString("body=%1").arg(bodyEnc)); 04892 q = nvps.join("&"); 04893 u.setQuery(q); 04894 } 04895 04896 if ( strcmp( action, "get" ) == 0 ) { 04897 if (u.protocol() != "mailto") 04898 u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) ); 04899 args.setDoPost( false ); 04900 } 04901 else { 04902 args.postData = formData; 04903 args.setDoPost( true ); 04904 04905 // construct some user headers if necessary 04906 if (contentType.isNull() || contentType == "application/x-www-form-urlencoded") 04907 args.setContentType( "Content-Type: application/x-www-form-urlencoded" ); 04908 else // contentType must be "multipart/form-data" 04909 args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary ); 04910 } 04911 04912 if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) { 04913 if( d->m_submitForm ) { 04914 kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl; 04915 return; 04916 } 04917 d->m_submitForm = new KHTMLPartPrivate::SubmitForm; 04918 d->m_submitForm->submitAction = action; 04919 d->m_submitForm->submitUrl = url; 04920 d->m_submitForm->submitFormData = formData; 04921 d->m_submitForm->target = _target; 04922 d->m_submitForm->submitContentType = contentType; 04923 d->m_submitForm->submitBoundary = boundary; 04924 connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain())); 04925 } 04926 else 04927 { 04928 emit d->m_extension->openURLRequest( u, args ); 04929 } 04930 } 04931 04932 void KHTMLPart::popupMenu( const QString &linkUrl ) 04933 { 04934 KURL popupURL; 04935 KURL linkKURL; 04936 KParts::URLArgs args; 04937 QString referrer; 04938 KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload; 04939 04940 if ( linkUrl.isEmpty() ) { // click on background 04941 KHTMLPart* khtmlPart = this; 04942 while ( khtmlPart->parentPart() ) 04943 { 04944 khtmlPart=khtmlPart->parentPart(); 04945 } 04946 popupURL = khtmlPart->url(); 04947 referrer = khtmlPart->pageReferrer(); 04948 if (hasSelection()) 04949 itemflags = KParts::BrowserExtension::ShowTextSelectionItems; 04950 else 04951 itemflags |= KParts::BrowserExtension::ShowNavigationItems; 04952 } else { // click on link 04953 popupURL = completeURL( linkUrl ); 04954 linkKURL = popupURL; 04955 referrer = this->referrer(); 04956 04957 if (!(d->m_strSelectedURLTarget).isEmpty() && 04958 (d->m_strSelectedURLTarget.lower() != "_top") && 04959 (d->m_strSelectedURLTarget.lower() != "_self") && 04960 (d->m_strSelectedURLTarget.lower() != "_parent")) { 04961 if (d->m_strSelectedURLTarget.lower() == "_blank") 04962 args.setForcesNewWindow(true); 04963 else { 04964 KHTMLPart *p = this; 04965 while (p->parentPart()) 04966 p = p->parentPart(); 04967 if (!p->frameExists(d->m_strSelectedURLTarget)) 04968 args.setForcesNewWindow(true); 04969 } 04970 } 04971 } 04972 04973 // Danger, Will Robinson. The Popup might stay around for a much 04974 // longer time than KHTMLPart. Deal with it. 04975 KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL ); 04976 QGuardedPtr<QObject> guard( client ); 04977 04978 QString mimetype = QString::fromLatin1( "text/html" ); 04979 args.metaData()["referrer"] = referrer; 04980 04981 if (!linkUrl.isEmpty()) // over a link 04982 { 04983 if (popupURL.isLocalFile()) // safe to do this 04984 { 04985 mimetype = KMimeType::findByURL(popupURL,0,true,false)->name(); 04986 } 04987 else // look at "extension" of link 04988 { 04989 const QString fname(popupURL.fileName(false)); 04990 if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty()) 04991 { 04992 KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true); 04993 04994 // Further check for mime types guessed from the extension which, 04995 // on a web page, are more likely to be a script delivering content 04996 // of undecidable type. If the mime type from the extension is one 04997 // of these, don't use it. Retain the original type 'text/html'. 04998 if (pmt->name() != KMimeType::defaultMimeType() && 04999 !pmt->is("application/x-perl") && 05000 !pmt->is("application/x-perl-module") && 05001 !pmt->is("application/x-php") && 05002 !pmt->is("application/x-python-bytecode") && 05003 !pmt->is("application/x-python") && 05004 !pmt->is("application/x-shellscript")) 05005 mimetype = pmt->name(); 05006 } 05007 } 05008 } 05009 05010 args.serviceType = mimetype; 05011 05012 emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/); 05013 05014 if ( !guard.isNull() ) { 05015 delete client; 05016 emit popupMenu(linkUrl, QCursor::pos()); 05017 d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null; 05018 } 05019 } 05020 05021 void KHTMLPart::slotParentCompleted() 05022 { 05023 //kdDebug(6050) << this << " slotParentCompleted()" << endl; 05024 if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() ) 05025 { 05026 //kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl; 05027 d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true ); 05028 } 05029 } 05030 05031 void KHTMLPart::slotChildStarted( KIO::Job *job ) 05032 { 05033 khtml::ChildFrame *child = frame( sender() ); 05034 05035 assert( child ); 05036 05037 child->m_bCompleted = false; 05038 05039 if ( d->m_bComplete ) 05040 { 05041 #if 0 05042 // WABA: Looks like this belongs somewhere else 05043 if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes 05044 { 05045 emit d->m_extension->openURLNotify(); 05046 } 05047 #endif 05048 d->m_bComplete = false; 05049 emit started( job ); 05050 } 05051 } 05052 05053 void KHTMLPart::slotChildCompleted() 05054 { 05055 slotChildCompleted( false ); 05056 } 05057 05058 void KHTMLPart::slotChildCompleted( bool pendingAction ) 05059 { 05060 khtml::ChildFrame *child = frame( sender() ); 05061 05062 if ( child ) { 05063 kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl; 05064 child->m_bCompleted = true; 05065 child->m_bPendingRedirection = pendingAction; 05066 child->m_args = KParts::URLArgs(); 05067 } 05068 checkCompleted(); 05069 } 05070 05071 void KHTMLPart::slotChildDocCreated() 05072 { 05073 const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender()); 05074 // Set domain to the frameset's domain 05075 // This must only be done when loading the frameset initially (#22039), 05076 // not when following a link in a frame (#44162). 05077 if ( d->m_doc && d->m_doc->isHTMLDocument() ) 05078 { 05079 if ( sender()->inherits("KHTMLPart") ) 05080 { 05081 DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain(); 05082 if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() ) 05083 //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl; 05084 static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain ); 05085 } 05086 } 05087 // So it only happens once 05088 disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) ); 05089 } 05090 05091 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args ) 05092 { 05093 khtml::ChildFrame *child = frame( sender()->parent() ); 05094 KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent())); 05095 05096 // TODO: handle child target correctly! currently the script are always executed fur the parent 05097 QString urlStr = url.url(); 05098 if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) { 05099 QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) ); 05100 executeScript( DOM::Node(), script ); 05101 return; 05102 } 05103 05104 QString frameName = args.frameName.lower(); 05105 if ( !frameName.isEmpty() ) { 05106 if ( frameName == QString::fromLatin1( "_top" ) ) 05107 { 05108 emit d->m_extension->openURLRequest( url, args ); 05109 return; 05110 } 05111 else if ( frameName == QString::fromLatin1( "_blank" ) ) 05112 { 05113 emit d->m_extension->createNewWindow( url, args ); 05114 return; 05115 } 05116 else if ( frameName == QString::fromLatin1( "_parent" ) ) 05117 { 05118 KParts::URLArgs newArgs( args ); 05119 newArgs.frameName = QString::null; 05120 05121 emit d->m_extension->openURLRequest( url, newArgs ); 05122 return; 05123 } 05124 else if ( frameName != QString::fromLatin1( "_self" ) ) 05125 { 05126 khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args ); 05127 05128 if ( !_frame ) 05129 { 05130 emit d->m_extension->openURLRequest( url, args ); 05131 return; 05132 } 05133 05134 child = _frame; 05135 } 05136 } 05137 05138 if ( child && child->m_type != khtml::ChildFrame::Object ) { 05139 // Inform someone that we are about to show something else. 05140 child->m_bNotify = true; 05141 requestObject( child, url, args ); 05142 } else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document 05143 { 05144 KParts::URLArgs newArgs( args ); 05145 newArgs.frameName = QString::null; 05146 emit d->m_extension->openURLRequest( url, newArgs ); 05147 } 05148 } 05149 05150 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * ) 05151 { 05152 emit d->m_extension->requestFocus(this); 05153 } 05154 05155 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj ) 05156 { 05157 assert( obj->inherits( "KParts::ReadOnlyPart" ) ); 05158 const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj ); 05159 05160 FrameIt it = d->m_frames.begin(); 05161 const FrameIt end = d->m_frames.end(); 05162 for (; it != end; ++it ) 05163 if ( (KParts::ReadOnlyPart *)(*it)->m_part == part ) 05164 return *it; 05165 05166 FrameIt oi = d->m_objects.begin(); 05167 const FrameIt oiEnd = d->m_objects.end(); 05168 for (; oi != oiEnd; ++oi ) 05169 if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part ) 05170 return *oi; 05171 05172 return 0L; 05173 } 05174 05175 //#define DEBUG_FINDFRAME 05176 05177 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart) 05178 { 05179 if (callingHtmlPart == this) 05180 return true; // trivial 05181 05182 if (htmlDocument().isNull()) { 05183 #ifdef DEBUG_FINDFRAME 05184 kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl; 05185 #endif 05186 return false; // we are empty? 05187 } 05188 05189 // now compare the domains 05190 if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() && 05191 !htmlDocument().isNull()) { 05192 DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain(); 05193 DOM::DOMString destDomain = htmlDocument().domain(); 05194 05195 #ifdef DEBUG_FINDFRAME 05196 kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl; 05197 #endif 05198 05199 if (actDomain == destDomain) 05200 return true; 05201 } 05202 #ifdef DEBUG_FINDFRAME 05203 else 05204 { 05205 kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl; 05206 } 05207 #endif 05208 return false; 05209 } 05210 05211 KHTMLPart * 05212 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame ) 05213 { 05214 #ifdef DEBUG_FINDFRAME 05215 kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl; 05216 #endif 05217 // Check access 05218 KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart); 05219 05220 if (!checkFrameAccess(callingHtmlPart)) 05221 return 0; 05222 05223 // match encoding used in KonqView::setViewName() 05224 if (!childFrame && !parentPart() && (QString::fromLocal8Bit(name()) == f)) 05225 return this; 05226 05227 FrameIt it = d->m_frames.find( f ); 05228 const FrameIt end = d->m_frames.end(); 05229 if ( it != end ) 05230 { 05231 #ifdef DEBUG_FINDFRAME 05232 kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl; 05233 #endif 05234 if (childFrame) 05235 *childFrame = *it; 05236 return this; 05237 } 05238 05239 it = d->m_frames.begin(); 05240 for (; it != end; ++it ) 05241 { 05242 KParts::ReadOnlyPart* const p = (*it)->m_part; 05243 if ( p && p->inherits( "KHTMLPart" )) 05244 { 05245 KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame); 05246 if (frameParent) 05247 return frameParent; 05248 } 05249 } 05250 return 0; 05251 } 05252 05253 05254 KHTMLPart *KHTMLPart::findFrame( const QString &f ) 05255 { 05256 khtml::ChildFrame *childFrame; 05257 KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame); 05258 if (parentFrame) 05259 { 05260 KParts::ReadOnlyPart *p = childFrame->m_part; 05261 if ( p && p->inherits( "KHTMLPart" )) 05262 return static_cast<KHTMLPart *>(p); 05263 } 05264 return 0; 05265 } 05266 05267 KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f) 05268 { 05269 khtml::ChildFrame *childFrame; 05270 return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L; 05271 } 05272 05273 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const 05274 { 05275 KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this); 05276 // Find active part in our frame manager, in case we are a frameset 05277 // and keep doing that (in case of nested framesets). 05278 // Just realized we could also do this recursively, calling part->currentFrame()... 05279 while ( part && part->inherits("KHTMLPart") && 05280 static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) { 05281 KHTMLPart* frameset = static_cast<KHTMLPart *>(part); 05282 part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart()); 05283 if ( !part ) return frameset; 05284 } 05285 return part; 05286 } 05287 05288 bool KHTMLPart::frameExists( const QString &frameName ) 05289 { 05290 ConstFrameIt it = d->m_frames.find( frameName ); 05291 if ( it == d->m_frames.end() ) 05292 return false; 05293 05294 // WABA: We only return true if the child actually has a frame 05295 // set. Otherwise we might find our preloaded-selve. 05296 // This happens when we restore the frameset. 05297 return (!(*it)->m_frame.isNull()); 05298 } 05299 05300 KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart) 05301 { 05302 KHTMLPart* const kp = ::qt_cast<KHTMLPart*>(framePart); 05303 if (kp) 05304 return kp->jScript(); 05305 05306 FrameIt it = d->m_frames.begin(); 05307 const FrameIt itEnd = d->m_frames.end(); 05308 05309 for (; it != itEnd; ++it) 05310 if (framePart == (*it)->m_part) { 05311 if (!(*it)->m_jscript) 05312 createJScript(*it); 05313 return (*it)->m_jscript; 05314 } 05315 return 0L; 05316 } 05317 05318 KHTMLPart *KHTMLPart::parentPart() 05319 { 05320 return ::qt_cast<KHTMLPart *>( parent() ); 05321 } 05322 05323 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url, 05324 const KParts::URLArgs &args, bool callParent ) 05325 { 05326 #ifdef DEBUG_FINDFRAME 05327 kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl; 05328 #endif 05329 khtml::ChildFrame *childFrame; 05330 KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame); 05331 if (childPart) 05332 { 05333 if (childPart == this) 05334 return childFrame; 05335 05336 childPart->requestObject( childFrame, url, args ); 05337 return 0; 05338 } 05339 05340 if ( parentPart() && callParent ) 05341 { 05342 khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent ); 05343 05344 if ( res ) 05345 parentPart()->requestObject( res, url, args ); 05346 } 05347 05348 return 0L; 05349 } 05350 05351 #ifndef NDEBUG 05352 static int s_saveStateIndentLevel = 0; 05353 #endif 05354 05355 void KHTMLPart::saveState( QDataStream &stream ) 05356 { 05357 #ifndef NDEBUG 05358 QString indent = QString().leftJustify( s_saveStateIndentLevel * 4, ' ' ); 05359 const int indentLevel = s_saveStateIndentLevel++; 05360 kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl; 05361 #endif 05362 05363 stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY() 05364 << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight(); 05365 05366 // save link cursor position 05367 int focusNodeNumber; 05368 if (!d->m_focusNodeRestored) 05369 focusNodeNumber = d->m_focusNodeNumber; 05370 else if (d->m_doc && d->m_doc->focusNode()) 05371 focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode()); 05372 else 05373 focusNodeNumber = -1; 05374 stream << focusNodeNumber; 05375 05376 // Save the doc's cache id. 05377 stream << d->m_cacheId; 05378 05379 // Save the state of the document (Most notably the state of any forms) 05380 QStringList docState; 05381 if (d->m_doc) 05382 { 05383 docState = d->m_doc->docState(); 05384 } 05385 stream << d->m_encoding << d->m_sheetUsed << docState; 05386 05387 stream << d->m_zoomFactor; 05388 05389 stream << d->m_httpHeaders; 05390 stream << d->m_pageServices; 05391 stream << d->m_pageReferrer; 05392 05393 // Save ssl data 05394 stream << d->m_ssl_in_use 05395 << d->m_ssl_peer_certificate 05396 << d->m_ssl_peer_chain 05397 << d->m_ssl_peer_ip 05398 << d->m_ssl_cipher 05399 << d->m_ssl_cipher_desc 05400 << d->m_ssl_cipher_version 05401 << d->m_ssl_cipher_used_bits 05402 << d->m_ssl_cipher_bits 05403 << d->m_ssl_cert_state 05404 << d->m_ssl_parent_ip 05405 << d->m_ssl_parent_cert; 05406 05407 05408 QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst; 05409 KURL::List frameURLLst; 05410 QValueList<QByteArray> frameStateBufferLst; 05411 05412 ConstFrameIt it = d->m_frames.begin(); 05413 const ConstFrameIt end = d->m_frames.end(); 05414 for (; it != end; ++it ) 05415 { 05416 if ( !(*it)->m_part ) 05417 continue; 05418 05419 frameNameLst << (*it)->m_name; 05420 frameServiceTypeLst << (*it)->m_serviceType; 05421 frameServiceNameLst << (*it)->m_serviceName; 05422 frameURLLst << (*it)->m_part->url(); 05423 05424 QByteArray state; 05425 QDataStream frameStream( state, IO_WriteOnly ); 05426 05427 if ( (*it)->m_extension ) 05428 (*it)->m_extension->saveState( frameStream ); 05429 05430 frameStateBufferLst << state; 05431 } 05432 05433 // Save frame data 05434 stream << (Q_UINT32) frameNameLst.count(); 05435 stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst; 05436 #ifndef NDEBUG 05437 s_saveStateIndentLevel = indentLevel; 05438 #endif 05439 } 05440 05441 void KHTMLPart::restoreState( QDataStream &stream ) 05442 { 05443 KURL u; 05444 Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight; 05445 Q_UINT32 frameCount; 05446 QStringList frameNames, frameServiceTypes, docState, frameServiceNames; 05447 KURL::List frameURLs; 05448 QValueList<QByteArray> frameStateBuffers; 05449 QValueList<int> fSizes; 05450 QString encoding, sheetUsed; 05451 long old_cacheId = d->m_cacheId; 05452 05453 stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight; 05454 05455 d->m_view->setMarginWidth( mWidth ); 05456 d->m_view->setMarginHeight( mHeight ); 05457 05458 // restore link cursor position 05459 // nth node is active. value is set in checkCompleted() 05460 stream >> d->m_focusNodeNumber; 05461 d->m_focusNodeRestored = false; 05462 05463 stream >> d->m_cacheId; 05464 05465 stream >> encoding >> sheetUsed >> docState; 05466 05467 d->m_encoding = encoding; 05468 d->m_sheetUsed = sheetUsed; 05469 05470 int zoomFactor; 05471 stream >> zoomFactor; 05472 setZoomFactor(zoomFactor); 05473 05474 stream >> d->m_httpHeaders; 05475 stream >> d->m_pageServices; 05476 stream >> d->m_pageReferrer; 05477 05478 // Restore ssl data 05479 stream >> d->m_ssl_in_use 05480 >> d->m_ssl_peer_certificate 05481 >> d->m_ssl_peer_chain 05482 >> d->m_ssl_peer_ip 05483 >> d->m_ssl_cipher 05484 >> d->m_ssl_cipher_desc 05485 >> d->m_ssl_cipher_version 05486 >> d->m_ssl_cipher_used_bits 05487 >> d->m_ssl_cipher_bits 05488 >> d->m_ssl_cert_state 05489 >> d->m_ssl_parent_ip 05490 >> d->m_ssl_parent_cert; 05491 05492 setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted ); 05493 05494 stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames 05495 >> frameURLs >> frameStateBuffers; 05496 05497 d->m_bComplete = false; 05498 d->m_bLoadEventEmitted = false; 05499 05500 // kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl; 05501 // kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl; 05502 // kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl; 05503 05504 if (d->m_cacheId == old_cacheId) 05505 { 05506 // Partial restore 05507 d->m_redirectionTimer.stop(); 05508 05509 FrameIt fIt = d->m_frames.begin(); 05510 const FrameIt fEnd = d->m_frames.end(); 05511 05512 for (; fIt != fEnd; ++fIt ) 05513 (*fIt)->m_bCompleted = false; 05514 05515 fIt = d->m_frames.begin(); 05516 05517 QStringList::ConstIterator fNameIt = frameNames.begin(); 05518 QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin(); 05519 QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin(); 05520 KURL::List::ConstIterator fURLIt = frameURLs.begin(); 05521 QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin(); 05522 05523 for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt ) 05524 { 05525 khtml::ChildFrame* const child = *fIt; 05526 05527 // kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl; 05528 05529 if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt ) 05530 { 05531 child->m_bPreloaded = true; 05532 child->m_name = *fNameIt; 05533 child->m_serviceName = *fServiceNameIt; 05534 processObjectRequest( child, *fURLIt, *fServiceTypeIt ); 05535 } 05536 if ( child->m_part ) 05537 { 05538 child->m_bCompleted = false; 05539 if ( child->m_extension && !(*fBufferIt).isEmpty() ) 05540 { 05541 QDataStream frameStream( *fBufferIt, IO_ReadOnly ); 05542 child->m_extension->restoreState( frameStream ); 05543 } 05544 else 05545 child->m_part->openURL( *fURLIt ); 05546 } 05547 } 05548 05549 KParts::URLArgs args( d->m_extension->urlArgs() ); 05550 args.xOffset = xOffset; 05551 args.yOffset = yOffset; 05552 args.docState = docState; 05553 d->m_extension->setURLArgs( args ); 05554 05555 d->m_view->resizeContents( wContents, hContents); 05556 d->m_view->setContentsPos( xOffset, yOffset ); 05557 05558 m_url = u; 05559 } 05560 else 05561 { 05562 // Full restore. 05563 closeURL(); 05564 // We must force a clear because we want to be sure to delete all 05565 // frames. 05566 d->m_bCleared = false; 05567 clear(); 05568 d->m_encoding = encoding; 05569 d->m_sheetUsed = sheetUsed; 05570 05571 QStringList::ConstIterator fNameIt = frameNames.begin(); 05572 const QStringList::ConstIterator fNameEnd = frameNames.end(); 05573 05574 QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin(); 05575 QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin(); 05576 KURL::List::ConstIterator fURLIt = frameURLs.begin(); 05577 QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin(); 05578 05579 for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt ) 05580 { 05581 khtml::ChildFrame* const newChild = new khtml::ChildFrame; 05582 newChild->m_bPreloaded = true; 05583 newChild->m_name = *fNameIt; 05584 newChild->m_serviceName = *fServiceNameIt; 05585 05586 // kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl; 05587 05588 const FrameIt childFrame = d->m_frames.append( newChild ); 05589 05590 processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt ); 05591 05592 (*childFrame)->m_bPreloaded = true; 05593 05594 if ( (*childFrame)->m_part ) 05595 { 05596 if ( (*childFrame)->m_extension ) 05597 if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() ) 05598 { 05599 QDataStream frameStream( *fBufferIt, IO_ReadOnly ); 05600 (*childFrame)->m_extension->restoreState( frameStream ); 05601 } 05602 else 05603 (*childFrame)->m_part->openURL( *fURLIt ); 05604 } 05605 } 05606 05607 KParts::URLArgs args( d->m_extension->urlArgs() ); 05608 args.xOffset = xOffset; 05609 args.yOffset = yOffset; 05610 args.docState = docState; 05611 05612 d->m_extension->setURLArgs( args ); 05613 if (!KHTMLPageCache::self()->isComplete(d->m_cacheId)) 05614 { 05615 d->m_restored = true; 05616 openURL( u ); 05617 d->m_restored = false; 05618 } 05619 else 05620 { 05621 restoreURL( u ); 05622 } 05623 } 05624 05625 } 05626 05627 void KHTMLPart::show() 05628 { 05629 if ( d->m_view ) 05630 d->m_view->show(); 05631 } 05632 05633 void KHTMLPart::hide() 05634 { 05635 if ( d->m_view ) 05636 d->m_view->hide(); 05637 } 05638 05639 DOM::Node KHTMLPart::nodeUnderMouse() const 05640 { 05641 return d->m_view->nodeUnderMouse(); 05642 } 05643 05644 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const 05645 { 05646 return d->m_view->nonSharedNodeUnderMouse(); 05647 } 05648 05649 void KHTMLPart::emitSelectionChanged() 05650 { 05651 emit d->m_extension->enableAction( "copy", hasSelection() ); 05652 if ( d->m_findDialog ) 05653 d->m_findDialog->setHasSelection( hasSelection() ); 05654 05655 emit d->m_extension->selectionInfo( selectedText() ); 05656 emit selectionChanged(); 05657 } 05658 05659 int KHTMLPart::zoomFactor() const 05660 { 05661 return d->m_zoomFactor; 05662 } 05663 05664 // ### make the list configurable ? 05665 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 }; 05666 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int)); 05667 static const int minZoom = 20; 05668 static const int maxZoom = 300; 05669 05670 // My idea of useful stepping ;-) (LS) 05671 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 }; 05672 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0]; 05673 05674 void KHTMLPart::slotIncZoom() 05675 { 05676 zoomIn(zoomSizes, zoomSizeCount); 05677 } 05678 05679 void KHTMLPart::slotDecZoom() 05680 { 05681 zoomOut(zoomSizes, zoomSizeCount); 05682 } 05683 05684 void KHTMLPart::slotIncZoomFast() 05685 { 05686 zoomIn(fastZoomSizes, fastZoomSizeCount); 05687 } 05688 05689 void KHTMLPart::slotDecZoomFast() 05690 { 05691 zoomOut(fastZoomSizes, fastZoomSizeCount); 05692 } 05693 05694 void KHTMLPart::zoomIn(const int stepping[], int count) 05695 { 05696 int zoomFactor = d->m_zoomFactor; 05697 05698 if (zoomFactor < maxZoom) { 05699 // find the entry nearest to the given zoomsizes 05700 for (int i = 0; i < count; ++i) 05701 if (stepping[i] > zoomFactor) { 05702 zoomFactor = stepping[i]; 05703 break; 05704 } 05705 setZoomFactor(zoomFactor); 05706 } 05707 } 05708 05709 void KHTMLPart::zoomOut(const int stepping[], int count) 05710 { 05711 int zoomFactor = d->m_zoomFactor; 05712 if (zoomFactor > minZoom) { 05713 // find the entry nearest to the given zoomsizes 05714 for (int i = count-1; i >= 0; --i) 05715 if (stepping[i] < zoomFactor) { 05716 zoomFactor = stepping[i]; 05717 break; 05718 } 05719 setZoomFactor(zoomFactor); 05720 } 05721 } 05722 05723 void KHTMLPart::setZoomFactor (int percent) 05724 { 05725 if (percent < minZoom) percent = minZoom; 05726 if (percent > maxZoom) percent = maxZoom; 05727 if (d->m_zoomFactor == percent) return; 05728 d->m_zoomFactor = percent; 05729 05730 if(d->m_doc) { 05731 QApplication::setOverrideCursor( waitCursor ); 05732 if (d->m_doc->styleSelector()) 05733 d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor); 05734 d->m_doc->recalcStyle( NodeImpl::Force ); 05735 QApplication::restoreOverrideCursor(); 05736 } 05737 05738 ConstFrameIt it = d->m_frames.begin(); 05739 const ConstFrameIt end = d->m_frames.end(); 05740 for (; it != end; ++it ) 05741 if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) { 05742 KParts::ReadOnlyPart* const p = ( *it )->m_part; 05743 static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor); 05744 } 05745 05746 if ( d->m_guiProfile == BrowserViewGUI ) { 05747 d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom ); 05748 d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom ); 05749 } 05750 } 05751 05752 void KHTMLPart::slotZoomView( int delta ) 05753 { 05754 if ( delta < 0 ) 05755 slotIncZoom(); 05756 else 05757 slotDecZoom(); 05758 } 05759 05760 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p) 05761 { 05762 if (!d->m_statusMessagesEnabled) 05763 return; 05764 05765 d->m_statusBarText[p] = text; 05766 05767 // shift handling ? 05768 QString tobe = d->m_statusBarText[BarHoverText]; 05769 if (tobe.isEmpty()) 05770 tobe = d->m_statusBarText[BarOverrideText]; 05771 if (tobe.isEmpty()) { 05772 tobe = d->m_statusBarText[BarDefaultText]; 05773 if (!tobe.isEmpty() && d->m_jobspeed) 05774 tobe += " "; 05775 if (d->m_jobspeed) 05776 tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) ); 05777 } 05778 tobe = "<qt>"+tobe; 05779 05780 emit ReadOnlyPart::setStatusBarText(tobe); 05781 } 05782 05783 05784 void KHTMLPart::setJSStatusBarText( const QString &text ) 05785 { 05786 setStatusBarText(text, BarOverrideText); 05787 } 05788 05789 void KHTMLPart::setJSDefaultStatusBarText( const QString &text ) 05790 { 05791 setStatusBarText(text, BarDefaultText); 05792 } 05793 05794 QString KHTMLPart::jsStatusBarText() const 05795 { 05796 return d->m_statusBarText[BarOverrideText]; 05797 } 05798 05799 QString KHTMLPart::jsDefaultStatusBarText() const 05800 { 05801 return d->m_statusBarText[BarDefaultText]; 05802 } 05803 05804 QString KHTMLPart::referrer() const 05805 { 05806 return d->m_referrer; 05807 } 05808 05809 QString KHTMLPart::pageReferrer() const 05810 { 05811 KURL referrerURL = KURL( d->m_pageReferrer ); 05812 if (referrerURL.isValid()) 05813 { 05814 QString protocol = referrerURL.protocol(); 05815 05816 if ((protocol == "http") || 05817 ((protocol == "https") && (m_url.protocol() == "https"))) 05818 { 05819 referrerURL.setRef(QString::null); 05820 referrerURL.setUser(QString::null); 05821 referrerURL.setPass(QString::null); 05822 return referrerURL.url(); 05823 } 05824 } 05825 05826 return QString::null; 05827 } 05828 05829 05830 QString KHTMLPart::lastModified() const 05831 { 05832 if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) { 05833 // Local file: set last-modified from the file's mtime. 05834 // Done on demand to save time when this isn't needed - but can lead 05835 // to slightly wrong results if updating the file on disk w/o reloading. 05836 QDateTime lastModif = QFileInfo( m_url.path() ).lastModified(); 05837 d->m_lastModified = lastModif.toString( Qt::LocalDate ); 05838 } 05839 //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl; 05840 return d->m_lastModified; 05841 } 05842 05843 void KHTMLPart::slotLoadImages() 05844 { 05845 if (d->m_doc ) 05846 d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() ); 05847 05848 ConstFrameIt it = d->m_frames.begin(); 05849 const ConstFrameIt end = d->m_frames.end(); 05850 for (; it != end; ++it ) 05851 if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) { 05852 KParts::ReadOnlyPart* const p = ( *it )->m_part; 05853 static_cast<KHTMLPart*>( p )->slotLoadImages(); 05854 } 05855 } 05856 05857 void KHTMLPart::reparseConfiguration() 05858 { 05859 KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings(); 05860 settings->init(); 05861 05862 setAutoloadImages( settings->autoLoadImages() ); 05863 if (d->m_doc) 05864 d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() ); 05865 05866 d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled(); 05867 d->m_bBackRightClick = settings->isBackRightClickEnabled(); 05868 d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host()); 05869 setDebugScript( settings->isJavaScriptDebugEnabled() ); 05870 d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host()); 05871 d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host()); 05872 d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled (); 05873 05874 delete d->m_settings; 05875 d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings()); 05876 05877 QApplication::setOverrideCursor( waitCursor ); 05878 khtml::CSSStyleSelector::reparseConfiguration(); 05879 if(d->m_doc) d->m_doc->updateStyleSelector(); 05880 QApplication::restoreOverrideCursor(); 05881 05882 if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled()) 05883 runAdFilter(); 05884 } 05885 05886 QStringList KHTMLPart::frameNames() const 05887 { 05888 QStringList res; 05889 05890 ConstFrameIt it = d->m_frames.begin(); 05891 const ConstFrameIt end = d->m_frames.end(); 05892 for (; it != end; ++it ) 05893 if (!(*it)->m_bPreloaded) 05894 res += (*it)->m_name; 05895 05896 return res; 05897 } 05898 05899 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const 05900 { 05901 QPtrList<KParts::ReadOnlyPart> res; 05902 05903 ConstFrameIt it = d->m_frames.begin(); 05904 const ConstFrameIt end = d->m_frames.end(); 05905 for (; it != end; ++it ) 05906 if (!(*it)->m_bPreloaded) 05907 res.append( (*it)->m_part ); 05908 05909 return res; 05910 } 05911 05912 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs ) 05913 { 05914 kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl; 05915 FrameIt it = d->m_frames.find( urlArgs.frameName ); 05916 05917 if ( it == d->m_frames.end() ) 05918 return false; 05919 05920 // Inform someone that we are about to show something else. 05921 if ( !urlArgs.lockHistory() ) 05922 emit d->m_extension->openURLNotify(); 05923 05924 requestObject( *it, url, urlArgs ); 05925 05926 return true; 05927 } 05928 05929 void KHTMLPart::setDNDEnabled( bool b ) 05930 { 05931 d->m_bDnd = b; 05932 } 05933 05934 bool KHTMLPart::dndEnabled() const 05935 { 05936 return d->m_bDnd; 05937 } 05938 05939 void KHTMLPart::customEvent( QCustomEvent *event ) 05940 { 05941 if ( khtml::MousePressEvent::test( event ) ) 05942 { 05943 khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) ); 05944 return; 05945 } 05946 05947 if ( khtml::MouseDoubleClickEvent::test( event ) ) 05948 { 05949 khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) ); 05950 return; 05951 } 05952 05953 if ( khtml::MouseMoveEvent::test( event ) ) 05954 { 05955 khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) ); 05956 return; 05957 } 05958 05959 if ( khtml::MouseReleaseEvent::test( event ) ) 05960 { 05961 khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) ); 05962 return; 05963 } 05964 05965 if ( khtml::DrawContentsEvent::test( event ) ) 05966 { 05967 khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) ); 05968 return; 05969 } 05970 05971 KParts::ReadOnlyPart::customEvent( event ); 05972 } 05973 05979 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset) 05980 { 05981 for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) { 05982 if (n->isText()) { 05983 khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n); 05984 const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes(); 05985 const unsigned lim = runs.count(); 05986 for (unsigned i = 0; i != lim; ++i) { 05987 if (runs[i]->m_y == y && textRenderer->element()) { 05988 startNode = textRenderer->element(); 05989 startOffset = runs[i]->m_start; 05990 return true; 05991 } 05992 } 05993 } 05994 05995 if (firstRunAt(n->firstChild(), y, startNode, startOffset)) { 05996 return true; 05997 } 05998 } 05999 06000 return false; 06001 } 06002 06008 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset) 06009 { 06010 khtml::RenderObject *n = renderNode; 06011 if (!n) { 06012 return false; 06013 } 06014 khtml::RenderObject *next; 06015 while ((next = n->nextSibling())) { 06016 n = next; 06017 } 06018 06019 while (1) { 06020 if (lastRunAt(n->firstChild(), y, endNode, endOffset)) { 06021 return true; 06022 } 06023 06024 if (n->isText()) { 06025 khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n); 06026 const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes(); 06027 for (int i = (int)runs.count()-1; i >= 0; --i) { 06028 if (runs[i]->m_y == y && textRenderer->element()) { 06029 endNode = textRenderer->element(); 06030 endOffset = runs[i]->m_start + runs[i]->m_len; 06031 return true; 06032 } 06033 } 06034 } 06035 06036 if (n == renderNode) { 06037 return false; 06038 } 06039 06040 n = n->previousSibling(); 06041 } 06042 } 06043 06044 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event ) 06045 { 06046 DOM::DOMString url = event->url(); 06047 QMouseEvent *_mouse = event->qmouseEvent(); 06048 DOM::Node innerNode = event->innerNode(); 06049 d->m_mousePressNode = innerNode; 06050 06051 d->m_dragStartPos = _mouse->pos(); 06052 06053 if ( !event->url().isNull() ) { 06054 d->m_strSelectedURL = event->url().string(); 06055 d->m_strSelectedURLTarget = event->target().string(); 06056 } 06057 else 06058 d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null; 06059 06060 if ( _mouse->button() == LeftButton || 06061 _mouse->button() == MidButton ) 06062 { 06063 d->m_bMousePressed = true; 06064 06065 #ifndef KHTML_NO_SELECTION 06066 if ( _mouse->button() == LeftButton ) 06067 { 06068 if ( (!d->m_strSelectedURL.isNull() && !isEditable()) 06069 || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) 06070 return; 06071 if ( !innerNode.isNull() && innerNode.handle()->renderer()) { 06072 int offset = 0; 06073 DOM::NodeImpl* node = 0; 06074 khtml::RenderObject::SelPointState state; 06075 innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(), 06076 event->absX()-innerNode.handle()->renderer()->xPos(), 06077 event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state ); 06078 d->m_extendMode = d->ExtendByChar; 06079 #ifdef KHTML_NO_CARET 06080 d->m_selectionStart = node; 06081 d->m_startOffset = offset; 06082 //if ( node ) 06083 // kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer() 06084 // << " offset=" << d->m_startOffset << endl; 06085 //else 06086 // kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl; 06087 d->m_selectionEnd = d->m_selectionStart; 06088 d->m_endOffset = d->m_startOffset; 06089 d->m_doc->clearSelection(); 06090 #else // KHTML_NO_CARET 06091 d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0); 06092 #endif // KHTML_NO_CARET 06093 d->m_initialNode = d->m_selectionStart; 06094 d->m_initialOffset = d->m_startOffset; 06095 // kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl; 06096 } 06097 else 06098 { 06099 #ifndef KHTML_NO_CARET 06100 // simply leave it. Is this a good idea? 06101 #else 06102 d->m_selectionStart = DOM::Node(); 06103 d->m_selectionEnd = DOM::Node(); 06104 #endif 06105 } 06106 emitSelectionChanged(); 06107 startAutoScroll(); 06108 } 06109 #else 06110 d->m_dragLastPos = _mouse->globalPos(); 06111 #endif 06112 } 06113 06114 if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick ) 06115 { 06116 d->m_bRightMousePressed = true; 06117 } else if ( _mouse->button() == RightButton ) 06118 { 06119 popupMenu( d->m_strSelectedURL ); 06120 // might be deleted, don't touch "this" 06121 } 06122 } 06123 06124 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event ) 06125 { 06126 QMouseEvent *_mouse = event->qmouseEvent(); 06127 if ( _mouse->button() == LeftButton ) 06128 { 06129 d->m_bMousePressed = true; 06130 DOM::Node innerNode = event->innerNode(); 06131 // Find selectionStart again, khtmlMouseReleaseEvent lost it 06132 if ( !innerNode.isNull() && innerNode.handle()->renderer()) { 06133 int offset = 0; 06134 DOM::NodeImpl* node = 0; 06135 khtml::RenderObject::SelPointState state; 06136 innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(), 06137 event->absX()-innerNode.handle()->renderer()->xPos(), 06138 event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state); 06139 06140 //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl; 06141 06142 if ( node && node->renderer() ) 06143 { 06144 // Extend selection to a complete word (double-click) or line (triple-click) 06145 bool selectLine = (event->clickCount() == 3); 06146 d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord; 06147 06148 // Extend existing selection if Shift was pressed 06149 if (_mouse->state() & ShiftButton) { 06150 d->caretNode() = node; 06151 d->caretOffset() = offset; 06152 d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints( 06153 d->m_selectionStart.handle(), d->m_startOffset, 06154 d->m_selectionEnd.handle(), d->m_endOffset) <= 0; 06155 d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd; 06156 d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset; 06157 } else { 06158 d->m_selectionStart = d->m_selectionEnd = node; 06159 d->m_startOffset = d->m_endOffset = offset; 06160 d->m_startBeforeEnd = true; 06161 d->m_initialNode = node; 06162 d->m_initialOffset = offset; 06163 } 06164 // kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl; 06165 06166 // Extend the start 06167 extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine ); 06168 // Extend the end 06169 extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine ); 06170 06171 //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << " - " << 06172 // d->m_selectionEnd.handle() << " " << d->m_endOffset << endl; 06173 06174 emitSelectionChanged(); 06175 d->m_doc 06176 ->setSelection(d->m_selectionStart.handle(),d->m_startOffset, 06177 d->m_selectionEnd.handle(),d->m_endOffset); 06178 #ifndef KHTML_NO_CARET 06179 bool v = d->m_view->placeCaret(); 06180 emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset()); 06181 #endif 06182 startAutoScroll(); 06183 } 06184 } 06185 } 06186 } 06187 06188 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines ) 06189 { 06190 khtml::RenderObject* obj = node->renderer(); 06191 06192 if (obj->isText() && selectLines) { 06193 int pos; 06194 khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj); 06195 khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos ); 06196 DOMString t = node->nodeValue(); 06197 DOM::NodeImpl* selNode = 0; 06198 long selOfs = 0; 06199 06200 if (!run) 06201 return; 06202 06203 int selectionPointY = run->m_y; 06204 06205 // Go up to first non-inline element. 06206 khtml::RenderObject *renderNode = renderer; 06207 while (renderNode && renderNode->isInline()) 06208 renderNode = renderNode->parent(); 06209 06210 renderNode = renderNode->firstChild(); 06211 06212 if (right) { 06213 // Look for all the last child in the block that is on the same line 06214 // as the selection point. 06215 if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs)) 06216 return; 06217 } else { 06218 // Look for all the first child in the block that is on the same line 06219 // as the selection point. 06220 if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs)) 06221 return; 06222 } 06223 06224 selectionNode = selNode; 06225 selectionOffset = selOfs; 06226 return; 06227 } 06228 06229 QString str; 06230 int len = 0; 06231 if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button 06232 str = static_cast<khtml::RenderText *>(obj)->data().string(); 06233 len = str.length(); 06234 } 06235 //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl; 06236 QChar ch; 06237 do { 06238 // Last char was ok, point to it 06239 if ( node ) { 06240 selectionNode = node; 06241 selectionOffset = offset; 06242 } 06243 06244 // Get another char 06245 while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) ) 06246 { 06247 obj = right ? obj->objectBelow() : obj->objectAbove(); 06248 //kdDebug() << "obj=" << obj << endl; 06249 if ( obj ) { 06250 //kdDebug() << "isText=" << obj->isText() << endl; 06251 str = QString::null; 06252 if ( obj->isText() ) 06253 str = static_cast<khtml::RenderText *>(obj)->data().string(); 06254 else if ( obj->isBR() ) 06255 str = '\n'; 06256 else if ( !obj->isInline() ) { 06257 obj = 0L; // parag limit -> done 06258 break; 06259 } 06260 len = str.length(); 06261 //kdDebug() << "str=" << str << " length=" << len << endl; 06262 // set offset - note that the first thing will be a ++ or -- on it. 06263 if ( right ) 06264 offset = -1; 06265 else 06266 offset = len; 06267 } 06268 } 06269 if ( !obj ) // end of parag or document 06270 break; 06271 node = obj->element(); 06272 if ( right ) 06273 { 06274 Q_ASSERT( offset < len-1 ); 06275 ++offset; 06276 } 06277 else 06278 { 06279 Q_ASSERT( offset > 0 ); 06280 --offset; 06281 } 06282 06283 // Test that char 06284 ch = str[ (int)offset ]; 06285 //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl; 06286 } while ( !ch.isSpace() && !ch.isPunct() ); 06287 06288 // make offset point after last char 06289 if (right) ++selectionOffset; 06290 } 06291 06292 #ifndef KHTML_NO_SELECTION 06293 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode) 06294 { 06295 int offset; 06296 //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl; 06297 DOM::NodeImpl* node=0; 06298 khtml::RenderObject::SelPointState state; 06299 innerNode.handle()->renderer()->checkSelectionPoint( x, y, 06300 absX-innerNode.handle()->renderer()->xPos(), 06301 absY-innerNode.handle()->renderer()->yPos(), node, offset, state); 06302 if (!node || !node->renderer()) return; 06303 06304 // Words at the beginning/end of line cannot be deselected in 06305 // ExtendByWord mode. Therefore, do not enforce it if the selection 06306 // point does not match the node under the mouse cursor. 06307 bool withinNode = innerNode == node; 06308 06309 // we have to get to know if end is before start or not... 06310 // shouldn't be null but it can happen with dynamic updating of nodes 06311 if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() || 06312 d->m_initialNode.isNull() || 06313 !d->m_selectionStart.handle()->renderer() || 06314 !d->m_selectionEnd.handle()->renderer()) return; 06315 06316 if (d->m_extendMode != d->ExtendByChar) { 06317 // check whether we should extend at the front, or at the back 06318 bool caretBeforeInit = RangeImpl::compareBoundaryPoints( 06319 d->caretNode().handle(), d->caretOffset(), 06320 d->m_initialNode.handle(), d->m_initialOffset) <= 0; 06321 bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset, 06322 d->m_initialNode.handle(), d->m_initialOffset) <= 0; 06323 // have to fix up start to point to the original end 06324 if (caretBeforeInit != nodeBeforeInit) { 06325 // kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl; 06326 extendSelection(d->m_initialNode.handle(), d->m_initialOffset, 06327 d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd, 06328 d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset, 06329 nodeBeforeInit, d->m_extendMode == d->ExtendByLine); 06330 } 06331 } 06332 06333 d->caretNode() = node; 06334 d->caretOffset() = offset; 06335 //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl; 06336 06337 d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints( 06338 d->m_selectionStart.handle(), d->m_startOffset, 06339 d->m_selectionEnd.handle(), d->m_endOffset) <= 0; 06340 06341 if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() ) 06342 { 06343 // kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl; 06344 if (d->m_extendMode != d->ExtendByChar && withinNode) 06345 extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine ); 06346 06347 if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset) 06348 d->m_doc 06349 ->setSelection(d->m_selectionStart.handle(),d->m_endOffset, 06350 d->m_selectionEnd.handle(),d->m_startOffset); 06351 else if (d->m_startBeforeEnd) 06352 d->m_doc 06353 ->setSelection(d->m_selectionStart.handle(),d->m_startOffset, 06354 d->m_selectionEnd.handle(),d->m_endOffset); 06355 else 06356 d->m_doc 06357 ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset, 06358 d->m_selectionStart.handle(),d->m_startOffset); 06359 } 06360 #ifndef KHTML_NO_CARET 06361 d->m_view->placeCaret(); 06362 #endif 06363 } 06364 06365 bool KHTMLPart::isExtendingSelection() const 06366 { 06367 // This is it, the whole detection. khtmlMousePressEvent only sets this 06368 // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB, 06369 // it's sufficient to only rely on this flag to detect selection extension. 06370 return d->m_bMousePressed; 06371 } 06372 #endif // KHTML_NO_SELECTION 06373 06374 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event ) 06375 { 06376 QMouseEvent *_mouse = event->qmouseEvent(); 06377 06378 if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick ) 06379 { 06380 popupMenu( d->m_strSelectedURL ); 06381 d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null; 06382 d->m_bRightMousePressed = false; 06383 } 06384 06385 DOM::DOMString url = event->url(); 06386 DOM::DOMString target = event->target(); 06387 DOM::Node innerNode = event->innerNode(); 06388 06389 #ifndef QT_NO_DRAGANDDROP 06390 if( d->m_bDnd && d->m_bMousePressed && 06391 ( (!d->m_strSelectedURL.isEmpty() && !isEditable()) 06392 || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) { 06393 if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() ) 06394 return; 06395 06396 QPixmap pix; 06397 HTMLImageElementImpl *img = 0L; 06398 QDragObject *drag = 0; 06399 KURL u; 06400 06401 // qDebug("****************** Event URL: %s", url.string().latin1()); 06402 // qDebug("****************** Event Target: %s", target.string().latin1()); 06403 06404 // Normal image... 06405 if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG ) 06406 { 06407 img = static_cast<HTMLImageElementImpl *>(innerNode.handle()); 06408 u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) ); 06409 pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop); 06410 } 06411 else 06412 { 06413 // Text or image link... 06414 u = completeURL( d->m_strSelectedURL ); 06415 pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium); 06416 } 06417 06418 u.setPass(QString::null); 06419 06420 KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() ); 06421 if ( !d->m_referrer.isEmpty() ) 06422 urlDrag->metaData()["referrer"] = d->m_referrer; 06423 06424 if( img && img->complete()) { 06425 KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() ); 06426 mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) ); 06427 mdrag->addDragObject( urlDrag ); 06428 drag = mdrag; 06429 } 06430 else 06431 drag = urlDrag; 06432 06433 if ( !pix.isNull() ) 06434 drag->setPixmap( pix ); 06435 06436 stopAutoScroll(); 06437 if(drag) 06438 drag->drag(); 06439 06440 // when we finish our drag, we need to undo our mouse press 06441 d->m_bMousePressed = false; 06442 d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null; 06443 return; 06444 } 06445 #endif 06446 06447 // Not clicked -> mouse over stuff 06448 if ( !d->m_bMousePressed ) 06449 { 06450 // The mouse is over something 06451 if ( url.length() ) 06452 { 06453 bool shiftPressed = ( _mouse->state() & ShiftButton ); 06454 06455 // Image map 06456 if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG ) 06457 { 06458 HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle()); 06459 if ( i && i->isServerMap() ) 06460 { 06461 khtml::RenderObject *r = i->renderer(); 06462 if(r) 06463 { 06464 int absx, absy, vx, vy; 06465 r->absolutePosition(absx, absy); 06466 view()->contentsToViewport( absx, absy, vx, vy ); 06467 06468 int x(_mouse->x() - vx), y(_mouse->y() - vy); 06469 06470 d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y); 06471 d->m_overURLTarget = target.string(); 06472 overURL( d->m_overURL, target.string(), shiftPressed ); 06473 return; 06474 } 06475 } 06476 } 06477 06478 // normal link 06479 if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target ) 06480 { 06481 d->m_overURL = url.string(); 06482 d->m_overURLTarget = target.string(); 06483 overURL( d->m_overURL, target.string(), shiftPressed ); 06484 } 06485 } 06486 else // Not over a link... 06487 { 06488 // reset to "default statusbar text" 06489 resetHoverText(); 06490 } 06491 } 06492 else { 06493 #ifndef KHTML_NO_SELECTION 06494 // selection stuff 06495 if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() && 06496 ( (_mouse->state() & LeftButton) != 0 )) { 06497 extendSelectionTo(event->x(), event->y(), 06498 event->absX(), event->absY(), innerNode); 06499 #else 06500 if ( d->m_doc && d->m_view ) { 06501 QPoint diff( _mouse->globalPos() - d->m_dragLastPos ); 06502 06503 if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) { 06504 d->m_view->scrollBy( -diff.x(), -diff.y() ); 06505 d->m_dragLastPos = _mouse->globalPos(); 06506 } 06507 #endif 06508 } 06509 } 06510 06511 } 06512 06513 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event ) 06514 { 06515 DOM::Node innerNode = event->innerNode(); 06516 d->m_mousePressNode = DOM::Node(); 06517 06518 if ( d->m_bMousePressed ) { 06519 setStatusBarText(QString::null, BarHoverText); 06520 stopAutoScroll(); 06521 } 06522 06523 // Used to prevent mouseMoveEvent from initiating a drag before 06524 // the mouse is pressed again. 06525 d->m_bMousePressed = false; 06526 06527 QMouseEvent *_mouse = event->qmouseEvent(); 06528 if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick ) 06529 { 06530 d->m_bRightMousePressed = false; 06531 KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface(); 06532 if( tmp_iface ) { 06533 tmp_iface->callMethod( "goHistory(int)", -1 ); 06534 } 06535 } 06536 #ifndef QT_NO_CLIPBOARD 06537 if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) { 06538 kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen=" 06539 << d->m_bOpenMiddleClick << endl; 06540 06541 if (d->m_bOpenMiddleClick) { 06542 KHTMLPart *p = this; 06543 while (p->parentPart()) p = p->parentPart(); 06544 p->d->m_extension->pasteRequest(); 06545 } 06546 } 06547 #endif 06548 06549 #ifndef KHTML_NO_SELECTION 06550 // delete selection in case start and end position are at the same point 06551 if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) { 06552 #ifndef KHTML_NO_CARET 06553 d->m_extendAtEnd = true; 06554 #else 06555 d->m_selectionStart = 0; 06556 d->m_selectionEnd = 0; 06557 d->m_startOffset = 0; 06558 d->m_endOffset = 0; 06559 #endif 06560 emitSelectionChanged(); 06561 } else { 06562 // we have to get to know if end is before start or not... 06563 // kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl; 06564 DOM::Node n = d->m_selectionStart; 06565 d->m_startBeforeEnd = false; 06566 if( d->m_selectionStart == d->m_selectionEnd ) { 06567 if( d->m_startOffset < d->m_endOffset ) 06568 d->m_startBeforeEnd = true; 06569 } else { 06570 #if 0 06571 while(!n.isNull()) { 06572 if(n == d->m_selectionEnd) { 06573 d->m_startBeforeEnd = true; 06574 break; 06575 } 06576 DOM::Node next = n.firstChild(); 06577 if(next.isNull()) next = n.nextSibling(); 06578 while( next.isNull() && !n.parentNode().isNull() ) { 06579 n = n.parentNode(); 06580 next = n.nextSibling(); 06581 } 06582 n = next; 06583 } 06584 #else 06585 // shouldn't be null but it can happen with dynamic updating of nodes 06586 if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() || 06587 !d->m_selectionStart.handle()->renderer() || 06588 !d->m_selectionEnd.handle()->renderer()) return; 06589 d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints( 06590 d->m_selectionStart.handle(), d->m_startOffset, 06591 d->m_selectionEnd.handle(), d->m_endOffset) <= 0; 06592 #endif 06593 } 06594 if(!d->m_startBeforeEnd) 06595 { 06596 DOM::Node tmpNode = d->m_selectionStart; 06597 int tmpOffset = d->m_startOffset; 06598 d->m_selectionStart = d->m_selectionEnd; 06599 d->m_startOffset = d->m_endOffset; 06600 d->m_selectionEnd = tmpNode; 06601 d->m_endOffset = tmpOffset; 06602 d->m_startBeforeEnd = true; 06603 d->m_extendAtEnd = !d->m_extendAtEnd; 06604 } 06605 #ifndef KHTML_NO_CARET 06606 bool v = d->m_view->placeCaret(); 06607 emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset()); 06608 #endif 06609 // get selected text and paste to the clipboard 06610 #ifndef QT_NO_CLIPBOARD 06611 QString text = selectedText(); 06612 text.replace(QChar(0xa0), ' '); 06613 disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection())); 06614 kapp->clipboard()->setText(text,QClipboard::Selection); 06615 connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection())); 06616 #endif 06617 //kdDebug( 6000 ) << "selectedText = " << text << endl; 06618 emitSelectionChanged(); 06619 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl; 06620 } 06621 #endif 06622 d->m_initialNode = 0; // don't hold nodes longer than necessary 06623 d->m_initialOffset = 0; 06624 06625 } 06626 06627 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * ) 06628 { 06629 } 06630 06631 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event ) 06632 { 06633 if ( event->activated() ) 06634 { 06635 emitSelectionChanged(); 06636 emit d->m_extension->enableAction( "print", d->m_doc != 0 ); 06637 06638 if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages ) 06639 { 06640 QPtrList<KAction> lst; 06641 lst.append( d->m_paLoadImages ); 06642 plugActionList( "loadImages", lst ); 06643 } 06644 } 06645 } 06646 06647 void KHTMLPart::slotPrintFrame() 06648 { 06649 if ( d->m_frames.count() == 0 ) 06650 return; 06651 06652 KParts::ReadOnlyPart *frame = currentFrame(); 06653 if (!frame) 06654 return; 06655 06656 KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame ); 06657 06658 if ( !ext ) 06659 return; 06660 06661 QMetaObject *mo = ext->metaObject(); 06662 06663 int idx = mo->findSlot( "print()", true ); 06664 if ( idx >= 0 ) { 06665 QUObject o[ 1 ]; 06666 ext->qt_invoke( idx, o ); 06667 } 06668 } 06669 06670 void KHTMLPart::slotSelectAll() 06671 { 06672 KParts::ReadOnlyPart *part = currentFrame(); 06673 if (part && part->inherits("KHTMLPart")) 06674 static_cast<KHTMLPart *>(part)->selectAll(); 06675 } 06676 06677 void KHTMLPart::startAutoScroll() 06678 { 06679 connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() )); 06680 d->m_scrollTimer.start(100, false); 06681 } 06682 06683 void KHTMLPart::stopAutoScroll() 06684 { 06685 disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() )); 06686 if (d->m_scrollTimer.isActive()) 06687 d->m_scrollTimer.stop(); 06688 } 06689 06690 06691 void KHTMLPart::slotAutoScroll() 06692 { 06693 if (d->m_view) 06694 d->m_view->doAutoScroll(); 06695 else 06696 stopAutoScroll(); // Safety 06697 } 06698 06699 void KHTMLPart::runAdFilter() 06700 { 06701 if ( parentPart() ) 06702 parentPart()->runAdFilter(); 06703 06704 if ( !d->m_doc ) 06705 return; 06706 06707 QPtrDictIterator<khtml::CachedObject> it( d->m_doc->docLoader()->m_docObjects ); 06708 for ( ; it.current(); ++it ) 06709 if ( it.current()->type() == khtml::CachedObject::Image ) { 06710 khtml::CachedImage *image = static_cast<khtml::CachedImage *>(it.current()); 06711 bool wasBlocked = image->m_wasBlocked; 06712 image->m_wasBlocked = KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( (*it).url().string() ) ); 06713 if ( image->m_wasBlocked != wasBlocked ) 06714 image->do_notify(image->pixmap(), image->valid_rect()); 06715 } 06716 06717 if ( KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() ) { 06718 for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) { 06719 06720 // We might be deleting 'node' shortly. 06721 nextNode = node->traverseNextNode(); 06722 06723 if ( node->id() == ID_IMG || 06724 node->id() == ID_IFRAME || 06725 (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE )) 06726 { 06727 if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) ) 06728 { 06729 // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter. 06730 node->ref(); 06731 NodeImpl *parent = node->parent(); 06732 if( parent ) 06733 { 06734 int exception = 0; 06735 parent->removeChild(node, exception); 06736 } 06737 node->deref(); 06738 } 06739 } 06740 } 06741 } 06742 } 06743 06744 void KHTMLPart::selectAll() 06745 { 06746 if (!d->m_doc) return; 06747 06748 NodeImpl *first; 06749 if (d->m_doc->isHTMLDocument()) 06750 first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body(); 06751 else 06752 first = d->m_doc; 06753 NodeImpl *next; 06754 06755 // Look for first text/cdata node that has a renderer, 06756 // or first childless replaced element 06757 while ( first && !(first->renderer() 06758 && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE) 06759 || (first->renderer()->isReplaced() && !first->renderer()->firstChild())))) 06760 { 06761 next = first->firstChild(); 06762 if ( !next ) next = first->nextSibling(); 06763 while( first && !next ) 06764 { 06765 first = first->parentNode(); 06766 if ( first ) 06767 next = first->nextSibling(); 06768 } 06769 first = next; 06770 } 06771 06772 NodeImpl *last; 06773 if (d->m_doc->isHTMLDocument()) 06774 last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body(); 06775 else 06776 last = d->m_doc; 06777 // Look for last text/cdata node that has a renderer, 06778 // or last childless replaced element 06779 // ### Instead of changing this loop, use findLastSelectableNode 06780 // in render_table.cpp (LS) 06781 while ( last && !(last->renderer() 06782 && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE) 06783 || (last->renderer()->isReplaced() && !last->renderer()->lastChild())))) 06784 { 06785 next = last->lastChild(); 06786 if ( !next ) next = last->previousSibling(); 06787 while ( last && !next ) 06788 { 06789 last = last->parentNode(); 06790 if ( last ) 06791 next = last->previousSibling(); 06792 } 06793 last = next; 06794 } 06795 06796 if ( !first || !last ) 06797 return; 06798 Q_ASSERT(first->renderer()); 06799 Q_ASSERT(last->renderer()); 06800 d->m_selectionStart = first; 06801 d->m_startOffset = 0; 06802 d->m_selectionEnd = last; 06803 d->m_endOffset = last->nodeValue().length(); 06804 d->m_startBeforeEnd = true; 06805 06806 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset, 06807 d->m_selectionEnd.handle(), d->m_endOffset ); 06808 06809 emitSelectionChanged(); 06810 } 06811 06812 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button) 06813 { 06814 bool linkAllowed = true; 06815 06816 if ( d->m_doc ) 06817 linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL); 06818 06819 if ( !linkAllowed ) { 06820 khtml::Tokenizer *tokenizer = d->m_doc->tokenizer(); 06821 if (tokenizer) 06822 tokenizer->setOnHold(true); 06823 06824 int response = KMessageBox::Cancel; 06825 if (!message.isEmpty()) 06826 { 06827 response = KMessageBox::warningContinueCancel( 0, 06828 message.arg(linkURL.htmlURL()), 06829 i18n( "Security Warning" ), 06830 button); 06831 } 06832 else 06833 { 06834 KMessageBox::error( 0, 06835 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()), 06836 i18n( "Security Alert" )); 06837 } 06838 06839 if (tokenizer) 06840 tokenizer->setOnHold(false); 06841 return (response==KMessageBox::Continue); 06842 } 06843 return true; 06844 } 06845 06846 void KHTMLPart::slotPartRemoved( KParts::Part *part ) 06847 { 06848 // kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl; 06849 if ( part == d->m_activeFrame ) 06850 { 06851 d->m_activeFrame = 0L; 06852 if ( !part->inherits( "KHTMLPart" ) ) 06853 { 06854 if (factory()) { 06855 factory()->removeClient( part ); 06856 } 06857 if (childClients()->containsRef(part)) { 06858 removeChildClient( part ); 06859 } 06860 } 06861 } 06862 } 06863 06864 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part ) 06865 { 06866 // kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged this=" << this << "part=" << part << endl; 06867 if ( part == this ) 06868 { 06869 kdError(6050) << "strange error! we activated ourselves" << endl; 06870 assert( false ); 06871 return; 06872 } 06873 // kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl; 06874 if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) ) 06875 { 06876 QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() ); 06877 if (frame->frameStyle() != QFrame::NoFrame) 06878 { 06879 frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken); 06880 frame->repaint(); 06881 } 06882 } 06883 06884 if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) ) 06885 { 06886 if (factory()) { 06887 factory()->removeClient( d->m_activeFrame ); 06888 } 06889 removeChildClient( d->m_activeFrame ); 06890 } 06891 if( part && !part->inherits( "KHTMLPart" ) ) 06892 { 06893 if (factory()) { 06894 factory()->addClient( part ); 06895 } 06896 insertChildClient( part ); 06897 } 06898 06899 06900 d->m_activeFrame = part; 06901 06902 if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) ) 06903 { 06904 QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() ); 06905 if (frame->frameStyle() != QFrame::NoFrame) 06906 { 06907 frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain); 06908 frame->repaint(); 06909 } 06910 kdDebug(6050) << "new active frame " << d->m_activeFrame << endl; 06911 } 06912 06913 updateActions(); 06914 06915 // (note: childObject returns 0 if the argument is 0) 06916 d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) ); 06917 } 06918 06919 void KHTMLPart::setActiveNode(const DOM::Node &node) 06920 { 06921 if (!d->m_doc || !d->m_view) 06922 return; 06923 06924 // Set the document's active node 06925 d->m_doc->setFocusNode(node.handle()); 06926 06927 // Scroll the view if necessary to ensure that the new focus node is visible 06928 QRect rect = node.handle()->getRect(); 06929 d->m_view->ensureVisible(rect.right(), rect.bottom()); 06930 d->m_view->ensureVisible(rect.left(), rect.top()); 06931 } 06932 06933 DOM::Node KHTMLPart::activeNode() const 06934 { 06935 return DOM::Node(d->m_doc?d->m_doc->focusNode():0); 06936 } 06937 06938 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name, NodeImpl* node ) 06939 { 06940 KJSProxy *proxy = jScript(); 06941 06942 if (!proxy) 06943 return 0; 06944 06945 return proxy->createHTMLEventHandler( m_url.url(), name, code, node ); 06946 } 06947 06948 KHTMLPart *KHTMLPart::opener() 06949 { 06950 return d->m_opener; 06951 } 06952 06953 void KHTMLPart::setOpener(KHTMLPart *_opener) 06954 { 06955 d->m_opener = _opener; 06956 } 06957 06958 bool KHTMLPart::openedByJS() 06959 { 06960 return d->m_openedByJS; 06961 } 06962 06963 void KHTMLPart::setOpenedByJS(bool _openedByJS) 06964 { 06965 d->m_openedByJS = _openedByJS; 06966 } 06967 06968 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet) 06969 { 06970 khtml::Cache::preloadStyleSheet(url, stylesheet); 06971 } 06972 06973 void KHTMLPart::preloadScript(const QString &url, const QString &script) 06974 { 06975 khtml::Cache::preloadScript(url, script); 06976 } 06977 06978 QCString KHTMLPart::dcopObjectId() const 06979 { 06980 QCString id; 06981 id.sprintf("html-widget%d", d->m_dcop_counter); 06982 return id; 06983 } 06984 06985 long KHTMLPart::cacheId() const 06986 { 06987 return d->m_cacheId; 06988 } 06989 06990 bool KHTMLPart::restored() const 06991 { 06992 return d->m_restored; 06993 } 06994 06995 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const 06996 { 06997 // parentPart() should be const! 06998 KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart(); 06999 if ( parent ) 07000 return parent->pluginPageQuestionAsked(mimetype); 07001 07002 return d->m_pluginPageQuestionAsked.contains(mimetype); 07003 } 07004 07005 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype) 07006 { 07007 if ( parentPart() ) 07008 parentPart()->setPluginPageQuestionAsked(mimetype); 07009 07010 d->m_pluginPageQuestionAsked.append(mimetype); 07011 } 07012 07013 void KHTMLPart::slotAutomaticDetectionLanguage( int _id ) 07014 { 07015 d->m_automaticDetection->setItemChecked( _id, true ); 07016 07017 switch ( _id ) { 07018 case 0 : 07019 d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection; 07020 break; 07021 case 1 : 07022 d->m_autoDetectLanguage = khtml::Decoder::Arabic; 07023 break; 07024 case 2 : 07025 d->m_autoDetectLanguage = khtml::Decoder::Baltic; 07026 break; 07027 case 3 : 07028 d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean; 07029 break; 07030 case 4 : 07031 d->m_autoDetectLanguage = khtml::Decoder::Chinese; 07032 break; 07033 case 5 : 07034 d->m_autoDetectLanguage = khtml::Decoder::Greek; 07035 break; 07036 case 6 : 07037 d->m_autoDetectLanguage = khtml::Decoder::Hebrew; 07038 break; 07039 case 7 : 07040 d->m_autoDetectLanguage = khtml::Decoder::Japanese; 07041 break; 07042 case 8 : 07043 d->m_autoDetectLanguage = khtml::Decoder::Korean; 07044 break; 07045 case 9 : 07046 d->m_autoDetectLanguage = khtml::Decoder::Russian; 07047 break; 07048 case 10 : 07049 d->m_autoDetectLanguage = khtml::Decoder::Thai; 07050 break; 07051 case 11 : 07052 d->m_autoDetectLanguage = khtml::Decoder::Turkish; 07053 break; 07054 case 12 : 07055 d->m_autoDetectLanguage = khtml::Decoder::Ukrainian; 07056 break; 07057 case 13 : 07058 d->m_autoDetectLanguage = khtml::Decoder::Unicode; 07059 break; 07060 case 14 : 07061 d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean; 07062 break; 07063 default : 07064 d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection; 07065 break; 07066 } 07067 07068 for ( int i = 0; i <= 14; ++i ) { 07069 if ( i != _id ) 07070 d->m_automaticDetection->setItemChecked( i, false ); 07071 } 07072 07073 d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true ); 07074 07075 setEncoding( QString::null, false ); 07076 07077 if( d->m_manualDetection ) 07078 d->m_manualDetection->setCurrentItem( -1 ); 07079 d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false ); 07080 } 07081 07082 khtml::Decoder *KHTMLPart::createDecoder() 07083 { 07084 khtml::Decoder *dec = new khtml::Decoder(); 07085 if( !d->m_encoding.isNull() ) 07086 dec->setEncoding( d->m_encoding.latin1(), 07087 d->m_haveEncoding ? khtml::Decoder::UserChosenEncoding : khtml::Decoder::EncodingFromHTTPHeader); 07088 else { 07089 // Inherit the default encoding from the parent frame if there is one. 07090 const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder) 07091 ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1(); 07092 dec->setEncoding(defaultEncoding, khtml::Decoder::DefaultEncoding); 07093 } 07094 #ifdef APPLE_CHANGES 07095 if (d->m_doc) 07096 d->m_doc->setDecoder(d->m_decoder); 07097 #endif 07098 dec->setAutoDetectLanguage( d->m_autoDetectLanguage ); 07099 return dec; 07100 } 07101 07102 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) { 07103 emit caretPositionChanged(node, offset); 07104 } 07105 07106 void KHTMLPart::restoreScrollPosition() 07107 { 07108 KParts::URLArgs args = d->m_extension->urlArgs(); 07109 07110 if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) { 07111 if ( !d->m_doc || !d->m_doc->parsing() ) 07112 disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition())); 07113 if ( !gotoAnchor(m_url.encodedHtmlRef()) ) 07114 gotoAnchor(m_url.htmlRef()); 07115 return; 07116 } 07117 07118 // Check whether the viewport has become large enough to encompass the stored 07119 // offsets. If the document has been fully loaded, force the new coordinates, 07120 // even if the canvas is too short (can happen when user resizes the window 07121 // during loading). 07122 if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset 07123 || d->m_bComplete) { 07124 d->m_view->setContentsPos(args.xOffset, args.yOffset); 07125 disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition())); 07126 } 07127 } 07128 07129 07130 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form) 07131 { 07132 #ifndef KHTML_NO_WALLET 07133 KHTMLPart *p; 07134 07135 for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) { 07136 } 07137 07138 if (p) { 07139 p->openWallet(form); 07140 return; 07141 } 07142 07143 if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails 07144 return; 07145 } 07146 07147 if (d->m_wallet) { 07148 if (d->m_bWalletOpened) { 07149 if (d->m_wallet->isOpen()) { 07150 form->walletOpened(d->m_wallet); 07151 return; 07152 } 07153 d->m_wallet->deleteLater(); 07154 d->m_wallet = 0L; 07155 d->m_bWalletOpened = false; 07156 } 07157 } 07158 07159 if (!d->m_wq) { 07160 KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous); 07161 d->m_wq = new KHTMLWalletQueue(this); 07162 d->m_wq->wallet = wallet; 07163 connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool))); 07164 connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*))); 07165 } 07166 assert(form); 07167 d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument())); 07168 #endif // KHTML_NO_WALLET 07169 } 07170 07171 07172 void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data) 07173 { 07174 #ifndef KHTML_NO_WALLET 07175 KHTMLPart *p; 07176 07177 for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) { 07178 } 07179 07180 if (p) { 07181 p->saveToWallet(key, data); 07182 return; 07183 } 07184 07185 if (d->m_wallet) { 07186 if (d->m_bWalletOpened) { 07187 if (d->m_wallet->isOpen()) { 07188 if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) { 07189 d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder()); 07190 } 07191 d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder()); 07192 d->m_wallet->writeMap(key, data); 07193 return; 07194 } 07195 d->m_wallet->deleteLater(); 07196 d->m_wallet = 0L; 07197 d->m_bWalletOpened = false; 07198 } 07199 } 07200 07201 if (!d->m_wq) { 07202 KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous); 07203 d->m_wq = new KHTMLWalletQueue(this); 07204 d->m_wq->wallet = wallet; 07205 connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool))); 07206 connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*))); 07207 } 07208 d->m_wq->savers.append(qMakePair(key, data)); 07209 #endif // KHTML_NO_WALLET 07210 } 07211 07212 07213 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) { 07214 #ifndef KHTML_NO_WALLET 07215 KHTMLPart *p; 07216 07217 for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) { 07218 } 07219 07220 if (p) { 07221 p->dequeueWallet(form); 07222 return; 07223 } 07224 07225 if (d->m_wq) { 07226 d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument())); 07227 } 07228 #endif // KHTML_NO_WALLET 07229 } 07230 07231 07232 void KHTMLPart::walletOpened(KWallet::Wallet *wallet) { 07233 #ifndef KHTML_NO_WALLET 07234 assert(!d->m_wallet); 07235 assert(d->m_wq); 07236 07237 d->m_wq->deleteLater(); // safe? 07238 d->m_wq = 0L; 07239 07240 if (!wallet) { 07241 d->m_bWalletOpened = false; 07242 return; 07243 } 07244 07245 d->m_wallet = wallet; 07246 d->m_bWalletOpened = true; 07247 connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed())); 07248 07249 if (!d->m_statusBarWalletLabel) { 07250 d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar()); 07251 d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small)); 07252 d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); 07253 d->m_statusBarWalletLabel->setUseCursor(false); 07254 d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false); 07255 d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance())); 07256 connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager())); 07257 connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu())); 07258 } else { 07259 QToolTip::remove(d->m_statusBarWalletLabel); 07260 } 07261 QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet())); 07262 #endif // KHTML_NO_WALLET 07263 } 07264 07265 07266 KWallet::Wallet *KHTMLPart::wallet() 07267 { 07268 #ifndef KHTML_NO_WALLET 07269 KHTMLPart *p; 07270 07271 for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) 07272 ; 07273 07274 if (p) 07275 return p->wallet(); 07276 07277 #endif // KHTML_NO_WALLET 07278 return d->m_wallet; 07279 } 07280 07281 07282 void KHTMLPart::slotWalletClosed() 07283 { 07284 #ifndef KHTML_NO_WALLET 07285 if (d->m_wallet) { 07286 d->m_wallet->deleteLater(); 07287 d->m_wallet = 0L; 07288 } 07289 d->m_bWalletOpened = false; 07290 if (d->m_statusBarWalletLabel) { 07291 d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel); 07292 delete d->m_statusBarWalletLabel; 07293 d->m_statusBarWalletLabel = 0L; 07294 } 07295 #endif // KHTML_NO_WALLET 07296 } 07297 07298 void KHTMLPart::launchWalletManager() 07299 { 07300 #ifndef KHTML_NO_WALLET 07301 if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) { 07302 KApplication::startServiceByDesktopName("kwalletmanager_show"); 07303 } else { 07304 DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1"); 07305 r.send("show"); 07306 r.send("raise"); 07307 } 07308 #endif // KHTML_NO_WALLET 07309 } 07310 07311 void KHTMLPart::walletMenu() 07312 { 07313 #ifndef KHTML_NO_WALLET 07314 KPopupMenu *m = new KPopupMenu(0L); 07315 m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed())); 07316 m->popup(QCursor::pos()); 07317 #endif // KHTML_NO_WALLET 07318 } 07319 07320 void KHTMLPart::slotToggleCaretMode() 07321 { 07322 setCaretMode(d->m_paToggleCaretMode->isChecked()); 07323 } 07324 07325 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) { 07326 d->m_formNotification = fn; 07327 } 07328 07329 KHTMLPart::FormNotification KHTMLPart::formNotification() const { 07330 return d->m_formNotification; 07331 } 07332 07333 KURL KHTMLPart::toplevelURL() 07334 { 07335 KHTMLPart* part = this; 07336 while (part->parentPart()) 07337 part = part->parentPart(); 07338 07339 if (!part) 07340 return KURL(); 07341 07342 return part->url(); 07343 } 07344 07345 bool KHTMLPart::isModified() const 07346 { 07347 if ( !d->m_doc ) 07348 return false; 07349 07350 return d->m_doc->unsubmittedFormChanges(); 07351 } 07352 07353 void KHTMLPart::setDebugScript( bool enable ) 07354 { 07355 unplugActionList( "debugScriptList" ); 07356 if ( enable ) { 07357 if (!d->m_paDebugScript) { 07358 d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" ); 07359 } 07360 d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L ); 07361 QPtrList<KAction> lst; 07362 lst.append( d->m_paDebugScript ); 07363 plugActionList( "debugScriptList", lst ); 07364 } 07365 d->m_bJScriptDebugEnabled = enable; 07366 } 07367 07368 void KHTMLPart::setSuppressedPopupIndicator( bool enable ) 07369 { 07370 setSuppressedPopupIndicator( enable, 0 ); 07371 } 07372 07373 void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart ) 07374 { 07375 if ( parentPart() ) { 07376 parentPart()->setSuppressedPopupIndicator( enable, originPart ); 07377 return; 07378 } 07379 07380 if ( enable && originPart ) { 07381 d->m_openableSuppressedPopups++; 07382 if ( d->m_suppressedPopupOriginParts.findIndex( originPart ) == -1 ) 07383 d->m_suppressedPopupOriginParts.append( originPart ); 07384 } 07385 07386 if ( enable && !d->m_statusBarPopupLabel ) { 07387 d->m_statusBarPopupLabel = new KURLLabel( d->m_statusBarExtension->statusBar() ); 07388 d->m_statusBarPopupLabel->setFixedHeight( instance()->iconLoader()->currentSize( KIcon::Small) ); 07389 d->m_statusBarPopupLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed )); 07390 d->m_statusBarPopupLabel->setUseCursor( false ); 07391 d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false ); 07392 d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) ); 07393 QToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) ); 07394 07395 connect(d->m_statusBarPopupLabel, SIGNAL(leftClickedURL()), SLOT(suppressedPopupMenu())); 07396 if (d->m_settings->jsPopupBlockerPassivePopup()) { 07397 QPixmap px; 07398 px = MainBarIcon( "window_suppressed" ); 07399 KPassivePopup::message(i18n("Popup Window Blocked"),i18n("This page has attempted to open a popup window but was blocked.\nYou can click on this icon in the status bar to control this behavior\nor to open the popup."),px,d->m_statusBarPopupLabel); 07400 } 07401 } else if ( !enable && d->m_statusBarPopupLabel ) { 07402 QToolTip::remove( d->m_statusBarPopupLabel ); 07403 d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel ); 07404 delete d->m_statusBarPopupLabel; 07405 d->m_statusBarPopupLabel = 0L; 07406 } 07407 } 07408 07409 void KHTMLPart::suppressedPopupMenu() { 07410 KPopupMenu *m = new KPopupMenu(0L); 07411 m->setCheckable(true); 07412 if ( d->m_openableSuppressedPopups ) 07413 m->insertItem(i18n("&Show Blocked Popup Window","Show %n Blocked Popup Windows", d->m_openableSuppressedPopups), this, SLOT(showSuppressedPopups())); 07414 m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()),0,57); 07415 m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup()); 07416 m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog())); 07417 m->popup(QCursor::pos()); 07418 } 07419 07420 void KHTMLPart::togglePopupPassivePopup() { 07421 // Same hack as in disableJSErrorExtension() 07422 d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() ); 07423 DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray()); 07424 } 07425 07426 void KHTMLPart::showSuppressedPopups() { 07427 for ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin(); 07428 i != d->m_suppressedPopupOriginParts.end(); ++i ) { 07429 if (KHTMLPart* part = *i) { 07430 KJS::Window *w = KJS::Window::retrieveWindow( part ); 07431 if (w) { 07432 w->showSuppressedWindows(); 07433 w->forgetSuppressedWindows(); 07434 } 07435 } 07436 } 07437 setSuppressedPopupIndicator( false ); 07438 d->m_openableSuppressedPopups = 0; 07439 d->m_suppressedPopupOriginParts.clear(); 07440 } 07441 07442 // Extension to use for "view document source", "save as" etc. 07443 // Using the right extension can help the viewer get into the right mode (#40496) 07444 QString KHTMLPart::defaultExtension() const 07445 { 07446 if ( !d->m_doc ) 07447 return ".html"; 07448 if ( !d->m_doc->isHTMLDocument() ) 07449 return ".xml"; 07450 return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html"; 07451 } 07452 07453 bool KHTMLPart::inProgress() const 07454 { 07455 if (d->m_runningScripts || (d->m_doc && d->m_doc->parsing())) 07456 return true; 07457 07458 // Any frame that hasn't completed yet ? 07459 ConstFrameIt it = d->m_frames.begin(); 07460 const ConstFrameIt end = d->m_frames.end(); 07461 for (; it != end; ++it ) { 07462 if ((*it)->m_run || !(*it)->m_bCompleted) 07463 return true; 07464 } 07465 07466 return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job; 07467 } 07468 07469 using namespace KParts; 07470 #include "khtml_part.moc" 07471 #include "khtmlpart_p.moc"