00001
00024 #include "html/html_documentimpl.h"
00025 #include "html/html_imageimpl.h"
00026 #include "html/html_headimpl.h"
00027 #include "html/html_baseimpl.h"
00028 #include "html/htmltokenizer.h"
00029 #include "html/html_miscimpl.h"
00030
00031 #include "khtmlview.h"
00032 #include "khtml_part.h"
00033 #include "khtmlpart_p.h"
00034 #include "khtml_settings.h"
00035 #include "misc/htmlattrs.h"
00036 #include "misc/htmlhashes.h"
00037
00038 #include "xml/xml_tokenizer.h"
00039 #include "xml/dom2_eventsimpl.h"
00040
00041 #include "khtml_factory.h"
00042 #include "rendering/render_object.h"
00043
00044 #include <dcopclient.h>
00045 #include <kapplication.h>
00046 #include <kdebug.h>
00047 #include <kurl.h>
00048 #include <kglobal.h>
00049 #include <kcharsets.h>
00050 #include <kglobalsettings.h>
00051
00052 #include "css/cssproperties.h"
00053 #include "css/cssstyleselector.h"
00054 #include "css/css_stylesheetimpl.h"
00055 #include <stdlib.h>
00056 #include <qptrstack.h>
00057
00058 template class QPtrStack<DOM::NodeImpl>;
00059
00060 using namespace DOM;
00061 using namespace khtml;
00062
00063
00064 HTMLDocumentImpl::HTMLDocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
00065 : DocumentImpl(_implementation, v)
00066 {
00067
00068 bodyElement = 0;
00069 htmlElement = 0;
00070
00071
00072
00073
00074
00075
00076
00077 connect( KHTMLFactory::vLinks(), SIGNAL( cleared()),
00078 SLOT( slotHistoryChanged() ));
00079 }
00080
00081 HTMLDocumentImpl::~HTMLDocumentImpl()
00082 {
00083 }
00084
00085 DOMString HTMLDocumentImpl::referrer() const
00086 {
00087 if ( view() )
00088 return view()->part()->pageReferrer();
00089 return DOMString();
00090 }
00091
00092 DOMString HTMLDocumentImpl::domain() const
00093 {
00094 if ( m_domain.isEmpty() )
00095 m_domain = KURL(URL()).host();
00096 return m_domain;
00097 }
00098
00099 void HTMLDocumentImpl::setDomain(const DOMString &newDomain)
00100 {
00101 if ( m_domain.isEmpty() )
00102 m_domain = KURL(URL()).host().lower();
00103
00104 if ( m_domain.isEmpty() )
00105 m_domain = newDomain.lower();
00106
00107
00108
00109 int oldLength = m_domain.length();
00110 int newLength = newDomain.length();
00111 if ( newLength < oldLength )
00112 {
00113 DOMString test = m_domain.copy();
00114 DOMString reference = newDomain.lower();
00115 if ( test[oldLength - newLength - 1] == '.' )
00116 {
00117 test.remove( 0, oldLength - newLength );
00118 if ( test == reference )
00119 m_domain = reference;
00120 }
00121 }
00122 }
00123
00124 DOMString HTMLDocumentImpl::lastModified() const
00125 {
00126 if ( view() )
00127 return view()->part()->lastModified();
00128 return DOMString();
00129 }
00130
00131 DOMString HTMLDocumentImpl::cookie() const
00132 {
00133 long windowId = 0;
00134 KHTMLView *v = view ();
00135
00136 if ( v && v->topLevelWidget() )
00137 windowId = v->topLevelWidget()->winId();
00138
00139 QCString replyType;
00140 QByteArray params, reply;
00141 QDataStream stream(params, IO_WriteOnly);
00142 stream << URL() << windowId;
00143 if (!kapp->dcopClient()->call("kcookiejar", "kcookiejar",
00144 "findDOMCookies(QString,long int)", params,
00145 replyType, reply))
00146 {
00147 kdWarning(6010) << "Can't communicate with cookiejar!" << endl;
00148 return DOMString();
00149 }
00150
00151 QDataStream stream2(reply, IO_ReadOnly);
00152 if(replyType != "QString") {
00153 kdError(6010) << "DCOP function findDOMCookies(...) returns "
00154 << replyType << ", expected QString" << endl;
00155 return DOMString();
00156 }
00157
00158 QString result;
00159 stream2 >> result;
00160 return DOMString(result);
00161 }
00162
00163 void HTMLDocumentImpl::setCookie( const DOMString & value )
00164 {
00165 long windowId = 0;
00166 KHTMLView *v = view ();
00167
00168 if ( v && v->topLevelWidget() )
00169 windowId = v->topLevelWidget()->winId();
00170
00171 QByteArray params;
00172 QDataStream stream(params, IO_WriteOnly);
00173 QString fake_header("Set-Cookie: ");
00174 fake_header.append(value.string());
00175 fake_header.append("\n");
00176 stream << URL() << fake_header.utf8() << windowId;
00177 if (!kapp->dcopClient()->send("kcookiejar", "kcookiejar",
00178 "addCookies(QString,QCString,long int)", params))
00179 {
00180
00181 KApplication::startServiceByDesktopName( "kcookiejar");
00182 if (!kapp->dcopClient()->send("kcookiejar", "kcookiejar",
00183 "addCookies(QString,QCString,long int)", params))
00184 kdWarning(6010) << "Can't communicate with cookiejar!" << endl;
00185 }
00186 }
00187
00188
00189
00190 HTMLElementImpl *HTMLDocumentImpl::body()
00191 {
00192 NodeImpl *de = documentElement();
00193 if (!de)
00194 return 0;
00195
00196
00197 NodeImpl* body = 0;
00198 for (NodeImpl* i = de->firstChild(); i; i = i->nextSibling()) {
00199 if (i->id() == ID_FRAMESET)
00200 return static_cast<HTMLElementImpl*>(i);
00201
00202 if (i->id() == ID_BODY)
00203 body = i;
00204 }
00205 return static_cast<HTMLElementImpl *>(body);
00206 }
00207
00208 void HTMLDocumentImpl::setBody(HTMLElementImpl *_body)
00209 {
00210 int exceptioncode = 0;
00211 HTMLElementImpl *b = body();
00212 if ( !_body && !b ) return;
00213 if ( !_body )
00214 documentElement()->removeChild( b, exceptioncode );
00215 else if ( !b )
00216 documentElement()->appendChild( _body, exceptioncode );
00217 else
00218 documentElement()->replaceChild( _body, b, exceptioncode );
00219 }
00220
00221 Tokenizer *HTMLDocumentImpl::createTokenizer()
00222 {
00223 return new HTMLTokenizer(docPtr(),m_view);
00224 }
00225
00226
00227
00228
00229
00230 bool HTMLDocumentImpl::childAllowed( NodeImpl *newChild )
00231 {
00232
00233 return (newChild->id() == ID_HTML || newChild->id() == ID_COMMENT);
00234 }
00235
00236 ElementImpl *HTMLDocumentImpl::createElement( const DOMString &name, int* pExceptioncode )
00237 {
00238 ElementImpl* e = createHTMLElement( name );
00239 if ( e )
00240 return e;
00241 return DOM::DocumentImpl::createElement( name, pExceptioncode );
00242 }
00243
00244 void HTMLDocumentImpl::slotHistoryChanged()
00245 {
00246 if ( true || !m_render )
00247 return;
00248
00249 recalcStyle( Force );
00250 m_render->repaint();
00251 }
00252
00253 HTMLMapElementImpl* HTMLDocumentImpl::getMap(const DOMString& _url)
00254 {
00255 QString url = _url.string();
00256 QString s;
00257 int pos = url.find('#');
00258
00259 s = QString(_url.unicode() + pos + 1, _url.length() - pos - 1);
00260
00261 QMapConstIterator<QString,HTMLMapElementImpl*> it = mapMap.find(s);
00262
00263 if (it != mapMap.end())
00264 return *it;
00265 else
00266 return 0;
00267 }
00268
00269 static bool isTransitional(const QString &spec, int start)
00270 {
00271 if((spec.find("TRANSITIONAL", start, false ) != -1 ) ||
00272 (spec.find("LOOSE", start, false ) != -1 ) ||
00273 (spec.find("FRAMESET", start, false ) != -1 ) ||
00274 (spec.find("LATIN1", start, false ) != -1 ) ||
00275 (spec.find("SYMBOLS", start, false ) != -1 ) ||
00276 (spec.find("SPECIAL", start, false ) != -1 ) ) {
00277
00278 return true;
00279 }
00280 return false;
00281 }
00282
00283 void HTMLDocumentImpl::close()
00284 {
00285 bool doload = !parsing() && m_tokenizer;
00286
00287 DocumentImpl::close();
00288
00289 HTMLElementImpl* b = body();
00290 if (b && doload) {
00291
00292
00293
00294
00295
00296
00297 b->dispatchWindowEvent(EventImpl::LOAD_EVENT, false, false);
00298
00299 b = body();
00300
00301
00302 if (b && b->id() == ID_FRAMESET)
00303 getDocument()->dispatchWindowEvent(EventImpl::LOAD_EVENT, false, false);
00304
00305
00306 if ( view() && ( view()->part()->d->m_redirectURL.isNull() ||
00307 view()->part()->d->m_delayRedirect > 1 ) )
00308 updateRendering();
00309 }
00310 }
00311
00312
00313 void HTMLDocumentImpl::determineParseMode( const QString &str )
00314 {
00315
00316
00317
00318 int oldPMode = pMode;
00319
00320
00321 pMode = Compat;
00322 hMode = Html3;
00323
00324 ParseMode systemId = Unknown;
00325 ParseMode publicId = Unknown;
00326
00327 int pos = 0;
00328 int doctype = str.find("!doctype", 0, false);
00329 if( doctype > 2 ) {
00330 pos = doctype - 2;
00331
00332 int start = doctype + 9;
00333 while ( start < (int)str.length() && str[start].isSpace() )
00334 start++;
00335 int espace = str.find(' ',start);
00336 QString name = str.mid(start,espace-start);
00337
00338 m_doctype->setName( name );
00339 }
00340
00341
00342 int start = str.find('<', pos);
00343 int stop = str.find('>', pos);
00344 if( start > -1 && stop > start ) {
00345 QString spec = str.mid( start + 1, stop - start - 1 );
00346
00347 start = 0;
00348 int quote = -1;
00349 if( doctype != -1 ) {
00350 while( (quote = spec.find( "\"", start )) != -1 ) {
00351 int quote2 = spec.find( "\"", quote+1 );
00352 if(quote2 < 0) quote2 = spec.length();
00353 QString val = spec.mid( quote+1, quote2 - quote-1 );
00354
00355
00356 pos = val.find("http://www.w3.org/tr/", 0, false);
00357 if ( pos != -1 ) {
00358
00359 if ( val.find("strict.dtd", pos, false) != -1 )
00360 systemId = Strict;
00361 else if (isTransitional(val, pos))
00362 systemId = Transitional;
00363 }
00364
00365
00366 pos = val.find("//dtd", 0, false );
00367 if ( pos != -1 ) {
00368 if( val.find( "xhtml", pos+6, false ) != -1 ) {
00369 hMode = XHtml;
00370 publicId = isTransitional(val, pos) ? Transitional : Strict;
00371 } else if ( val.find( "15445:1999", pos+6 ) != -1 ) {
00372 hMode = Html4;
00373 publicId = Strict;
00374 } else {
00375 int tagPos = val.find( "html", pos+6, false );
00376 if( tagPos == -1 )
00377 tagPos = val.find( "hypertext markup", pos+6, false );
00378 if ( tagPos != -1 ) {
00379 tagPos = val.find(QRegExp("[0-9]"), tagPos );
00380 int version = val.mid( tagPos, 1 ).toInt();
00381
00382 if( version > 3 ) {
00383 hMode = Html4;
00384 publicId = isTransitional( val, tagPos ) ? Transitional : Strict;
00385 }
00386 }
00387 }
00388 }
00389 start = quote2 + 1;
00390 }
00391 }
00392
00393 if( systemId == publicId )
00394 pMode = publicId;
00395 else if ( systemId == Unknown )
00396 pMode = hMode == Html4 ? Compat : publicId;
00397 else if ( publicId == Transitional && systemId == Strict ) {
00398 pMode = hMode == Html3 ? Compat : Strict;
00399 } else
00400 pMode = Compat;
00401
00402 if ( hMode == XHtml )
00403 pMode = Strict;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 if ( pMode != oldPMode && styleSelector() )
00415 recalcStyleSelector();
00416 }
00417
00418 #include "html_documentimpl.moc"