void ObjectManipulator::removeUserFolder()
{
    ObjectTreeViewItem *item = dynamic_cast<ObjectTreeViewItem *>
        (getCurrentObjectTree()->currentItem());
    if (item == 0 || item->getUserFolderParent() == 0) return;
    ObjectTreeViewItem *parent = dynamic_cast<ObjectTreeViewItem *>
        (item->parent());
    assert(parent != 0);

    vector<FWObject *> objs;
    for (int ii = 0; ii < item->childCount(); ii++) {
        ObjectTreeViewItem *child = dynamic_cast<ObjectTreeViewItem *>
            (item->child(ii));

        FWObject *obj = child->getFWObject();
        if (obj->getRO()) {
            QMessageBox::critical(this, "Firewall Builder",
                                  tr("Folder with locked object "
                                     "cannot be deleted"));
            return;
        }

        objs.push_back(obj);
    }

    if (objs.size() > 0) {
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
        ConfirmDeleteObjectDialog confirm(this);
        confirm.load(objs);
        QApplication::restoreOverrideCursor();
        if (confirm.exec() == QDialog::Rejected) return;
    }

    FWCmdMacro *macro = new FWCmdMacro(tr("Delete user folder"));

    QList<QTreeWidgetItem *> children = item->takeChildren();
    while (!children.isEmpty()) {
        ObjectTreeViewItem *child = dynamic_cast<ObjectTreeViewItem *>
            (children.takeFirst());
        assert(child != 0);

        FWObject *obj = child->getFWObject();
        if (mw->isEditorVisible() && mw->getOpenedEditor() == obj) {
            mw->hideEditor();
        }

        deleteObject(obj, macro);
    }

    FWCmdRemoveUserFolder *cmd =
        new FWCmdRemoveUserFolder(m_project, parent->getFWObject(),
                                  item->getUserFolderName(), "", macro);
    FWObject *newObj = cmd->getNewState();
    set<string> folders = stringToSet(newObj->getStr("subfolders"));
    folders.erase(item->getUserFolderName().toUtf8().constData());
    newObj->setStr("subfolders", setToString(folders));

    m_project->undoStack->push(macro);
}
clusterMembersDialog::clusterMembersDialog(QWidget *parent, FWObject *o)
    : QDialog(parent), table_update(false)
{
    m_dialog = new Ui::clusterMembersDialog_q;
    m_dialog->setupUi(this);
    setWindowModality(Qt::WindowModal);

    // assign clustergroup object
    obj = o;
    FWObject *parent_host = Host::getParentHost(obj);
    host_os = parent_host->getStr("host_OS").c_str();
    platform = parent_host->getStr("platform").c_str();

    // if empty, retry with parent of parent (interface level)
    if (host_os.isEmpty())
    {
        FWObject *parent = NULL;
        parent = obj->getParent();
        if (parent == NULL)
        {
            throw FWException("clusterMembersDialog: parent is NULL!");
        }
        parent = parent->getParent();
        if (parent == NULL)
        {
            throw FWException("clusterMembersDialog: parent is NULL!");
        }
        host_os = parent->getStr("host_OS").c_str();
        platform = parent->getStr("platform").c_str();
    }

    string type = obj->getStr("type");
    enable_master_column = Resources::os_res[host_os.toStdString()]->getResourceBool(
        "/FWBuilderResources/Target/protocols/" + type + "/needs_master");
    if (!enable_master_column) m_dialog->fwSelectedTable->hideColumn(2);

    // prepare lists of firewalls (selected, available)
    getSelectedMembers();
    getPossibleMembers();

    // init views
    updateAvailableTree();
    updateSelectedTable();
}
void RoutingRuleOptionsDialog::loadFWObject(FWObject *o)
{
    obj=o;

    FWObject *p = obj;
    while ( !Firewall::cast(p) ) p = p->getParent();
    platform = p->getStr("platform").c_str();

    Rule      *rule = dynamic_cast<Rule*>(o);
    FWOptions *ropt = rule->getOptionsObject();

    int wid = 0;
    if (platform=="iptables") wid = 0;
    else      wid = 1;

    /*
        if (platform=="ipf")      wid = 1;
        if (platform=="pf")       wid = 2;
        if (platform=="ipfw")     wid = 3;
    */

    m_dialog->wStack->setCurrentIndex( wid );
    m_dialog->wStack->widget(wid)->raise();

    data.clear();

    if (platform=="iptables")
    {
        data.registerOption(m_dialog->routing_non_critical_rule, ropt,  "no_fail");
    }

    init = true;
    data.loadAll();

    init = false;
}
void ObjectManipulator::addSubfolderSlot()
{
    const QAction *qAct = dynamic_cast<const QAction *>(sender());
    if (qAct == 0) return;

    FWObject *obj = getCurrentObjectTree()->getCurrentObject();
    assert(obj->getId() == qAct->data().toInt());

    QString folder = QInputDialog::getText(0, tr("Add Subfolder"),
                                           tr("Enter new subfolder name"));
    folder = folder.simplified();
    if (folder.isEmpty()) return;
    if (folder.contains(',')) {
        QMessageBox::warning(this, "Firewall Builder",
                             tr("Subfolder cannot contain a comma"), "&OK",
                             QString::null, QString::null, 0, 1);
        return;
    }

    /* See if the subfolder already exists */
    string folderStr = folder.toUtf8().constData();
    set<string> folders = stringToSet(obj->getStr("subfolders"));
    if (folders.find(folderStr) != folders.end()) return;
    folders.insert(folderStr);

    if (fwbdebug) {
        qDebug() << "ObjectManipulator::addSubfolder: " << folder;
    }

    FWCmdAddUserFolder *cmd = new FWCmdAddUserFolder(m_project, obj, folder,
                                                     tr("Add subfolder"));
    FWObject *newObj = cmd->getNewState();
    newObj->setStr("subfolders", setToString(folders));

    m_project->undoStack->push(cmd);
}
bool interfaceProperties::validateInterface(FWObject *target,
                                            FWObject *intf,
                                            bool check_types,
                                            QString &err)
{
    if (Interface::cast(target) && Interface::cast(intf))
    {
        if (!Interface::cast(target)->validateChild(intf))
        {
            // See Interface::validateChild(). Currently the only
            // condition when interface can not become a child of
            // another interface is when interface has subinterfaces
            // of its own.
            err = QObject::tr("Interface %1 can not become subinterface of %2 "
                              "because only one level of subinterfaces is allowed.")
                .arg(intf->getName().c_str())
                .arg(target->getName().c_str());
            return false;
        }

        if (check_types)
        {
            // We check types when this method is called from a compiler
            string target_interface_type =
                Interface::cast(target)->getOptionsObject()->getStr("type");
            if (target_interface_type.empty()) target_interface_type = "ethernet";

            FWObject *fw = Host::getParentHost(target);
            //FWObject *fw = Interface::cast(target)->getParentHost();
            QString host_os = fw->getStr("host_OS").c_str();
            Resources* os_res = Resources::os_res[host_os.toStdString()];
            list<string> interface_type_pairs;
            os_res->getResourceStrList(
                "/FWBuilderResources/Target/subinterfaces/" + target_interface_type,
                interface_type_pairs);
            list<string> interface_types;
            for (list<string>::iterator it=interface_type_pairs.begin();
                 it!=interface_type_pairs.end(); ++it)
            {
                QString p = it->c_str();
                interface_types.push_back(p.split(",")[0].toStdString());
            }

            // Implement interface type checks here
            string interface_type = Interface::cast(intf)->getOptionsObject()->getStr("type");
            if (interface_type.empty()) interface_type = "ethernet";

            if (std::find(interface_types.begin(), interface_types.end(),
                          interface_type) == interface_types.end())
            {
                err = QObject::tr("Interface %1 (type '%2') can not be a child "
                                  "of interface %3 (type '%4')")
                    .arg(intf->getName().c_str())
                    .arg(interface_type.c_str())
                    .arg(target->getName().c_str())
                    .arg(target_interface_type.c_str());
                return false;
            }
        }
    }

    if (Cluster::cast(target) && Interface::cast(intf))
    {
        // Note that @target may not be actually a parent of @intf at
        // the time of call to this function. We use this function to
        // validate operation of making @intf a child of @target. @intf
        // can have some other parent at the moment.
        FWObject *parent_interface = intf->getParent();
        if (Interface::isA(parent_interface))
        {
            string interface_type = Interface::cast(intf)->getOptionsObject()->getStr("type");
            if (interface_type.empty()) interface_type = "ethernet";
            string parent_interface_type =
                Interface::cast(parent_interface)->getOptionsObject()->getStr("type");
            if (parent_interface_type.empty()) parent_interface_type = "ethernet";
            if (parent_interface_type == "bridge" && interface_type == "ethernet")
            {
                err = QObject::tr("Interface %1 is a bridge port, "
                                  "it can not belong to a cluster")
                    .arg(intf->getName().c_str());
                return false;
            }
            if (parent_interface_type == "bonding" && interface_type == "ethernet")
            {
                err = QObject::tr("Interface %1 is a bonding interface slave, "
                                  "it can not belong to a cluster")
                    .arg(intf->getName().c_str());
                return false;
            }
        }
    }

    return validateInterface(target, intf->getName().c_str(), err);
}
/*
 * we manage only addresses of vrrp cluster interfaces.
 *
 * We ignore addresses of heartbeat and openais cluster interfaces.
 * To ignore them, we pass list of addresses managed by heartbeat to
 * shell function update_addresses (defined in configlet
 * "update_addresses") as its second argument to make it ignore these
 *
 * This code assumes the name of the cluster interface is the same as
 * names of the corresponding interfaces of member firewalls.
 */
