DOMString ElementImpl::openTagStartToString() const
{
    DOMString result = DOMString("<") + tagName();

    NamedAttrMapImpl *attrMap = attributes(true);

    if (attrMap) {
	unsigned long numAttrs = attrMap->length();
	for (unsigned long i = 0; i < numAttrs; i++) {
	    result += " ";

	    AttributeImpl *attribute = attrMap->attributeItem(i);
	    AttrImpl *attr = attribute->attrImpl();

	    if (attr) {
		result += attr->toString();
	    } else {
		result += getDocument()->attrName(attribute->id());
		if (!attribute->value().isNull()) {
		    result += "=\"";
		    // FIXME: substitute entities for any instances of " or '
		    result += attribute->value();
		    result += "\"";
		}
	    }
	}
    }

    return result;
}
void ElementImpl::setAttributeMap( NamedAttrMapImpl* list )
{
    if (inDocument())
        getDocument()->incDOMTreeVersion();

    // If setting the whole map changes the id attribute, we need to
    // call updateId.

    AttributeImpl *oldId = namedAttrMap ? namedAttrMap->getAttributeItem(ATTR_ID) : 0;
    AttributeImpl *newId = list ? list->getAttributeItem(ATTR_ID) : 0;

    if (oldId || newId) {
	updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    }

    if(namedAttrMap)
        namedAttrMap->deref();

    namedAttrMap = list;

    if(namedAttrMap) {
        namedAttrMap->ref();
        namedAttrMap->element = this;
        unsigned int len = namedAttrMap->length();
        for(unsigned int i = 0; i < len; i++)
            attributeChanged(namedAttrMap->attrs[i]);
    }
}
NamedAttrMapImpl& NamedAttrMapImpl::operator=(const NamedAttrMapImpl& other)
{
    // clone all attributes in the other map, but attach to our element
    if (!element) return *this;

    // If assigning the map changes the id attribute, we need to call
    // updateId.

    AttributeImpl *oldId = getAttributeItem(ATTR_ID);
    AttributeImpl *newId = other.getAttributeItem(ATTR_ID);

    if (oldId || newId) {
	element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    }

    clearAttributes();
    len = other.len;
    attrs = new AttributeImpl* [len];

    // first initialize attrs vector, then call attributeChanged on it
    // this allows attributeChanged to use getAttribute
    for (uint i = 0; i < len; i++) {
        attrs[i] = other.attrs[i]->clone();
        attrs[i]->ref();
    }

    // FIXME: This is wasteful.  The class list could be preserved on a copy, and we
    // wouldn't have to waste time reparsing the attribute.
    // The derived class, HTMLNamedAttrMapImpl, which manages a parsed class list for the CLASS attribute,
    // will update its member variable when parse attribute is called.
    for(uint i = 0; i < len; i++)
        element->attributeChanged(attrs[i], true);

    return *this;
}
void ElementImpl::setAttribute(NodeImpl::Id id, DOMStringImpl* value, int &exceptioncode )
{
    if (inDocument())
        getDocument()->incDOMTreeVersion();

    // allocate attributemap if necessary
    AttributeImpl* old = attributes(false)->getAttributeItem(id);

    // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    if (namedAttrMap->isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return;
    }

    if (id == ATTR_ID) {
	updateId(old ? old->value() : nullAtom, value);
    }
    
    if (old && !value)
        namedAttrMap->removeAttribute(id);
    else if (!old && value)
        namedAttrMap->addAttribute(createAttribute(id, value));
    else if (old && value) {
        old->setValue(value);
        attributeChanged(old);
    }
}
예제 #5
0
NodeImpl *KHTMLParser::handleIsindex( Token *t )
{
    NodeImpl *n;
    HTMLFormElementImpl *myform = form;
    if ( !myform ) {
        myform = new HTMLFormElementImpl(document);
        n = myform;
    } else
        n = new HTMLDivElementImpl( document );
    NodeImpl *child = new HTMLHRElementImpl( document );
    n->addChild( child );
    AttributeImpl* a = t->attrs ? t->attrs->getAttributeItem(ATTR_PROMPT) : 0;
#if APPLE_CHANGES && !KWIQ
    DOMString text = searchableIndexIntroduction();
#elif KWIQ // FIXME: KWIQ: Internationalization. Hardcoded string.
    DOMString text = "This is a searchable index. Enter search keywords: ";
#else
    DOMString text = i18n("This is a searchable index. Enter search keywords: ");
#endif
    if (a)
        text = DOMString(a->value()) + " ";
    child = new TextImpl(document, text);
    n->addChild( child );
    child = new HTMLIsIndexElementImpl(document, myform);
    static_cast<ElementImpl *>(child)->setAttribute(ATTR_TYPE, "khtml_isindex");
    n->addChild( child );
    child = new HTMLHRElementImpl( document );
    n->addChild( child );

    return n;
}
NodeImpl *KHTMLParser::handleIsindex( Token *t )
{
    NodeImpl *n;
    HTMLFormElementImpl *myform = form;
    if ( !myform ) {
        myform = new HTMLFormElementImpl(document, true);
        n = myform;
    } else
        n = new HTMLDivElementImpl( document, ID_DIV );
    NodeImpl *child = new HTMLHRElementImpl( document );
    n->addChild( child );
    AttributeImpl* a = t->attrs ? t->attrs->getAttributeItem(ATTR_PROMPT) : 0;
    DOMString text = i18n("This is a searchable index. Enter search keywords: ");
    if (a)
        text = a->value();
    child = new TextImpl(document, text.implementation());
    n->addChild( child );
    child = new HTMLIsIndexElementImpl(document, myform);
    static_cast<ElementImpl *>(child)->setAttribute(ATTR_TYPE, "khtml_isindex");
    n->addChild( child );
    child = new HTMLHRElementImpl( document );
    n->addChild( child );

    return n;
}
// The DOM2 spec doesn't say that removeAttribute[NS] throws NOT_FOUND_ERR
// if the attribute is not found, but at this level we have to throw NOT_FOUND_ERR
// because of removeNamedItem, removeNamedItemNS, and removeAttributeNode.
Node NamedAttrMapImpl::removeNamedItem ( NodeImpl::Id id, int &exceptioncode )
{
    // ### should this really be raised when the attribute to remove isn't there at all?
    // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    if (isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return Node();
    }

    AttributeImpl* a = getAttributeItem(id);
    if (!a) {
        exceptioncode = DOMException::NOT_FOUND_ERR;
        return Node();
    }

    if (!a->attrImpl())  a->allocateImpl(element);
    Node r(a->attrImpl());

    if (id == ATTR_ID) {
	element->updateId(a->value(), nullAtom);
    }

    removeAttribute(id);
    return r;
}
AttrImpl *NamedAttrMapImpl::getNamedItem ( NodeImpl::Id id ) const
{
    AttributeImpl* a = getAttributeItem(id);
    if (!a) return 0;

    if (!a->attrImpl())
        a->allocateImpl(element);

    return a->attrImpl();
}
const AtomicString& ElementImpl::getAttribute(NodeImpl::Id id) const
{
    if (id == ATTR_STYLE)
        updateStyleAttributeIfNeeded();

    if (namedAttrMap) {
        AttributeImpl* a = namedAttrMap->getAttributeItem(id);
        if (a) return a->value();
    }
    return nullAtom;
}
void ElementImpl::dump(QTextStream *stream, QString ind) const
{
    updateStyleAttributeIfNeeded();
    if (namedAttrMap) {
        for (uint i = 0; i < namedAttrMap->length(); i++) {
            AttributeImpl *attr = namedAttrMap->attributeItem(i);
            *stream << " " << DOMString(getDocument()->attrName(attr->id())).string().ascii()
                    << "=\"" << DOMString(attr->value()).string().ascii() << "\"";
        }
    }

    NodeBaseImpl::dump(stream,ind);
}
void ElementImpl::removedFromDocument()
{
    if (hasID()) {
        NamedAttrMapImpl *attrs = attributes(true);
        if (attrs) {
            AttributeImpl *idAttr = attrs->getAttributeItem(ATTR_ID);
            if (idAttr && !idAttr->isNull()) {
                updateId(idAttr->value(), nullAtom);
            }
        }
    }

    NodeBaseImpl::removedFromDocument();
}
예제 #12
0
void ObjectResolver::Resolve()
{
    for (auto it = objectRefs.Begin(); it != objectRefs.End(); ++it)
    {
        auto refIt = objects.Find(it->oldId);
        // See if we can find the referred to object
        if (refIt != objects.End())
        {
            AttributeImpl<ObjectRef>* typedAttr = static_cast<AttributeImpl<ObjectRef>*>(it->attr);
            typedAttr->SetValue(it->object, ObjectRef(refIt->second->Id()));
        }
        else
            LOGWARNING("Could not resolve object reference " + String(it->oldId));
    }
}
Node NamedAttrMapImpl::setNamedItem ( NodeImpl* arg, int &exceptioncode )
{
    if (!element) {
        exceptioncode = DOMException::NOT_FOUND_ERR;
        return 0;
    }

    // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
    if (isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return 0;
    }

    // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map.
    if (arg->getDocument() != element->getDocument()) {
        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
        return 0;
    }

    // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node
    if (!arg->isAttributeNode()) {
        exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
        return 0;
    }
    AttrImpl *attr = static_cast<AttrImpl*>(arg);

    AttributeImpl* a = attr->attrImpl();
    AttributeImpl* old = getAttributeItem(a->id());
    if (old == a) return arg; // we know about it already

    // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object.
    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    if (attr->ownerElement()) {
        exceptioncode = DOMException::INUSE_ATTRIBUTE_ERR;
        return 0;
    }

    if (a->id() == ATTR_ID) {
	element->updateId(old ? old->value() : nullAtom, a->value());
    }

    // ### slightly inefficient - resizes attribute array twice.
    Node r;
    if (old) {
        if (!old->attrImpl())
            old->allocateImpl(element);
        r = old->_impl;
        removeAttribute(a->id());
    }

    addAttribute(a);
    return r;
}
void ElementImpl::insertedIntoDocument()
{
    // need to do superclass processing first so inDocument() is true
    // by the time we reach updateId
    NodeBaseImpl::insertedIntoDocument();

    if (hasID()) {
        NamedAttrMapImpl *attrs = attributes(true);
        if (attrs) {
            AttributeImpl *idAttr = attrs->getAttributeItem(ATTR_ID);
            if (idAttr && !idAttr->isNull()) {
                updateId(nullAtom, idAttr->value());
            }
        }
    }
}
예제 #15
0
DOMString ElementImpl::openTagStartToString(bool expandurls) const
{
    DOMString result = DOMString("<") + tagName();

    NamedAttrMapImpl *attrMap = attributes(true);

    if(attrMap)
    {
        unsigned long numAttrs = attrMap->length();
        for(unsigned long i = 0; i < numAttrs; i++)
        {
            result += " ";

            AttributeImpl *attribute = attrMap->attrAt(i);
            AttrImpl *attr = attribute->attr();

            if(attr)
            {
                result += attr->toString();
            }
            else
            {
                result += getDocument()->getName(NodeImpl::AttributeId, attribute->id());
                if(!attribute->value().isNull())
                {
                    result += "=\"";
                    // FIXME: substitute entities for any instances of " or '
                    // Expand out all urls, i.e. the src and href attributes
                    if(expandurls && (attribute->id() == ATTR_SRC || attribute->id() == ATTR_HREF))
                        if(getDocument())
                        {
                            // We need to sanitize the urls - strip out the passwords.
                            // FIXME:   are src=  and href=  the only places that might have a password and need to be sanitized?
                            KURL safeURL(getDocument()->completeURL(attribute->value().string()));
                            safeURL.setPass(QString::null);
                            result += safeURL.htmlURL();
                        }
                        else
                        {
                            kdWarning() << "getDocument() returned false";
                            result += attribute->value();
                        }
                    else
                        result += attribute->value();
                    result += "\"";
                }
            }
        }
    }

    return result;
}
bool HTMLNamedAttrMapImpl::mapsEquivalent(const HTMLNamedAttrMapImpl* otherMap) const
{
    // The # of decls must match.
    if (declCount() != otherMap->declCount())
        return false;
    
    // The values for each decl must match.
    for (uint i = 0; i < length(); i++) {
        HTMLAttributeImpl* attr = attributeItem(i);
        if (attr->decl()) {
            AttributeImpl* otherAttr = otherMap->getAttributeItem(attr->id());
            if (!otherAttr || (attr->value() != otherAttr->value()))
                return false;
        }
    }
    return true;
}
void NamedAttrMapImpl::removeAttribute(NodeImpl::Id id)
{
    unsigned long index = len+1;
    for (unsigned long i = 0; i < len; ++i)
        if (attrs[i]->id() == id) {
            index = i;
            break;
        }

    if (index >= len) return;

    // Remove the attribute from the list
    AttributeImpl* attr = attrs[index];
    if (attrs[index]->_impl)
        attrs[index]->_impl->m_element = 0;
    if (len == 1) {
        delete [] attrs;
        attrs = 0;
        len = 0;
    }
    else {
        AttributeImpl **newAttrs = new AttributeImpl* [len-1];
        uint i;
        for (i = 0; i < uint(index); i++)
            newAttrs[i] = attrs[i];
        len--;
        for (; i < len; i++)
            newAttrs[i] = attrs[i+1];
        delete [] attrs;
        attrs = newAttrs;
    }

    // Notify the element that the attribute has been removed
    // dispatch appropriate mutation events
    if (element && !attr->_value.isNull()) {
        AtomicString value = attr->_value;
        attr->_value = nullAtom;
        element->attributeChanged(attr);
        attr->_value = value;
    }
    if (element) {
        element->dispatchAttrRemovalEvent(attr);
        element->dispatchSubtreeModifiedEvent(false);
    }
    attr->deref();
}
AttributeImpl* AttributeImpl::clone(bool) const
{
    AttributeImpl* result = new AttributeImpl(m_id, _value);
    result->setPrefix(_prefix);
    return result;
}
예제 #19
0
bool KHTMLParser::insertNode(NodeImpl *n, bool flat)
{
    int id = n->id();

    // let's be stupid and just try to insert it.
    // this should work if the document is wellformed
#ifdef PARSER_DEBUG
    NodeImpl *tmp = current;
#endif
    NodeImpl *newNode = current->addChild(n);
    if ( newNode ) {
#ifdef PARSER_DEBUG
        kdDebug( 6035 ) << "added " << n->nodeName().string() << " to " << tmp->nodeName().string() << ", new current=" << newNode->nodeName().string() << endl;
#endif
        // don't push elements without end tag on the stack
        if(tagPriority[id] != 0 && !flat)
        {
            pushBlock(id, tagPriority[id]);
            if (newNode == current)
                popBlock(id);
            else
                setCurrent(newNode);
#if SPEED_DEBUG < 2
            if(!n->attached() && HTMLWidget)
                n->attach();
#endif
        }
        else {
#if SPEED_DEBUG < 2
            if(!n->attached() && HTMLWidget)
                n->attach();
            if (n->maintainsState()) {
                document->document()->registerMaintainsState(n);
                QStringList &states = document->document()->restoreState();
                if (!states.isEmpty())
                    n->restoreState(states);
            }
            n->closeRenderer();
#endif
        }

        return true;
    } else {
#ifdef PARSER_DEBUG
        kdDebug( 6035 ) << "ADDING NODE FAILED!!!! current = " << current->nodeName().string() << ", new = " << n->nodeName().string() << endl;
#endif
        // error handling...
        HTMLElementImpl *e;
        bool handled = false;

        // switch according to the element to insert
        switch(id)
        {
        case ID_TR:
        case ID_TH:
        case ID_TD:
            if (inStrayTableContent && !isTableRelatedTag(current->id())) {
                // pop out to the nearest enclosing table-related tag.
                while (!isTableRelatedTag(current->id()))
                    popOneBlock();
                return insertNode(n);
            }
            break;
        case ID_COMMENT:
            break;
        case ID_HEAD:
            // ### alllow not having <HTML> in at all, as per HTML spec
            if (!current->isDocumentNode() && current->id() != ID_HTML )
                return false;
            break;
        // We can deal with a base, meta and link element in the body, by just adding the element to head.
        case ID_META:
        case ID_LINK:
        case ID_BASE:
            if( !head )
                createHead();
            if( head ) {
                if ( head->addChild(n) ) {
#if SPEED_DEBUG < 2
                    if(!n->attached() && HTMLWidget)
                        n->attach();
#endif
                    return true;
                } else {
                    return false;
                }
            }
            break;
        case ID_HTML:
            if (!current->isDocumentNode() ) {
                if ( doc()->firstChild()->id() == ID_HTML) {
                    // we have another <HTML> element.... apply attributes to existing one
                    // make sure we don't overwrite already existing attributes
                    NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true);
                    NamedAttrMapImpl *bmap = static_cast<ElementImpl*>(doc()->firstChild())->attributes(false);
                    bool changed = false;
                    for (unsigned long l = 0; map && l < map->length(); ++l) {
                        AttributeImpl* it = map->attributeItem(l);
                        changed = !bmap->getAttributeItem(it->id());
                        bmap->insertAttribute(it->clone(false));
                    }
                    if ( changed )
                        doc()->recalcStyle( NodeImpl::Inherit );
                }
                return false;
            }
            break;
        case ID_TITLE:
        case ID_STYLE:
            if ( !head )
                createHead();
            if ( head ) {
                DOM::NodeImpl *newNode = head->addChild(n);
                if ( newNode ) {
                    pushBlock(id, tagPriority[id]);
                    setCurrent(newNode);
#if SPEED_DEBUG < 2
                    if(!n->attached() && HTMLWidget)
                        n->attach();
#endif
                } else {
#ifdef PARSER_DEBUG
                    kdDebug( 6035 ) << "adding style before to body failed!!!!" << endl;
#endif
                    discard_until = ID_STYLE + ID_CLOSE_TAG;
                    return false;
                }
                return true;
            } else if(inBody) {
                discard_until = ID_STYLE + ID_CLOSE_TAG;
                return false;
            }
            break;
        // SCRIPT and OBJECT are allowed in the body.
        case ID_BODY:
            if(inBody && doc()->body()) {
                // we have another <BODY> element.... apply attributes to existing one
                // make sure we don't overwrite already existing attributes
                // some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor>
                NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true);
                NamedAttrMapImpl *bmap = doc()->body()->attributes(false);
                bool changed = false;
                for (unsigned long l = 0; map && l < map->length(); ++l) {
                    AttributeImpl* it = map->attributeItem(l);
                    changed = !bmap->getAttributeItem(it->id());
                    bmap->insertAttribute(it->clone(false));
                }
                if ( changed )
                    doc()->recalcStyle( NodeImpl::Inherit );
            } else if ( current->isDocumentNode() )
                break;
            return false;
            break;

        // the following is a hack to move non rendered elements
        // outside of tables.
        // needed for broken constructs like <table><form ...><tr>....
        case ID_INPUT:
        {
            ElementImpl *e = static_cast<ElementImpl *>(n);
            DOMString type = e->getAttribute(ATTR_TYPE);

            if ( strcasecmp( type, "hidden" ) == 0 && form) {
                form->addChild(n);
#if SPEED_DEBUG < 2
                if(!n->attached() && HTMLWidget)
                    n->attach();
#endif
                return true;
            }
            break;
        }
        case ID_TEXT:
            // ignore text inside the following elements.
            switch(current->id())
            {
            case ID_SELECT:
                return false;
            default:
                ;
                // fall through!!
            };
            break;
        case ID_DD:
        case ID_DT:
            e = new HTMLDListElementImpl(document);
            if ( insertNode(e) ) {
                insertNode(n);
                return true;
            }
            break;
        case ID_AREA:
        {
            if(map)
            {
                map->addChild(n);
#if SPEED_DEBUG < 2
                if(!n->attached() && HTMLWidget)
                    n->attach();
#endif
                handled = true;
            }
            else
                return false;
            return true;
        }
        default:
            break;
        }

        // switch on the currently active element
        switch(current->id())
        {
        case ID_HTML:
            switch(id)
            {
            case ID_SCRIPT:
            case ID_STYLE:
            case ID_META:
            case ID_LINK:
            case ID_OBJECT:
            case ID_EMBED:
            case ID_TITLE:
            case ID_ISINDEX:
            case ID_BASE:
                if(!head) {
                    head = new HTMLHeadElementImpl(document);
                    e = head;
                    insertNode(e);
                    handled = true;
                }
                break;
            case ID_TEXT: {
                TextImpl *t = static_cast<TextImpl *>(n);
                if (t->containsOnlyWhitespace())
                    return false;
                /* Fall through to default */
            }
            default:
                if ( haveFrameSet ) break;
                e = new HTMLBodyElementImpl(document);
                startBody();
                insertNode(e);
                handled = true;
                break;
            }
            break;
        case ID_HEAD:
            // we can get here only if the element is not allowed in head.
            if (id == ID_HTML)
                return false;
            else {
                // This means the body starts here...
                if ( haveFrameSet ) break;
                popBlock(ID_HEAD);
                e = new HTMLBodyElementImpl(document);
                startBody();
                insertNode(e);
                handled = true;
            }
            break;
        case ID_BODY:
            break;
        case ID_CAPTION:
            // Illegal content in a caption. Close the caption and try again.
            popBlock(ID_CAPTION);
            switch( id ) {
            case ID_THEAD:
            case ID_TFOOT:
            case ID_TBODY:
            case ID_TR:
            case ID_TD:
            case ID_TH:
                return insertNode(n, flat);
            }
            break;
        case ID_TABLE:
        case ID_THEAD:
        case ID_TFOOT:
        case ID_TBODY:
        case ID_TR:
            switch(id)
            {
            case ID_TABLE:
                popBlock(ID_TABLE); // end the table
                handled = true;      // ...and start a new one
                break;
            case ID_TEXT:
            {
                TextImpl *t = static_cast<TextImpl *>(n);
                if (t->containsOnlyWhitespace())
                    return false;
                DOMStringImpl *i = t->string();
                unsigned int pos = 0;
                while(pos < i->l && ( *(i->s+pos) == QChar(' ') ||
                                      *(i->s+pos) == QChar(0xa0))) pos++;
                if(pos == i->l)
                    break;
            }
            default:
            {
                NodeImpl *node = current;
                NodeImpl *parent = node->parentNode();

                NodeImpl *parentparent = parent->parentNode();

                if (n->isTextNode() ||
                        ( node->id() == ID_TR &&
                          ( parent->id() == ID_THEAD ||
                            parent->id() == ID_TBODY ||
                            parent->id() == ID_TFOOT ) && parentparent->id() == ID_TABLE ) ||
                        ( !checkChild( ID_TR, id ) && ( node->id() == ID_THEAD || node->id() == ID_TBODY || node->id() == ID_TFOOT ) &&
                          parent->id() == ID_TABLE ))
                {
                    node = (node->id() == ID_TABLE) ? node :
                           ((node->id() == ID_TR) ? parentparent : parent);
                    NodeImpl *parent = node->parentNode();
                    int exceptioncode = 0;
                    parent->insertBefore( n, node, exceptioncode );
                    if ( exceptioncode ) {
#ifdef PARSER_DEBUG
                        kdDebug( 6035 ) << "adding content before table failed!" << endl;
#endif
                        break;
                    }
                    if (n->isElementNode() && tagPriority[id] != 0 &&
                            !flat && endTag[id] != DOM::FORBIDDEN)
                    {
                        pushBlock(id, tagPriority[id]);
                        setCurrent(n);
                        inStrayTableContent++;
                        blockStack->strayTableContent = true;
                    }
                    return true;
                }

                if ( current->id() == ID_TR )
                    e = new HTMLTableCellElementImpl(document, ID_TD);
                else if ( current->id() == ID_TABLE )
                    e = new HTMLTableSectionElementImpl( document, ID_TBODY, true /* implicit */ );
                else
                    e = new HTMLTableRowElementImpl( document );

                insertNode(e);
                handled = true;
                break;
            } // end default
            } // end switch
            break;
        case ID_OBJECT:
            discard_until = id + ID_CLOSE_TAG;
            return false;
        case ID_UL:
        case ID_OL:
        case ID_DIR:
        case ID_MENU:
            e = new HTMLDivElementImpl(document);
            insertNode(e);
            handled = true;
            break;
        case ID_DL:
            popBlock(ID_DL);
            handled = true;
            break;
        case ID_DT:
            popBlock(ID_DT);
            handled = true;
            break;
        case ID_SELECT:
            if( n->isInline() )
                return false;
            break;
        case ID_P:
        case ID_H1:
        case ID_H2:
        case ID_H3:
        case ID_H4:
        case ID_H5:
        case ID_H6:
            if(!n->isInline())
            {
                popBlock(current->id());
                handled = true;
            }
            break;
        case ID_OPTION:
        case ID_OPTGROUP:
            if (id == ID_OPTGROUP)
            {
                popBlock(current->id());
                handled = true;
            }
            else if(id == ID_SELECT)
            {
                // IE treats a nested select as </select>. Let's do the same
                popBlock( ID_SELECT );
                break;
            }
            break;
        // head elements in the body should be ignored.
        case ID_ADDRESS:
            popBlock(ID_ADDRESS);
            handled = true;
            break;
        case ID_COLGROUP:
            if (id != ID_TEXT) {
                popBlock(ID_COLGROUP);
                handled = true;
            }
            break;
        case ID_FONT:
            popBlock(ID_FONT);
            handled = true;
            break;
        default:
            if(current->isDocumentNode())
            {
                if(current->firstChild() == 0) {
                    e = new HTMLHtmlElementImpl(document);
                    insertNode(e);
                    handled = true;
                }
            }
            else if(current->isInline())
            {
                popInlineBlocks();
                handled = true;
            }
        }

        // if we couldn't handle the error, just rethrow the exception...
        if(!handled)
        {
            //kdDebug( 6035 ) << "Exception handler failed in HTMLPArser::insertNode()" << endl;
            return false;
        }

        return insertNode(n);
    }
}
예제 #20
0
bool KHTMLParser::insertNode(NodeImpl *n, bool flat)
{
    int id = n->id();

    // let's be stupid and just try to insert it.
    // this should work if the document is wellformed
#ifdef PARSER_DEBUG
    NodeImpl *tmp = current;
#endif
    NodeImpl *newNode = current->addChild(n);
    if ( newNode ) {
#ifdef PARSER_DEBUG
        kdDebug( 6035 ) << "added " << n->nodeName().string() << " to " << tmp->nodeName().string() << ", new current=" << newNode->nodeName().string() << endl;
#endif

	// have to do this here (and not when creating the node, as we don't know before where we add the LI element to.
	if ( id == ID_LI && n->isElementNode() ) {
	    int cid = current->id();
	    if ( cid != ID_UL && cid != ID_OL )
	    static_cast<HTMLElementImpl*>(n)->addCSSProperty(CSS_PROP_LIST_STYLE_POSITION, CSS_VAL_INSIDE);
	}

	// don't push elements without end tag on the stack
        if(tagPriority[id] != 0 && !flat) {
#if SPEED_DEBUG < 2
            if(!n->attached() && HTMLWidget )
                n->attach();
#endif
	    if(n->isInline()) m_inline = true;
            pushBlock(id, tagPriority[id]);
            current = newNode;
        } else {
#if SPEED_DEBUG < 2
            if(!n->attached() && HTMLWidget)
                n->attach();
            if (n->maintainsState()) {
                document->document()->registerMaintainsState(n);
                QString state(document->document()->nextState());
                if (!state.isNull()) n->restoreState(state);
            }
            if(n->renderer())
                n->renderer()->close();
#endif
	    if(n->isInline()) m_inline = true;
        }

#if SPEED_DEBUG < 1
        if(tagPriority[id] == 0 && n->renderer())
            n->renderer()->calcMinMaxWidth();
#endif
        return true;
    } else {
#ifdef PARSER_DEBUG
        kdDebug( 6035 ) << "ADDING NODE FAILED!!!! current = " << current->nodeName().string() << ", new = " << n->nodeName().string() << endl;
#endif
        // error handling...
        HTMLElementImpl *e;
        bool handled = false;

	// never create anonymous objects just to hold a space.
	if ( id == ID_TEXT &&
	     static_cast<TextImpl *>(n)->string()->l == 1 &&
	     static_cast<TextImpl *>(n)->string()->s[0] == " " )
	    return false;

        // switch according to the element to insert
        switch(id)
        {
        case ID_COMMENT:
            break;
        case ID_HEAD:
            // ### alllow not having <HTML> in at all, as per HTML spec
            if (!current->isDocumentNode() && current->id() != ID_HTML )
                return false;
            break;
        case ID_META:
        case ID_LINK:
        case ID_ISINDEX:
        case ID_BASE:
            if( !head )
                createHead();
            if( head ) {
                if ( head->addChild(n) ) {
#if SPEED_DEBUG < 2
                    if(!n->attached() && HTMLWidget)
                        n->attach();
#endif
		}

                return true;
            }

            break;
        case ID_HTML:
            if (!current->isDocumentNode() ) {
		if ( doc()->firstChild()->id() == ID_HTML) {
		    // we have another <HTML> element.... apply attributes to existing one
		    // make sure we don't overwrite already existing attributes
		    NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true);
		    NamedAttrMapImpl *bmap = static_cast<ElementImpl*>(doc()->firstChild())->attributes(false);
		    bool changed = false;
		    for (unsigned long l = 0; map && l < map->length(); ++l) {
			AttributeImpl* it = map->attributeItem(l);
			changed = !bmap->getAttributeItem(it->id());
			bmap->insertAttribute(new AttributeImpl(it->id(), it->val()));
		    }
		    if ( changed )
			doc()->recalcStyle( NodeImpl::Inherit );
		}
                return false;
	    }
            break;
        case ID_TITLE:
        case ID_STYLE:
            if ( !head )
                createHead();
            if ( head ) {
                DOM::NodeImpl *newNode = head->addChild(n);
                if ( newNode ) {
                    pushBlock(id, tagPriority[id]);
                    current = newNode;
#if SPEED_DEBUG < 2
		    if(!n->attached() && HTMLWidget)
                        n->attach();
#endif
                } else {
#ifdef PARSER_DEBUG
                    kdDebug( 6035 ) << "adding style before to body failed!!!!" << endl;
#endif
                    discard_until = ID_STYLE + ID_CLOSE_TAG;
                    return false;
                }
                return true;
            } else if(inBody) {
                discard_until = id + ID_CLOSE_TAG;
                return false;
            }
            break;
        case ID_SCRIPT:
            // if we failed to insert it, go into skip mode
            discard_until = id + ID_CLOSE_TAG;
            break;
        case ID_BODY:
            if(inBody && doc()->body()) {
                // we have another <BODY> element.... apply attributes to existing one
                // make sure we don't overwrite already existing attributes
                // some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor>
                NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true);
                NamedAttrMapImpl *bmap = doc()->body()->attributes(false);
                bool changed = false;
                for (unsigned long l = 0; map && l < map->length(); ++l) {
                    AttributeImpl* it = map->attributeItem(l);
                    changed = !bmap->getAttributeItem(it->id());
                    bmap->insertAttribute(new AttributeImpl(it->id(), it->val()));
                }
                if ( changed )
                    doc()->recalcStyle( NodeImpl::Inherit );
            } else if ( current->isDocumentNode() )
                break;
            return false;
            break;

            // the following is a hack to move non rendered elements
            // outside of tables.
            // needed for broken constructs like <table><form ...><tr>....
        case ID_INPUT:
        {
            ElementImpl *e = static_cast<ElementImpl *>(n);
            DOMString type = e->getAttribute(ATTR_TYPE);

            if ( strcasecmp( type, "hidden" ) != 0 )
                break;
            // Fall through!
        }
        case ID_TEXT:
            // ignore text inside the following elements.
            switch(current->id())
            {
            case ID_SELECT:
                return false;
            default:
                ;
                // fall through!!
            };
            break;
        case ID_DD:
        case ID_DT:
            e = new HTMLDListElementImpl(document);
            if ( insertNode(e) ) {
                insertNode(n);
                return true;
            }
            break;
        case ID_AREA:
        {
            if(map)
            {
                map->addChild(n);
#if SPEED_DEBUG < 2
                if(!n->attached() && HTMLWidget)
		    n->attach();
#endif
                handled = true;
            }
            else
                return false;
            return true;
        }
        case ID_TD:
        case ID_TH:
            // lets try to close the konqblock
            if ( haveKonqBlock ) {
                popBlock( ID__KONQBLOCK );
                haveKonqBlock = false;
                return insertNode( n );
            }
        default:
            break;
        }

        // switch on the currently active element
        switch(current->id())
        {
        case ID_HTML:
            switch(id)
            {
            case ID_SCRIPT:
            case ID_STYLE:
            case ID_META:
            case ID_LINK:
            case ID_OBJECT:
            case ID_EMBED:
            case ID_TITLE:
            case ID_ISINDEX:
            case ID_BASE:
                if(!head) {
                    head = new HTMLHeadElementImpl(document);
                    e = head;
                    insertNode(e);
                    handled = true;
                }
                break;
            default:
                if ( haveFrameSet ) break;
                e = new HTMLBodyElementImpl(document);
                startBody();
                insertNode(e);
                handled = true;
                break;
            }
            break;
        case ID_HEAD:
            // we can get here only if the element is not allowed in head.
            if (id == ID_HTML)
                return false;
            else {
                // This means the body starts here...
                if ( haveFrameSet ) break;
                popBlock(ID_HEAD);
                e = new HTMLBodyElementImpl(document);
                startBody();
                insertNode(e);
                handled = true;
            }
            break;
        case ID_BODY:
            break;
        case ID__KONQBLOCK:
            switch( id ) {
            case ID_THEAD:
            case ID_TFOOT:
            case ID_TBODY:
            case ID_TR:
            case ID_TD:
            case ID_TH:
                // now the actual table contents starts
                // lets close our anonymous block before the table
                // and go ahead!
                popBlock( ID__KONQBLOCK );
                haveKonqBlock = false;
                handled = checkChild( current->id(), id );
                break;
            default:
                break;
            }
            break;
        case ID_TABLE:
        case ID_THEAD:
        case ID_TFOOT:
        case ID_TBODY:
        case ID_TR:
            switch(id)
            {
            case ID_TABLE:
                popBlock(ID_TABLE); // end the table
                handled = checkChild( current->id(), id);
                break;
            case ID_TEXT:
            {
                TextImpl *t = static_cast<TextImpl *>(n);
                DOMStringImpl *i = t->string();
                unsigned int pos = 0;
                while(pos < i->l && ( *(i->s+pos) == QChar(' ') ||
                                      *(i->s+pos) == QChar(0xa0))) pos++;
                if(pos == i->l)
                    break;
            }
            default:
            {
                NodeImpl *node = current;
                NodeImpl *parent = node->parentNode();

                NodeImpl *parentparent = parent->parentNode();

                if(( node->id() == ID_TR &&
                     ( parent->id() == ID_THEAD ||
                       parent->id() == ID_TBODY ||
                       parent->id() == ID_TFOOT ) && parentparent->id() == ID_TABLE ) ||
                   ( !checkChild( ID_TR, id ) && ( node->id() == ID_THEAD || node->id() == ID_TBODY || node->id() == ID_TFOOT ) &&
                     parent->id() == ID_TABLE ) )
                {
                    node = ( node->id() == ID_TR ) ? parentparent : parent;
                    NodeImpl *parent = node->parentNode();
                    int exceptioncode = 0;
                    NodeImpl *container = new HTMLGenericElementImpl( document, ID__KONQBLOCK );
                    parent->insertBefore( container, node, exceptioncode );
                    if ( exceptioncode ) {
#ifdef PARSER_DEBUG
                        kdDebug( 6035 ) << "adding anonymous container before table failed!" << endl;
#endif
                        break;
                    }
                    if ( !container->attached() && HTMLWidget )
			container->attach();
                    pushBlock( ID__KONQBLOCK, tagPriority[ID__KONQBLOCK] );
                    haveKonqBlock = true;
                    current = container;
                    handled = true;
                    break;
                }

                if ( current->id() == ID_TR )
                    e = new HTMLTableCellElementImpl(document, ID_TD);
                else if ( current->id() == ID_TABLE )
                    e = new HTMLTableSectionElementImpl( document, ID_TBODY, true /* implicit */ );
                else
                    e = new HTMLTableRowElementImpl( document );

                insertNode(e);
                handled = true;
                break;
            } // end default
            } // end switch
            break;
        case ID_OBJECT:
            discard_until = id + ID_CLOSE_TAG;
            return false;
        case ID_UL:
        case ID_OL:
        case ID_DIR:
        case ID_MENU:
            e = new HTMLLIElementImpl(document);
            e->addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_NONE);
            insertNode(e);
            handled = true;
            break;
        case ID_SELECT:
            if( n->isInline() )
                return false;
            break;
        case ID_P:
        case ID_H1:
        case ID_H2:
        case ID_H3:
        case ID_H4:
        case ID_H5:
        case ID_H6:
            if(!n->isInline())
            {
                popBlock(current->id());
                handled = true;
            }
            break;
        case ID_OPTION:
            if (id == ID_OPTGROUP)
            {
                popBlock(ID_OPTION);
                handled = true;
            }
            else if(id == ID_SELECT)
            {
                // IE treats a nested select as </select>. Let's do the same
                popBlock( ID_SELECT );
                break;
            }
            break;
            // head elements in the body should be ignored.

        case ID_DL:
        case ID_DT:
        case ID_ADDRESS:
        case ID_COLGROUP:
        case ID_FONT:
        case ID_CAPTION:
            popBlock(current->id());
            handled = true;
            break;
        default:
            if(current->isDocumentNode())
            {
                if(current->firstChild() == 0) {
                    e = new HTMLHtmlElementImpl(document);
                    insertNode(e);
                    handled = true;
                }
            }
            else if(current->isInline())
            {
                popInlineBlocks();
                handled = true;
            }
        }

        // if we couldn't handle the error, just rethrow the exception...
        if(!handled)
        {
            //kdDebug( 6035 ) << "Exception handler failed in HTMLPArser::insertNode()" << endl;
            return false;
        }

        return insertNode(n);
    }
}
예제 #21
0
void RenderPartObject::updateWidget()
{
  QString url;
  QString serviceType;
  QStringList params;
  KHTMLPart *part = m_view->part();

  setNeedsLayoutAndMinMaxRecalc();

  if (element()->id() == ID_OBJECT) {

      HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());

      // Check for a child EMBED tag.
      HTMLEmbedElementImpl *embed = 0;
      for (NodeImpl *child = o->firstChild(); child; child = child->nextSibling()) {
          if (child->id() == ID_EMBED) {
              embed = static_cast<HTMLEmbedElementImpl *>( child );
              break;
          }
      }
      
      // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT.
      HTMLElementImpl *embedOrObject;
      if (embed) {
          embedOrObject = (HTMLElementImpl *)embed;
          DOMString attribute = embedOrObject->getAttribute(ATTR_WIDTH);
          if (!attribute.isEmpty()) {
              o->setAttribute(ATTR_WIDTH, attribute);
          }
          attribute = embedOrObject->getAttribute(ATTR_HEIGHT);
          if (!attribute.isEmpty()) {
              o->setAttribute(ATTR_HEIGHT, attribute);
          }
          url = embed->url;
          serviceType = embed->serviceType;
      } else {
          embedOrObject = (HTMLElementImpl *)o;
      }
      
      // If there was no URL or type defined in EMBED, try the OBJECT tag.
      if (url.isEmpty()) {
          url = o->url;
      }
      if (serviceType.isEmpty()) {
          serviceType = o->serviceType;
      }
      
      // Then try the PARAM tags for the URL and type attributes.
      NodeImpl *child = o->firstChild();
      while (child && (url.isEmpty() || serviceType.isEmpty())) {
          if (child->id() == ID_PARAM) {
              HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child );
              QString name = p->name().lower();
              if (url.isEmpty() && (QString::equals(name,"src") || QString::equals(name,"movie") || QString::equals(name,"code"))) {
                  url = p->value();
              }
              if (serviceType.isEmpty() && QString::equals(name,"type")) {
                  serviceType = p->value();
              }
              
          }
          child = child->nextSibling();
      }
      
      // Lastly try to map a specific CLASSID to a type.
      if (serviceType.isEmpty() && !o->classId.isEmpty()) {
          if (o->classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000")) {
              // It is ActiveX, but the nsplugin system handling
              // should also work, that's why we don't override the
              // serviceType with application/x-activex-handler
              // but let the KTrader in khtmlpart::createPart() detect
              // the user's preference: launch with activex viewer or
              // with nspluginviewer (Niko)
              serviceType = "application/x-shockwave-flash";
          } else if(o->classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) {
              serviceType = "audio/x-pn-realaudio-plugin";
          } else if(o->classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) {
              serviceType = "video/quicktime";
          } else if(o->classId.contains("166B1BCA-3F9C-11CF-8075-444553540000")) {
              serviceType = "application/x-director";
          } else {
              // We have a clsid, means this is activex (Niko)
              serviceType = "application/x-activex-handler";
          }
          // TODO: add more plugins here
      }
      
      // If no URL and type, abort.
      if (url.isEmpty() && serviceType.isEmpty()) {
#ifdef DEBUG_LAYOUT
          kdDebug() << "RenderPartObject::close - empty url and serverType" << endl;
#endif
          return;
      }
      
      // Turn the attributes of either the EMBED tag or OBJECT tag into an array.
      NamedAttrMapImpl* attributes = embedOrObject->attributes();
      if (attributes) {
          for (unsigned long i = 0; i < attributes->length(); ++i) {
              AttributeImpl* it = attributes->attributeItem(i);
              params.append(o->getDocument()->attrName(it->id()).string() + "=\"" + it->value().string() + "\"");
          }
      }
      
      params.append( QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( o->classId ) );
      params.append( QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( o->getAttribute(ATTR_CODEBASE).string() ) );
      
      part->requestObject( this, url, serviceType, params );
  } else if ( element()->id() == ID_EMBED ) {

      HTMLEmbedElementImpl *o = static_cast<HTMLEmbedElementImpl *>(element());
      url = o->url;
      serviceType = o->serviceType;

      if ( url.isEmpty() && serviceType.isEmpty() ) {
#ifdef DEBUG_LAYOUT
          kdDebug() << "RenderPartObject::close - empty url and serverType" << endl;
#endif
          return;
      }
      // add all attributes set on the embed object
      NamedAttrMapImpl* a = o->attributes();
      if (a) {
          for (unsigned long i = 0; i < a->length(); ++i) {
              AttributeImpl* it = a->attributeItem(i);
              params.append(o->getDocument()->attrName(it->id()).string() + "=\"" + it->value().string() + "\"");
          }
      }
      part->requestObject( this, url, serviceType, params );
  } else {
      assert(element()->id() == ID_IFRAME);
      HTMLIFrameElementImpl *o = static_cast<HTMLIFrameElementImpl *>(element());
      url = o->url.string();
      if (url.isEmpty())
	  url = "about:blank";
      KHTMLView *v = static_cast<KHTMLView *>(m_view);
      bool requestSucceeded = v->part()->requestFrame( this, url, o->name.string(), QStringList(), true );
      if (requestSucceeded && QString::equals(url,"about:blank")) {
	  KHTMLPart *newPart = v->part()->findFrame( o->name.string() );
	  if (newPart && newPart->xmlDocImpl()) {
	      newPart->xmlDocImpl()->setBaseURL( v->part()->baseURL().url() );
	  }
      }
  }
}