bool NATCompiler_ipf::ExpandPortRange::processNext()
{
    NATRule *rule=getNext(); if (rule==NULL) return false;

    Service          *osrv=compiler->getFirstOSrv(rule);

    if (UDPService::isA(osrv) || TCPService::isA(osrv))
    {
	int rs = TCPUDPService::cast(osrv)->getDstRangeStart();
	int re = TCPUDPService::cast(osrv)->getDstRangeEnd();

        int numPorts = re-rs+1;
        if (numPorts==1)
        {
            tmp_queue.push_back(rule);
            return true;
        }

        if (numPorts > 20)
        {
            ostringstream ostr;
            ostr << string("Expanding port range ") << osrv->getName()
                 << " creates " << numPorts << " rules";
            compiler->warning(rule, ostr.str());
        }

        string newSrvType = TCPService::TYPENAME;
        if (UDPService::isA(osrv)) newSrvType = UDPService::TYPENAME;

        for (int p=rs; p<=re; ++p)
        {
            NATRule *r = compiler->dbcopy->createNATRule();
            r->duplicate(rule);

            FWObject *newSrv = compiler->dbcopy->create(newSrvType);
            newSrv->duplicate(osrv,true);
            TCPUDPService::cast(newSrv)->setDstRangeStart(p);
            TCPUDPService::cast(newSrv)->setDstRangeEnd(p);
            compiler->persistent_objects->add(newSrv,false);
            compiler->dbcopy->addToIndex(newSrv);

            RuleElementOSrv *nosrv = r->getOSrv();
            nosrv->clearChildren();
            nosrv->addRef(newSrv);

            compiler->temp_ruleset->add(r);
            tmp_queue.push_back(r);
        }
    } else
    {
        tmp_queue.push_back(rule);
    }
    return true;
}
FWObject* ObjectManipulator::actuallyPasteTo(FWObject *target,
                                              FWObject *obj,
                                              std::map<int,int> &map_ids)
{
    //FWObject *res = NULL;

    FWObject *ta = prepareForInsertion(target, obj);
    if (ta == NULL) return NULL;

    if (!isObjectAllowed(ta, obj)) return NULL;

    // we disable copy/cut/paste/duplicate menu items for objects that
    // can't be copied or duplicated in
    // ObjectManipulator::getMenuState() but will check here just in
    // case
    if (AttachedNetworks::isA(obj)) return NULL;

    if (fwbdebug)
        qDebug() << "ObjectManipulator::actuallyPasteTo"
                 << "target=" << target->getPath().c_str()
                 << "ta=" << ta->getPath().c_str();

    QString new_name = makeNameUnique(
        ta, obj->getName().c_str(), obj->getTypeName().c_str());

    try
    {
/* clipboard holds a copy of the object */
        if (obj->getRoot() != ta->getRoot())
        {
            if (fwbdebug) qDebug("Copy object %s (%d) to a different object tree",
                                 obj->getName().c_str(), obj->getId());
            FWCmdAddObject *cmd = new FWCmdAddObject(m_project, target, NULL,
                                                     QObject::tr("Paste object"));
            FWObject *new_state = cmd->getNewState();
            cmd->setNeedTreeReload(true);
            // recursivelyCopySubtree() needs access to the target tree root
            // when it copies subtree, so have to copy into the actual target
            // tree.
            FWObject *nobj = m_project->db()->recursivelyCopySubtree(target, obj, map_ids);
            if (new_name != nobj->getName().c_str())
                nobj->setName(string(new_name.toUtf8()));
            target->remove(nobj, false);
            new_state->add(nobj);
            m_project->undoStack->push(cmd);
            return nobj;
        }

        Group *grp = Group::cast(ta);
        if (grp!=NULL && !FWBTree().isSystem(ta))
        {
            if (fwbdebug) qDebug("Copy object %s (%d) to a regular group",
                                 obj->getName().c_str(), obj->getId());
/* check for duplicates. We just won't add an object if it is already there */
            int cp_id = obj->getId();
            list<FWObject*>::iterator j;
            for (j=grp->begin(); j!=grp->end(); ++j)
            {
                FWObject *o1=*j;
                if(cp_id==o1->getId()) return o1;

                FWReference *ref;
                if( (ref=FWReference::cast(o1))!=NULL &&
                    cp_id==ref->getPointerId()) return o1;
            }
            FWCmdChange *cmd = new FWCmdChange(
                m_project, grp,
                QObject::tr("Paste object"));
            //cmd->setNeedTreeReload(false);
            FWObject *new_state = cmd->getNewState();
            new_state->addRef(obj);
            m_project->undoStack->push(cmd);
            return obj;

        } else
        {
/* add a copy of the object to system group , or
 * add ruleset object to a firewall.
 */
            if (fwbdebug)
                qDebug("Copy object %s (%d) to a system group, "
                       "a ruleset to a firewall or an address to an interface",
                       obj->getName().c_str(), obj->getId());

            FWObject *nobj = m_project->db()->create(obj->getTypeName());
            assert(nobj!=NULL);
            //nobj->ref();
            nobj->duplicate(obj, true);
            if (new_name != nobj->getName().c_str())
                nobj->setName(string(new_name.toUtf8()));

            // If we paste interface, reset the type of the copy
            // See #299
            if (Interface::isA(obj) && Interface::isA(ta))
            {
                Interface *new_intf = Interface::cast(nobj);
                new_intf->getOptionsObject()->setStr("type", "ethernet");
                // see #391 : need to reset "mamagement" flag in the copy
                // to make sure we do not end up with two management interfaces
                new_intf->setManagement(false);
            }

            FWCmdChange *cmd = new FWCmdAddObject(m_project, ta, nobj,
                                                  QObject::tr("Paste object"));
            FWObject *new_state = cmd->getNewState();

            // adding object to new_state is reduntant but
            // FWCmdAddObject supports this for consistency
            new_state->add(nobj);
            m_project->undoStack->push(cmd);

            return nobj;
        }
    }
    catch(FWException &ex)
    {
        QMessageBox::warning(
            this,"Firewall Builder",
            ex.toString().c_str(),
            "&Continue", QString::null,QString::null,
            0, 1 );
    }

    return NULL;
}