00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kacleditwidget.h"
00022 #include "kacleditwidget_p.h"
00023
00024 #include <config-acl.h>
00025 #ifdef HAVE_POSIX_ACL
00026
00027 #include <qpainter.h>
00028 #include <qpushbutton.h>
00029 #include <QButtonGroup>
00030 #include <QGroupBox>
00031 #include <qradiobutton.h>
00032 #include <qcombobox.h>
00033 #include <qlabel.h>
00034 #include <qcheckbox.h>
00035 #include <qlayout.h>
00036 #include <QStackedWidget>
00037 #include <QMouseEvent>
00038 #include <QHeaderView>
00039
00040 #include <klocale.h>
00041 #include <kfileitem.h>
00042 #include <kdebug.h>
00043 #include <kdialog.h>
00044 #include <kvbox.h>
00045 #include <khbox.h>
00046
00047 #ifdef HAVE_ACL_LIBACL_H
00048 # include <acl/libacl.h>
00049 #endif
00050 extern "C" {
00051 #include <pwd.h>
00052 #include <grp.h>
00053 }
00054 #include <assert.h>
00055
00056 static struct {
00057 const char* label;
00058 const char* pixmapName;
00059 QPixmap* pixmap;
00060 } s_itemAttributes[] = {
00061 { I18N_NOOP( "Owner" ), "user-grey", 0 },
00062 { I18N_NOOP( "Owning Group" ), "group-grey", 0 },
00063 { I18N_NOOP( "Others" ), "others-grey", 0 },
00064 { I18N_NOOP( "Mask" ), "mask", 0 },
00065 { I18N_NOOP( "Named User" ), "user", 0 },
00066 { I18N_NOOP( "Named Group" ), "group", 0 },
00067 };
00068
00069 class KACLEditWidget::KACLEditWidgetPrivate
00070 {
00071 public:
00072 KACLEditWidgetPrivate()
00073 {
00074 }
00075
00076
00077 void _k_slotUpdateButtons();
00078
00079 KACLListView *m_listView;
00080 QPushButton *m_AddBtn;
00081 QPushButton *m_EditBtn;
00082 QPushButton *m_DelBtn;
00083 };
00084
00085 KACLEditWidget::KACLEditWidget( QWidget *parent )
00086 : QWidget(parent), d(new KACLEditWidgetPrivate)
00087 {
00088 QHBoxLayout *hbox = new QHBoxLayout( this );
00089 hbox->setMargin( 0 );
00090 hbox->setSpacing( KDialog::spacingHint() );
00091 d->m_listView = new KACLListView(this);
00092 hbox->addWidget(d->m_listView);
00093 connect(d->m_listView->selectionModel(),
00094 SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection& )),
00095 this,
00096 SLOT(_k_slotUpdateButtons()));
00097 QVBoxLayout *vbox = new QVBoxLayout();
00098 hbox->addLayout( vbox );
00099 vbox->setSpacing( KDialog::spacingHint() );
00100 d->m_AddBtn = new QPushButton(i18n("Add Entry..."), this);
00101 vbox->addWidget(d->m_AddBtn);
00102 d->m_AddBtn->setObjectName(QLatin1String("add_entry_button"));
00103 connect(d->m_AddBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotAddEntry()));
00104 d->m_EditBtn = new QPushButton(i18n("Edit Entry..."), this);
00105 vbox->addWidget(d->m_EditBtn);
00106 d->m_EditBtn->setObjectName(QLatin1String("edit_entry_button"));
00107 connect(d->m_EditBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotEditEntry()));
00108 d->m_DelBtn = new QPushButton(i18n("Delete Entry"), this);
00109 vbox->addWidget(d->m_DelBtn);
00110 d->m_DelBtn->setObjectName(QLatin1String("delete_entry_button"));
00111 connect(d->m_DelBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotRemoveEntry()));
00112 vbox->addItem( new QSpacerItem( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
00113 d->_k_slotUpdateButtons();
00114 }
00115
00116 KACLEditWidget::~KACLEditWidget()
00117 {
00118 delete d;
00119 }
00120
00121 void KACLEditWidget::KACLEditWidgetPrivate::_k_slotUpdateButtons()
00122 {
00123 bool atLeastOneIsNotDeletable = false;
00124 bool atLeastOneIsNotAllowedToChangeType = false;
00125 int selectedCount = 0;
00126 QList<QTreeWidgetItem*> selected = m_listView->selectedItems();
00127 QListIterator<QTreeWidgetItem*> it( selected );
00128 while ( it.hasNext() ) {
00129 KACLListViewItem *item = static_cast<KACLListViewItem*>( it.next() );
00130 ++selectedCount;
00131 if ( !item->isDeletable() )
00132 atLeastOneIsNotDeletable = true;
00133 if ( !item->isAllowedToChangeType() )
00134 atLeastOneIsNotAllowedToChangeType = true;
00135 }
00136 m_EditBtn->setEnabled( selectedCount && !atLeastOneIsNotAllowedToChangeType );
00137 m_DelBtn->setEnabled( selectedCount && !atLeastOneIsNotDeletable );
00138 }
00139
00140 KACL KACLEditWidget::getACL() const
00141 {
00142 return d->m_listView->getACL();
00143 }
00144
00145 KACL KACLEditWidget::getDefaultACL() const
00146 {
00147 return d->m_listView->getDefaultACL();
00148 }
00149
00150 void KACLEditWidget::setACL( const KACL &acl )
00151 {
00152 return d->m_listView->setACL(acl);
00153 }
00154
00155 void KACLEditWidget::setDefaultACL( const KACL &acl )
00156 {
00157 return d->m_listView->setDefaultACL(acl);
00158 }
00159
00160 void KACLEditWidget::setAllowDefaults( bool value )
00161 {
00162 d->m_listView->setAllowDefaults(value);
00163 }
00164
00165 KACLListViewItem::KACLListViewItem( QTreeWidget* parent,
00166 KACLListView::EntryType _type,
00167 unsigned short _value, bool defaults,
00168 const QString& _qualifier )
00169 : QTreeWidgetItem( parent),
00170 type( _type ), value( _value ), isDefault( defaults ),
00171 qualifier( _qualifier ), isPartial( false )
00172 {
00173 m_pACLListView = qobject_cast<KACLListView*>( parent );
00174 repaint();
00175 }
00176
00177
00178 KACLListViewItem::~ KACLListViewItem()
00179 {
00180
00181 }
00182
00183 QString KACLListViewItem::key() const
00184 {
00185 QString key;
00186 if ( !isDefault )
00187 key = "A";
00188 else
00189 key = "B";
00190 switch ( type )
00191 {
00192 case KACLListView::User:
00193 key += 'A';
00194 break;
00195 case KACLListView::Group:
00196 key += 'B';
00197 break;
00198 case KACLListView::Others:
00199 key += 'C';
00200 break;
00201 case KACLListView::Mask:
00202 key += 'D';
00203 break;
00204 case KACLListView::NamedUser:
00205 key += 'E' + text( 1 );
00206 break;
00207 case KACLListView::NamedGroup:
00208 key += 'F' + text( 1 );
00209 break;
00210 default:
00211 key += text( 0 );
00212 break;
00213 }
00214 return key;
00215 }
00216
00217 bool KACLListViewItem::operator< ( const QTreeWidgetItem& other ) const
00218 {
00219 return key() < static_cast<const KACLListViewItem&>(other).key();
00220 }
00221
00222 void KACLListViewItem::paintCell( QPainter* p, const QColorGroup &cg,
00223 int column, int width, int alignment )
00224 {
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 }
00251
00252
00253 void KACLListViewItem::updatePermPixmaps()
00254 {
00255 unsigned int partialPerms = value;
00256
00257 if ( value & ACL_READ )
00258 setIcon( 2, m_pACLListView->getYesPixmap() );
00259 else if ( partialPerms & ACL_READ )
00260 setIcon( 2, m_pACLListView->getYesPartialPixmap() );
00261 else
00262 setIcon( 2, QIcon() );
00263
00264 if ( value & ACL_WRITE )
00265 setIcon( 3, m_pACLListView->getYesPixmap() );
00266 else if ( partialPerms & ACL_WRITE )
00267 setIcon( 3, m_pACLListView->getYesPartialPixmap() );
00268 else
00269 setIcon( 3, QIcon() );
00270
00271 if ( value & ACL_EXECUTE )
00272 setIcon( 4, m_pACLListView->getYesPixmap() );
00273 else if ( partialPerms & ACL_EXECUTE )
00274 setIcon( 4, m_pACLListView->getYesPartialPixmap() );
00275 else
00276 setIcon( 4, QIcon() );
00277 }
00278
00279 void KACLListViewItem::repaint()
00280 {
00281 int idx = 0;
00282 switch ( type )
00283 {
00284 case KACLListView::User:
00285 idx = KACLListView::OWNER_IDX;
00286 break;
00287 case KACLListView::Group:
00288 idx = KACLListView::GROUP_IDX;
00289 break;
00290 case KACLListView::Others:
00291 idx = KACLListView::OTHERS_IDX;
00292 break;
00293 case KACLListView::Mask:
00294 idx = KACLListView::MASK_IDX;
00295 break;
00296 case KACLListView::NamedUser:
00297 idx = KACLListView::NAMED_USER_IDX;
00298 break;
00299 case KACLListView::NamedGroup:
00300 idx = KACLListView::NAMED_GROUP_IDX;
00301 break;
00302 default:
00303 idx = KACLListView::OWNER_IDX;
00304 break;
00305 }
00306 setText( 0, i18n(s_itemAttributes[idx].label) );
00307 setIcon( 0, *s_itemAttributes[idx].pixmap );
00308 if ( isDefault )
00309 setText( 0, text( 0 ) + i18n( " (Default)" ) );
00310 setText( 1, qualifier );
00311
00312 updatePermPixmaps();
00313 }
00314
00315 void KACLListViewItem::calcEffectiveRights()
00316 {
00317 QString strEffective = QString( "---" );
00318
00319
00320
00321 if ( m_pACLListView->hasMaskEntry()
00322 && ( type == KACLListView::NamedUser
00323 || type == KACLListView::Group
00324 || type == KACLListView::NamedGroup )
00325 && !isDefault )
00326 {
00327
00328 strEffective[0] = ( m_pACLListView->maskPermissions() & value & ACL_READ ) ? 'r' : '-';
00329 strEffective[1] = ( m_pACLListView->maskPermissions() & value & ACL_WRITE ) ? 'w' : '-';
00330 strEffective[2] = ( m_pACLListView->maskPermissions() & value & ACL_EXECUTE ) ? 'x' : '-';
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 }
00347 else
00348 {
00349
00350 strEffective[0] = ( value & ACL_READ ) ? 'r' : '-';
00351 strEffective[1] = ( value & ACL_WRITE ) ? 'w' : '-';
00352 strEffective[2] = ( value & ACL_EXECUTE ) ? 'x' : '-';
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 }
00364 setText( 5, strEffective );
00365 }
00366
00367 bool KACLListViewItem::isDeletable() const
00368 {
00369 bool isMaskAndDeletable = false;
00370 if (type == KACLListView::Mask ) {
00371 if ( !isDefault && m_pACLListView->maskCanBeDeleted() )
00372 isMaskAndDeletable = true;
00373 else if ( isDefault && m_pACLListView->defaultMaskCanBeDeleted() )
00374 isMaskAndDeletable = true;
00375 }
00376 return type != KACLListView::User &&
00377 type != KACLListView::Group &&
00378 type != KACLListView::Others &&
00379 ( type != KACLListView::Mask || isMaskAndDeletable );
00380 }
00381
00382 bool KACLListViewItem::isAllowedToChangeType() const
00383 {
00384 return type != KACLListView::User &&
00385 type != KACLListView::Group &&
00386 type != KACLListView::Others &&
00387 type != KACLListView::Mask;
00388 }
00389
00390 void KACLListViewItem::togglePerm( acl_perm_t perm )
00391 {
00392 value ^= perm;
00393 if ( type == KACLListView::Mask && !isDefault ) {
00394 m_pACLListView->setMaskPermissions( value );
00395 }
00396 calcEffectiveRights();
00397 updatePermPixmaps();
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 }
00415
00416
00417
00418 EditACLEntryDialog::EditACLEntryDialog( KACLListView *listView, KACLListViewItem *item,
00419 const QStringList &users,
00420 const QStringList &groups,
00421 const QStringList &defaultUsers,
00422 const QStringList &defaultGroups,
00423 int allowedTypes, int allowedDefaultTypes,
00424 bool allowDefaults )
00425 : KDialog( listView ),
00426 m_listView( listView ), m_item( item ), m_users( users ), m_groups( groups ),
00427 m_defaultUsers( defaultUsers ), m_defaultGroups( defaultGroups ),
00428 m_allowedTypes( allowedTypes ), m_allowedDefaultTypes( allowedDefaultTypes ),
00429 m_defaultCB( 0 )
00430 {
00431 setObjectName( "edit_entry_dialog" );
00432 setModal( true );
00433 setCaption( i18n( "Edit ACL Entry" ) );
00434 setButtons( KDialog::Ok | KDialog::Cancel );
00435 setDefaultButton( KDialog::Ok );
00436 showButtonSeparator( false );
00437
00438 QWidget *page = new QWidget( this );
00439 setMainWidget( page );
00440 QVBoxLayout *mainLayout = new QVBoxLayout( page );
00441 mainLayout->setMargin( 0 );
00442 mainLayout->setSpacing( spacingHint() );
00443 QGroupBox *gb = new QGroupBox( i18n("Entry Type"), page );
00444 QVBoxLayout *gbLayout = new QVBoxLayout( gb );
00445 gbLayout->setSpacing( spacingHint() );
00446
00447 m_buttonGroup = new QButtonGroup( page );
00448
00449 if ( allowDefaults ) {
00450 m_defaultCB = new QCheckBox( i18n("Default for new files in this folder"), page );
00451 m_defaultCB->setObjectName( QLatin1String( "defaultCB" ) );
00452 mainLayout->addWidget( m_defaultCB );
00453 connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00454 this, SLOT( slotUpdateAllowedUsersAndGroups() ) );
00455 connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00456 this, SLOT( slotUpdateAllowedTypes() ) );
00457 }
00458
00459 QRadioButton *ownerType = new QRadioButton( i18n("Owner"), gb );
00460 ownerType->setObjectName( QLatin1String( "ownerType" ) );
00461 gbLayout->addWidget( ownerType );
00462 m_buttonGroup->addButton( ownerType );
00463 m_buttonIds.insert( ownerType, KACLListView::User );
00464 QRadioButton *owningGroupType = new QRadioButton( i18n("Owning Group"), gb );
00465 owningGroupType->setObjectName( QLatin1String( "owningGroupType" ) );
00466 gbLayout->addWidget( owningGroupType );
00467 m_buttonGroup->addButton( owningGroupType );
00468 m_buttonIds.insert( owningGroupType, KACLListView::Group );
00469 QRadioButton *othersType = new QRadioButton( i18n("Others"), gb );
00470 othersType->setObjectName( QLatin1String( "othersType" ) );
00471 gbLayout->addWidget( othersType );
00472 m_buttonGroup->addButton( othersType );
00473 m_buttonIds.insert( othersType, KACLListView::Others );
00474 QRadioButton *maskType = new QRadioButton( i18n("Mask"), gb );
00475 maskType->setObjectName( QLatin1String( "maskType" ) );
00476 gbLayout->addWidget( maskType );
00477 m_buttonGroup->addButton( maskType );
00478 m_buttonIds.insert( maskType, KACLListView::Mask );
00479 QRadioButton *namedUserType = new QRadioButton( i18n("Named user"), gb );
00480 namedUserType->setObjectName( QLatin1String( "namesUserType" ) );
00481 gbLayout->addWidget( namedUserType );
00482 m_buttonGroup->addButton( namedUserType );
00483 m_buttonIds.insert( namedUserType, KACLListView::NamedUser );
00484 QRadioButton *namedGroupType = new QRadioButton( i18n("Named group"), gb );
00485 namedGroupType->setObjectName( QLatin1String( "namedGroupType" ) );
00486 gbLayout->addWidget( namedGroupType );
00487 m_buttonGroup->addButton( namedGroupType );
00488 m_buttonIds.insert( namedGroupType, KACLListView::NamedGroup );
00489
00490 mainLayout->addWidget( gb );
00491
00492 connect( m_buttonGroup, SIGNAL( buttonClicked( QAbstractButton* ) ),
00493 this, SLOT( slotSelectionChanged( QAbstractButton * ) ) );
00494
00495 m_widgetStack = new QStackedWidget( page );
00496 mainLayout->addWidget( m_widgetStack );
00497
00498 KHBox *usersBox = new KHBox( m_widgetStack );
00499 m_widgetStack->insertWidget( KACLListView::NamedUser,usersBox );
00500
00501 KHBox *groupsBox = new KHBox( m_widgetStack );
00502 m_widgetStack->insertWidget( KACLListView::NamedGroup,groupsBox );
00503
00504 QLabel *usersLabel = new QLabel( i18n( "User: " ), usersBox );
00505 m_usersCombo = new KComboBox( usersBox );
00506 m_usersCombo->setEditable( false );
00507 m_usersCombo->setObjectName( QLatin1String( "users" ) );
00508 usersLabel->setBuddy( m_usersCombo );
00509
00510 QLabel *groupsLabel = new QLabel( i18n( "Group: " ), groupsBox );
00511 m_groupsCombo = new KComboBox( groupsBox );
00512 m_groupsCombo->setEditable( false );
00513 m_groupsCombo->setObjectName( QLatin1String( "groups" ) );
00514 groupsLabel->setBuddy( m_groupsCombo );
00515
00516 if ( m_item ) {
00517 m_buttonIds.key( m_item->type )->setChecked( true );
00518 if ( m_defaultCB )
00519 m_defaultCB->setChecked( m_item->isDefault );
00520 slotUpdateAllowedTypes();
00521 slotSelectionChanged( m_buttonIds.key( m_item->type ) );
00522 slotUpdateAllowedUsersAndGroups();
00523 if ( m_item->type == KACLListView::NamedUser ) {
00524 m_usersCombo->setItemText( m_usersCombo->currentIndex(), m_item->qualifier );
00525 } else if ( m_item->type == KACLListView::NamedGroup ) {
00526 m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), m_item->qualifier );
00527 }
00528 } else {
00529
00530 m_buttonIds.key( KACLListView::NamedUser )->setChecked( true );
00531 slotUpdateAllowedTypes();
00532 slotSelectionChanged( m_buttonIds.key( KACLListView::NamedUser ) );
00533 slotUpdateAllowedUsersAndGroups();
00534 }
00535 incrementInitialSize( QSize( 100, 0 ) );
00536 connect(this,SIGNAL(okClicked()), this, SLOT(slotOk()));
00537 }
00538
00539 void EditACLEntryDialog::slotUpdateAllowedTypes()
00540 {
00541 int allowedTypes = m_allowedTypes;
00542 if ( m_defaultCB && m_defaultCB->isChecked() ) {
00543 allowedTypes = m_allowedDefaultTypes;
00544 }
00545 for ( int i=1; i < KACLListView::AllTypes; i=i*2 ) {
00546 if ( allowedTypes & i )
00547 m_buttonIds.key( i )->show();
00548 else
00549 m_buttonIds.key( i )->hide();
00550 }
00551 }
00552
00553 void EditACLEntryDialog::slotUpdateAllowedUsersAndGroups()
00554 {
00555 const QString oldUser = m_usersCombo->currentText();
00556 const QString oldGroup = m_groupsCombo->currentText();
00557 m_usersCombo->clear();
00558 m_groupsCombo->clear();
00559 if ( m_defaultCB && m_defaultCB->isChecked() ) {
00560 m_usersCombo->addItems( m_defaultUsers );
00561 if ( m_defaultUsers.contains( oldUser ) )
00562 m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
00563 m_groupsCombo->addItems( m_defaultGroups );
00564 if ( m_defaultGroups.contains( oldGroup ) )
00565 m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
00566 } else {
00567 m_usersCombo->addItems( m_users );
00568 if ( m_users.contains( oldUser ) )
00569 m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
00570 m_groupsCombo->addItems( m_groups );
00571 if ( m_groups.contains( oldGroup ) )
00572 m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
00573 }
00574 }
00575 void EditACLEntryDialog::slotOk()
00576 {
00577 KACLListView::EntryType type = static_cast<KACLListView::EntryType>( m_buttonIds[m_buttonGroup->checkedButton()] );
00578
00579 kWarning() << "Type 2: " << type;
00580
00581 QString qualifier;
00582 if ( type == KACLListView::NamedUser )
00583 qualifier = m_usersCombo->currentText();
00584 if ( type == KACLListView::NamedGroup )
00585 qualifier = m_groupsCombo->currentText();
00586
00587 if ( !m_item ) {
00588 m_item = new KACLListViewItem( m_listView, type, ACL_READ | ACL_WRITE | ACL_EXECUTE, false, qualifier );
00589 } else {
00590 m_item->type = type;
00591 m_item->qualifier = qualifier;
00592 }
00593 if ( m_defaultCB )
00594 m_item->isDefault = m_defaultCB->isChecked();
00595 m_item->repaint();
00596
00597 KDialog::accept();
00598 }
00599
00600 void EditACLEntryDialog::slotSelectionChanged( QAbstractButton *button )
00601 {
00602 switch ( m_buttonIds[ button ] ) {
00603 case KACLListView::User:
00604 case KACLListView::Group:
00605 case KACLListView::Others:
00606 case KACLListView::Mask:
00607 m_widgetStack->setEnabled( false );
00608 break;
00609 case KACLListView::NamedUser:
00610 m_widgetStack->setEnabled( true );
00611 m_widgetStack->setCurrentIndex( KACLListView::NamedUser );
00612 break;
00613 case KACLListView::NamedGroup:
00614 m_widgetStack->setEnabled( true );
00615 m_widgetStack->setCurrentIndex( KACLListView::NamedGroup );
00616 break;
00617 default:
00618 break;
00619 }
00620 }
00621
00622
00623 KACLListView::KACLListView( QWidget* parent )
00624 : QTreeWidget( parent ),
00625 m_hasMask( false ), m_allowDefaults( false )
00626 {
00627
00628 setColumnCount( 6 );
00629 QStringList headers;
00630 headers << i18n( "Type" );
00631 headers << i18n( "Name" );
00632 headers << i18nc( "read permission", "r" );
00633 headers << i18nc( "write permission", "w" );
00634 headers << i18nc( "execute permission", "x" );
00635 headers << i18n( "Effective" );
00636 setHeaderLabels( headers );
00637
00638 setSortingEnabled( false );
00639 setSelectionMode( QAbstractItemView::ExtendedSelection );
00640 header()->setResizeMode( QHeaderView::ResizeToContents );
00641
00642
00643 for ( int i=0; i < LAST_IDX; ++i ) {
00644 s_itemAttributes[i].pixmap = new QPixmap( QString::fromLatin1(":/images/%1").arg(s_itemAttributes[i].pixmapName) );
00645 }
00646 m_yesPixmap = new QPixmap( ":/images/yes.png" );
00647 m_yesPartialPixmap = new QPixmap( ":/images/yespartial.png" );
00648
00649
00650
00651 struct passwd *user = 0;
00652 setpwent();
00653 while ( ( user = getpwent() ) != 0 ) {
00654 m_allUsers << QString::fromLatin1( user->pw_name );
00655 }
00656 endpwent();
00657
00658 struct group *gr = 0;
00659 setgrent();
00660 while ( ( gr = getgrent() ) != 0 ) {
00661 m_allGroups << QString::fromLatin1( gr->gr_name );
00662 }
00663 endgrent();
00664 m_allUsers.sort();
00665 m_allGroups.sort();
00666
00667 connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
00668 this, SLOT( slotItemClicked( QTreeWidgetItem*, int ) ) );
00669 }
00670
00671
00672 KACLListView::~KACLListView()
00673 {
00674 for ( int i=0; i < LAST_IDX; ++i ) {
00675 delete s_itemAttributes[i].pixmap;
00676 }
00677 delete m_yesPixmap;
00678 delete m_yesPartialPixmap;
00679 }
00680
00681 QStringList KACLListView::allowedUsers( bool defaults, KACLListViewItem *allowedItem )
00682 {
00683 QStringList allowedUsers = m_allUsers;
00684 QTreeWidgetItemIterator it( this );
00685 while ( *it ) {
00686 const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00687 ++it;
00688 if ( !item->type == NamedUser || item->isDefault != defaults ) continue;
00689 if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00690 allowedUsers.removeAll( item->qualifier );
00691 }
00692 return allowedUsers;
00693 }
00694
00695 QStringList KACLListView::allowedGroups( bool defaults, KACLListViewItem *allowedItem )
00696 {
00697 QStringList allowedGroups = m_allGroups;
00698 QTreeWidgetItemIterator it( this );
00699 while ( *it ) {
00700 const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00701 ++it;
00702 if ( !item->type == NamedGroup || item->isDefault != defaults ) continue;
00703 if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00704 allowedGroups.removeAll( item->qualifier );
00705 }
00706 return allowedGroups;
00707 }
00708
00709 void KACLListView::fillItemsFromACL( const KACL &pACL, bool defaults )
00710 {
00711
00712 QTreeWidgetItemIterator it( this );
00713 while ( KACLListViewItem *item = static_cast<KACLListViewItem*>( *it ) ) {
00714 ++it;
00715 if ( item->isDefault == defaults )
00716 delete item;
00717 }
00718 KACLListViewItem *item =
00719 new KACLListViewItem( this, User, pACL.ownerPermissions(), defaults );
00720
00721 item = new KACLListViewItem( this, Group, pACL.owningGroupPermissions(), defaults );
00722
00723 item = new KACLListViewItem( this, Others, pACL.othersPermissions(), defaults );
00724
00725 bool hasMask = false;
00726 unsigned short mask = pACL.maskPermissions( hasMask );
00727 if ( hasMask ) {
00728 item = new KACLListViewItem( this, Mask, mask, defaults );
00729 }
00730
00731
00732 const ACLUserPermissionsList &userList = pACL.allUserPermissions();
00733 ACLUserPermissionsConstIterator itu = userList.begin();
00734 while ( itu != userList.end() ) {
00735 new KACLListViewItem( this, NamedUser, (*itu).second, defaults, (*itu).first );
00736 ++itu;
00737 }
00738
00739
00740 const ACLUserPermissionsList &groupList = pACL.allGroupPermissions();
00741 ACLUserPermissionsConstIterator itg = groupList.begin();
00742 while ( itg != groupList.end() ) {
00743 new KACLListViewItem( this, NamedGroup, (*itg).second, defaults, (*itg).first );
00744 ++itg;
00745 }
00746 }
00747
00748 void KACLListView::setACL( const KACL &acl )
00749 {
00750 if ( !acl.isValid() ) return;
00751
00752 m_ACL = acl;
00753 fillItemsFromACL( m_ACL );
00754
00755 m_mask = acl.maskPermissions( m_hasMask );
00756 calculateEffectiveRights();
00757 }
00758
00759 void KACLListView::setDefaultACL( const KACL &acl )
00760 {
00761 if ( !acl.isValid() ) return;
00762 m_defaultACL = acl;
00763 fillItemsFromACL( m_defaultACL, true );
00764 calculateEffectiveRights();
00765 }
00766
00767 KACL KACLListView::itemsToACL( bool defaults ) const
00768 {
00769 KACL newACL( 0 );
00770 bool atLeastOneEntry = false;
00771 ACLUserPermissionsList users;
00772 ACLGroupPermissionsList groups;
00773 QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00774 while ( QTreeWidgetItem* qlvi = *it ) {
00775 ++it;
00776 const KACLListViewItem* item = static_cast<KACLListViewItem*>( qlvi );
00777 if ( item->isDefault != defaults ) continue;
00778 atLeastOneEntry = true;
00779 switch ( item->type ) {
00780 case User:
00781 newACL.setOwnerPermissions( item->value );
00782 break;
00783 case Group:
00784 newACL.setOwningGroupPermissions( item->value );
00785 break;
00786 case Others:
00787 newACL.setOthersPermissions( item->value );
00788 break;
00789 case Mask:
00790 newACL.setMaskPermissions( item->value );
00791 break;
00792 case NamedUser:
00793 users.append( qMakePair( item->text( 1 ), item->value ) );
00794 break;
00795 case NamedGroup:
00796 groups.append( qMakePair( item->text( 1 ), item->value ) );
00797 break;
00798 default:
00799 break;
00800 }
00801 }
00802 if ( atLeastOneEntry ) {
00803 newACL.setAllUserPermissions( users );
00804 newACL.setAllGroupPermissions( groups );
00805 if ( newACL.isValid() )
00806 return newACL;
00807 }
00808 return KACL();
00809 }
00810
00811 KACL KACLListView::getACL()
00812 {
00813 return itemsToACL( false );
00814 }
00815
00816
00817 KACL KACLListView::getDefaultACL()
00818 {
00819 return itemsToACL( true );
00820 }
00821
00822 void KACLListView::contentsMousePressEvent( QMouseEvent * e )
00823 {
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 }
00860
00861 void KACLListView::slotItemClicked( QTreeWidgetItem* pItem, int col )
00862 {
00863 if ( !pItem ) return;
00864
00865 QTreeWidgetItemIterator it( this );
00866 while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
00867 ++it;
00868 if ( !item->isSelected() ) continue;
00869 switch ( col )
00870 {
00871 case 2:
00872 item->togglePerm( ACL_READ );
00873 break;
00874 case 3:
00875 item->togglePerm( ACL_WRITE );
00876 break;
00877 case 4:
00878 item->togglePerm( ACL_EXECUTE );
00879 break;
00880
00881 default:
00882 ;
00883 }
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 }
00908
00909
00910 void KACLListView::calculateEffectiveRights()
00911 {
00912 QTreeWidgetItemIterator it( this );
00913 KACLListViewItem* pItem;
00914 while ( ( pItem = dynamic_cast<KACLListViewItem*>( *it ) ) != 0 )
00915 {
00916 ++it;
00917 pItem->calcEffectiveRights();
00918 }
00919 }
00920
00921
00922 unsigned short KACLListView::maskPermissions() const
00923 {
00924 return m_mask;
00925 }
00926
00927
00928 void KACLListView::setMaskPermissions( unsigned short maskPerms )
00929 {
00930 m_mask = maskPerms;
00931 calculateEffectiveRights();
00932 }
00933
00934
00935 acl_perm_t KACLListView::maskPartialPermissions() const
00936 {
00937
00938 return 0;
00939 }
00940
00941
00942 void KACLListView::setMaskPartialPermissions( acl_perm_t )
00943 {
00944
00945 calculateEffectiveRights();
00946 }
00947
00948 bool KACLListView::hasDefaultEntries() const
00949 {
00950 QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00951 while ( *it ) {
00952 const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00953 ++it;
00954 if ( item->isDefault ) return true;
00955 }
00956 return false;
00957 }
00958
00959 const KACLListViewItem* KACLListView::findDefaultItemByType( EntryType type ) const
00960 {
00961 return findItemByType( type, true );
00962 }
00963
00964 const KACLListViewItem* KACLListView::findItemByType( EntryType type, bool defaults ) const
00965 {
00966 QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00967 while ( *it ) {
00968 const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00969 ++it;
00970 if ( item->isDefault == defaults && item->type == type ) {
00971 return item;
00972 }
00973 }
00974 return 0;
00975 }
00976
00977
00978 unsigned short KACLListView::calculateMaskValue( bool defaults ) const
00979 {
00980
00981 bool dummy;
00982 return itemsToACL( defaults ).maskPermissions( dummy );
00983 }
00984
00985 void KACLListView::slotAddEntry()
00986 {
00987 int allowedTypes = NamedUser | NamedGroup;
00988 if ( !m_hasMask )
00989 allowedTypes |= Mask;
00990 int allowedDefaultTypes = NamedUser | NamedGroup;
00991 if ( !findDefaultItemByType( Mask ) )
00992 allowedDefaultTypes |= Mask;
00993 if ( !hasDefaultEntries() )
00994 allowedDefaultTypes |= User | Group;
00995 EditACLEntryDialog dlg( this, 0,
00996 allowedUsers( false ), allowedGroups( false ),
00997 allowedUsers( true ), allowedGroups( true ),
00998 allowedTypes, allowedDefaultTypes, m_allowDefaults );
00999 dlg.exec();
01000 KACLListViewItem *item = dlg.item();
01001 if ( !item ) return;
01002 if ( item->type == Mask && !item->isDefault ) {
01003 m_hasMask = true;
01004 m_mask = item->value;
01005 }
01006 if ( item->isDefault && !hasDefaultEntries() ) {
01007
01008 if ( item->type != User ) {
01009 unsigned short v = findDefaultItemByType( User )->value;
01010 new KACLListViewItem( this, User, v, true );
01011 }
01012 if ( item->type != Group ) {
01013 unsigned short v = findDefaultItemByType( Group )->value;
01014 new KACLListViewItem( this, Group, v, true );
01015 }
01016 if ( item->type != Others ) {
01017 unsigned short v = findDefaultItemByType( Others )->value;
01018 new KACLListViewItem( this, Others, v, true );
01019 }
01020 }
01021 const KACLListViewItem *defaultMaskItem = findDefaultItemByType( Mask );
01022 if ( item->isDefault && !defaultMaskItem ) {
01023 unsigned short v = calculateMaskValue( true );
01024 new KACLListViewItem( this, Mask, v, true );
01025 }
01026 if ( !item->isDefault && !m_hasMask &&
01027 ( item->type == Group
01028 || item->type == NamedUser
01029 || item->type == NamedGroup ) ) {
01030
01031 unsigned short v = calculateMaskValue( false );
01032 new KACLListViewItem( this, Mask, v, false );
01033 m_hasMask = true;
01034 m_mask = v;
01035 }
01036 calculateEffectiveRights();
01037 sortItems( sortColumn(), Qt::AscendingOrder );
01038 setCurrentItem( item );
01039
01040
01041 if ( topLevelItemCount() == 1 )
01042 emit currentItemChanged( item, item );
01043 }
01044
01045 void KACLListView::slotEditEntry()
01046 {
01047 QTreeWidgetItem * current = currentItem();
01048 if ( !current ) return;
01049 KACLListViewItem *item = static_cast<KACLListViewItem*>( current );
01050 int allowedTypes = item->type | NamedUser | NamedGroup;
01051 bool itemWasMask = item->type == Mask;
01052 if ( !m_hasMask || itemWasMask )
01053 allowedTypes |= Mask;
01054 int allowedDefaultTypes = item->type | NamedUser | NamedGroup;
01055 if ( !findDefaultItemByType( Mask ) )
01056 allowedDefaultTypes |= Mask;
01057 if ( !hasDefaultEntries() )
01058 allowedDefaultTypes |= User | Group;
01059
01060 EditACLEntryDialog dlg( this, item,
01061 allowedUsers( false, item ), allowedGroups( false, item ),
01062 allowedUsers( true, item ), allowedGroups( true, item ),
01063 allowedTypes, allowedDefaultTypes, m_allowDefaults );
01064 dlg.exec();
01065 if ( itemWasMask && item->type != Mask ) {
01066 m_hasMask = false;
01067 m_mask = 0;
01068 }
01069 if ( !itemWasMask && item->type == Mask ) {
01070 m_mask = item->value;
01071 m_hasMask = true;
01072 }
01073 calculateEffectiveRights();
01074 sortItems( sortColumn(), Qt::AscendingOrder );
01075 }
01076
01077 void KACLListView::slotRemoveEntry()
01078 {
01079 QTreeWidgetItemIterator it( this, QTreeWidgetItemIterator::Selected );
01080 while ( *it ) {
01081 KACLListViewItem *item = static_cast<KACLListViewItem*>( *it );
01082 ++it;
01083
01084
01085
01086 if ( item->type == Mask ) {
01087 bool itemWasDefault = item->isDefault;
01088 if ( !itemWasDefault && maskCanBeDeleted() ) {
01089 m_hasMask= false;
01090 m_mask = 0;
01091 delete item;
01092 } else if ( itemWasDefault && defaultMaskCanBeDeleted() ) {
01093 delete item;
01094 } else {
01095 item->value = 0;
01096 item->repaint();
01097 }
01098 if ( !itemWasDefault )
01099 calculateEffectiveRights();
01100 } else {
01101
01102 if ( !item->isDefault &&
01103 ( item->type == User
01104 || item->type == Group
01105 || item->type == Others ) ) {
01106 item->value = 0;
01107 item->repaint();
01108 } else {
01109 delete item;
01110 }
01111 }
01112 }
01113 }
01114
01115 bool KACLListView::maskCanBeDeleted() const
01116 {
01117 return !findItemByType( NamedUser ) && !findItemByType( NamedGroup );
01118 }
01119
01120 bool KACLListView::defaultMaskCanBeDeleted() const
01121 {
01122 return !findDefaultItemByType( NamedUser ) && !findDefaultItemByType( NamedGroup );
01123 }
01124
01125 #include "kacleditwidget.moc"
01126 #include "kacleditwidget_p.moc"
01127 #endif
01128