File indexing completed on 2024-04-28 15:22:57
0001 /** 0002 * This file is part of the DOM implementation for KDE. 0003 * 0004 * Copyright 1999 Lars Knoll (knoll@kde.org) 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 #include "dom/dom_exception.h" 0024 #include "xml/dom_docimpl.h" 0025 #include "xml/dom_elementimpl.h" 0026 #include "html/html_formimpl.h" 0027 0028 using namespace DOM; 0029 0030 Attr::Attr() : Node() 0031 { 0032 } 0033 0034 Attr::Attr(const Attr &other) : Node(other) 0035 { 0036 } 0037 0038 Attr::Attr(AttrImpl *_impl) 0039 { 0040 impl = _impl; 0041 if (impl) { 0042 impl->ref(); 0043 } 0044 } 0045 0046 Attr &Attr::operator = (const Node &other) 0047 { 0048 NodeImpl *ohandle = other.handle(); 0049 if (impl != ohandle) { 0050 if (!ohandle || !ohandle->isAttributeNode()) { 0051 if (impl) { 0052 impl->deref(); 0053 } 0054 impl = nullptr; 0055 } else { 0056 Node::operator =(other); 0057 } 0058 } 0059 return *this; 0060 } 0061 0062 Attr &Attr::operator = (const Attr &other) 0063 { 0064 Node::operator =(other); 0065 return *this; 0066 } 0067 0068 Attr::~Attr() 0069 { 0070 } 0071 0072 DOMString Attr::name() const 0073 { 0074 if (!impl) { 0075 throw DOMException(DOMException::NOT_FOUND_ERR); 0076 } 0077 return ((AttrImpl *)impl)->name(); 0078 } 0079 0080 bool Attr::specified() const 0081 { 0082 if (impl) { 0083 return ((AttrImpl *)impl)->specified(); 0084 } 0085 return 0; 0086 } 0087 0088 Element Attr::ownerElement() const 0089 { 0090 if (!impl) { 0091 return nullptr; 0092 } 0093 return static_cast<AttrImpl *>(impl)->ownerElement(); 0094 } 0095 0096 DOMString Attr::value() const 0097 { 0098 if (!impl) { 0099 throw DOMException(DOMException::NOT_FOUND_ERR); 0100 } 0101 return impl->nodeValue(); 0102 } 0103 0104 void Attr::setValue(const DOMString &newValue) 0105 { 0106 if (!impl) { 0107 return; 0108 } 0109 0110 int exceptioncode = 0; 0111 ((AttrImpl *)impl)->setValue(newValue, exceptioncode); 0112 if (exceptioncode) { 0113 throw DOMException(exceptioncode); 0114 } 0115 } 0116 0117 // --------------------------------------------------------------------------- 0118 0119 Element::Element() : Node() 0120 { 0121 } 0122 0123 Element::Element(const Element &other) : Node(other) 0124 { 0125 } 0126 0127 Element::Element(ElementImpl *impl) : Node(impl) 0128 { 0129 } 0130 0131 Element &Element::operator = (const Node &other) 0132 { 0133 NodeImpl *ohandle = other.handle(); 0134 if (impl != ohandle) { 0135 if (!ohandle || !ohandle->isElementNode()) { 0136 if (impl) { 0137 impl->deref(); 0138 } 0139 impl = nullptr; 0140 } else { 0141 Node::operator =(other); 0142 } 0143 } 0144 return *this; 0145 } 0146 0147 Element &Element::operator = (const Element &other) 0148 { 0149 Node::operator =(other); 0150 return *this; 0151 } 0152 0153 Element::~Element() 0154 { 0155 } 0156 0157 DOMString Element::tagName() const 0158 { 0159 if (!impl) { 0160 throw DOMException(DOMException::NOT_FOUND_ERR); 0161 } 0162 return static_cast<ElementImpl *>(impl)->tagName(); 0163 } 0164 0165 DOMString Element::getAttribute(const DOMString &name) 0166 { 0167 // ### getAttribute() and getAttributeNS() are supposed to return the empty string if the attribute 0168 // does not exist. However, there are a number of places around khtml that expect a null string 0169 // for nonexistent attributes. These need to be changed to use hasAttribute() instead. 0170 if (!impl) { 0171 throw DOMException(DOMException::NOT_FOUND_ERR); 0172 } 0173 if (!name.implementation()) { 0174 throw DOMException(DOMException::NOT_FOUND_ERR); 0175 } 0176 0177 return static_cast<ElementImpl *>(impl)->getAttribute(name); 0178 } 0179 0180 void Element::setAttribute(const DOMString &name, const DOMString &value) 0181 { 0182 if (!impl) { 0183 throw DOMException(DOMException::NOT_FOUND_ERR); 0184 } 0185 int exceptioncode = 0; 0186 static_cast<ElementImpl *>(impl)->setAttribute(name, value, exceptioncode); 0187 if (exceptioncode) { 0188 throw DOMException(exceptioncode); 0189 } 0190 } 0191 0192 void Element::removeAttribute(const DOMString &name) 0193 { 0194 if (!impl) { 0195 throw DOMException(DOMException::NOT_FOUND_ERR); 0196 } 0197 0198 int exceptioncode = 0; 0199 static_cast<ElementImpl *>(impl)->removeAttribute(name, exceptioncode); 0200 // it's allowed to remove attributes that don't exist. 0201 if (exceptioncode && exceptioncode != DOMException::NOT_FOUND_ERR) { 0202 throw DOMException(exceptioncode); 0203 } 0204 } 0205 0206 Attr Element::getAttributeNode(const DOMString &name) 0207 { 0208 if (!impl) { 0209 throw DOMException(DOMException::NOT_FOUND_ERR); 0210 } 0211 if (!name.implementation()) { 0212 throw DOMException(DOMException::NOT_FOUND_ERR); 0213 } 0214 0215 return static_cast<ElementImpl *>(impl)->getAttributeNode(name); 0216 } 0217 0218 Attr Element::setAttributeNode(const Attr &newAttr) 0219 { 0220 if (!impl || newAttr.isNull()) { 0221 throw DOMException(DOMException::NOT_FOUND_ERR); 0222 } 0223 // WRONG_DOCUMENT_ERR and INUSE_ATTRIBUTE_ERR are already tested & thrown by setNamedItem 0224 0225 int exceptioncode = 0; 0226 Attr r = static_cast<ElementImpl *>(impl)->setAttributeNode( 0227 static_cast<AttrImpl *>(newAttr.handle()), exceptioncode); 0228 if (exceptioncode) { 0229 throw DOMException(exceptioncode); 0230 } 0231 return r; 0232 } 0233 0234 Attr Element::removeAttributeNode(const Attr &oldAttr) 0235 { 0236 int exceptioncode = 0; 0237 if (!impl) { 0238 throw DOMException(DOMException::NOT_FOUND_ERR); 0239 } 0240 0241 Attr ret = static_cast<ElementImpl *>(impl)->removeAttributeNode( 0242 static_cast<AttrImpl *>(oldAttr.handle()), exceptioncode); 0243 if (exceptioncode) { 0244 throw DOMException(exceptioncode); 0245 } 0246 0247 return ret; 0248 } 0249 0250 NodeList Element::getElementsByTagName(const DOMString &tagName) 0251 { 0252 if (!impl) { 0253 return nullptr; 0254 } 0255 return static_cast<ElementImpl *>(impl)->getElementsByTagName(tagName); 0256 } 0257 0258 NodeList Element::getElementsByTagNameNS(const DOMString &namespaceURI, 0259 const DOMString &localName) 0260 { 0261 if (!impl) { 0262 return nullptr; 0263 } 0264 return static_cast<ElementImpl *>(impl)->getElementsByTagNameNS(namespaceURI, localName); 0265 } 0266 0267 NodeList Element::getElementsByClassName(const DOMString &className) 0268 { 0269 if (!impl) { 0270 return nullptr; 0271 } 0272 return impl->getElementsByClassName(className); 0273 } 0274 0275 DOMString Element::getAttributeNS(const DOMString &namespaceURI, 0276 const DOMString &localName) 0277 { 0278 if (!impl) { 0279 throw DOMException(DOMException::NOT_FOUND_ERR); 0280 } 0281 ElementImpl *e = static_cast<ElementImpl *>(impl); 0282 int exceptioncode = 0; 0283 DOMString ret = e->getAttributeNS(namespaceURI, localName, exceptioncode); 0284 if (exceptioncode) { 0285 throw DOMException(exceptioncode); 0286 } 0287 return ret; 0288 } 0289 0290 void Element::setAttributeNS(const DOMString &namespaceURI, 0291 const DOMString &qualifiedName, 0292 const DOMString &value) 0293 { 0294 if (!impl) { 0295 throw DOMException(DOMException::NOT_FOUND_ERR); 0296 } 0297 0298 int exceptioncode = 0; 0299 static_cast<ElementImpl *>(impl)->setAttributeNS(namespaceURI, qualifiedName, value, exceptioncode); 0300 if (exceptioncode) { 0301 throw DOMException(exceptioncode); 0302 } 0303 } 0304 0305 void Element::removeAttributeNS(const DOMString &namespaceURI, 0306 const DOMString &localName) 0307 { 0308 if (!impl) { 0309 throw DOMException(DOMException::NOT_FOUND_ERR); 0310 } 0311 0312 int exceptioncode = 0; 0313 static_cast<ElementImpl *>(impl)->removeAttributeNS(namespaceURI, localName, exceptioncode); 0314 if (exceptioncode) { 0315 throw DOMException(exceptioncode); 0316 } 0317 } 0318 0319 Attr Element::getAttributeNodeNS(const DOMString &namespaceURI, 0320 const DOMString &localName) 0321 { 0322 if (!impl) { 0323 throw DOMException(DOMException::NOT_FOUND_ERR); 0324 } 0325 0326 int exceptioncode = 0; 0327 Attr r = static_cast<ElementImpl *>(impl)->getAttributeNodeNS(namespaceURI, localName, exceptioncode); 0328 if (exceptioncode) { 0329 throw DOMException(exceptioncode); 0330 } 0331 return r; 0332 } 0333 0334 Attr Element::setAttributeNodeNS(const Attr &newAttr) 0335 { 0336 if (!impl) { 0337 throw DOMException(DOMException::NOT_FOUND_ERR); 0338 } 0339 0340 int exceptioncode = 0; 0341 Attr r = static_cast<ElementImpl *>(impl)->setAttributeNodeNS( 0342 static_cast<AttrImpl *>(newAttr.handle()), exceptioncode); 0343 return r; 0344 } 0345 0346 bool Element::hasAttribute(const DOMString &name) 0347 { 0348 if (!impl) { 0349 return false; // ### throw ? 0350 } 0351 return static_cast<ElementImpl *>(impl)->hasAttribute(name); 0352 } 0353 0354 bool Element::hasAttributeNS(const DOMString &namespaceURI, 0355 const DOMString &localName) 0356 { 0357 if (!impl) { 0358 return false; 0359 } 0360 return static_cast<ElementImpl *>(impl)->hasAttributeNS(namespaceURI, localName); 0361 } 0362 0363 bool Element::isHTMLElement() const 0364 { 0365 if (!impl) { 0366 return false; 0367 } 0368 return ((ElementImpl *)impl)->isHTMLElement(); 0369 } 0370 0371 Element Element::form() const 0372 { 0373 if (!impl || !impl->isGenericFormElement()) { 0374 return nullptr; 0375 } 0376 return static_cast<HTMLGenericFormElementImpl *>(impl)->form(); 0377 ElementImpl *f = static_cast<HTMLGenericFormElementImpl *>(impl)->form(); 0378 0379 if (f && f->implicitNode()) { 0380 return nullptr; 0381 } 0382 return f; 0383 } 0384 0385 CSSStyleDeclaration Element::style() 0386 { 0387 if (impl) { 0388 return ((ElementImpl *)impl)->getInlineStyleDecls(); 0389 } 0390 return nullptr; 0391 } 0392 0393 Element Element::firstElementChild() const 0394 { 0395 if (!impl) { 0396 throw DOMException(DOMException::NOT_FOUND_ERR); 0397 } 0398 return static_cast<ElementImpl *>(impl)->firstElementChild(); 0399 } 0400 0401 Element Element::lastElementChild() const 0402 { 0403 if (!impl) { 0404 throw DOMException(DOMException::NOT_FOUND_ERR); 0405 } 0406 return static_cast<ElementImpl *>(impl)->lastElementChild(); 0407 } 0408 0409 Element Element::previousElementSibling() const 0410 { 0411 if (!impl) { 0412 throw DOMException(DOMException::NOT_FOUND_ERR); 0413 } 0414 return static_cast<ElementImpl *>(impl)->previousElementSibling(); 0415 } 0416 0417 Element Element::nextElementSibling() const 0418 { 0419 if (!impl) { 0420 throw DOMException(DOMException::NOT_FOUND_ERR); 0421 } 0422 return static_cast<ElementImpl *>(impl)->nextElementSibling(); 0423 } 0424 0425 unsigned long Element::childElementCount() const 0426 { 0427 if (!impl) { 0428 throw DOMException(DOMException::NOT_FOUND_ERR); 0429 } 0430 return static_cast<ElementImpl *>(impl)->childElementCount(); 0431 } 0432 0433 Element Element::querySelector(const DOMString &query) const 0434 { 0435 int ec = 0; 0436 if (!impl) { 0437 throw DOMException(DOMException::NOT_FOUND_ERR); 0438 } 0439 Element res = impl->querySelector(query, ec).get(); 0440 if (ec) { 0441 throw DOMException(ec); 0442 } 0443 return res; 0444 } 0445 0446 NodeList Element::querySelectorAll(const DOMString &query) const 0447 { 0448 int ec = 0; 0449 if (!impl) { 0450 throw DOMException(DOMException::NOT_FOUND_ERR); 0451 } 0452 NodeList res = impl->querySelectorAll(query, ec).get(); 0453 if (ec) { 0454 throw DOMException(ec); 0455 } 0456 return res; 0457 } 0458 0459 static inline bool isExtender(ushort c) 0460 { 0461 return c > 0x00B6 && 0462 (c == 0x00B7 || c == 0x02D0 || c == 0x02D1 || c == 0x0387 || 0463 c == 0x0640 || c == 0x0E46 || c == 0x0EC6 || c == 0x3005 || 0464 (c >= 0x3031 && c <= 0x3035) || 0465 (c >= 0x309D && c <= 0x309E) || 0466 (c >= 0x30FC && c <= 0x30FE) 0467 ); 0468 } 0469 0470 bool Element::khtmlValidAttrName(const DOMString &name) 0471 { 0472 // Check if name is valid 0473 // https://www.w3.org/TR/2000/REC-xml-20001006#NT-Name 0474 DOMStringImpl *_name = name.implementation(); 0475 QChar ch = _name->s[0]; 0476 if (!ch.isLetter() && ch != '_' && ch != ':') { 0477 return false; // first char isn't valid 0478 } 0479 for (uint i = 0; i < _name->l; ++i) { 0480 ch = _name->s[i]; 0481 if (!ch.isLetter() && !ch.isDigit() && ch != '.' 0482 && ch != '-' && ch != '_' && ch != ':' 0483 && ch.category() != QChar::Mark_SpacingCombining 0484 && !isExtender(ch.unicode())) { 0485 return false; 0486 } 0487 } 0488 return true; 0489 } 0490 0491 bool Element::khtmlValidPrefix(const DOMString &name) 0492 { 0493 // Null prefix is ok. If not null, reuse code from khtmlValidAttrName 0494 return !name.implementation() || khtmlValidAttrName(name); 0495 } 0496 0497 bool Element::khtmlValidQualifiedName(const DOMString &name) 0498 { 0499 return khtmlValidAttrName(name); 0500 } 0501 0502 bool Element::khtmlMalformedQualifiedName(const DOMString &name) 0503 { 0504 // #### see XML Namespaces spec for possibly more 0505 0506 // ### does this disctinction make sense? 0507 if (name.isNull()) { 0508 return true; 0509 } 0510 if (name.isEmpty()) { 0511 return false; 0512 } 0513 0514 // a prefix is optional but both prefix as well as local part 0515 // cannot be empty 0516 int colonpos = name.find(':'); 0517 if (colonpos == 0 || colonpos == name.length() - 1) { 0518 return true; 0519 } 0520 0521 return false; 0522 } 0523 0524 bool Element::khtmlMalformedPrefix(const DOMString &/*name*/) 0525 { 0526 // #### 0527 return false; 0528 }