KHtml

dom_xmlimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 2000 Peter Kelly ([email protected])
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "dom_xmlimpl.h"
23 
24 #include <dom/dom_exception.h>
25 
26 #include "dom_docimpl.h"
27 #include "dom_stringimpl.h"
28 #include <css/css_stylesheetimpl.h>
29 #include <css/css_mediaquery.h>
30 #include <misc/loader.h>
31 
32 using namespace DOM;
33 
34 EntityImpl::EntityImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
35 {
36  m_publicId = nullptr;
37  m_systemId = nullptr;
38  m_notationName = nullptr;
39  m_name = nullptr;
40 }
41 
42 EntityImpl::EntityImpl(DocumentImpl *doc, DOMString _name) : NodeBaseImpl(doc)
43 {
44  m_publicId = nullptr;
45  m_systemId = nullptr;
46  m_notationName = nullptr;
47  m_name = _name.implementation();
48  if (m_name) {
49  m_name->ref();
50  }
51 }
52 
53 EntityImpl::EntityImpl(DocumentImpl *doc, DOMString _publicId, DOMString _systemId, DOMString _notationName) : NodeBaseImpl(doc)
54 {
55  m_publicId = _publicId.implementation();
56  if (m_publicId) {
57  m_publicId->ref();
58  }
59  m_systemId = _systemId.implementation();
60  if (m_systemId) {
61  m_systemId->ref();
62  }
63  m_notationName = _notationName.implementation();
64  if (m_notationName) {
65  m_notationName->ref();
66  }
67  m_name = nullptr;
68 }
69 
70 EntityImpl::~EntityImpl()
71 {
72  if (m_publicId) {
73  m_publicId->deref();
74  }
75  if (m_systemId) {
76  m_systemId->deref();
77  }
78  if (m_notationName) {
79  m_notationName->deref();
80  }
81  if (m_name) {
82  m_name->deref();
83  }
84 }
85 
86 DOMString EntityImpl::publicId() const
87 {
88  return m_publicId;
89 }
90 
91 DOMString EntityImpl::systemId() const
92 {
93  return m_systemId;
94 }
95 
96 DOMString EntityImpl::notationName() const
97 {
98  return m_notationName;
99 }
100 
101 DOMString EntityImpl::nodeName() const
102 {
103  return m_name;
104 }
105 
106 unsigned short EntityImpl::nodeType() const
107 {
108  return Node::ENTITY_NODE;
109 }
110 
111 WTF::PassRefPtr<NodeImpl> EntityImpl::cloneNode(bool /*deep*/)
112 {
113  // Spec says cloning Document nodes is "implementation dependent"
114  // so we do not support it...
115  return nullptr;
116 }
117 
118 // DOM Section 1.1.1
119 bool EntityImpl::childTypeAllowed(unsigned short type)
120 {
121  switch (type) {
122  case Node::ELEMENT_NODE:
123  case Node::PROCESSING_INSTRUCTION_NODE:
124  case Node::COMMENT_NODE:
125  case Node::TEXT_NODE:
126  case Node::CDATA_SECTION_NODE:
127  case Node::ENTITY_REFERENCE_NODE:
128  return true;
129  break;
130  default:
131  return false;
132  }
133 }
134 
135 DOMString EntityImpl::toString() const
136 {
137  DOMString result = "<!ENTITY' ";
138 
139  if (m_name && m_name->l != 0) {
140  result += " ";
141  result += m_name;
142  }
143 
144  if (m_publicId && m_publicId->l != 0) {
145  result += " PUBLIC \"";
146  result += m_publicId;
147  result += "\" \"";
148  result += m_systemId;
149  result += "\"";
150  } else if (m_systemId && m_systemId->l != 0) {
151  result += " SYSTEM \"";
152  result += m_systemId;
153  result += "\"";
154  }
155 
156  if (m_notationName && m_notationName->l != 0) {
157  result += " NDATA ";
158  result += m_notationName;
159  }
160 
161  result += ">";
162 
163  return result;
164 }
165 
166 // -------------------------------------------------------------------------
167 
168 EntityReferenceImpl::EntityReferenceImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
169 {
170  m_entityName = nullptr;
171 }
172 
173 EntityReferenceImpl::EntityReferenceImpl(DocumentImpl *doc, DOMStringImpl *_entityName) : NodeBaseImpl(doc)
174 {
175  m_entityName = _entityName;
176  if (m_entityName) {
177  m_entityName->ref();
178  }
179 }
180 
181 EntityReferenceImpl::~EntityReferenceImpl()
182 {
183  if (m_entityName) {
184  m_entityName->deref();
185  }
186 }
187 
188 DOMString EntityReferenceImpl::nodeName() const
189 {
190  return m_entityName;
191 }
192 
193 unsigned short EntityReferenceImpl::nodeType() const
194 {
195  return Node::ENTITY_REFERENCE_NODE;
196 }
197 
198 WTF::PassRefPtr<NodeImpl> EntityReferenceImpl::cloneNode(bool deep)
199 {
200  EntityReferenceImpl *clone = new EntityReferenceImpl(docPtr(), m_entityName);
201  // ### make sure children are readonly
202  // ### since we are a reference, should we clone children anyway (even if not deep?)
203  if (deep) {
204  cloneChildNodes(clone);
205  }
206  return clone;
207 }
208 
209 // DOM Section 1.1.1
210 bool EntityReferenceImpl::childTypeAllowed(unsigned short type)
211 {
212  switch (type) {
213  case Node::ELEMENT_NODE:
214  case Node::PROCESSING_INSTRUCTION_NODE:
215  case Node::COMMENT_NODE:
216  case Node::TEXT_NODE:
217  case Node::CDATA_SECTION_NODE:
218  case Node::ENTITY_REFERENCE_NODE:
219  return true;
220  break;
221  default:
222  return false;
223  }
224 }
225 
226 DOMString EntityReferenceImpl::toString() const
227 {
228  DOMString result = "&";
229  result += m_entityName;
230  result += ";";
231 
232  return result;
233 }
234 
235 // -------------------------------------------------------------------------
236 
237 NotationImpl::NotationImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
238 {
239  m_publicId = nullptr;
240  m_systemId = nullptr;
241  m_name = nullptr;
242 }
243 
244 NotationImpl::NotationImpl(DocumentImpl *doc, DOMString _name, DOMString _publicId, DOMString _systemId) : NodeBaseImpl(doc)
245 {
246  m_name = _name.implementation();
247  if (m_name) {
248  m_name->ref();
249  }
250  m_publicId = _publicId.implementation();
251  if (m_publicId) {
252  m_publicId->ref();
253  }
254  m_systemId = _systemId.implementation();
255  if (m_systemId) {
256  m_systemId->ref();
257  }
258 }
259 
260 NotationImpl::~NotationImpl()
261 {
262  if (m_name) {
263  m_name->deref();
264  }
265  if (m_publicId) {
266  m_publicId->deref();
267  }
268  if (m_systemId) {
269  m_systemId->deref();
270  }
271 }
272 
273 DOMString NotationImpl::publicId() const
274 {
275  return m_publicId;
276 }
277 
278 DOMString NotationImpl::systemId() const
279 {
280  return m_systemId;
281 }
282 
283 DOMString NotationImpl::nodeName() const
284 {
285  return m_name;
286 }
287 
288 unsigned short NotationImpl::nodeType() const
289 {
290  return Node::NOTATION_NODE;
291 }
292 
293 WTF::PassRefPtr<NodeImpl> NotationImpl::cloneNode(bool /*deep*/)
294 {
295  // Spec says cloning Document nodes is "implementation dependent"
296  // so we do not support it...
297  return nullptr;
298 }
299 
300 // DOM Section 1.1.1
301 bool NotationImpl::childTypeAllowed(unsigned short /*type*/)
302 {
303  return false;
304 }
305 
306 // -------------------------------------------------------------------------
307 
308 // ### need a way of updating these properly whenever child nodes of the processing instruction
309 // change or are added/removed
310 
311 ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
312 {
313  m_target = nullptr;
314  m_data = nullptr;
315  m_localHref = nullptr;
316  m_alternate = false;
317  m_title = nullptr;
318  m_media = nullptr;
319  m_sheet = nullptr;
320  m_cachedSheet = nullptr;
321 }
322 
323 ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentImpl *doc, DOMString _target, DOMString _data) : NodeBaseImpl(doc)
324 {
325  m_target = _target.implementation();
326  if (m_target) {
327  m_target->ref();
328  }
329  m_data = _data.implementation();
330  if (m_data) {
331  m_data->ref();
332  }
333  m_sheet = nullptr;
334  m_cachedSheet = nullptr;
335  m_localHref = nullptr;
336  m_title = nullptr;
337  m_media = nullptr;
338  m_alternate = false;
339 }
340 
341 ProcessingInstructionImpl::~ProcessingInstructionImpl()
342 {
343  if (m_target) {
344  m_target->deref();
345  }
346  if (m_title) {
347  m_title->deref();
348  }
349  if (m_media) {
350  m_media->deref();
351  }
352  if (m_data) {
353  m_data->deref();
354  }
355  if (m_cachedSheet) {
356  m_cachedSheet->deref(this);
357  }
358  if (m_sheet) {
359  m_sheet->deref();
360  }
361 }
362 
363 DOMString ProcessingInstructionImpl::target() const
364 {
365  return m_target;
366 }
367 
368 void ProcessingInstructionImpl::setData(const DOMString &_data, int &exceptioncode)
369 {
370  // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
371  if (isReadOnly()) {
372  exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
373  return;
374  }
375 
376  if (m_data) {
377  m_data->deref();
378  }
379  m_data = _data.implementation();
380  if (m_data) {
381  m_data->ref();
382  }
383 }
384 
385 DOMString ProcessingInstructionImpl::nodeName() const
386 {
387  return m_target;
388 }
389 
390 unsigned short ProcessingInstructionImpl::nodeType() const
391 {
392  return Node::PROCESSING_INSTRUCTION_NODE;
393 }
394 
395 DOMString ProcessingInstructionImpl::nodeValue() const
396 {
397  return m_data;
398 }
399 
400 void ProcessingInstructionImpl::setNodeValue(const DOMString &_nodeValue, int &exceptioncode)
401 {
402  // NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
403  setData(_nodeValue, exceptioncode);
404 }
405 
406 WTF::PassRefPtr<NodeImpl> ProcessingInstructionImpl::cloneNode(bool /*deep*/)
407 {
408  // ### copy m_localHref
409  return new ProcessingInstructionImpl(docPtr(), m_target, m_data);
410 }
411 
412 DOMString ProcessingInstructionImpl::localHref() const
413 {
414  return m_localHref;
415 }
416 
417 // DOM Section 1.1.1
418 bool ProcessingInstructionImpl::childTypeAllowed(unsigned short /*type*/)
419 {
420  return false;
421 }
422 
423 void ProcessingInstructionImpl::checkStyleSheet()
424 {
425  if (m_target && DOMString(m_target) == "xml-stylesheet") {
426  // see https://www.w3.org/TR/xml-stylesheet/
427  // ### check that this occurs only in the prolog
428  // ### support stylesheet included in a fragment of this (or another) document
429  // ### make sure this gets called when adding from javascript
430  XMLAttributeReader attrReader(DOMString(m_data).string());
431  bool attrsOk;
432  QXmlAttributes attrs = attrReader.readAttrs(attrsOk);
433  if (!attrsOk) {
434  return;
435  }
436  if (attrs.value("type") != "text/css" && !attrs.value("type").isEmpty()) {
437  return;
438  }
439 
440  DOMString href = attrs.value("href");
441  DOMString alternate = attrs.value("alternate");
442  m_alternate = alternate == "yes";
443  DOMString title = attrs.value("title");
444  DOMString media = attrs.value("media");
445  if (m_title) {
446  m_title->deref();
447  }
448  m_title = title.implementation();
449  if (m_title) {
450  m_title->ref();
451  }
452  if (m_media) {
453  m_media->deref();
454  }
455  m_media = media.implementation();
456  if (m_media) {
457  m_media->ref();
458  }
459 
460  if (href.length() > 1) {
461  if (href[0] == '#') {
462  if (m_localHref) {
463  m_localHref->deref();
464  }
465  m_localHref = href.implementation()->split(1);
466  if (m_localHref) {
467  m_localHref->ref();
468  }
469  } else {
470  // ### some validation on the URL?
471  // ### FIXME charset
472  if (m_cachedSheet) {
473  m_cachedSheet->deref(this);
474  }
475  m_cachedSheet = document()->docLoader()->requestStyleSheet(document()->completeURL(href.string()), QString());
476  if (m_cachedSheet) {
477  document()->addPendingSheet(); //before ref, because during the ref it might load!
478  m_cachedSheet->ref(this);
479  }
480  }
481 
482  }
483  }
484 }
485 
486 StyleSheetImpl *ProcessingInstructionImpl::sheet() const
487 {
488  return m_sheet;
489 }
490 
491 void ProcessingInstructionImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset, const DOM::DOMString &mimetype)
492 {
493  if (m_sheet) {
494  m_sheet->deref();
495  }
496  m_sheet = new CSSStyleSheetImpl(document(), url);
497  m_sheet->ref();
498  m_sheet->setCharset(charset);
499  m_sheet->setTitle(m_title);
500  m_sheet->setMedia(new MediaListImpl((CSSStyleSheetImpl *)m_sheet, m_media, false));
501  m_sheet->parseString(khtml::isAcceptableCSSMimetype(mimetype) ? sheet : "");
502  if (m_cachedSheet) {
503  m_cachedSheet->deref(this);
504  }
505  m_cachedSheet = nullptr;
506 
507  document()->styleSheetLoaded();
508 }
509 
510 void ProcessingInstructionImpl::setStyleSheet(CSSStyleSheetImpl *sheet)
511 {
512  if (m_sheet) {
513  m_sheet->deref();
514  }
515  m_sheet = sheet;
516  if (m_sheet) {
517  m_sheet->ref();
518  m_sheet->setTitle(m_title);
519  }
520 }
521 
522 DOMString ProcessingInstructionImpl::toString() const
523 {
524  DOMString result = "<?";
525  result += m_target;
526  result += " ";
527  result += m_data;
528  result += ">";
529  return result;
530 }
531 
532 int ProcessingInstructionImpl::maxCharacterOffset() const
533 {
534  return m_data ? static_cast<int>(m_data->length()) : 0;
535 }
536 
537 // -------------------------------------------------------------------------
538 
539 XMLAttributeReader::XMLAttributeReader(const QString &_attrString)
540 {
541  m_attrString = _attrString;
542 }
543 
544 XMLAttributeReader::~XMLAttributeReader()
545 {
546 }
547 
548 QXmlAttributes XMLAttributeReader::readAttrs(bool &ok)
549 {
550  // parse xml file
551  QXmlInputSource source;
552  source.setData("<?xml version=\"1.0\"?><attrs " + m_attrString + " />");
553  QXmlSimpleReader reader;
554  reader.setContentHandler(this);
555  ok = reader.parse(source);
556  return attrs;
557 }
558 
559 bool XMLAttributeReader::startElement(const QString & /*namespaceURI*/, const QString &localName,
560  const QString & /*qName*/, const QXmlAttributes &atts)
561 {
562  if (localName == "attrs") {
563  attrs = atts;
564  return true;
565  } else {
566  return false; // we shouldn't have any other elements
567  }
568 }
virtual void setData(const QString &dat)
void setData(const DOMString &)
see data NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
Definition: dom_xml.cpp:287
StyleSheet sheet() const
Introduced in DOM Level 2 This method is from the LinkStyle interface.
Definition: dom_xml.cpp:304
bool isEmpty() const const
DOMString localName() const
Introduced in DOM Level 2.
Definition: dom_node.cpp:433
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
This library provides a full-featured HTML parser and widget.
virtual bool parse(const QXmlInputSource &input) override
DOMStringImpl * implementation() const
Definition: dom_string.h:145
QString value(int index) const const
virtual void setContentHandler(QXmlContentHandler *handler) override
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:01 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.