bool interfaceProperties::manageIpAddresses(Interface *intf,
                                            QStringList &update_addresses,
                                            QStringList &ignore_addresses)
{
    update_addresses.clear();
    ignore_addresses.clear();

    FWObject *fw = Host::getParentHost(intf);
    //FWObject *fw = intf->getParentHost();
    Resources *os_res = Resources::os_res[fw->getStr("host_OS")];
    assert(os_res != nullptr);

    if (intf->isDyn()) return false;
    if (intf->isBridgePort()) return false;
    if (intf->isSlave()) return false;
    if (intf->isUnnumbered()) return false;   // see #1506

    string intf_name = intf->getName();

    if (intf->getOptionsObject()->getBool("cluster_interface"))
    {
        if (intf->isLoopback()) return false;

        if (intf->isFailoverInterface())
        {
            FWObject *failover_group =
                intf->getFirstByType(FailoverClusterGroup::TYPENAME);
            string failover_type = failover_group->getStr("type");

            if (os_res->getResourceBool(
                    "/FWBuilderResources/Target/protocols/" + failover_type + "/manage_addresses"))
            {
                getListOfAddresses(intf, update_addresses);
                return true;
            } else
                return false;
        }

        /*
         * if this is cluster interface with the same name as fw interface
         * (as happens in case of hearbeat or openais), skip it
         */
        if (intf->getOptionsObject()->getStr("base_device") == intf_name)
            return false;
    } else
    {
        // regular interface. Lets see if there is cluster interface
        // with the same name. If there is and its failover protocol
        // is heartbeat or openais, we should ignore all addresses it
        // might have.

        getListOfAddresses(intf, update_addresses);

        list<FWObject*> interfaces = fw->getByTypeDeep(Interface::TYPENAME);
        list<FWObject*>::iterator i;
        for (i=interfaces.begin(); i!=interfaces.end(); ++i )
        {
            Interface *iface = Interface::cast(*i);
            assert(iface);

            if (iface->getName() == intf_name &&
                iface->getOptionsObject()->getBool("cluster_interface") &&
                iface->isFailoverInterface())
            {
                FWObject *failover_group =
                    iface->getFirstByType(FailoverClusterGroup::TYPENAME);
                string failover_type = failover_group->getStr("type");

                // some protocols do not like it when failover ip address
                // is managed outside their software
                if (! os_res->getResourceBool(
                        "/FWBuilderResources/Target/protocols/" + failover_type + "/manage_addresses"))
                    getListOfAddresses(iface, ignore_addresses);
                break;
            }
        }
    }

    return true;
}