1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-24 12:17:26 +01:00

fixed d&d and copy/paste with dependencies

This commit is contained in:
Vadim Kurland 2008-07-28 04:30:38 +00:00
parent fe68889d63
commit 32d56b4bf1
8 changed files with 112 additions and 229 deletions

View File

@ -1,5 +1,13 @@
2008-07-27 Vadim Kurland <vadim@vk.crocodile.org>
* ObjectManipulator.h (class ObjectManipulator): removed strange
methods copyObjWithDeep and copyObj2Tree. Fixed drag&drop between
different data files. Copy/Paste and D&D between different data
files properly copy all dependencies and fix references in rules
and groups. Tested with recursive groups (group references itself)
and firewalls with rules referencing other firewalls with groups
and other objects.
* ObjectManipulator.cpp (ObjectManipulator::duplicateWithDependencies):
duplicate object that references other objects and create copies
of these other objects. Examples: firewall (rules reference other

View File

@ -1660,8 +1660,6 @@ FWObject* ObjectManipulator::pasteTo(FWObject *target, FWObject *obj,
FWObject *ta = target;
openLib(ta->getLibrary());
if (IPv4::isA(ta) || IPv6::isA(ta)) ta=ta->getParent();
@ -1678,9 +1676,6 @@ FWObject* ObjectManipulator::pasteTo(FWObject *target, FWObject *obj,
return nobj;
}
Host *hst = Host::cast(ta); // works for firewall, too
Interface *intf = Interface::cast(ta);
if ( m_project->isSystem(ta))
{
/* add a copy of the object to system group */
@ -1753,7 +1748,7 @@ FWObject* ObjectManipulator::duplicateWithDependencies(FWObject *target,
if (fwbdebug)
qDebug("pasteTo: object %s has %d dependencies",
obj->getName().c_str(), deps.size());
obj->getName().c_str(), int(deps.size()));
for (list<FWObject*>::iterator i=deps.begin(); i!=deps.end(); ++i)
{
@ -1825,12 +1820,6 @@ FWObject* ObjectManipulator::duplicateWithDependencies(FWObject *target,
".dedup_marker", dedup_marker);
assert(new_obj!=NULL);
map_ids[old_obj->getId()] = new_obj->getId();
if (fwbdebug) qDebug("Replace IDs: %d -> %d",
old_obj->getId(), new_obj->getId());
repl_counter = nobj->replaceRef(old_obj->getId(), new_obj->getId());
} else
{
FWObject *copy_obj;
@ -1843,43 +1832,52 @@ FWObject* ObjectManipulator::duplicateWithDependencies(FWObject *target,
} else
copy_obj = m_project->db()->findInIndex(
map_ids[old_obj->getId()]);
if (fwbdebug) qDebug("Replace IDs: %d -> %d",
old_obj->getId(), copy_obj->getId());
repl_counter = nobj->replaceRef(old_obj->getId(),copy_obj->getId());
}
if (fwbdebug) qDebug("Replaced %d references in rules", repl_counter);
}
// one more pass to copy groups
// Do it separately to avoid collisions on the ".dedup_marker" value
if (fwbdebug)
{
for (map<int,int>::iterator it=map_ids.begin(); it!=map_ids.end(); ++it)
qDebug("ID mapping %d -> %d", it->first, it->second);
}
int repl_counter = fixReferences(nobj, map_ids);
if (fwbdebug) qDebug("Replaced %d references in object %s",
repl_counter, nobj->getName().c_str());
// one more pass to fix ferences in other firewalls we might have
// copied and groups.
for (list<FWObject*>::iterator i=deps.begin(); i!=deps.end(); ++i)
{
FWObject *old_obj = *i;
//if (map_ids.count(old_obj->getId()) > 0) continue;
if (Group::cast(old_obj))
if (Firewall::cast(old_obj) || Group::cast(old_obj))
{
if (fwbdebug) qDebug("Group %s", old_obj->getName().c_str());
FWObject *ngrp = m_project->db()->findInIndex(
FWObject *other_new_obj = m_project->db()->findInIndex(
map_ids[old_obj->getId()]);
assert(ngrp);
assert(other_new_obj);
for (FWObject::iterator j1=old_obj->begin(); j1!=old_obj->end(); ++j1)
{
if (FWReference::cast(*j1)==NULL) continue;
int old_id = FWReference::cast(*j1)->getPointerId();
int repl_counter = ngrp->replaceRef(old_id, map_ids[old_id]);
if (fwbdebug) qDebug("Replaced %d references", repl_counter);
}
repl_counter = fixReferences(other_new_obj, map_ids);
if (fwbdebug)
qDebug("Replaced %d references in object %s",
repl_counter, other_new_obj->getName().c_str());
}
}
return nobj;
}
/*
* fix references in children of obj according to the map_ids which
* maps old IDs to the new ones. Return the number of fixed references.
*/
int ObjectManipulator::fixReferences(FWObject *obj, map<int,int> &map_ids)
{
int total_counter = 0;
for (map<int,int>::iterator it=map_ids.begin(); it!=map_ids.end(); ++it)
total_counter += obj->replaceRef(it->first, it->second);
return total_counter;
}
void ObjectManipulator::lockObject()
{
@ -2767,101 +2765,6 @@ FWObject* ObjectManipulator::actuallyCreateObject(FWObject *parent,
return nobj;
}
FWObject* ObjectManipulator::copyObj2Tree(
const QString &/*objType*/, const QString &/*objName*/,
FWObject *copyFrom, FWObject *parent, bool /*askLib*/)
{
if (!validateDialog()) return NULL;
ids.clear();
if (Interface::isA(copyFrom) && Firewall::isA(parent))
{
FWObject *no = pasteTo (parent,copyFrom, true);
return no;
}
FWObject *nobj = copyFrom->getRoot()->create(copyFrom->getTypeName());
nobj->duplicate(copyFrom, true);
nobj->setRoot(copyFrom->getRoot());
return copyObjWithDeep(nobj);
}
FWObject * ObjectManipulator::copyObjWithDeep(FWObject *copyFrom)
{
if (copyFrom==NULL) return NULL;
FWObject *nobj= copyFrom;
if (nobj->getId() > -1)
{
if (ids.contains(nobj->getId()))
{
return nobj;
}
else
{
ids.insert(nobj->getId());
}
}
FWReference * ref = FWReference::cast(nobj);
if (ref!=NULL)
{
copyObjWithDeep(ref->getPointer());
return ref ;
}
Group * group = Group::cast(nobj);
if (group!=NULL)
{
for (list<FWObject*>::iterator i=nobj->begin() ; i!=nobj->end(); ++i)
{
copyObjWithDeep(*i);
}
}
Firewall * fw = Firewall::cast(nobj);
if (fw!=NULL)
{
for (libfwbuilder::FWObject::iterator i=fw->begin(); i!=fw->end(); i++)
{
RuleSet *rule = RuleSet::cast(*i);
if (rule==NULL)
continue;
copyObjWithDeep(rule);
}
}
RuleSet * ruleset = RuleSet::cast(nobj);
if (ruleset!=NULL)
{
for (list<FWObject*>::iterator i=ruleset->begin() ; i!=ruleset->end(); ++i)
{
copyObjWithDeep(*i);
}
}
Rule * rule = Rule::cast(nobj);
if (rule!=NULL)
{
for (int col =0; col < 5; col++)
{
RuleElement *re = m_project->getRE(rule, col);
if (!re) continue;
copyObjWithDeep(re);
}
return rule;
}
FWObject * lib = getCurrentLib();
if (lib->getRoot()->getById(nobj->getId(),true)==NULL)
{
FWObject *par = m_project->getFWTree()->getStandardSlotForObject(
lib, nobj->getTypeName().c_str());
pasteTo (par, nobj, false);
}
return nobj;
}
void ObjectManipulator::newLibrary()
{
if (!validateDialog()) return;

View File

@ -129,6 +129,8 @@ class ObjectManipulator : public QWidget/*ObjectManipulator_q*/ {
libfwbuilder::ObjectGroup *gr,
std::set<libfwbuilder::Firewall*> &fo);
int fixReferences(libfwbuilder::FWObject *obj, std::map<int,int> &map_ids);
ProjectPanel *m_project;
@ -172,13 +174,6 @@ public slots:
const QString &objType,
const QString &objName,
libfwbuilder::FWObject *copyFrom=NULL);
libfwbuilder::FWObject * copyObj2Tree(const QString &objType,
const QString &objName,
libfwbuilder::FWObject *copyFrom,
libfwbuilder::FWObject *parent=NULL,
bool ask4Lib=true);
libfwbuilder::FWObject * copyObjWithDeep(libfwbuilder::FWObject *copyFrom);
void newLibrary();

View File

@ -510,18 +510,23 @@ void ObjectTreeView::dragMoveEvent( QDragMoveEvent *ev)
void ObjectTreeView::dropEvent(QDropEvent *ev)
{
if (fwbdebug) qDebug("ObjectTreeView::dropEvent");
list<FWObject*> dragol;
if (FWObjectDrag::decode(ev, dragol))
{
for (list<FWObject*>::iterator i=dragol.begin();
i!=dragol.end(); ++i)
for (list<FWObject*>::iterator i=dragol.begin(); i!=dragol.end(); ++i)
{
FWObject *dragobj = *i;
assert(dragobj);
ObjectTreeView * otvsource = dynamic_cast<ObjectTreeView *>(ev->source());
ObjectTreeView * otvsource =
dynamic_cast<ObjectTreeView *>(ev->source());
if (otvsource!=NULL)
{
FWObjectDatabase* root = otvsource->getCurrentObject()->getRoot();
FWObjectDatabase* root =
otvsource->getCurrentObject()->getRoot();
int id = dragobj->getId();
FWObject * item = root->getById(id, true);
if (fwbdebug)
@ -533,24 +538,24 @@ void ObjectTreeView::dropEvent(QDropEvent *ev)
}
//ProjectPanel * ppsource = otvsource->m_project ;
}
QString n=QString::fromUtf8(dragobj->getName().c_str());
m_project->copyObj2Tree(dragobj->getTypeName().c_str(), n, dragobj,
getDropTarget(ev, dragobj), false);
FWObject *target = getDropTarget(ev, dragobj);
if (fwbdebug)
qDebug("ObjectTreeView::dropEvent paste %s -> %s",
dragobj->getName().c_str(), target->getName().c_str());
m_project->pasteTo(target, dragobj);
}
}
if (fwbdebug) qDebug("ObjectTreeView::dropEvent done");
}
FWObject *ObjectTreeView::getDropTarget(QDropEvent *ev, FWObject* dragobj)
{//If dag object is an interface or IPv4 object it should be paste to node on which it is dropped
{
QTreeWidgetItem *ovi = itemAt(ev->pos());
ObjectTreeViewItem *otvi=dynamic_cast<ObjectTreeViewItem*>(ovi);
FWObject *trobj;
if (otvi && (trobj = otvi->getFWObject()) && !trobj->isReadOnly() &&
(Interface::isA(dragobj) //Firewall::isA(trobj) &&
|| (Interface::isA(trobj) && IPv4::isA(dragobj))))
return trobj;
return 0;
ObjectTreeViewItem *otvi = dynamic_cast<ObjectTreeViewItem*>(ovi);
return otvi->getFWObject();
}
void ObjectTreeView::dragLeaveEvent( QDragLeaveEvent *ev)
@ -562,21 +567,13 @@ void ObjectTreeView::dragLeaveEvent( QDragLeaveEvent *ev)
void ObjectTreeView::mouseMoveEvent( QMouseEvent * e )
{
/*if (startingDrag)
{
QDrag *drag = dragObject();
drag->start();
}
else*/
QTreeWidget::mouseMoveEvent(e);
if (e==NULL) return;
}
void ObjectTreeView::mousePressEvent( QMouseEvent *e )
{
if (fwbdebug)
qDebug("ObjectTreeView::mousePressEvent");
if (fwbdebug) qDebug("ObjectTreeView::mousePressEvent");
second_click = false;
process_mouse_release_event = true;

View File

@ -624,17 +624,6 @@ FWObject* ProjectPanel::createObject(FWObject *parent,
return m_panel->om->createObject(parent, objType, objName, copyFrom);
}
FWObject* ProjectPanel::copyObj2Tree(const QString &objType,
const QString &objName,
FWObject *copyFrom,
FWObject *parent,
bool ask4Lib)
{
return m_panel->om->copyObj2Tree(
objType, objName, copyFrom, parent, ask4Lib);
}
void ProjectPanel::moveObject(FWObject *target,
FWObject *obj)
{

View File

@ -151,11 +151,6 @@ public:
const QString &objName,
libfwbuilder::FWObject *copyFrom=NULL);
libfwbuilder::FWObject* copyObj2Tree(const QString &objType,
const QString &objName,
libfwbuilder::FWObject *copyFrom=NULL,
libfwbuilder::FWObject *parent=NULL,
bool ask4Lib = true);
FWWindow* getWindow (){ return mainW;}
void moveObject(libfwbuilder::FWObject *target,

View File

@ -3498,17 +3498,6 @@ void RuleSetView::deleteObject(int row, int col, FWObject *obj)
m_project->findObjectWidget->reset();
}
bool RuleSetView::insertObjectFromOther(int row, int col, FWObject *obj)
{
QString n=QString::fromUtf8(obj->getName().c_str());
if (!m_project->hasObject(obj))
{
obj = m_project->copyObj2Tree(obj->getTypeName().c_str(), n, obj);
if (!obj) return false;
}
return insertObject(row, col, obj);
}
bool RuleSetView::insertObject(int row, int col, FWObject *obj)
{
if (fwbdebug)
@ -3948,21 +3937,14 @@ void RuleSetView::dragMoveEvent( QDragMoveEvent *ev)
/*
* See bug 1226069 Segfault: Drag&Drop between two instances
*
* There is a problem with this code: Since we pass "live" pointer to
* FWObject* object in the drag event, drag&drop should not be used to
* pass objects between different instances of the GUI running at the
* same time. Trying to do so causes receiving program to crash
* because it tries to access an object using memory pointer that it
* obtained from another program. Apparently C++ standard does not
* define behavior of the program in case it tries to access memory
* using bad pointer, so it does not throw any exception we could
* catch. Real solution, of course, is to pass object's ID together
* with some identification for the data file in the drag event and
* then on receiving end scan the tree looking for this
* object. Unfortunately this is too slow with our current API desing.
*
* TODO: The problem requires more detailed investigation, possibly
* including API redesign.
* v3.0: we do not permit d&d of an object from one data
* file to another. mostly just to avoid confusing side
* effects because such operation requires copy of all
* object's dependencies. This means simple d&d operation
* can in fact silently copy whole bunch of objects into
* the tree, which is may not be even visible for the user
* if parts of the tree are collapsed or obscured by other
* windows.
*/
if (FWObjectDrag::decode(ev, dragol))
@ -3973,7 +3955,10 @@ void RuleSetView::dragMoveEvent( QDragMoveEvent *ev)
FWObject *dragobj = NULL;
dragobj = dynamic_cast<FWObject*>(*i);
if(dragobj!=NULL)
{
acceptE &= (dragobj->getRoot()==ruleset->getRoot());
acceptE &= re->validateChild(dragobj);
}
}
ev->setAccepted( acceptE );
return;
@ -4017,37 +4002,43 @@ void RuleSetView::dropEvent(QDropEvent *ev)
list<FWObject*> dragol;
if (!FWObjectDrag::decode(ev, dragol)) return;
for (list<FWObject*>::iterator i=dragol.begin();
i!=dragol.end(); ++i)
for (list<FWObject*>::iterator i=dragol.begin(); i!=dragol.end(); ++i)
{
FWObject *dragobj = *i;
assert(dragobj!=NULL);
if (fwbdebug)
qDebug("RuleSetView::dropEvent dragobj=%s",
dragobj->getName().c_str());
if (fwbdebug) qDebug("RuleSetView::dropEvent dragobj=%s",
dragobj->getName().c_str());
if (ev->source()!=this)
{
insertObjectFromOther(row, col, dragobj);
// since ev->source()!=this, this is d&d of an object from
// the tree into rule. Do not allow d&d from a different
// file since it requires copying of the dependencies
// which is a side-effect and might be confusing for the
// user.
if (ruleset->getRoot()!=dragobj->getRoot()) return;
if (insertObject(row, col, dragobj))
changeCurrentCell(row, col, true);
} else
{
// since ev->source()==this, this is d&d of an object from
// one rule to another.
clearSelection();
if (ev->keyboardModifiers() & Qt::ControlModifier)
{
if (insertObject(row,col,dragobj)) //copy
if (insertObject(row, col, dragobj)) //copy
changeCurrentCell(row, col, true);
}
else //move
{
if (insertObject(row,col,dragobj) )
if (insertObject(row, col, dragobj) )
{
deleteObject(oldRow,oldCol,dragobj);
deleteObject(oldRow, oldCol, dragobj);
changeCurrentCell(row, col, true);
}
}
}
}
ev->accept();

View File

@ -464,28 +464,31 @@ public:
private:
ProjectPanel *m_project;
virtual libfwbuilder::RuleElement* getRE( int row, int col ) = 0;
virtual libfwbuilder::RuleElement* getRE( libfwbuilder::Rule* r, int col ) = 0;
virtual libfwbuilder::RuleElement* getRE(int row, int col ) = 0;
virtual libfwbuilder::RuleElement* getRE(libfwbuilder::Rule* r, int col) =0;
QPixmap getPixmap(libfwbuilder::FWObject *obj, PixmapAttr pmattr = Normal) const;
QString objectText(libfwbuilder::RuleElement *re,libfwbuilder::FWObject *obj);
QPixmap getPixmap(libfwbuilder::FWObject *obj,
PixmapAttr pmattr = Normal) const;
QString objectText(libfwbuilder::RuleElement *re,
libfwbuilder::FWObject *obj);
QSize getPMSize();
void fixRulePosition(libfwbuilder::Rule *r, libfwbuilder::FWObject *parent, int pos);
QSize drawIconInRule(QPainter &p, int x, int y, libfwbuilder::RuleElement *re,
void fixRulePosition(libfwbuilder::Rule *r,
libfwbuilder::FWObject *parent, int pos);
QSize drawIconInRule(QPainter &p, int x, int y,
libfwbuilder::RuleElement *re,
libfwbuilder::FWObject *o1);
QString chooseIcon(QString icn);
bool showCommentTip(QPoint pos, QHelpEvent *he);
void drawComment(QPainter &p, int row, int col, const QRect &cr);
bool insertObjectFromOther(int row, int col, libfwbuilder::FWObject *obj);
};
class PolicyView : public RuleSetView
{
virtual libfwbuilder::RuleElement* getRE( int row, int col ) ;
virtual libfwbuilder::RuleElement* getRE( libfwbuilder::Rule* r, int col ) ;
virtual libfwbuilder::RuleElement* getRE(int row, int col);
virtual libfwbuilder::RuleElement* getRE(libfwbuilder::Rule* r, int col);
public:
@ -498,12 +501,13 @@ class PolicyView : public RuleSetView
class InterfacePolicyView : public RuleSetView
{
virtual libfwbuilder::RuleElement* getRE( int row, int col ) ;
virtual libfwbuilder::RuleElement* getRE( libfwbuilder::Rule* r, int col ) ;
virtual libfwbuilder::RuleElement* getRE(int row, int col ) ;
virtual libfwbuilder::RuleElement* getRE(libfwbuilder::Rule* r, int col ) ;
public:
InterfacePolicyView(ProjectPanel *project, libfwbuilder::InterfacePolicy *p, QWidget *parent);
InterfacePolicyView(ProjectPanel *project,
libfwbuilder::InterfacePolicy *p, QWidget *parent);
virtual ~InterfacePolicyView() {}
virtual void init();
@ -513,8 +517,8 @@ class InterfacePolicyView : public RuleSetView
class NATView : public RuleSetView
{
virtual libfwbuilder::RuleElement* getRE( int row, int col ) ;
virtual libfwbuilder::RuleElement* getRE( libfwbuilder::Rule* r, int col ) ;
virtual libfwbuilder::RuleElement* getRE(int row, int col ) ;
virtual libfwbuilder::RuleElement* getRE(libfwbuilder::Rule* r, int col);
public:
@ -528,12 +532,13 @@ class NATView : public RuleSetView
class RoutingView : public RuleSetView
{
virtual libfwbuilder::RuleElement* getRE( int row, int col ) ;
virtual libfwbuilder::RuleElement* getRE( libfwbuilder::Rule* r, int col ) ;
virtual libfwbuilder::RuleElement* getRE(int row, int col);
virtual libfwbuilder::RuleElement* getRE(libfwbuilder::Rule* r, int col);
public:
RoutingView(ProjectPanel *project, libfwbuilder::Routing *p, QWidget *parent);
RoutingView(ProjectPanel *project,
libfwbuilder::Routing *p, QWidget *parent);
virtual ~RoutingView() {}
virtual void init();