• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

kacleditwidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Sean Harmer <sh@rama.homelinux.org>             *
00003  *                         Till Adam <adam@kde.org>                        *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Library General Public License as       *
00007  *   published by  the Free Software Foundation; either version 2 of the   *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
00019  ***************************************************************************/
00020 
00021 
00022 #include "kacleditwidget.h"
00023 #include "kacleditwidget_p.h"
00024 
00025 #ifdef USE_POSIX_ACL
00026 
00027 #include <qpainter.h>
00028 #include <qptrlist.h>
00029 #include <qvbox.h>
00030 #include <qhbox.h>
00031 #include <qpushbutton.h>
00032 #include <qvbuttongroup.h>
00033 #include <qradiobutton.h>
00034 #include <qcombobox.h>
00035 #include <qlabel.h>
00036 #include <qcheckbox.h>
00037 #include <qlayout.h>
00038 #include <qwidgetstack.h>
00039 #include <qheader.h>
00040 
00041 #include <klocale.h>
00042 #include <kfileitem.h>
00043 #include <kdebug.h>
00044 #include <kdialog.h>
00045 #include <kdialogbase.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 #include "images.h"
00057 
00058 static struct {
00059     const char* label;
00060     const char* pixmapName;
00061     QPixmap* pixmap;
00062 } s_itemAttributes[] = {
00063     { I18N_NOOP( "Owner" ), "user-grey", 0 },
00064     { I18N_NOOP( "Owning Group" ), "group-grey", 0 },
00065     { I18N_NOOP( "Others" ), "others-grey", 0 },
00066     { I18N_NOOP( "Mask" ), "mask", 0 },
00067     { I18N_NOOP( "Named User" ), "user", 0 },
00068     { I18N_NOOP( "Named Group" ), "group", 0 },
00069 };
00070 
00071 KACLEditWidget::KACLEditWidget( QWidget *parent, const char *name )
00072    :QWidget( parent, name )
00073 {
00074     QHBox *hbox = new QHBox( parent );
00075     hbox->setSpacing(  KDialog::spacingHint() );
00076     m_listView = new KACLListView( hbox, "acl_listview" );
00077     connect( m_listView, SIGNAL( selectionChanged() ),
00078             this, SLOT( slotUpdateButtons() ) );
00079     QVBox *vbox = new QVBox( hbox );
00080     vbox->setSpacing(  KDialog::spacingHint() );
00081     m_AddBtn = new QPushButton( i18n( "Add Entry..." ), vbox, "add_entry_button" );
00082     connect( m_AddBtn, SIGNAL( clicked() ), m_listView, SLOT( slotAddEntry() ) );
00083     m_EditBtn = new QPushButton( i18n( "Edit Entry..." ), vbox, "edit_entry_button" );
00084     connect( m_EditBtn, SIGNAL( clicked() ), m_listView, SLOT( slotEditEntry() ) );
00085     m_DelBtn = new QPushButton( i18n( "Delete Entry" ), vbox, "delete_entry_button" );
00086     connect( m_DelBtn, SIGNAL( clicked() ), m_listView, SLOT( slotRemoveEntry() ) );
00087     QWidget *spacer = new QWidget( vbox );
00088     spacer->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding );
00089     slotUpdateButtons();
00090 }
00091 
00092 void KACLEditWidget::slotUpdateButtons()
00093 {
00094     bool atLeastOneIsNotDeletable = false;
00095     bool atLeastOneIsNotAllowedToChangeType = false;
00096     int selectedCount = 0;
00097     QListViewItemIterator it( m_listView, QListViewItemIterator::Selected );
00098     while ( KACLListViewItem *item = dynamic_cast<KACLListViewItem*>( it.current() ) ) {
00099         ++it; ++selectedCount;
00100         if ( !item->isDeletable() )
00101             atLeastOneIsNotDeletable = true;
00102         if ( !item->isAllowedToChangeType() )
00103             atLeastOneIsNotAllowedToChangeType = true;
00104     }
00105     m_EditBtn->setEnabled( selectedCount && !atLeastOneIsNotAllowedToChangeType );
00106     m_DelBtn->setEnabled( selectedCount && !atLeastOneIsNotDeletable );
00107 }
00108 
00109 KACL KACLEditWidget::getACL() const
00110 {
00111   return m_listView->getACL();
00112 }
00113 
00114 KACL KACLEditWidget::getDefaultACL() const
00115 {
00116   return m_listView->getDefaultACL();
00117 }
00118 
00119 void KACLEditWidget::setACL( const KACL &acl )
00120 {
00121   return m_listView->setACL( acl );
00122 }
00123 
00124 void KACLEditWidget::setDefaultACL( const KACL &acl )
00125 {
00126   return m_listView->setDefaultACL( acl );
00127 }
00128 
00129 void KACLEditWidget::setAllowDefaults( bool value )
00130 {
00131     m_listView->setAllowDefaults( value );
00132 }
00133 
00134 void KACLEditWidget::setReadOnly( bool on )
00135 {
00136     m_listView->setEnabled( !on );
00137     m_AddBtn->setEnabled( !on );
00138     if ( !on )
00139       slotUpdateButtons();
00140 }
00141 
00142 KACLListViewItem::KACLListViewItem( QListView* parent,
00143                                     KACLListView::EntryType _type,
00144                                     unsigned short _value, bool defaults,
00145                                     const QString& _qualifier )
00146  : KListViewItem( parent, parent->lastItem() ), // we want to append
00147    type( _type ), value( _value ), isDefault( defaults ),
00148    qualifier( _qualifier ), isPartial( false )
00149 {
00150     m_pACLListView = dynamic_cast<KACLListView*>( parent );
00151     repaint();
00152 }
00153 
00154 
00155 KACLListViewItem::~ KACLListViewItem()
00156 {
00157 
00158 }
00159 
00160 QString KACLListViewItem::key( int, bool ) const
00161 {
00162     QString key;
00163     if ( !isDefault )
00164         key = "A";
00165     else
00166         key = "B";
00167     switch ( type )
00168     {
00169         case KACLListView::User:
00170             key += "A";
00171             break;
00172         case KACLListView::Group:
00173             key += "B";
00174             break;
00175         case KACLListView::Others:
00176             key += "C";
00177             break;
00178         case KACLListView::Mask:
00179             key += "D";
00180             break;
00181         case KACLListView::NamedUser:
00182             key += "E" + text( 1 );
00183             break;
00184         case KACLListView::NamedGroup:
00185             key += "F" + text( 1 );
00186             break;
00187         default:
00188             key += text( 0 );
00189             break;
00190     }
00191     return key;
00192 }
00193 
00194 void KACLListViewItem::paintCell( QPainter* p, const QColorGroup &cg,
00195                                   int column, int width, int alignment )
00196 {
00197     QColorGroup mycg = cg;
00198     if ( isDefault ) {
00199         mycg.setColor( QColorGroup::Text, QColor( 0, 0, 255 ) );
00200     }
00201     if ( isPartial ) {
00202         QFont font = p->font();
00203         font.setItalic( true );
00204         mycg.setColor( QColorGroup::Text, QColor( 100, 100, 100 ) );
00205         p->setFont( font );
00206     }
00207     KListViewItem::paintCell( p, mycg, column, width, alignment );
00208 
00209     KACLListViewItem *below =0;
00210     if ( itemBelow() )
00211         below = static_cast<KACLListViewItem*>( itemBelow() );
00212     const bool lastUser = type == KACLListView::NamedUser && below && below->type == KACLListView::NamedGroup;
00213     const bool lastNonDefault = !isDefault && below && below->isDefault;
00214     if ( type == KACLListView::Mask || lastUser || lastNonDefault )
00215     {
00216         p->setPen( QPen( Qt::gray, 0, QPen::DotLine ) );
00217         if ( type == KACLListView::Mask )
00218             p->drawLine( 0, 0, width - 1, 0 );
00219         p->drawLine( 0, height() - 1, width - 1, height() - 1 );
00220     }
00221 }
00222 
00223 
00224 void KACLListViewItem::updatePermPixmaps()
00225 {
00226     unsigned int partialPerms = value;
00227 
00228     if ( value & ACL_READ )
00229         setPixmap( 2, m_pACLListView->getYesPixmap() );
00230     else if ( partialPerms & ACL_READ )
00231         setPixmap( 2, m_pACLListView->getYesPartialPixmap() );
00232     else
00233         setPixmap( 2, QPixmap() );
00234 
00235     if ( value & ACL_WRITE )
00236         setPixmap( 3, m_pACLListView->getYesPixmap() );
00237     else if ( partialPerms & ACL_WRITE )
00238         setPixmap( 3, m_pACLListView->getYesPartialPixmap() );
00239     else
00240         setPixmap( 3, QPixmap() );
00241 
00242     if ( value & ACL_EXECUTE )
00243         setPixmap( 4, m_pACLListView->getYesPixmap() );
00244     else if ( partialPerms & ACL_EXECUTE )
00245         setPixmap( 4, m_pACLListView->getYesPartialPixmap() );
00246     else
00247         setPixmap( 4, QPixmap() );
00248 }
00249 
00250 void KACLListViewItem::repaint()
00251 {
00252     int idx = 0;
00253     switch ( type )
00254     {
00255       case KACLListView::User:
00256           idx = KACLListView::OWNER_IDX;
00257             break;
00258         case KACLListView::Group:
00259           idx = KACLListView::GROUP_IDX;
00260             break;
00261         case KACLListView::Others:
00262           idx = KACLListView::OTHERS_IDX;
00263             break;
00264         case KACLListView::Mask:
00265           idx = KACLListView::MASK_IDX;
00266             break;
00267         case KACLListView::NamedUser:
00268           idx = KACLListView::NAMED_USER_IDX;
00269             break;
00270         case KACLListView::NamedGroup:
00271           idx = KACLListView::NAMED_GROUP_IDX;
00272             break;
00273         default:
00274           idx = KACLListView::OWNER_IDX;
00275             break;
00276     }
00277     setText( 0, i18n(s_itemAttributes[idx].label) );
00278     setPixmap( 0, *s_itemAttributes[idx].pixmap );
00279     if ( isDefault )
00280         setText( 0, text( 0 ) + i18n( " (Default)" ) );
00281     setText( 1, qualifier );
00282     // Set the pixmaps for which of the perms are set
00283     updatePermPixmaps();
00284 }
00285 
00286 void KACLListViewItem::calcEffectiveRights()
00287 {
00288     QString strEffective = QString( "---" );
00289 
00290     // Do we need to worry about the mask entry? It applies to named users,
00291     // owning group, and named groups
00292     if ( m_pACLListView->hasMaskEntry()
00293             && ( type == KACLListView::NamedUser
00294               || type == KACLListView::Group
00295               || type == KACLListView::NamedGroup ) 
00296             && !isDefault )
00297     {
00298 
00299         strEffective[0] = ( m_pACLListView->maskPermissions() & value & ACL_READ ) ? 'r' : '-';
00300         strEffective[1] = ( m_pACLListView->maskPermissions() & value & ACL_WRITE ) ? 'w' : '-';
00301         strEffective[2] = ( m_pACLListView->maskPermissions() & value & ACL_EXECUTE ) ? 'x' : '-';
00302 /*
00303         // What about any partial perms?
00304         if ( maskPerms & partialPerms & ACL_READ || // Partial perms on entry
00305              maskPartialPerms & perms & ACL_READ || // Partial perms on mask
00306              maskPartialPerms & partialPerms & ACL_READ ) // Partial perms on mask and entry
00307             strEffective[0] = 'R';
00308         if ( maskPerms & partialPerms & ACL_WRITE || // Partial perms on entry
00309              maskPartialPerms & perms & ACL_WRITE || // Partial perms on mask
00310              maskPartialPerms & partialPerms & ACL_WRITE ) // Partial perms on mask and entry
00311             strEffective[1] = 'W';
00312         if ( maskPerms & partialPerms & ACL_EXECUTE || // Partial perms on entry
00313              maskPartialPerms & perms & ACL_EXECUTE || // Partial perms on mask
00314              maskPartialPerms & partialPerms & ACL_EXECUTE ) // Partial perms on mask and entry
00315             strEffective[2] = 'X';
00316 */
00317     }
00318     else
00319     {
00320         // No, the effective value are just the value in this entry
00321         strEffective[0] = ( value & ACL_READ ) ? 'r' : '-';
00322         strEffective[1] = ( value & ACL_WRITE ) ? 'w' : '-';
00323         strEffective[2] = ( value & ACL_EXECUTE ) ? 'x' : '-';
00324 
00325         /*
00326         // What about any partial perms?
00327         if ( partialPerms & ACL_READ )
00328             strEffective[0] = 'R';
00329         if ( partialPerms & ACL_WRITE )
00330             strEffective[1] = 'W';
00331         if ( partialPerms & ACL_EXECUTE )
00332             strEffective[2] = 'X';
00333             */
00334     }
00335     setText( 5, strEffective );
00336 }
00337 
00338 bool KACLListViewItem::isDeletable() const
00339 {
00340     bool isMaskAndDeletable = false;
00341     if (type == KACLListView::Mask ) {
00342         if ( !isDefault &&  m_pACLListView->maskCanBeDeleted() )
00343             isMaskAndDeletable = true;
00344         else if ( isDefault &&  m_pACLListView->defaultMaskCanBeDeleted() )
00345             isMaskAndDeletable = true;
00346     }
00347     return type != KACLListView::User &&
00348            type != KACLListView::Group &&
00349            type != KACLListView::Others &&
00350            ( type != KACLListView::Mask || isMaskAndDeletable );
00351 }
00352 
00353 bool KACLListViewItem::isAllowedToChangeType() const
00354 {
00355     return type != KACLListView::User &&
00356            type != KACLListView::Group &&
00357            type != KACLListView::Others &&
00358            type != KACLListView::Mask;
00359 }
00360 
00361 void KACLListViewItem::togglePerm( acl_perm_t perm )
00362 {
00363     value ^= perm; // Toggle the perm
00364     if ( type == KACLListView::Mask && !isDefault ) {
00365         m_pACLListView->setMaskPermissions( value );
00366     }
00367     calcEffectiveRights();
00368     updatePermPixmaps();
00369 /*
00370     // If the perm is in the partial perms then remove it. i.e. Once
00371     // a user changes a partial perm it then applies to all selected files.
00372     if ( m_pEntry->m_partialPerms & perm )
00373         m_pEntry->m_partialPerms ^= perm;
00374 
00375     m_pEntry->setPartialEntry( false );
00376     // Make sure that all entries have their effective rights calculated if
00377     // we are changing the ACL_MASK entry.
00378     if ( type == Mask )
00379     {
00380         m_pACLListView->setMaskPartialPermissions( m_pEntry->m_partialPerms );
00381         m_pACLListView->setMaskPermissions( value );
00382         m_pACLListView->calculateEffectiveRights();
00383     }
00384 */
00385 }
00386 
00387 
00388 
00389 EditACLEntryDialog::EditACLEntryDialog( KACLListView *listView, KACLListViewItem *item,
00390                                         const QStringList &users,
00391                                         const QStringList &groups,
00392                                         const QStringList &defaultUsers,
00393                                         const QStringList &defaultGroups,
00394                                         int allowedTypes, int allowedDefaultTypes,
00395                                         bool allowDefaults )
00396       : KDialogBase( listView, "edit_entry_dialog", true,
00397               i18n( "Edit ACL Entry" ), KDialogBase::Ok|KDialogBase::Cancel,
00398               KDialogBase::Ok, false ), 
00399         m_listView( listView ), m_item( item ), m_users( users ), m_groups( groups ),
00400         m_defaultUsers( defaultUsers ), m_defaultGroups( defaultGroups ),
00401         m_allowedTypes( allowedTypes ), m_allowedDefaultTypes( allowedDefaultTypes ),
00402         m_defaultCB( 0 )
00403 {
00404     QWidget *page = new QWidget(  this );
00405     setMainWidget( page );
00406     QVBoxLayout *mainLayout = new QVBoxLayout( page, 0, spacingHint(), "mainLayout" );
00407     m_buttonGroup = new QVButtonGroup( i18n("Entry Type"), page, "bg" );
00408 
00409     if ( allowDefaults ) {
00410         m_defaultCB = new QCheckBox( i18n("Default for new files in this folder"), page, "defaultCB" );
00411         mainLayout->addWidget( m_defaultCB );
00412         connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00413                  this, SLOT( slotUpdateAllowedUsersAndGroups() ) );
00414         connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00415                  this, SLOT( slotUpdateAllowedTypes() ) );
00416 
00417     }
00418 
00419     mainLayout->addWidget( m_buttonGroup );
00420 
00421     QRadioButton *ownerType = new QRadioButton( i18n("Owner"), m_buttonGroup, "ownerType" );
00422     m_buttonGroup->insert( ownerType, KACLListView::User );
00423     QRadioButton *owningGroupType = new QRadioButton( i18n("Owning Group"), m_buttonGroup, "owningGroupType" );
00424     m_buttonGroup->insert( owningGroupType, KACLListView::Group );
00425     QRadioButton *othersType = new QRadioButton( i18n("Others"), m_buttonGroup, "othersType" );
00426     m_buttonGroup->insert( othersType, KACLListView::Others );
00427     QRadioButton *maskType = new QRadioButton( i18n("Mask"), m_buttonGroup, "maskType" );
00428     m_buttonGroup->insert( maskType, KACLListView::Mask );
00429     QRadioButton *namedUserType = new QRadioButton( i18n("Named User"), m_buttonGroup, "namesUserType" );
00430     m_buttonGroup->insert( namedUserType, KACLListView::NamedUser );
00431     QRadioButton *namedGroupType = new QRadioButton( i18n("Named Group"), m_buttonGroup, "namedGroupType" );
00432     m_buttonGroup->insert( namedGroupType, KACLListView::NamedGroup );
00433 
00434     connect( m_buttonGroup, SIGNAL( clicked( int ) ),
00435              this, SLOT( slotSelectionChanged( int ) ) );
00436 
00437     m_widgetStack = new QWidgetStack( page );
00438     mainLayout->addWidget( m_widgetStack );
00439 
00440     QHBox *usersBox = new QHBox( m_widgetStack );
00441     m_widgetStack->addWidget( usersBox, KACLListView::NamedUser );
00442 
00443     QHBox *groupsBox = new QHBox( m_widgetStack );
00444     m_widgetStack->addWidget( groupsBox, KACLListView::NamedGroup );
00445 
00446     QLabel *usersLabel = new QLabel( i18n( "User: " ), usersBox );
00447     m_usersCombo = new QComboBox( false, usersBox, "users" );
00448     usersLabel->setBuddy( m_usersCombo );
00449 
00450     QLabel *groupsLabel = new QLabel( i18n( "Group: " ), groupsBox );
00451     m_groupsCombo = new QComboBox( false, groupsBox, "groups" );
00452     groupsLabel->setBuddy( m_groupsCombo );
00453 
00454     if ( m_item ) {
00455         m_buttonGroup->setButton( m_item->type );
00456         if ( m_defaultCB )
00457             m_defaultCB->setChecked( m_item->isDefault );
00458         slotUpdateAllowedTypes();
00459         slotSelectionChanged( m_item->type );
00460         slotUpdateAllowedUsersAndGroups();
00461         if ( m_item->type == KACLListView::NamedUser ) {
00462             m_usersCombo->setCurrentText( m_item->qualifier );
00463         } else if ( m_item->type == KACLListView::NamedGroup ) {
00464             m_groupsCombo->setCurrentText( m_item->qualifier );
00465         }
00466     } else {
00467         // new entry, preselect "named user", arguably the most common one
00468         m_buttonGroup->setButton( KACLListView::NamedUser );
00469         slotUpdateAllowedTypes();
00470         slotSelectionChanged( KACLListView::NamedUser );
00471         slotUpdateAllowedUsersAndGroups();
00472     }
00473     incInitialSize(  QSize( 100, 0 ) );
00474 }
00475 
00476 void EditACLEntryDialog::slotUpdateAllowedTypes()
00477 {
00478     int allowedTypes = m_allowedTypes;
00479     if ( m_defaultCB && m_defaultCB->isChecked() ) {
00480         allowedTypes = m_allowedDefaultTypes;
00481     }
00482     for ( int i=1; i < KACLListView::AllTypes; i=i*2 ) {
00483         if ( allowedTypes & i )
00484             m_buttonGroup->find( i )->show();
00485         else
00486             m_buttonGroup->find( i )->hide();
00487     }
00488 }
00489 
00490 void EditACLEntryDialog::slotUpdateAllowedUsersAndGroups()
00491 {
00492     const QString oldUser = m_usersCombo->currentText();
00493     const QString oldGroup = m_groupsCombo->currentText();
00494     m_usersCombo->clear();
00495     m_groupsCombo->clear();
00496     if ( m_defaultCB && m_defaultCB->isChecked() ) {
00497         m_usersCombo->insertStringList( m_defaultUsers );
00498         if ( m_defaultUsers.find( oldUser ) != m_defaultUsers.end() )
00499             m_usersCombo->setCurrentText( oldUser );
00500         m_groupsCombo->insertStringList( m_defaultGroups );
00501         if ( m_defaultGroups.find( oldGroup ) != m_defaultGroups.end() )
00502             m_groupsCombo->setCurrentText( oldGroup );
00503     } else {
00504         m_usersCombo->insertStringList( m_users );
00505         if ( m_users.find( oldUser ) != m_users.end() )
00506             m_usersCombo->setCurrentText( oldUser );
00507         m_groupsCombo->insertStringList( m_groups );
00508         if ( m_groups.find( oldGroup ) != m_groups.end() )
00509             m_groupsCombo->setCurrentText( oldGroup );
00510     }
00511 }
00512 void EditACLEntryDialog::slotOk()
00513 {
00514     KACLListView::EntryType type = static_cast<KACLListView::EntryType>( m_buttonGroup->selectedId() );
00515 
00516     QString qualifier;
00517     if ( type == KACLListView::NamedUser )
00518       qualifier = m_usersCombo->currentText();
00519     if ( type == KACLListView::NamedGroup )
00520       qualifier = m_groupsCombo->currentText();
00521 
00522     if ( !m_item ) {
00523         m_item = new KACLListViewItem( m_listView, type, ACL_READ | ACL_WRITE | ACL_EXECUTE, false, qualifier );
00524     } else {
00525         m_item->type = type;
00526         m_item->qualifier = qualifier;
00527     }
00528     if ( m_defaultCB )
00529         m_item->isDefault = m_defaultCB->isChecked();
00530     m_item->repaint();
00531 
00532     KDialogBase::slotOk();
00533 }
00534 
00535 void EditACLEntryDialog::slotSelectionChanged( int id )
00536 {
00537     switch ( id ) {
00538         case KACLListView::User:
00539         case KACLListView::Group:
00540         case KACLListView::Others:
00541         case KACLListView::Mask:
00542             m_widgetStack->setEnabled( false );
00543             break;
00544         case KACLListView::NamedUser:
00545             m_widgetStack->setEnabled( true );
00546             m_widgetStack->raiseWidget( KACLListView::NamedUser );
00547             break;
00548         case KACLListView::NamedGroup:
00549             m_widgetStack->setEnabled( true );
00550             m_widgetStack->raiseWidget( KACLListView::NamedGroup );
00551             break;
00552         default:
00553             break;
00554     }
00555 }
00556 
00557 
00558 KACLListView::KACLListView( QWidget* parent, const char* name )
00559  : KListView( parent, name ),
00560    m_hasMask( false ), m_allowDefaults( false )
00561 {
00562     // Add the columns
00563     addColumn( i18n( "Type" ) );
00564     addColumn( i18n( "Name" ) );
00565     addColumn( i18n( "read permission", "r" ) );
00566     addColumn( i18n( "write permission", "w" ) );
00567     addColumn( i18n( "execute permission", "x" ) );
00568     addColumn( i18n( "Effective" ) );
00569 
00570     header()->setClickEnabled( false );
00571 
00572     // Load the avatars
00573     for ( int i=0; i < LAST_IDX; ++i ) {
00574         s_itemAttributes[i].pixmap = new QPixmap( qembed_findImage( s_itemAttributes[i].pixmapName ) );
00575     }
00576     m_yesPixmap = new QPixmap( qembed_findImage( "yes" ) );
00577     m_yesPartialPixmap = new QPixmap( qembed_findImage( "yespartial" ) );
00578 
00579     setSelectionMode( QListView::Extended );
00580 
00581     // fill the lists of all legal users and groups
00582     struct passwd *user = 0;
00583     setpwent();
00584     while ( ( user = getpwent() ) != 0 ) {
00585        m_allUsers << QString::fromLatin1( user->pw_name );
00586     }
00587     endpwent();
00588 
00589     struct group *gr = 0;
00590     setgrent();
00591     while ( ( gr = getgrent() ) != 0 ) {
00592        m_allGroups << QString::fromLatin1( gr->gr_name );
00593     }
00594     endgrent();
00595     m_allUsers.sort();
00596     m_allGroups.sort();
00597 }
00598 
00599 
00600 KACLListView::~KACLListView()
00601 {
00602     for ( int i=0; i < LAST_IDX; ++i ) {
00603        delete s_itemAttributes[i].pixmap;
00604     }
00605     delete m_yesPixmap;
00606     delete m_yesPartialPixmap;
00607 }
00608 
00609 QStringList KACLListView::allowedUsers( bool defaults, KACLListViewItem *allowedItem )
00610 {
00611     QStringList allowedUsers = m_allUsers;
00612     QListViewItemIterator it( this );
00613     while ( it.current() ) {
00614         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00615         ++it;
00616         if ( !item->type == NamedUser || item->isDefault != defaults ) continue;
00617         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00618         allowedUsers.remove( item->qualifier );
00619     }
00620     return allowedUsers;
00621 }
00622 
00623 QStringList KACLListView::allowedGroups( bool defaults, KACLListViewItem *allowedItem )
00624 {
00625     QStringList allowedGroups = m_allGroups;
00626     QListViewItemIterator it( this );
00627     while ( it.current() ) {
00628         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00629         ++it;
00630         if ( !item->type == NamedGroup || item->isDefault != defaults ) continue;
00631         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00632         allowedGroups.remove( item->qualifier );
00633     }
00634     return allowedGroups;
00635 }
00636 
00637 void KACLListView::fillItemsFromACL( const KACL &pACL, bool defaults )
00638 {
00639     // clear out old entries of that ilk
00640     QListViewItemIterator it( this );
00641     while ( KACLListViewItem *item = static_cast<KACLListViewItem*>( it.current() ) ) {
00642         ++it;
00643         if ( item->isDefault == defaults )
00644             delete item;
00645     }
00646     KACLListViewItem *item =
00647         new KACLListViewItem( this, User, pACL.ownerPermissions(), defaults );
00648 
00649     item = new KACLListViewItem( this, Group, pACL.owningGroupPermissions(), defaults );
00650 
00651     item = new KACLListViewItem( this, Others, pACL.othersPermissions(), defaults );
00652 
00653     bool hasMask = false;
00654     unsigned short mask = pACL.maskPermissions( hasMask );
00655     if ( hasMask ) {
00656         item = new KACLListViewItem( this, Mask, mask, defaults );
00657     }
00658 
00659     // read all named user entries
00660     const ACLUserPermissionsList &userList =  pACL.allUserPermissions();
00661     ACLUserPermissionsConstIterator itu = userList.begin();
00662     while ( itu != userList.end() ) {
00663         new KACLListViewItem( this, NamedUser, (*itu).second, defaults, (*itu).first );
00664         ++itu;
00665     }
00666 
00667     // and now all named groups
00668     const ACLUserPermissionsList &groupList =  pACL.allGroupPermissions();
00669     ACLUserPermissionsConstIterator itg = groupList.begin();
00670     while ( itg != groupList.end() ) {
00671         new KACLListViewItem( this, NamedGroup, (*itg).second, defaults, (*itg).first );
00672         ++itg;
00673     }
00674 }
00675 
00676 void KACLListView::setACL( const KACL &acl )
00677 {
00678     if ( !acl.isValid() ) return;
00679     // Remove any entries left over from displaying a previous ACL
00680     m_ACL = acl;
00681     fillItemsFromACL( m_ACL );
00682 
00683     m_mask = acl.maskPermissions( m_hasMask );
00684     calculateEffectiveRights();
00685 }
00686 
00687 void KACLListView::setDefaultACL( const KACL &acl )
00688 {
00689     if ( !acl.isValid() ) return;
00690     m_defaultACL = acl;
00691     fillItemsFromACL( m_defaultACL, true );
00692     calculateEffectiveRights();
00693 }
00694 
00695 KACL KACLListView::itemsToACL( bool defaults ) const
00696 {
00697     KACL newACL( 0 );
00698     bool atLeastOneEntry = false;
00699     ACLUserPermissionsList users;
00700     ACLGroupPermissionsList groups;
00701     QListViewItemIterator it( const_cast<KACLListView*>( this ) );
00702     while ( QListViewItem* qlvi = it.current() ) {
00703         ++it;
00704         const KACLListViewItem* item = static_cast<KACLListViewItem*>( qlvi );
00705         if ( item->isDefault != defaults ) continue;
00706         atLeastOneEntry = true;
00707         switch ( item->type ) {
00708             case User:
00709                 newACL.setOwnerPermissions( item->value );
00710                 break;
00711             case Group:
00712                 newACL.setOwningGroupPermissions( item->value );
00713                 break;
00714             case Others:
00715                 newACL.setOthersPermissions( item->value );
00716                 break;
00717             case Mask:
00718                 newACL.setMaskPermissions( item->value );
00719                 break;
00720             case NamedUser:
00721                 users.append( qMakePair( item->text( 1 ), item->value ) );
00722                 break;
00723             case NamedGroup:
00724                 groups.append( qMakePair( item->text( 1 ), item->value ) );
00725                 break;
00726             default:
00727                 break;
00728         }
00729     }
00730     if ( atLeastOneEntry ) {
00731         newACL.setAllUserPermissions( users );
00732         newACL.setAllGroupPermissions( groups );
00733         if ( newACL.isValid() )
00734             return newACL;
00735     }
00736     return KACL();
00737 }
00738 
00739 KACL KACLListView::getACL()
00740 {
00741     return itemsToACL( false );
00742 }
00743 
00744 
00745 KACL KACLListView::getDefaultACL()
00746 {
00747     return itemsToACL( true );
00748 }
00749 
00750 void KACLListView::contentsMousePressEvent( QMouseEvent * e )
00751 {
00752     QListViewItem *clickedItem = itemAt( contentsToViewport(  e->pos() ) );
00753     if ( !clickedItem ) return;
00754     // if the click is on an as yet unselected item, select it first
00755     if ( !clickedItem->isSelected() )
00756         KListView::contentsMousePressEvent( e );
00757 
00758     if ( !currentItem() ) return;
00759     int column = header()->sectionAt( e->x() );
00760     acl_perm_t perm;
00761     switch ( column )
00762     {
00763         case 2:
00764             perm = ACL_READ;
00765             break;
00766         case 3:
00767             perm = ACL_WRITE;
00768             break;
00769         case 4:
00770             perm = ACL_EXECUTE;
00771             break;
00772         default:
00773             return KListView::contentsMousePressEvent( e );
00774     }
00775     KACLListViewItem* referenceItem = static_cast<KACLListViewItem*>( clickedItem );
00776     unsigned short referenceHadItSet = referenceItem->value & perm;
00777     QListViewItemIterator it( this );
00778     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( it.current() ) ) {
00779         ++it;
00780         if ( !item->isSelected() ) continue;
00781         // toggle those with the same value as the clicked item, leave the others
00782         if ( referenceHadItSet == ( item->value & perm ) )
00783             item->togglePerm( perm );
00784     }
00785 }
00786 
00787 void KACLListView::entryClicked( QListViewItem* pItem, const QPoint& /*pt*/, int col )
00788 {
00789     if ( !pItem ) return;
00790 
00791     QListViewItemIterator it( this );
00792     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( it.current() ) ) {
00793         ++it;
00794         if ( !item->isSelected() ) continue;
00795         switch ( col )
00796         {
00797             case 2:
00798                 item->togglePerm( ACL_READ );
00799                 break;
00800             case 3:
00801                 item->togglePerm( ACL_WRITE );
00802                 break;
00803             case 4:
00804                 item->togglePerm( ACL_EXECUTE );
00805                 break;
00806 
00807             default:
00808                 ; // Do nothing
00809         }
00810     }
00811     /*
00812     // Has the user changed one of the required entries in a default ACL?
00813     if ( m_pACL->aclType() == ACL_TYPE_DEFAULT &&
00814     ( col == 2 || col == 3 || col == 4 ) &&
00815     ( pACLItem->entryType() == ACL_USER_OBJ ||
00816     pACLItem->entryType() == ACL_GROUP_OBJ ||
00817     pACLItem->entryType() == ACL_OTHER ) )
00818     {
00819     // Mark the required entries as no longer being partial entries.
00820     // That is, they will get applied to all selected directories.
00821     KACLListViewItem* pUserObj = findACLEntryByType( this, ACL_USER_OBJ );
00822     pUserObj->entry()->setPartialEntry( false );
00823 
00824     KACLListViewItem* pGroupObj = findACLEntryByType( this, ACL_GROUP_OBJ );
00825     pGroupObj->entry()->setPartialEntry( false );
00826 
00827     KACLListViewItem* pOther = findACLEntryByType( this, ACL_OTHER );
00828     pOther->entry()->setPartialEntry( false );
00829 
00830     update();
00831     }
00832      */
00833 }
00834 
00835 
00836 void KACLListView::calculateEffectiveRights()
00837 {
00838     QListViewItemIterator it( this );
00839     KACLListViewItem* pItem;
00840     while ( ( pItem = dynamic_cast<KACLListViewItem*>( it.current() ) ) != 0 )
00841     {
00842         ++it;
00843         pItem->calcEffectiveRights();
00844     }
00845 }
00846 
00847 
00848 unsigned short KACLListView::maskPermissions() const
00849 {
00850   return m_mask;
00851 }
00852 
00853 
00854 void KACLListView::setMaskPermissions( unsigned short maskPerms )
00855 {
00856     m_mask = maskPerms;
00857     calculateEffectiveRights();
00858 }
00859 
00860 
00861 acl_perm_t KACLListView::maskPartialPermissions() const
00862 {
00863   //  return m_pMaskEntry->m_partialPerms;
00864   return 0;
00865 }
00866 
00867 
00868 void KACLListView::setMaskPartialPermissions( acl_perm_t /*maskPartialPerms*/ )
00869 {
00870     //m_pMaskEntry->m_partialPerms = maskPartialPerms;
00871     calculateEffectiveRights();
00872 }
00873 
00874 bool KACLListView::hasDefaultEntries() const
00875 {
00876     QListViewItemIterator it( const_cast<KACLListView*>( this ) );
00877     while ( it.current() ) {
00878         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( it.current() );
00879         ++it;
00880         if ( item->isDefault ) return true;
00881     }
00882     return false;
00883 }
00884 
00885 const KACLListViewItem* KACLListView::findDefaultItemByType( EntryType type ) const
00886 {
00887     return findItemByType( type, true );
00888 }
00889 
00890 const KACLListViewItem* KACLListView::findItemByType( EntryType type, bool defaults ) const
00891 {
00892     QListViewItemIterator it( const_cast<KACLListView*>( this ) );
00893     while ( it.current() ) {
00894         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( it.current() );
00895         ++it;
00896         if ( item->isDefault == defaults && item->type == type ) {
00897             return item;
00898         }
00899     }
00900     return 0;
00901 }
00902 
00903 
00904 unsigned short KACLListView::calculateMaskValue( bool defaults ) const
00905 {
00906     // KACL auto-adds the relevant maks entries, so we can simply query
00907     bool dummy;
00908     return itemsToACL( defaults ).maskPermissions( dummy );
00909 }
00910 
00911 void KACLListView::slotAddEntry()
00912 {
00913     int allowedTypes = NamedUser | NamedGroup;
00914     if ( !m_hasMask )
00915         allowedTypes |= Mask;
00916     int allowedDefaultTypes = NamedUser | NamedGroup;
00917     if ( !findDefaultItemByType( Mask ) )
00918         allowedDefaultTypes |=  Mask;
00919     if ( !hasDefaultEntries() )
00920         allowedDefaultTypes |= User | Group;
00921     EditACLEntryDialog dlg( this, 0,
00922                             allowedUsers( false ), allowedGroups( false ),
00923                             allowedUsers( true ), allowedGroups( true ),
00924                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
00925     dlg.exec();
00926     KACLListViewItem *item = dlg.item();
00927     if ( !item ) return; // canceled
00928     if ( item->type == Mask && !item->isDefault ) {
00929         m_hasMask = true;
00930         m_mask = item->value;
00931     }
00932     if ( item->isDefault && !hasDefaultEntries() ) {
00933         // first default entry, fill in what is needed
00934         if ( item->type != User ) {
00935             unsigned short v = findDefaultItemByType( User )->value;
00936             new KACLListViewItem( this, User, v, true );
00937         }
00938         if ( item->type != Group ) {
00939             unsigned short v = findDefaultItemByType( Group )->value;
00940             new KACLListViewItem( this, Group, v, true );
00941         }
00942         if ( item->type != Others ) {
00943             unsigned short v = findDefaultItemByType( Others )->value;
00944             new KACLListViewItem( this, Others, v, true );
00945         }
00946     }
00947     const KACLListViewItem *defaultMaskItem = findDefaultItemByType( Mask );
00948     if ( item->isDefault && !defaultMaskItem ) {
00949         unsigned short v = calculateMaskValue( true );
00950         new KACLListViewItem( this, Mask, v, true );
00951     }
00952     if ( !item->isDefault && !m_hasMask &&
00953             ( item->type == Group
00954               || item->type == NamedUser
00955               || item->type == NamedGroup ) ) {
00956         // auto-add a mask entry
00957         unsigned short v = calculateMaskValue( false );
00958         new KACLListViewItem( this, Mask, v, false );
00959         m_hasMask = true;
00960         m_mask = v;
00961     }
00962     calculateEffectiveRights();
00963     sort();
00964     setCurrentItem( item );
00965     // QListView doesn't seem to emit, in this case, and we need to update 
00966     // the buttons...
00967     if ( childCount() == 1 ) 
00968         emit currentChanged( item );
00969 }
00970 
00971 void KACLListView::slotEditEntry()
00972 {
00973     QListViewItem * current = currentItem();
00974     if ( !current ) return;
00975     KACLListViewItem *item = static_cast<KACLListViewItem*>( current );
00976     int allowedTypes = item->type | NamedUser | NamedGroup;
00977     bool itemWasMask = item->type == Mask;
00978     if ( !m_hasMask || itemWasMask )
00979         allowedTypes |= Mask;
00980     int allowedDefaultTypes = item->type | NamedUser | NamedGroup;
00981     if ( !findDefaultItemByType( Mask ) )
00982         allowedDefaultTypes |=  Mask;
00983     if ( !hasDefaultEntries() )
00984         allowedDefaultTypes |= User | Group;
00985 
00986     EditACLEntryDialog dlg( this, item,
00987                             allowedUsers( false, item ), allowedGroups( false, item ),
00988                             allowedUsers( true, item ), allowedGroups( true, item ),
00989                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
00990     dlg.exec();
00991     if ( itemWasMask && item->type != Mask ) {
00992         m_hasMask = false;
00993         m_mask = 0;
00994     }
00995     if ( !itemWasMask && item->type == Mask ) {
00996         m_mask = item->value;
00997         m_hasMask = true;
00998     }
00999     calculateEffectiveRights();
01000     sort();
01001 }
01002 
01003 void KACLListView::slotRemoveEntry()
01004 {
01005     QListViewItemIterator it( this, QListViewItemIterator::Selected );
01006     while ( it.current() ) {
01007         KACLListViewItem *item = static_cast<KACLListViewItem*>( it.current() );
01008         ++it;
01009         /* First check if it's a mask entry and if so, make sure that there is
01010          * either no name user or group entry, which means the mask can be 
01011          * removed, or don't remove it, but reset it. That is allowed. */
01012         if ( item->type == Mask ) {
01013             bool itemWasDefault = item->isDefault;
01014             if ( !itemWasDefault && maskCanBeDeleted() ) {
01015                 m_hasMask= false;
01016                 m_mask = 0;
01017                 delete item;
01018             } else if ( itemWasDefault && defaultMaskCanBeDeleted() ) {
01019                 delete item;
01020             } else {
01021                 item->value = 0;
01022                 item->repaint();
01023             }
01024             if ( !itemWasDefault )
01025                 calculateEffectiveRights();
01026         } else {
01027             // for the base permissions, disable them, which is what libacl does
01028             if ( !item->isDefault &&
01029                     ( item->type == User
01030                       || item->type == Group
01031                       || item->type == Others ) ) {
01032                 item->value = 0;
01033                 item->repaint();
01034             } else {
01035                 delete item;
01036             }
01037         }
01038     }
01039 }
01040 
01041 bool KACLListView::maskCanBeDeleted() const
01042 {
01043    return !findItemByType( NamedUser ) && !findItemByType( NamedGroup );
01044 }
01045 
01046 bool KACLListView::defaultMaskCanBeDeleted() const
01047 {
01048     return !findDefaultItemByType( NamedUser ) && !findDefaultItemByType( NamedGroup );
01049 }
01050 
01051 #include "kacleditwidget.moc"
01052 #include "kacleditwidget_p.moc"
01053 #endif
01054 // vim:set ts=8 sw=4:

kio

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal