• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KIO

  • sources
  • kde-4.12
  • kdelibs
  • kio
  • kfile
kacleditwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Sean Harmer <sh@rama.homelinux.org> *
3  * 2005 - 2007 Till Adam <adam@kde.org> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU Library General Public License as *
7  * published by the Free Software Foundation; either version 2 of the *
8  * License, or (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19  ***************************************************************************/
20 
21 #include "kacleditwidget.h"
22 #include "kacleditwidget_p.h"
23 
24 #include <config-acl.h>
25 #ifdef HAVE_POSIX_ACL
26 
27 #include <qpainter.h>
28 #include <qpushbutton.h>
29 #include <QButtonGroup>
30 #include <QGroupBox>
31 #include <qradiobutton.h>
32 #include <qcombobox.h>
33 #include <qlabel.h>
34 #include <qcheckbox.h>
35 #include <qlayout.h>
36 #include <QStackedWidget>
37 #include <QMouseEvent>
38 #include <QHeaderView>
39 
40 #include <klocale.h>
41 #include <kfileitem.h>
42 #include <kdebug.h>
43 #include <kdialog.h>
44 #include <kvbox.h>
45 #include <khbox.h>
46 
47 #ifdef HAVE_ACL_LIBACL_H
48 # include <acl/libacl.h>
49 #endif
50 extern "C" {
51 #include <pwd.h>
52 #include <grp.h>
53 }
54 #include <assert.h>
55 
56 static struct {
57  const char* label;
58  const char* pixmapName;
59  QPixmap* pixmap;
60 } s_itemAttributes[] = {
61  { I18N_NOOP( "Owner" ), "user-grey", 0 },
62  { I18N_NOOP( "Owning Group" ), "group-grey", 0 },
63  { I18N_NOOP( "Others" ), "others-grey", 0 },
64  { I18N_NOOP( "Mask" ), "mask", 0 },
65  { I18N_NOOP( "Named User" ), "user", 0 },
66  { I18N_NOOP( "Named Group" ), "group", 0 },
67 };
68 
69 class KACLEditWidget::KACLEditWidgetPrivate
70 {
71 public:
72  KACLEditWidgetPrivate()
73  {
74  }
75 
76  // slots
77  void _k_slotUpdateButtons();
78 
79  KACLListView *m_listView;
80  QPushButton *m_AddBtn;
81  QPushButton *m_EditBtn;
82  QPushButton *m_DelBtn;
83 };
84 
85 KACLEditWidget::KACLEditWidget( QWidget *parent )
86  : QWidget(parent), d(new KACLEditWidgetPrivate)
87 {
88  QHBoxLayout *hbox = new QHBoxLayout( this );
89  hbox->setMargin( 0 );
90  d->m_listView = new KACLListView(this);
91  hbox->addWidget(d->m_listView);
92  connect(d->m_listView->selectionModel(),
93  SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
94  this,
95  SLOT(_k_slotUpdateButtons()));
96  QVBoxLayout *vbox = new QVBoxLayout();
97  hbox->addLayout( vbox );
98  d->m_AddBtn = new QPushButton(i18n("Add Entry..."), this);
99  vbox->addWidget(d->m_AddBtn);
100  d->m_AddBtn->setObjectName(QLatin1String("add_entry_button"));
101  connect(d->m_AddBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotAddEntry()));
102  d->m_EditBtn = new QPushButton(i18n("Edit Entry..."), this);
103  vbox->addWidget(d->m_EditBtn);
104  d->m_EditBtn->setObjectName(QLatin1String("edit_entry_button"));
105  connect(d->m_EditBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotEditEntry()));
106  d->m_DelBtn = new QPushButton(i18n("Delete Entry"), this);
107  vbox->addWidget(d->m_DelBtn);
108  d->m_DelBtn->setObjectName(QLatin1String("delete_entry_button"));
109  connect(d->m_DelBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotRemoveEntry()));
110  vbox->addItem( new QSpacerItem( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
111  d->_k_slotUpdateButtons();
112 }
113 
114 KACLEditWidget::~KACLEditWidget()
115 {
116  delete d;
117 }
118 
119 void KACLEditWidget::KACLEditWidgetPrivate::_k_slotUpdateButtons()
120 {
121  bool atLeastOneIsNotDeletable = false;
122  bool atLeastOneIsNotAllowedToChangeType = false;
123  int selectedCount = 0;
124  QList<QTreeWidgetItem*> selected = m_listView->selectedItems();
125  QListIterator<QTreeWidgetItem*> it( selected );
126  while ( it.hasNext() ) {
127  KACLListViewItem *item = static_cast<KACLListViewItem*>( it.next() );
128  ++selectedCount;
129  if ( !item->isDeletable() )
130  atLeastOneIsNotDeletable = true;
131  if ( !item->isAllowedToChangeType() )
132  atLeastOneIsNotAllowedToChangeType = true;
133  }
134  m_EditBtn->setEnabled( selectedCount && !atLeastOneIsNotAllowedToChangeType );
135  m_DelBtn->setEnabled( selectedCount && !atLeastOneIsNotDeletable );
136 }
137 
138 KACL KACLEditWidget::getACL() const
139 {
140  return d->m_listView->getACL();
141 }
142 
143 KACL KACLEditWidget::getDefaultACL() const
144 {
145  return d->m_listView->getDefaultACL();
146 }
147 
148 void KACLEditWidget::setACL( const KACL &acl )
149 {
150  return d->m_listView->setACL(acl);
151 }
152 
153 void KACLEditWidget::setDefaultACL( const KACL &acl )
154 {
155  return d->m_listView->setDefaultACL(acl);
156 }
157 
158 void KACLEditWidget::setAllowDefaults( bool value )
159 {
160  d->m_listView->setAllowDefaults(value);
161 }
162 
163 KACLListViewItem::KACLListViewItem( QTreeWidget* parent,
164  KACLListView::EntryType _type,
165  unsigned short _value, bool defaults,
166  const QString& _qualifier )
167  : QTreeWidgetItem( parent),
168  type( _type ), value( _value ), isDefault( defaults ),
169  qualifier( _qualifier ), isPartial( false )
170 {
171  m_pACLListView = qobject_cast<KACLListView*>( parent );
172  repaint();
173 }
174 
175 
176 KACLListViewItem::~ KACLListViewItem()
177 {
178 
179 }
180 
181 QString KACLListViewItem::key() const
182 {
183  QString key;
184  if ( !isDefault )
185  key = 'A';
186  else
187  key = 'B';
188  switch ( type )
189  {
190  case KACLListView::User:
191  key += 'A';
192  break;
193  case KACLListView::Group:
194  key += 'B';
195  break;
196  case KACLListView::Others:
197  key += 'C';
198  break;
199  case KACLListView::Mask:
200  key += 'D';
201  break;
202  case KACLListView::NamedUser:
203  key += 'E' + text( 1 );
204  break;
205  case KACLListView::NamedGroup:
206  key += 'F' + text( 1 );
207  break;
208  default:
209  key += text( 0 );
210  break;
211  }
212  return key;
213 }
214 
215 bool KACLListViewItem::operator< ( const QTreeWidgetItem& other ) const
216 {
217  return key() < static_cast<const KACLListViewItem&>(other).key();
218 }
219 
220 #if 0
221 void KACLListViewItem::paintCell( QPainter* p, const QColorGroup &cg,
222  int column, int width, int alignment )
223 {
224  if ( isDefault ) {
225  setForeground( QColor( 0, 0, 255 ) );
226  }
227  if ( isPartial ) {
228  QFont font = p->font();
229  font.setItalic( true );
230  setForeground( QColor( 100, 100, 100 ) );
231  p->setFont( font );
232  }
233  QTreeWidgetItem::paintCell( p, mycg, column, width, alignment );
234 
235  KACLListViewItem *below =0;
236  if ( itemBelow() )
237  below = static_cast<KACLListViewItem*>( itemBelow() );
238  const bool lastUser = type == KACLListView::NamedUser && below && below->type == KACLListView::NamedGroup;
239  const bool lastNonDefault = !isDefault && below && below->isDefault;
240  if ( type == KACLListView::Mask || lastUser || lastNonDefault )
241  {
242  p->setPen( QPen( Qt::gray, 0, Qt::DotLine ) );
243  if ( type == KACLListView::Mask )
244  p->drawLine( 0, 0, width - 1, 0 );
245  p->drawLine( 0, height() - 1, width - 1, height() - 1 );
246  }
247 }
248 #endif
249 
250 
251 void KACLListViewItem::updatePermPixmaps()
252 {
253  unsigned int partialPerms = value;
254 
255  if ( value & ACL_READ )
256  setIcon( 2, m_pACLListView->getYesPixmap() );
257  else if ( partialPerms & ACL_READ )
258  setIcon( 2, m_pACLListView->getYesPartialPixmap() );
259  else
260  setIcon( 2, QIcon() );
261 
262  if ( value & ACL_WRITE )
263  setIcon( 3, m_pACLListView->getYesPixmap() );
264  else if ( partialPerms & ACL_WRITE )
265  setIcon( 3, m_pACLListView->getYesPartialPixmap() );
266  else
267  setIcon( 3, QIcon() );
268 
269  if ( value & ACL_EXECUTE )
270  setIcon( 4, m_pACLListView->getYesPixmap() );
271  else if ( partialPerms & ACL_EXECUTE )
272  setIcon( 4, m_pACLListView->getYesPartialPixmap() );
273  else
274  setIcon( 4, QIcon() );
275 }
276 
277 void KACLListViewItem::repaint()
278 {
279  int idx = 0;
280  switch ( type )
281  {
282  case KACLListView::User:
283  idx = KACLListView::OWNER_IDX;
284  break;
285  case KACLListView::Group:
286  idx = KACLListView::GROUP_IDX;
287  break;
288  case KACLListView::Others:
289  idx = KACLListView::OTHERS_IDX;
290  break;
291  case KACLListView::Mask:
292  idx = KACLListView::MASK_IDX;
293  break;
294  case KACLListView::NamedUser:
295  idx = KACLListView::NAMED_USER_IDX;
296  break;
297  case KACLListView::NamedGroup:
298  idx = KACLListView::NAMED_GROUP_IDX;
299  break;
300  default:
301  idx = KACLListView::OWNER_IDX;
302  break;
303  }
304  setText( 0, i18n(s_itemAttributes[idx].label) );
305  setIcon( 0, *s_itemAttributes[idx].pixmap );
306  if ( isDefault )
307  setText( 0, text( 0 ) + i18n( " (Default)" ) );
308  setText( 1, qualifier );
309  // Set the pixmaps for which of the perms are set
310  updatePermPixmaps();
311 }
312 
313 void KACLListViewItem::calcEffectiveRights()
314 {
315  QString strEffective = QString( "---" );
316 
317  // Do we need to worry about the mask entry? It applies to named users,
318  // owning group, and named groups
319  if ( m_pACLListView->hasMaskEntry()
320  && ( type == KACLListView::NamedUser
321  || type == KACLListView::Group
322  || type == KACLListView::NamedGroup )
323  && !isDefault )
324  {
325 
326  strEffective[0] = ( m_pACLListView->maskPermissions() & value & ACL_READ ) ? 'r' : '-';
327  strEffective[1] = ( m_pACLListView->maskPermissions() & value & ACL_WRITE ) ? 'w' : '-';
328  strEffective[2] = ( m_pACLListView->maskPermissions() & value & ACL_EXECUTE ) ? 'x' : '-';
329 /*
330  // What about any partial perms?
331  if ( maskPerms & partialPerms & ACL_READ || // Partial perms on entry
332  maskPartialPerms & perms & ACL_READ || // Partial perms on mask
333  maskPartialPerms & partialPerms & ACL_READ ) // Partial perms on mask and entry
334  strEffective[0] = 'R';
335  if ( maskPerms & partialPerms & ACL_WRITE || // Partial perms on entry
336  maskPartialPerms & perms & ACL_WRITE || // Partial perms on mask
337  maskPartialPerms & partialPerms & ACL_WRITE ) // Partial perms on mask and entry
338  strEffective[1] = 'W';
339  if ( maskPerms & partialPerms & ACL_EXECUTE || // Partial perms on entry
340  maskPartialPerms & perms & ACL_EXECUTE || // Partial perms on mask
341  maskPartialPerms & partialPerms & ACL_EXECUTE ) // Partial perms on mask and entry
342  strEffective[2] = 'X';
343 */
344  }
345  else
346  {
347  // No, the effective value are just the value in this entry
348  strEffective[0] = ( value & ACL_READ ) ? 'r' : '-';
349  strEffective[1] = ( value & ACL_WRITE ) ? 'w' : '-';
350  strEffective[2] = ( value & ACL_EXECUTE ) ? 'x' : '-';
351 
352  /*
353  // What about any partial perms?
354  if ( partialPerms & ACL_READ )
355  strEffective[0] = 'R';
356  if ( partialPerms & ACL_WRITE )
357  strEffective[1] = 'W';
358  if ( partialPerms & ACL_EXECUTE )
359  strEffective[2] = 'X';
360  */
361  }
362  setText( 5, strEffective );
363 }
364 
365 bool KACLListViewItem::isDeletable() const
366 {
367  bool isMaskAndDeletable = false;
368  if (type == KACLListView::Mask ) {
369  if ( !isDefault && m_pACLListView->maskCanBeDeleted() )
370  isMaskAndDeletable = true;
371  else if ( isDefault && m_pACLListView->defaultMaskCanBeDeleted() )
372  isMaskAndDeletable = true;
373  }
374  return type != KACLListView::User &&
375  type != KACLListView::Group &&
376  type != KACLListView::Others &&
377  ( type != KACLListView::Mask || isMaskAndDeletable );
378 }
379 
380 bool KACLListViewItem::isAllowedToChangeType() const
381 {
382  return type != KACLListView::User &&
383  type != KACLListView::Group &&
384  type != KACLListView::Others &&
385  type != KACLListView::Mask;
386 }
387 
388 void KACLListViewItem::togglePerm( acl_perm_t perm )
389 {
390  value ^= perm; // Toggle the perm
391  if ( type == KACLListView::Mask && !isDefault ) {
392  m_pACLListView->setMaskPermissions( value );
393  }
394  calcEffectiveRights();
395  updatePermPixmaps();
396 /*
397  // If the perm is in the partial perms then remove it. i.e. Once
398  // a user changes a partial perm it then applies to all selected files.
399  if ( m_pEntry->m_partialPerms & perm )
400  m_pEntry->m_partialPerms ^= perm;
401 
402  m_pEntry->setPartialEntry( false );
403  // Make sure that all entries have their effective rights calculated if
404  // we are changing the ACL_MASK entry.
405  if ( type == Mask )
406  {
407  m_pACLListView->setMaskPartialPermissions( m_pEntry->m_partialPerms );
408  m_pACLListView->setMaskPermissions( value );
409  m_pACLListView->calculateEffectiveRights();
410  }
411 */
412 }
413 
414 
415 
416 EditACLEntryDialog::EditACLEntryDialog( KACLListView *listView, KACLListViewItem *item,
417  const QStringList &users,
418  const QStringList &groups,
419  const QStringList &defaultUsers,
420  const QStringList &defaultGroups,
421  int allowedTypes, int allowedDefaultTypes,
422  bool allowDefaults )
423  : KDialog( listView ),
424  m_listView( listView ), m_item( item ), m_users( users ), m_groups( groups ),
425  m_defaultUsers( defaultUsers ), m_defaultGroups( defaultGroups ),
426  m_allowedTypes( allowedTypes ), m_allowedDefaultTypes( allowedDefaultTypes ),
427  m_defaultCB( 0 )
428 {
429  setObjectName( "edit_entry_dialog" );
430  setModal( true );
431  setCaption( i18n( "Edit ACL Entry" ) );
432  setButtons( KDialog::Ok | KDialog::Cancel );
433  setDefaultButton( KDialog::Ok );
434 
435  QWidget *page = new QWidget( this );
436  setMainWidget( page );
437  QVBoxLayout *mainLayout = new QVBoxLayout( page );
438  mainLayout->setMargin( 0 );
439  QGroupBox *gb = new QGroupBox( i18n("Entry Type"), page );
440  QVBoxLayout *gbLayout = new QVBoxLayout( gb );
441 
442  m_buttonGroup = new QButtonGroup( page );
443 
444  if ( allowDefaults ) {
445  m_defaultCB = new QCheckBox( i18n("Default for new files in this folder"), page );
446  m_defaultCB->setObjectName( QLatin1String( "defaultCB" ) );
447  mainLayout->addWidget( m_defaultCB );
448  connect( m_defaultCB, SIGNAL(toggled(bool)),
449  this, SLOT(slotUpdateAllowedUsersAndGroups()) );
450  connect( m_defaultCB, SIGNAL(toggled(bool)),
451  this, SLOT(slotUpdateAllowedTypes()) );
452  }
453 
454  QRadioButton *ownerType = new QRadioButton( i18n("Owner"), gb );
455  ownerType->setObjectName( QLatin1String( "ownerType" ) );
456  gbLayout->addWidget( ownerType );
457  m_buttonGroup->addButton( ownerType );
458  m_buttonIds.insert( ownerType, KACLListView::User );
459  QRadioButton *owningGroupType = new QRadioButton( i18n("Owning Group"), gb );
460  owningGroupType->setObjectName( QLatin1String( "owningGroupType" ) );
461  gbLayout->addWidget( owningGroupType );
462  m_buttonGroup->addButton( owningGroupType );
463  m_buttonIds.insert( owningGroupType, KACLListView::Group );
464  QRadioButton *othersType = new QRadioButton( i18n("Others"), gb );
465  othersType->setObjectName( QLatin1String( "othersType" ) );
466  gbLayout->addWidget( othersType );
467  m_buttonGroup->addButton( othersType );
468  m_buttonIds.insert( othersType, KACLListView::Others );
469  QRadioButton *maskType = new QRadioButton( i18n("Mask"), gb );
470  maskType->setObjectName( QLatin1String( "maskType" ) );
471  gbLayout->addWidget( maskType );
472  m_buttonGroup->addButton( maskType );
473  m_buttonIds.insert( maskType, KACLListView::Mask );
474  QRadioButton *namedUserType = new QRadioButton( i18n("Named user"), gb );
475  namedUserType->setObjectName( QLatin1String( "namesUserType" ) );
476  gbLayout->addWidget( namedUserType );
477  m_buttonGroup->addButton( namedUserType );
478  m_buttonIds.insert( namedUserType, KACLListView::NamedUser );
479  QRadioButton *namedGroupType = new QRadioButton( i18n("Named group"), gb );
480  namedGroupType->setObjectName( QLatin1String( "namedGroupType" ) );
481  gbLayout->addWidget( namedGroupType );
482  m_buttonGroup->addButton( namedGroupType );
483  m_buttonIds.insert( namedGroupType, KACLListView::NamedGroup );
484 
485  mainLayout->addWidget( gb );
486 
487  connect( m_buttonGroup, SIGNAL(buttonClicked(QAbstractButton*)),
488  this, SLOT(slotSelectionChanged(QAbstractButton*)) );
489 
490  m_widgetStack = new QStackedWidget( page );
491  mainLayout->addWidget( m_widgetStack );
492 
493  KHBox *usersBox = new KHBox( m_widgetStack );
494  m_widgetStack->addWidget( usersBox );
495 
496  KHBox *groupsBox = new KHBox( m_widgetStack );
497  m_widgetStack->addWidget( groupsBox );
498 
499  QLabel *usersLabel = new QLabel( i18n( "User: " ), usersBox );
500  m_usersCombo = new KComboBox( usersBox );
501  m_usersCombo->setEditable( false );
502  m_usersCombo->setObjectName( QLatin1String( "users" ) );
503  usersLabel->setBuddy( m_usersCombo );
504 
505  QLabel *groupsLabel = new QLabel( i18n( "Group: " ), groupsBox );
506  m_groupsCombo = new KComboBox( groupsBox );
507  m_groupsCombo->setEditable( false );
508  m_groupsCombo->setObjectName( QLatin1String( "groups" ) );
509  groupsLabel->setBuddy( m_groupsCombo );
510 
511  if ( m_item ) {
512  m_buttonIds.key( m_item->type )->setChecked( true );
513  if ( m_defaultCB )
514  m_defaultCB->setChecked( m_item->isDefault );
515  slotUpdateAllowedTypes();
516  slotSelectionChanged( m_buttonIds.key( m_item->type ) );
517  slotUpdateAllowedUsersAndGroups();
518  if ( m_item->type == KACLListView::NamedUser ) {
519  m_usersCombo->setItemText( m_usersCombo->currentIndex(), m_item->qualifier );
520  } else if ( m_item->type == KACLListView::NamedGroup ) {
521  m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), m_item->qualifier );
522  }
523  } else {
524  // new entry, preselect "named user", arguably the most common one
525  m_buttonIds.key( KACLListView::NamedUser )->setChecked( true );
526  slotUpdateAllowedTypes();
527  slotSelectionChanged( m_buttonIds.key( KACLListView::NamedUser ) );
528  slotUpdateAllowedUsersAndGroups();
529  }
530  incrementInitialSize( QSize( 100, 0 ) );
531  connect(this,SIGNAL(okClicked()), this, SLOT(slotOk()));
532 }
533 
534 void EditACLEntryDialog::slotUpdateAllowedTypes()
535 {
536  int allowedTypes = m_allowedTypes;
537  if ( m_defaultCB && m_defaultCB->isChecked() ) {
538  allowedTypes = m_allowedDefaultTypes;
539  }
540  for ( int i=1; i < KACLListView::AllTypes; i=i*2 ) {
541  if ( allowedTypes & i )
542  m_buttonIds.key( i )->show();
543  else
544  m_buttonIds.key( i )->hide();
545  }
546 }
547 
548 void EditACLEntryDialog::slotUpdateAllowedUsersAndGroups()
549 {
550  const QString oldUser = m_usersCombo->currentText();
551  const QString oldGroup = m_groupsCombo->currentText();
552  m_usersCombo->clear();
553  m_groupsCombo->clear();
554  if ( m_defaultCB && m_defaultCB->isChecked() ) {
555  m_usersCombo->addItems( m_defaultUsers );
556  if ( m_defaultUsers.contains( oldUser ) )
557  m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
558  m_groupsCombo->addItems( m_defaultGroups );
559  if ( m_defaultGroups.contains( oldGroup ) )
560  m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
561  } else {
562  m_usersCombo->addItems( m_users );
563  if ( m_users.contains( oldUser ) )
564  m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
565  m_groupsCombo->addItems( m_groups );
566  if ( m_groups.contains( oldGroup ) )
567  m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
568  }
569 }
570 void EditACLEntryDialog::slotOk()
571 {
572  KACLListView::EntryType type = static_cast<KACLListView::EntryType>( m_buttonIds[m_buttonGroup->checkedButton()] );
573 
574  kWarning() << "Type 2: " << type;
575 
576  QString qualifier;
577  if ( type == KACLListView::NamedUser )
578  qualifier = m_usersCombo->currentText();
579  if ( type == KACLListView::NamedGroup )
580  qualifier = m_groupsCombo->currentText();
581 
582  if ( !m_item ) {
583  m_item = new KACLListViewItem( m_listView, type, ACL_READ | ACL_WRITE | ACL_EXECUTE, false, qualifier );
584  } else {
585  m_item->type = type;
586  m_item->qualifier = qualifier;
587  }
588  if ( m_defaultCB )
589  m_item->isDefault = m_defaultCB->isChecked();
590  m_item->repaint();
591 
592  KDialog::accept();
593 }
594 
595 void EditACLEntryDialog::slotSelectionChanged( QAbstractButton *button )
596 {
597  switch ( m_buttonIds[ button ] ) {
598  case KACLListView::User:
599  case KACLListView::Group:
600  case KACLListView::Others:
601  case KACLListView::Mask:
602  m_widgetStack->setEnabled( false );
603  break;
604  case KACLListView::NamedUser:
605  m_widgetStack->setEnabled( true );
606  m_widgetStack->setCurrentIndex( 0 /* User */ );
607  break;
608  case KACLListView::NamedGroup:
609  m_widgetStack->setEnabled( true );
610  m_widgetStack->setCurrentIndex( 1 /* Group */ );
611  break;
612  default:
613  break;
614  }
615 }
616 
617 
618 KACLListView::KACLListView( QWidget* parent )
619  : QTreeWidget( parent ),
620  m_hasMask( false ), m_allowDefaults( false )
621 {
622  // Add the columns
623  setColumnCount( 6 );
624  QStringList headers;
625  headers << i18n( "Type" );
626  headers << i18n( "Name" );
627  headers << i18nc( "read permission", "r" );
628  headers << i18nc( "write permission", "w" );
629  headers << i18nc( "execute permission", "x" );
630  headers << i18n( "Effective" );
631  setHeaderLabels( headers );
632 
633  setSortingEnabled( false );
634  setSelectionMode( QAbstractItemView::ExtendedSelection );
635  header()->setResizeMode( QHeaderView::ResizeToContents );
636  setRootIsDecorated( false );
637 
638  // Load the avatars
639  for ( int i=0; i < LAST_IDX; ++i ) {
640  s_itemAttributes[i].pixmap = new QPixmap( QString::fromLatin1(":/images/%1").arg(s_itemAttributes[i].pixmapName) );
641  }
642  m_yesPixmap = new QPixmap( ":/images/yes.png" );
643  m_yesPartialPixmap = new QPixmap( ":/images/yespartial.png" );
644 
645 
646  // fill the lists of all legal users and groups
647  struct passwd *user = 0;
648  setpwent();
649  while ( ( user = getpwent() ) != 0 ) {
650  m_allUsers << QString::fromLatin1( user->pw_name );
651  }
652  endpwent();
653 
654  struct group *gr = 0;
655  setgrent();
656  while ( ( gr = getgrent() ) != 0 ) {
657  m_allGroups << QString::fromLatin1( gr->gr_name );
658  }
659  endgrent();
660  m_allUsers.sort();
661  m_allGroups.sort();
662 
663  connect( this, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
664  this, SLOT(slotItemClicked(QTreeWidgetItem*,int)) );
665 }
666 
667 
668 KACLListView::~KACLListView()
669 {
670  for ( int i=0; i < LAST_IDX; ++i ) {
671  delete s_itemAttributes[i].pixmap;
672  }
673  delete m_yesPixmap;
674  delete m_yesPartialPixmap;
675 }
676 
677 QStringList KACLListView::allowedUsers( bool defaults, KACLListViewItem *allowedItem )
678 {
679  QStringList allowedUsers = m_allUsers;
680  QTreeWidgetItemIterator it( this );
681  while ( *it ) {
682  const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
683  ++it;
684  if ( item->type != NamedUser || item->isDefault != defaults ) continue;
685  if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
686  allowedUsers.removeAll( item->qualifier );
687  }
688  return allowedUsers;
689 }
690 
691 QStringList KACLListView::allowedGroups( bool defaults, KACLListViewItem *allowedItem )
692 {
693  QStringList allowedGroups = m_allGroups;
694  QTreeWidgetItemIterator it( this );
695  while ( *it ) {
696  const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
697  ++it;
698  if ( item->type != NamedGroup || item->isDefault != defaults ) continue;
699  if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
700  allowedGroups.removeAll( item->qualifier );
701  }
702  return allowedGroups;
703 }
704 
705 void KACLListView::fillItemsFromACL( const KACL &pACL, bool defaults )
706 {
707  // clear out old entries of that ilk
708  QTreeWidgetItemIterator it( this );
709  while ( KACLListViewItem *item = static_cast<KACLListViewItem*>( *it ) ) {
710  ++it;
711  if ( item->isDefault == defaults )
712  delete item;
713  }
714  KACLListViewItem *item =
715  new KACLListViewItem( this, User, pACL.ownerPermissions(), defaults );
716 
717  item = new KACLListViewItem( this, Group, pACL.owningGroupPermissions(), defaults );
718 
719  item = new KACLListViewItem( this, Others, pACL.othersPermissions(), defaults );
720 
721  bool hasMask = false;
722  unsigned short mask = pACL.maskPermissions( hasMask );
723  if ( hasMask ) {
724  item = new KACLListViewItem( this, Mask, mask, defaults );
725  }
726 
727  // read all named user entries
728  const ACLUserPermissionsList &userList = pACL.allUserPermissions();
729  ACLUserPermissionsConstIterator itu = userList.begin();
730  while ( itu != userList.end() ) {
731  new KACLListViewItem( this, NamedUser, (*itu).second, defaults, (*itu).first );
732  ++itu;
733  }
734 
735  // and now all named groups
736  const ACLUserPermissionsList &groupList = pACL.allGroupPermissions();
737  ACLUserPermissionsConstIterator itg = groupList.begin();
738  while ( itg != groupList.end() ) {
739  new KACLListViewItem( this, NamedGroup, (*itg).second, defaults, (*itg).first );
740  ++itg;
741  }
742 }
743 
744 void KACLListView::setACL( const KACL &acl )
745 {
746  if ( !acl.isValid() ) return;
747  // Remove any entries left over from displaying a previous ACL
748  m_ACL = acl;
749  fillItemsFromACL( m_ACL );
750 
751  m_mask = acl.maskPermissions( m_hasMask );
752  calculateEffectiveRights();
753 }
754 
755 void KACLListView::setDefaultACL( const KACL &acl )
756 {
757  if ( !acl.isValid() ) return;
758  m_defaultACL = acl;
759  fillItemsFromACL( m_defaultACL, true );
760  calculateEffectiveRights();
761 }
762 
763 KACL KACLListView::itemsToACL( bool defaults ) const
764 {
765  KACL newACL( 0 );
766  bool atLeastOneEntry = false;
767  ACLUserPermissionsList users;
768  ACLGroupPermissionsList groups;
769  QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
770  while ( QTreeWidgetItem* qlvi = *it ) {
771  ++it;
772  const KACLListViewItem* item = static_cast<KACLListViewItem*>( qlvi );
773  if ( item->isDefault != defaults ) continue;
774  atLeastOneEntry = true;
775  switch ( item->type ) {
776  case User:
777  newACL.setOwnerPermissions( item->value );
778  break;
779  case Group:
780  newACL.setOwningGroupPermissions( item->value );
781  break;
782  case Others:
783  newACL.setOthersPermissions( item->value );
784  break;
785  case Mask:
786  newACL.setMaskPermissions( item->value );
787  break;
788  case NamedUser:
789  users.append( qMakePair( item->text( 1 ), item->value ) );
790  break;
791  case NamedGroup:
792  groups.append( qMakePair( item->text( 1 ), item->value ) );
793  break;
794  default:
795  break;
796  }
797  }
798  if ( atLeastOneEntry ) {
799  newACL.setAllUserPermissions( users );
800  newACL.setAllGroupPermissions( groups );
801  if ( newACL.isValid() )
802  return newACL;
803  }
804  return KACL();
805 }
806 
807 KACL KACLListView::getACL()
808 {
809  return itemsToACL( false );
810 }
811 
812 
813 KACL KACLListView::getDefaultACL()
814 {
815  return itemsToACL( true );
816 }
817 
818 void KACLListView::contentsMousePressEvent( QMouseEvent * /*e*/ )
819 {
820  /*
821  QTreeWidgetItem *clickedItem = itemAt( e->pos() );
822  if ( !clickedItem ) return;
823  // if the click is on an as yet unselected item, select it first
824  if ( !clickedItem->isSelected() )
825  QAbstractItemView::contentsMousePressEvent( e );
826 
827  if ( !currentItem() ) return;
828  int column = header()->sectionAt( e->x() );
829  acl_perm_t perm;
830  switch ( column )
831  {
832  case 2:
833  perm = ACL_READ;
834  break;
835  case 3:
836  perm = ACL_WRITE;
837  break;
838  case 4:
839  perm = ACL_EXECUTE;
840  break;
841  default:
842  return QTreeWidget::contentsMousePressEvent( e );
843  }
844  KACLListViewItem* referenceItem = static_cast<KACLListViewItem*>( clickedItem );
845  unsigned short referenceHadItSet = referenceItem->value & perm;
846  QTreeWidgetItemIterator it( this );
847  while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
848  ++it;
849  if ( !item->isSelected() ) continue;
850  // toggle those with the same value as the clicked item, leave the others
851  if ( referenceHadItSet == ( item->value & perm ) )
852  item->togglePerm( perm );
853  }
854  */
855 }
856 
857 void KACLListView::slotItemClicked( QTreeWidgetItem* pItem, int col )
858 {
859  if ( !pItem ) return;
860 
861  QTreeWidgetItemIterator it( this );
862  while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
863  ++it;
864  if ( !item->isSelected() ) continue;
865  switch ( col )
866  {
867  case 2:
868  item->togglePerm( ACL_READ );
869  break;
870  case 3:
871  item->togglePerm( ACL_WRITE );
872  break;
873  case 4:
874  item->togglePerm( ACL_EXECUTE );
875  break;
876 
877  default:
878  ; // Do nothing
879  }
880  }
881  /*
882  // Has the user changed one of the required entries in a default ACL?
883  if ( m_pACL->aclType() == ACL_TYPE_DEFAULT &&
884  ( col == 2 || col == 3 || col == 4 ) &&
885  ( pACLItem->entryType() == ACL_USER_OBJ ||
886  pACLItem->entryType() == ACL_GROUP_OBJ ||
887  pACLItem->entryType() == ACL_OTHER ) )
888  {
889  // Mark the required entries as no longer being partial entries.
890  // That is, they will get applied to all selected directories.
891  KACLListViewItem* pUserObj = findACLEntryByType( this, ACL_USER_OBJ );
892  pUserObj->entry()->setPartialEntry( false );
893 
894  KACLListViewItem* pGroupObj = findACLEntryByType( this, ACL_GROUP_OBJ );
895  pGroupObj->entry()->setPartialEntry( false );
896 
897  KACLListViewItem* pOther = findACLEntryByType( this, ACL_OTHER );
898  pOther->entry()->setPartialEntry( false );
899 
900  update();
901  }
902  */
903 }
904 
905 
906 void KACLListView::calculateEffectiveRights()
907 {
908  QTreeWidgetItemIterator it( this );
909  KACLListViewItem* pItem;
910  while ( ( pItem = dynamic_cast<KACLListViewItem*>( *it ) ) != 0 )
911  {
912  ++it;
913  pItem->calcEffectiveRights();
914  }
915 }
916 
917 
918 unsigned short KACLListView::maskPermissions() const
919 {
920  return m_mask;
921 }
922 
923 
924 void KACLListView::setMaskPermissions( unsigned short maskPerms )
925 {
926  m_mask = maskPerms;
927  calculateEffectiveRights();
928 }
929 
930 
931 acl_perm_t KACLListView::maskPartialPermissions() const
932 {
933  // return m_pMaskEntry->m_partialPerms;
934  return 0;
935 }
936 
937 
938 void KACLListView::setMaskPartialPermissions( acl_perm_t /*maskPartialPerms*/ )
939 {
940  //m_pMaskEntry->m_partialPerms = maskPartialPerms;
941  calculateEffectiveRights();
942 }
943 
944 bool KACLListView::hasDefaultEntries() const
945 {
946  QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
947  while ( *it ) {
948  const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
949  ++it;
950  if ( item->isDefault ) return true;
951  }
952  return false;
953 }
954 
955 const KACLListViewItem* KACLListView::findDefaultItemByType( EntryType type ) const
956 {
957  return findItemByType( type, true );
958 }
959 
960 const KACLListViewItem* KACLListView::findItemByType( EntryType type, bool defaults ) const
961 {
962  QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
963  while ( *it ) {
964  const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
965  ++it;
966  if ( item->isDefault == defaults && item->type == type ) {
967  return item;
968  }
969  }
970  return 0;
971 }
972 
973 
974 unsigned short KACLListView::calculateMaskValue( bool defaults ) const
975 {
976  // KACL auto-adds the relevant maks entries, so we can simply query
977  bool dummy;
978  return itemsToACL( defaults ).maskPermissions( dummy );
979 }
980 
981 void KACLListView::slotAddEntry()
982 {
983  int allowedTypes = NamedUser | NamedGroup;
984  if ( !m_hasMask )
985  allowedTypes |= Mask;
986  int allowedDefaultTypes = NamedUser | NamedGroup;
987  if ( !findDefaultItemByType( Mask ) )
988  allowedDefaultTypes |= Mask;
989  if ( !hasDefaultEntries() )
990  allowedDefaultTypes |= User | Group;
991  EditACLEntryDialog dlg( this, 0,
992  allowedUsers( false ), allowedGroups( false ),
993  allowedUsers( true ), allowedGroups( true ),
994  allowedTypes, allowedDefaultTypes, m_allowDefaults );
995  dlg.exec();
996  KACLListViewItem *item = dlg.item();
997  if ( !item ) return; // canceled
998  if ( item->type == Mask && !item->isDefault ) {
999  m_hasMask = true;
1000  m_mask = item->value;
1001  }
1002  if ( item->isDefault && !hasDefaultEntries() ) {
1003  // first default entry, fill in what is needed
1004  if ( item->type != User ) {
1005  unsigned short v = findDefaultItemByType( User )->value;
1006  new KACLListViewItem( this, User, v, true );
1007  }
1008  if ( item->type != Group ) {
1009  unsigned short v = findDefaultItemByType( Group )->value;
1010  new KACLListViewItem( this, Group, v, true );
1011  }
1012  if ( item->type != Others ) {
1013  unsigned short v = findDefaultItemByType( Others )->value;
1014  new KACLListViewItem( this, Others, v, true );
1015  }
1016  }
1017  const KACLListViewItem *defaultMaskItem = findDefaultItemByType( Mask );
1018  if ( item->isDefault && !defaultMaskItem ) {
1019  unsigned short v = calculateMaskValue( true );
1020  new KACLListViewItem( this, Mask, v, true );
1021  }
1022  if ( !item->isDefault && !m_hasMask &&
1023  ( item->type == Group
1024  || item->type == NamedUser
1025  || item->type == NamedGroup ) ) {
1026  // auto-add a mask entry
1027  unsigned short v = calculateMaskValue( false );
1028  new KACLListViewItem( this, Mask, v, false );
1029  m_hasMask = true;
1030  m_mask = v;
1031  }
1032  calculateEffectiveRights();
1033  sortItems( sortColumn(), Qt::AscendingOrder );
1034  setCurrentItem( item );
1035  // QTreeWidget doesn't seem to emit, in this case, and we need to update
1036  // the buttons...
1037  if ( topLevelItemCount() == 1 )
1038  emit currentItemChanged( item, item );
1039 }
1040 
1041 void KACLListView::slotEditEntry()
1042 {
1043  QTreeWidgetItem * current = currentItem();
1044  if ( !current ) return;
1045  KACLListViewItem *item = static_cast<KACLListViewItem*>( current );
1046  int allowedTypes = item->type | NamedUser | NamedGroup;
1047  bool itemWasMask = item->type == Mask;
1048  if ( !m_hasMask || itemWasMask )
1049  allowedTypes |= Mask;
1050  int allowedDefaultTypes = item->type | NamedUser | NamedGroup;
1051  if ( !findDefaultItemByType( Mask ) )
1052  allowedDefaultTypes |= Mask;
1053  if ( !hasDefaultEntries() )
1054  allowedDefaultTypes |= User | Group;
1055 
1056  EditACLEntryDialog dlg( this, item,
1057  allowedUsers( false, item ), allowedGroups( false, item ),
1058  allowedUsers( true, item ), allowedGroups( true, item ),
1059  allowedTypes, allowedDefaultTypes, m_allowDefaults );
1060  dlg.exec();
1061  if ( itemWasMask && item->type != Mask ) {
1062  m_hasMask = false;
1063  m_mask = 0;
1064  }
1065  if ( !itemWasMask && item->type == Mask ) {
1066  m_mask = item->value;
1067  m_hasMask = true;
1068  }
1069  calculateEffectiveRights();
1070  sortItems( sortColumn(), Qt::AscendingOrder );
1071 }
1072 
1073 void KACLListView::slotRemoveEntry()
1074 {
1075  QTreeWidgetItemIterator it( this, QTreeWidgetItemIterator::Selected );
1076  while ( *it ) {
1077  KACLListViewItem *item = static_cast<KACLListViewItem*>( *it );
1078  ++it;
1079  /* First check if it's a mask entry and if so, make sure that there is
1080  * either no name user or group entry, which means the mask can be
1081  * removed, or don't remove it, but reset it. That is allowed. */
1082  if ( item->type == Mask ) {
1083  bool itemWasDefault = item->isDefault;
1084  if ( !itemWasDefault && maskCanBeDeleted() ) {
1085  m_hasMask= false;
1086  m_mask = 0;
1087  delete item;
1088  } else if ( itemWasDefault && defaultMaskCanBeDeleted() ) {
1089  delete item;
1090  } else {
1091  item->value = 0;
1092  item->repaint();
1093  }
1094  if ( !itemWasDefault )
1095  calculateEffectiveRights();
1096  } else {
1097  // for the base permissions, disable them, which is what libacl does
1098  if ( !item->isDefault &&
1099  ( item->type == User
1100  || item->type == Group
1101  || item->type == Others ) ) {
1102  item->value = 0;
1103  item->repaint();
1104  } else {
1105  delete item;
1106  }
1107  }
1108  }
1109 }
1110 
1111 bool KACLListView::maskCanBeDeleted() const
1112 {
1113  return !findItemByType( NamedUser ) && !findItemByType( NamedGroup );
1114 }
1115 
1116 bool KACLListView::defaultMaskCanBeDeleted() const
1117 {
1118  return !findDefaultItemByType( NamedUser ) && !findDefaultItemByType( NamedGroup );
1119 }
1120 
1121 #include "kacleditwidget.moc"
1122 #include "kacleditwidget_p.moc"
1123 #endif
1124 // vim:set ts=8 sw=4:
QColor
kdialog.h
Group
i18n
QString i18n(const char *text)
header
const char header[]
kdebug.h
QTreeWidget
KACL::ownerPermissions
unsigned short ownerPermissions() const
The standard (non-extended) part of an ACL.
Definition: kacl.cpp:207
group
mask
#define mask
label
QString label(StandardShortcut id)
QWidget
KACL::allGroupPermissions
ACLGroupPermissionsList allGroupPermissions() const
Returns the list of all group permission entries.
Definition: kacl.cpp:553
QPushButton
KDialog
QString
I18N_NOOP
#define I18N_NOOP(x)
KACL::isValid
bool isValid() const
Returns whether the KACL object represents a valid acl.
Definition: kacl.cpp:120
klocale.h
kacleditwidget.h
i18nc
QString i18nc(const char *ctxt, const char *text)
QStringList
QGroupBox
kvbox.h
KACL::owningGroupPermissions
unsigned short owningGroupPermissions() const
Definition: kacl.cpp:226
kacleditwidget_p.h
KACL::maskPermissions
unsigned short maskPermissions(bool &exists) const
Return the entry for the permissions mask if there is one and sets exists to true.
Definition: kacl.cpp:281
QFont
KACL
The KACL class encapsulates a POSIX Access Control List.
Definition: kacl.h:47
KACL::othersPermissions
unsigned short othersPermissions() const
Definition: kacl.cpp:245
khbox.h
QLabel
ACLUserPermissionsConstIterator
QList< ACLUserPermissions >::const_iterator ACLUserPermissionsConstIterator
Definition: kacl.h:34
KComboBox
KACL::allUserPermissions
ACLUserPermissionsList allUserPermissions() const
Returns the list of all group permission entries.
Definition: kacl.cpp:415
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QSize
KHBox
KACL::setACL
bool setACL(const QString &aclStr)
Sets the whole list from a string.
Definition: kacl.cpp:590
kfileitem.h
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:50:02 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal