| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# xmlhttprequest.cpp

    00001 // -*- c-basic-offset: 2 -*-
    00002 /*
    00003  *  This file is part of the KDE libraries
    00004  *  Copyright (C) 2003 Apple Computer, Inc.
    00005  *
    00006  *  This library is free software; you can redistribute it and/or
    00007  *  modify it under the terms of the GNU Lesser General Public
    00008  *  License as published by the Free Software Foundation; either
    00009  *  version 2 of the License, or (at your option) any later version.
    00010  *
    00011  *  This library is distributed in the hope that it will be useful,
    00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014  *  Lesser General Public License for more details.
    00015  *
    00016  *  You should have received a copy of the GNU Lesser General Public
    00017  *  License along with this library; if not, write to the Free Software
    00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00019  */
    00020
    00021 #include "xmlhttprequest.h"
    00022 #include "xmlhttprequest.lut.h"
    00023 #include "kjs_window.h"
    00024 #include "kjs_events.h"
    00025
    00026 #include "dom/dom_doc.h"
    00027 #include "dom/dom_exception.h"
    00028 #include "dom/dom_string.h"
    00029 #include "misc/loader.h"
    00030 #include "html/html_documentimpl.h"
    00031 #include "xml/dom2_eventsimpl.h"
    00032
    00033 #include "khtml_part.h"
    00034 #include "khtmlview.h"
    00035
    00036 #include <kio/scheduler.h>
    00037 #include <kio/job.h>
    00038 #include <qobject.h>
    00039 #include <kdebug.h>
    00040
    00041 #ifdef APPLE_CHANGES
    00042 #include "KWQLoader.h"
    00043 #else
    00044 #include <kio/netaccess.h>
    00045 using KIO::NetAccess;
    00046 #endif
    00047
    00048 using namespace KJS;
    00049 using khtml::Decoder;
    00050
    00052
    00053 /* Source for XMLHttpRequestProtoTable.
    00054 @begin XMLHttpRequestProtoTable 7
    00055   abort         XMLHttpRequest::Abort           DontDelete|Function 0
    00056   getAllResponseHeaders XMLHttpRequest::GetAllResponseHeaders   DontDelete|Function 0
    00057   getResponseHeader XMLHttpRequest::GetResponseHeader   DontDelete|Function 1
    00058   open          XMLHttpRequest::Open            DontDelete|Function 5
    00059   send          XMLHttpRequest::Send            DontDelete|Function 1
    00060   setRequestHeader  XMLHttpRequest::SetRequestHeader    DontDelete|Function 2
    00061 @end
    00062 */
    00063 DEFINE_PROTOTYPE("XMLHttpRequest",XMLHttpRequestProto)
    00064 IMPLEMENT_PROTOFUNC_DOM(XMLHttpRequestProtoFunc)
    00065 IMPLEMENT_PROTOTYPE(XMLHttpRequestProto,XMLHttpRequestProtoFunc)
    00066
    00067 namespace KJS {
    00068
    00069 XMLHttpRequestQObject::XMLHttpRequestQObject(XMLHttpRequest *_jsObject)
    00070 {
    00071   jsObject = _jsObject;
    00072 }
    00073
    00074 #ifdef APPLE_CHANGES
    00075 void XMLHttpRequestQObject::slotData( KIO::Job* job, const char *data, int size )
    00076 {
    00077   jsObject->slotData(job, data, size);
    00078 }
    00079 #else
    00080 void XMLHttpRequestQObject::slotData( KIO::Job* job, const QByteArray &data )
    00081 {
    00082   jsObject->slotData(job, data);
    00083 }
    00084 #endif
    00085
    00086 void XMLHttpRequestQObject::slotFinished( KIO::Job* job )
    00087 {
    00088   jsObject->slotFinished(job);
    00089 }
    00090
    00091 void XMLHttpRequestQObject::slotRedirection( KIO::Job* job, const KURL& url)
    00092 {
    00093   jsObject->slotRedirection( job, url );
    00094 }
    00095
    00096 XMLHttpRequestConstructorImp::XMLHttpRequestConstructorImp(ExecState *, const DOM::Document &d)
    00097     : ObjectImp(), doc(d)
    00098 {
    00099 }
    00100
    00101 bool XMLHttpRequestConstructorImp::implementsConstruct() const
    00102 {
    00103   return true;
    00104 }
    00105
    00106 Object XMLHttpRequestConstructorImp::construct(ExecState *exec, const List &)
    00107 {
    00108   return Object(new XMLHttpRequest(exec, doc));
    00109 }
    00110
    00111 const ClassInfo XMLHttpRequest::info = { "XMLHttpRequest", 0, &XMLHttpRequestTable, 0 };
    00112
    00113
    00114 /* Source for XMLHttpRequestTable.
    00115 @begin XMLHttpRequestTable 7
    00116   readyState        XMLHttpRequest::ReadyState      DontDelete|ReadOnly
    00117   responseText      XMLHttpRequest::ResponseText        DontDelete|ReadOnly
    00118   responseXML       XMLHttpRequest::ResponseXML     DontDelete|ReadOnly
    00119   status        XMLHttpRequest::Status          DontDelete|ReadOnly
    00120   statusText        XMLHttpRequest::StatusText      DontDelete|ReadOnly
    00121   onreadystatechange    XMLHttpRequest::Onreadystatechange  DontDelete
    00122   onload        XMLHttpRequest::Onload          DontDelete
    00123 @end
    00124 */
    00125
    00126 Value XMLHttpRequest::tryGet(ExecState *exec, const Identifier &propertyName) const
    00127 {
    00128   return DOMObjectLookupGetValue<XMLHttpRequest,DOMObject>(exec, propertyName, &XMLHttpRequestTable, this);
    00129 }
    00130
    00131 Value XMLHttpRequest::getValueProperty(ExecState *exec, int token) const
    00132 {
    00133   switch (token) {
    00134   case ReadyState:
    00135     return Number(state);
    00136   case ResponseText:
    00137     return getString(DOM::DOMString(response));
    00138   case ResponseXML:
    00139     if (state != Completed) {
    00140       return Undefined();
    00141     }
    00142     if (!createdDocument) {
    00143       QString mimeType = "text/xml";
    00144
    00145       Value header = getResponseHeader("Content-Type");
    00146       if (header.type() != UndefinedType) {
    00147     mimeType = QStringList::split(";", header.toString(exec).qstring())[0].stripWhiteSpace();
    00148       }
    00149
    00150       if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "application/xhtml+xml") {
    00151     responseXML = DOM::Document(doc->implementation()->createDocument());
    00152
    00153     DOM::DocumentImpl *docImpl = static_cast<DOM::DocumentImpl *>(responseXML.handle());
    00154
    00155     docImpl->open();
    00156     docImpl->write(response);
    00157     docImpl->finishParsing();
    00158     docImpl->close();
    00159
    00160     typeIsXML = true;
    00161       } else {
    00162     typeIsXML = false;
    00163       }
    00164       createdDocument = true;
    00165     }
    00166
    00167     if (!typeIsXML) {
    00168       return Undefined();
    00169     }
    00170
    00171     return getDOMNode(exec,responseXML);
    00172   case Status:
    00173     return getStatus();
    00174   case StatusText:
    00175     return getStatusText();
    00176   case Onreadystatechange:
    00177    if (onReadyStateChangeListener && onReadyStateChangeListener->listenerObjImp()) {
    00178      return onReadyStateChangeListener->listenerObj();
    00179    } else {
    00180      return Null();
    00181    }
    00182   case Onload:
    00183    if (onLoadListener && onLoadListener->listenerObjImp()) {
    00184      return onLoadListener->listenerObj();
    00185    } else {
    00186     return Null();
    00187    }
    00188   default:
    00189     kdWarning() << "XMLHttpRequest::getValueProperty unhandled token " << token << endl;
    00190     return Value();
    00191   }
    00192 }
    00193
    00194 void XMLHttpRequest::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
    00195 {
    00196   DOMObjectLookupPut<XMLHttpRequest,DOMObject>(exec, propertyName, value, attr, &XMLHttpRequestTable, this );
    00197 }
    00198
    00199 void XMLHttpRequest::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
    00200 {
    00201   switch(token) {
    00202   case Onreadystatechange:
    00203     onReadyStateChangeListener = Window::retrieveActive(exec)->getJSEventListener(value, true);
    00204     if (onReadyStateChangeListener) onReadyStateChangeListener->ref();
    00205     break;
    00206   case Onload:
    00207     onLoadListener = Window::retrieveActive(exec)->getJSEventListener(value, true);
    00208     if (onLoadListener) onLoadListener->ref();
    00209     break;
    00210   default:
    00211     kdWarning() << "XMLHttpRequest::putValue unhandled token " << token << endl;
    00212   }
    00213 }
    00214
    00215 XMLHttpRequest::XMLHttpRequest(ExecState *exec, const DOM::Document &d)
    00216   : DOMObject(XMLHttpRequestProto::self(exec)),
    00217     qObject(new XMLHttpRequestQObject(this)),
    00218     doc(static_cast<DOM::DocumentImpl*>(d.handle())),
    00219     async(true),
    00220     contentType(QString::null),
    00221     job(0),
    00222     state(Uninitialized),
    00223     onReadyStateChangeListener(0),
    00224     onLoadListener(0),
    00225     decoder(0),
    00226     createdDocument(false),
    00227     aborted(false)
    00228 {
    00229 }
    00230
    00231 XMLHttpRequest::~XMLHttpRequest()
    00232 {
    00233   delete qObject;
    00234   qObject = 0;
    00235   delete decoder;
    00236   decoder = 0;
    00237 }
    00238
    00239 void XMLHttpRequest::changeState(XMLHttpRequestState newState)
    00240 {
    00241   if (state != newState) {
    00242     state = newState;
    00243
    00244     if (onReadyStateChangeListener != 0 && doc->view() && doc->view()->part()) {
    00245       DOM::Event ev = doc->view()->part()->document().createEvent("HTMLEvents");
    00246       ev.initEvent("readystatechange", true, true);
    00247       onReadyStateChangeListener->handleEvent(ev);
    00248     }
    00249
    00250     if (state == Completed && onLoadListener != 0 && doc->view() && doc->view()->part()) {
    00251       DOM::Event ev = doc->view()->part()->document().createEvent("HTMLEvents");
    00252       ev.initEvent("load", true, true);
    00253       onLoadListener->handleEvent(ev);
    00254     }
    00255   }
    00256 }
    00257
    00258 bool XMLHttpRequest::urlMatchesDocumentDomain(const KURL& _url) const
    00259 {
    00260   KURL documentURL(doc->URL());
    00261
    00262   // a local file can load anything
    00263   if (documentURL.protocol().lower() == "file") {
    00264     return true;
    00265   }
    00266
    00267   // but a remote document can only load from the same port on the server
    00268   if (documentURL.protocol().lower() == _url.protocol().lower() &&
    00269       documentURL.host().lower() == _url.host().lower() &&
    00270       documentURL.port() == _url.port()) {
    00271     return true;
    00272   }
    00273
    00274   return false;
    00275 }
    00276
    00277 void XMLHttpRequest::open(const QString& _method, const KURL& _url, bool _async)
    00278 {
    00279   abort();
    00280   aborted = false;
    00281
    00282   // clear stuff from possible previous load
    00283   requestHeaders = QString();
    00284   responseHeaders = QString();
    00285   response = QString();
    00286   createdDocument = false;
    00287   responseXML = DOM::Document();
    00288
    00289   changeState(Uninitialized);
    00290
    00291   if (aborted) {
    00292     return;
    00293   }
    00294
    00295   if (!urlMatchesDocumentDomain(_url)) {
    00296     return;
    00297   }
    00298
    00299
    00300   method = _method;
    00301   url = _url;
    00302   async = _async;
    00303
    00304   changeState(Loading);
    00305 }
    00306
    00307 void XMLHttpRequest::send(const QString& _body)
    00308 {
    00309   aborted = false;
    00310   if (method.lower() == "post" && (url.protocol().lower() == "http" || url.protocol().lower() == "https") ) {
    00311       // FIXME: determine post encoding correctly by looking in headers for charset
    00312       job = KIO::http_post( url, QCString(_body.utf8()), false );
    00313       if(contentType.isNull())
    00314     job->addMetaData( "content-type", "Content-type: text/plain" );
    00315       else
    00316     job->addMetaData( "content-type", contentType );
    00317   }
    00318   else
    00319   {
    00320      job = KIO::get( url, false, false );
    00321   }
    00322   if (requestHeaders.length() > 0) {
    00323     job->addMetaData("customHTTPHeader", requestHeaders);
    00324   }
    00325   job->addMetaData( "PropagateHttpHeader", "true" );
    00326
    00327   if (!async) {
    00328     QByteArray data;
    00329     KURL finalURL;
    00330     QString headers;
    00331
    00332 #ifdef APPLE_CHANGES
    00333     data = KWQServeSynchronousRequest(khtml::Cache::loader(), doc->docLoader(), job, finalURL, headers);
    00334 #else
    00335     QMap<QString, QString> metaData;
    00336     if ( NetAccess::synchronousRun( job, 0, &data, &finalURL, &metaData ) ) {
    00337       headers = metaData[ "HTTP-Headers" ];
    00338     }
    00339 #endif
    00340     job = 0;
    00341     processSyncLoadResults(data, finalURL, headers);
    00342     return;
    00343   }
    00344
    00345   qObject->connect( job, SIGNAL( result( KIO::Job* ) ),
    00346             SLOT( slotFinished( KIO::Job* ) ) );
    00347 #ifdef APPLE_CHANGES
    00348   qObject->connect( job, SIGNAL( data( KIO::Job*, const char*, int ) ),
    00349             SLOT( slotData( KIO::Job*, const char*, int ) ) );
    00350 #else
    00351   qObject->connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
    00352             SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
    00353 #endif
    00354   qObject->connect( job, SIGNAL(redirection(KIO::Job*, const KURL& ) ),
    00355             SLOT( slotRedirection(KIO::Job*, const KURL&) ) );
    00356
    00357 #ifdef APPLE_CHANGES
    00358   KWQServeRequest(khtml::Cache::loader(), doc->docLoader(), job);
    00359 #else
    00360   KIO::Scheduler::scheduleJob( job );
    00361 #endif
    00362 }
    00363
    00364 void XMLHttpRequest::abort()
    00365 {
    00366   if (job) {
    00367     job->kill();
    00368     job = 0;
    00369   }
    00370   delete decoder;
    00371   decoder = 0;
    00372   aborted = true;
    00373 }
    00374
    00375 void XMLHttpRequest::setRequestHeader(const QString& name, const QString &value)
    00376 {
    00377   // Content-type needs to be set seperately from the other headers
    00378   if(name.lower() == "content-type") {
    00379     contentType = "Content-type: " + value;
    00380     return;
    00381   }
    00382   if (requestHeaders.length() > 0) {
    00383     requestHeaders += "\r\n";
    00384   }
    00385   requestHeaders += name;
    00386   requestHeaders += ": ";
    00387   requestHeaders += value;
    00388 }
    00389
    00390 Value XMLHttpRequest::getAllResponseHeaders() const
    00391 {
    00392   if (responseHeaders.isEmpty()) {
    00393     return Undefined();
    00394   }
    00395
    00396   int endOfLine = responseHeaders.find("\n");
    00397
    00398   if (endOfLine == -1) {
    00399     return Undefined();
    00400   }
    00401
    00402   return String(responseHeaders.mid(endOfLine + 1) + "\n");
    00403 }
    00404
    00405 Value XMLHttpRequest::getResponseHeader(const QString& name) const
    00406 {
    00407   if (responseHeaders.isEmpty()) {
    00408     return Undefined();
    00409   }
    00410
    00411   QRegExp headerLinePattern(name + ":", false);
    00412
    00413   int matchLength;
    00414   int headerLinePos = headerLinePattern.search(responseHeaders, 0);
    00415   matchLength = headerLinePattern.matchedLength();
    00416   while (headerLinePos != -1) {
    00417     if (headerLinePos == 0 || responseHeaders[headerLinePos-1] == '\n') {
    00418       break;
    00419     }
    00420
    00421     headerLinePos = headerLinePattern.search(responseHeaders, headerLinePos + 1);
    00422     matchLength = headerLinePattern.matchedLength();
    00423   }
    00424
    00425
    00426   if (headerLinePos == -1) {
    00427     return Undefined();
    00428   }
    00429
    00430   int endOfLine = responseHeaders.find("\n", headerLinePos + matchLength);
    00431
    00432   return String(responseHeaders.mid(headerLinePos + matchLength, endOfLine - (headerLinePos + matchLength)).stripWhiteSpace());
    00433 }
    00434
    00435 Value XMLHttpRequest::getStatus() const
    00436 {
    00437   if (responseHeaders.isEmpty()) {
    00438     return Undefined();
    00439   }
    00440
    00441   int endOfLine = responseHeaders.find("\n");
    00442   QString firstLine = endOfLine == -1 ? responseHeaders : responseHeaders.left(endOfLine);
    00443   int codeStart = firstLine.find(" ");
    00444   int codeEnd = firstLine.find(" ", codeStart + 1);
    00445
    00446   if (codeStart == -1 || codeEnd == -1) {
    00447     return Undefined();
    00448   }
    00449
    00450   QString number = firstLine.mid(codeStart + 1, codeEnd - (codeStart + 1));
    00451
    00452   bool ok = false;
    00453   int code = number.toInt(&ok);
    00454   if (!ok) {
    00455     return Undefined();
    00456   }
    00457
    00458   return Number(code);
    00459 }
    00460
    00461 Value XMLHttpRequest::getStatusText() const
    00462 {
    00463   if (responseHeaders.isEmpty()) {
    00464     return Undefined();
    00465   }
    00466
    00467   int endOfLine = responseHeaders.find("\n");
    00468   QString firstLine = endOfLine == -1 ? responseHeaders : responseHeaders.left(endOfLine);
    00469   int codeStart = firstLine.find(" ");
    00470   int codeEnd = firstLine.find(" ", codeStart + 1);
    00471
    00472   if (codeStart == -1 || codeEnd == -1) {
    00473     return Undefined();
    00474   }
    00475
    00476   QString statusText = firstLine.mid(codeEnd + 1, endOfLine - (codeEnd + 1)).stripWhiteSpace();
    00477
    00478   return String(statusText);
    00479 }
    00480
    00481 void XMLHttpRequest::processSyncLoadResults(const QByteArray &data, const KURL &finalURL, const QString &headers)
    00482 {
    00483   if (!urlMatchesDocumentDomain(finalURL)) {
    00484     abort();
    00485     return;
    00486   }
    00487
    00488   responseHeaders = headers;
    00489   changeState(Loaded);
    00490   if (aborted) {
    00491     return;
    00492   }
    00493
    00494 #ifdef APPLE_CHANGES
    00495   const char *bytes = (const char *)data.data();
    00496   int len = (int)data.size();
    00497
    00498   slotData(0, bytes, len);
    00499 #else
    00500   slotData(0, data);
    00501 #endif
    00502
    00503   if (aborted) {
    00504     return;
    00505   }
    00506
    00507   slotFinished(0);
    00508 }
    00509
    00510 void XMLHttpRequest::slotFinished(KIO::Job *)
    00511 {
    00512   if (decoder) {
    00513     response += decoder->flush();
    00514   }
    00515
    00516   // make sure to forget about the job before emitting completed,
    00517   // since changeState triggers JS code, which might e.g. call abort.
    00518   job = 0;
    00519   changeState(Completed);
    00520
    00521   delete decoder;
    00522   decoder = 0;
    00523 }
    00524
    00525 void XMLHttpRequest::slotRedirection(KIO::Job*, const KURL& url)
    00526 {
    00527   if (!urlMatchesDocumentDomain(url)) {
    00528     abort();
    00529   }
    00530 }
    00531
    00532 #ifdef APPLE_CHANGES
    00533 void XMLHttpRequest::slotData( KIO::Job*, const char *data, int len )
    00534 #else
    00535 void XMLHttpRequest::slotData(KIO::Job*, const QByteArray &_data)
    00536 #endif
    00537 {
    00538   if (state < Loaded ) {
    00539     responseHeaders = job->queryMetaData("HTTP-Headers");
    00540     changeState(Loaded);
    00541   }
    00542
    00543 #ifndef APPLE_CHANGES
    00544   const char *data = (const char *)_data.data();
    00545   int len = (int)_data.size();
    00546 #endif
    00547
    00548   if ( decoder == NULL ) {
    00549     decoder = new Decoder;
    00550     if (!encoding.isNull())
    00551       decoder->setEncoding(encoding.latin1(), Decoder::EncodingFromHTTPHeader);
    00552     else {
    00553       // FIXME: Inherit the default encoding from the parent document?
    00554     }
    00555   }
    00556   if (len == 0)
    00557     return;
    00558
    00559   if (len == -1)
    00560     len = strlen(data);
    00561
    00562   QString decoded = decoder->decode(data, len);
    00563
    00564   response += decoded;
    00565
    00566   if (!aborted) {
    00567     changeState(Interactive);
    00568   }
    00569 }
    00570
    00571 Value XMLHttpRequestProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
    00572 {
    00573   if (!thisObj.inherits(&XMLHttpRequest::info)) {
    00574     Object err = Error::create(exec,TypeError);
    00575     exec->setException(err);
    00576     return err;
    00577   }
    00578
    00579   XMLHttpRequest *request = static_cast<XMLHttpRequest *>(thisObj.imp());
    00580   switch (id) {
    00581   case XMLHttpRequest::Abort:
    00582     request->abort();
    00583     return Undefined();
    00584   case XMLHttpRequest::GetAllResponseHeaders:
    00585     if (args.size() != 0) {
    00586     return Undefined();
    00587     }
    00588
    00589     return request->getAllResponseHeaders();
    00590   case XMLHttpRequest::GetResponseHeader:
    00591     if (args.size() != 1) {
    00592     return Undefined();
    00593     }
    00594
    00595     return request->getResponseHeader(args[0].toString(exec).qstring());
    00596   case XMLHttpRequest::Open:
    00597     {
    00598       if (args.size() < 2 || args.size() > 5) {
    00599         return Undefined();
    00600       }
    00601
    00602       QString method = args[0].toString(exec).qstring();
    00603       KHTMLPart *part = ::qt_cast<KHTMLPart *>(Window::retrieveActive(exec)->part());
    00604       if (!part)
    00605         return Undefined();
    00606       KURL url = KURL(part->document().completeURL(args[1].toString(exec).qstring()).string());
    00607
    00608       bool async = true;
    00609       if (args.size() >= 3) {
    00610     async = args[2].toBoolean(exec);
    00611       }
    00612
    00613       if (args.size() >= 4) {
    00614     url.setUser(args[3].toString(exec).qstring());
    00615       }
    00616
    00617       if (args.size() >= 5) {
    00618     url.setPass(args[4].toString(exec).qstring());
    00619       }
    00620
    00621       request->open(method, url, async);
    00622
    00623       return Undefined();
    00624     }
    00625   case XMLHttpRequest::Send:
    00626     {
    00627       if (args.size() > 1) {
    00628         return Undefined();
    00629       }
    00630
    00631       if (request->state != Loading) {
    00632     return Undefined();
    00633       }
    00634
    00635       QString body;
    00636
    00637       if (args.size() >= 1) {
    00638     Object obj = Object::dynamicCast(args[0]);
    00639     if (!obj.isNull() && obj.inherits(&DOMDocument::info)) {
    00640       DOM::Node docNode = static_cast<KJS::DOMDocument *>(obj.imp())->toNode();
    00641       DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl *>(docNode.handle());
    00642
    00643       try {
    00644         body = doc->toString().string();
    00645         // FIXME: also need to set content type, including encoding!
    00646
    00647       } catch(DOM::DOMException& e) {
    00648          Object err = Error::create(exec, GeneralError, "Exception serializing document");
    00649          exec->setException(err);
    00650       }
    00651     } else {
    00652       body = args[0].toString(exec).qstring();
    00653     }
    00654       }
    00655
    00656       request->send(body);
    00657
    00658       return Undefined();
    00659     }
    00660   case XMLHttpRequest::SetRequestHeader:
    00661     if (args.size() != 2) {
    00662       return Undefined();
    00663     }
    00664
    00665     request->setRequestHeader(args[0].toString(exec).qstring(), args[1].toString(exec).qstring());
    00666
    00667     return Undefined();
    00668   }
    00669
    00670   return Undefined();
    00671 }
    00672
    00673 } // end namespace
    00674
    00675 #include "xmlhttprequest.moc"

This file is part of the documentation for khtml Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:33:19 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003