Source Code (Use browser search to find items of interest.)

Class Index

kdelibs'FilePermissionsPropsPage (./kdelibs/kfile/kpropsdlg.h:319)

class FilePermissionsPropsPage : public PropsPage
{
  Q_OBJECT
public:
  /**
   * Constructor
   */
  FilePermissionsPropsPage( PropertiesDialog *_props );

  virtual QString tabName() const { return i18n("&Permissions"); }
  virtual void applyChanges();

  /**
   * Tests whether the file specified by _items needs a 'Permissions' page.
   */
  static bool supports( KFileItemList _items );

protected slots:

  void slotChmodResult( KIO::Job * );

protected:
  QCheckBox *permBox[3][4];

  QComboBox *grpCombo;
  KLineEdit *usrEdit, *grpEdit;

  /**
   * Old permissions
   */
  mode_t permissions;
  /**
   * Old group
   */
  QString strGroup;
  /**
   * Old owner
   */
  QString strOwner;

  /**
   * Changeable Permissions
   */
  static mode_t fperm[3][4];
};

/**
 * Used to edit the files containing
 * [Desktop Entry]
 * Type=Application
 *
 * Such files are used to represent a program in kpanel and kfm.
 */

kdelibs'FilePermissionsPropsPage::FilePermissionsPropsPage() (./kdelibs/kfile/kpropsdlg.cpp:668)

FilePermissionsPropsPage::FilePermissionsPropsPage( PropertiesDialog *_props )
  : PropsPage( _props )
{
  grpCombo = 0L; grpEdit = 0;
  usrEdit = 0L;
  QString path = properties->kurl().path(-1);
  QString fname = properties->kurl().filename();
  bool isLocal = properties->kurl().isLocalFile();

  bool IamRoot = (geteuid() == 0);
  bool isMyFile, isDir, isLink;

  isLink = properties->item()->isLink();
  isDir = S_ISDIR(properties->item()->mode());
  permissions = properties->item()->permissions();
  strOwner = properties->item()->user();
  strGroup = properties->item()->group();

  struct passwd *user;
  struct group *ge;
  if (isLocal) {
    struct stat buff;
    lstat( QFile::encodeName(path), &buff ); // display uid/gid of the link, if it's a link
    user = getpwuid( buff.st_uid );
    ge = getgrgid( buff.st_gid );

    isMyFile = (geteuid() == buff.st_uid);
    if ( user != 0L )
      strOwner = user->pw_name;


    if ( ge != 0L ) {
      strGroup = ge->gr_name;
      if (strGroup.isEmpty())
        strGroup.sprintf("%d",ge->gr_gid);
    } else
      strGroup.sprintf("%d",buff.st_gid);
  } else {
    //isMyFile = false; // we have to assume remote files aren't ours.
    isMyFile = true; // how could we know?
    //KIO::chmod will tell, if we had no right to change permissions
  }

  QBoxLayout *box = new QVBoxLayout( this, KDialog::spacingHint() );

  QLabel *l, *cl[3];
  QGroupBox *gb;
  QGridLayout *gl;

  /* Group: Access Permissions */
  gb = new QGroupBox ( i18n("Access permissions"), this );
  box->addWidget (gb);

  gl = new QGridLayout (gb, 6, 6, 15);
  gl->addRowSpacing(0, 10);

  l = new QLabel(i18n("Class"), gb);
  gl->addWidget(l, 1, 0);

  if (isDir)
    l = new QLabel( i18n("Show\nEntries"), gb );
  else
    l = new QLabel( i18n("Read"), gb );
  gl->addWidget (l, 1, 1);

  if (isDir)
    l = new QLabel( i18n("Write\nEntries"), gb );
  else
    l = new QLabel( i18n("Write"), gb );
  gl->addWidget (l, 1, 2);

  if (isDir)
    l = new QLabel( i18n("Enter"), gb );
  else
    l = new QLabel( i18n("Exec"), gb );
  // GJ: Add space between normal and special modes
  QSize size = l->sizeHint();
  size.setWidth(size.width() + 15);
  l->setFixedSize(size);
  gl->addWidget (l, 1, 3);

  l = new QLabel( i18n("Special"), gb );
  gl->addMultiCellWidget(l, 1, 1, 4, 5);

  cl[0] = new QLabel( i18n("User"), gb );
  //l->setEnabled (IamRoot || isMyFile);
  gl->addWidget (cl[0], 2, 0);

  cl[1] = new QLabel( i18n("Group"), gb );
  gl->addWidget (cl[1], 3, 0);

  cl[2] = new QLabel( i18n("Others"), gb );
  gl->addWidget (cl[2], 4, 0);

  l = new QLabel(i18n("Set UID"), gb);
  gl->addWidget(l, 2, 5);

  l = new QLabel(i18n("Set GID"), gb);
  gl->addWidget(l, 3, 5);

  l = new QLabel(i18n("Sticky"), gb);
  gl->addWidget(l, 4, 5);

    /* Draw Checkboxes */
  for (int row = 0; row < 3 ; ++row) {
    for (int col = 0; col < 4; ++col) {
      QCheckBox *cb = new QCheckBox(gb);
      cb->setChecked(permissions & fperm[row][col]);
      cb->setEnabled ((isMyFile || IamRoot) && (!isLink));
      permBox[row][col] = cb;
      gl->addWidget (permBox[row][col], row+2, col+1);
    }
  }
  gl->setColStretch(6, 10);

    /**** Group: Ownership ****/
  gb = new QGroupBox ( i18n("Ownership"), this );
  box->addWidget (gb);

  gl = new QGridLayout (gb, 4, 3, 15);
  gl->addRowSpacing(0, 10);

  /*** Set Owner ***/
  l = new QLabel( i18n("User:"), gb );
  gl->addWidget (l, 1, 0);

  /* GJ: Don't autocomplete more than 1000 users. This is a kind of random
   * value. Huge sites having 10.000+ user have a fair chance of using NIS,
   * (possibly) making this unacceptably slow.
   * OTOH, it is nice to offer this functionality for the standard user.
   */
  int i, maxEntries = 1000;

   /* File owner: For root, offer a KLineEdit with autocompletion.
    * For a user, who can never chown() a file, offer a QLabel.
    */
  if (IamRoot && isLocal)
  {
    usrEdit = new KLineEdit( gb );
    KCompletion *compl = usrEdit->completionObject();
    compl->setSorted(true);
    setpwent();
    for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); i++)
      compl->addItem(QString::fromLatin1(user->pw_name));
    endpwent();
    usrEdit->setCompletionMode((i < maxEntries) ? KGlobalSettings::CompletionAuto :
	  KGlobalSettings::CompletionNone);
    usrEdit->setText(strOwner);
    gl->addWidget(usrEdit, 1, 1);
  }
  else
  {
    l = new QLabel(strOwner, gb);
    gl->addWidget(l, 1, 1);
  }

  /*** Set Group ***/

  QStringList groupList;
  QCString strUser;
  user = getpwuid(geteuid());
  if (user != 0L)
    strUser = user->pw_name;

  if (IamRoot || isMyFile)
  {
    setgrent();
    for (i=0; ((ge = getgrent()) != 0L) && (i < maxEntries); i++)
    {
      if (IamRoot)
	groupList += QString::fromLatin1(ge->gr_name);
      else
      {
	/* pick just the groups the user can change the file to */
	char ** members = ge->gr_mem;
	char * member;
	while ((member = *members) != 0L) {
	  if (strUser == member) {
	    groupList += QString::fromLatin1(ge->gr_name);
	    break;
	  }
	  ++members;
	}
      }
    }
    endgrent();

    /* add the effective Group to the list .. */
    ge = getgrgid (getegid());
    if (ge) {
      QString name = QString::fromLatin1(ge->gr_name);
      if (name.isEmpty())
	name.setNum(ge->gr_gid);
      if (groupList.find(name) == groupList.end())
	groupList += name;
    }

    /* add the group the file currently belongs to ..
     * .. if its not there already
     */
    if (groupList.find(strGroup) == groupList.end())
      groupList += strGroup;
  }

  l = new QLabel( i18n("Group:"), gb );
  gl->addWidget (l, 2, 0);

  /* Set group: if possible to change:
   * - Offer a KLineEdit for root, since he can change to any group.
   * - Offer a QComboBox for a normal user, since he can change to a fixed
   *   (small) set of groups only.
   * If not changable: offer a QLabel.
   */
  if (IamRoot && isLocal)
  {
    grpEdit = new KLineEdit(gb);
    KCompletion *compl = new KCompletion;
    compl->setItems(groupList);
    grpEdit->setCompletionObject(compl, true);
    grpEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
    grpEdit->setText(strGroup);
    gl->addWidget(grpEdit, 2, 1);
  }
  else if ((groupList.count() > 1) && isMyFile && isLocal)
  {
    grpCombo = new QComboBox(gb);
    grpCombo->insertStringList(groupList);
    grpCombo->setCurrentItem(groupList.findIndex(strGroup));
    gl->addWidget(grpCombo, 2, 1);
  }
  else
  {
    l = new QLabel(strGroup, gb);
    gl->addWidget(l, 2, 1);
  }

  gl->setColStretch(2, 10);
  box->addStretch (10);

  if (isMyFile)
    cl[0]->setText(i18n("<b>User</b>"));
  else if (groupList.contains(strGroup))
    cl[1]->setText(i18n("<b>Group</b>"));
  else
    cl[2]->setText(i18n("<b>Others</b>"));
}


kdelibs'FilePermissionsPropsPage::supports() (./kdelibs/kfile/kpropsdlg.cpp:915)

bool FilePermissionsPropsPage::supports( KFileItemList /*_items*/ )
{
  return true;
}


kdelibs'FilePermissionsPropsPage::applyChanges() (./kdelibs/kfile/kpropsdlg.cpp:920)

void FilePermissionsPropsPage::applyChanges()
{
  mode_t p = 0L;
  for (int row = 0;row < 3; ++row)
    for (int col = 0; col < 4; ++col)
      if (permBox[row][col]->isChecked())
	p |= fperm[row][col];

  QString owner, group;
  if (usrEdit)
    owner = usrEdit->text();
  else
    owner = strOwner;
  if (grpEdit)
    group = grpEdit->text();
  else if (grpCombo)
    group = grpCombo->currentText();
  else
    group = strGroup;

  // First update group / owner
  // (permissions have to set after, in case of suid and sgid)
  if ((owner != strOwner) || (group != strGroup))
  {
    struct passwd* pw = getpwnam(owner.latin1());
    struct group* g = getgrnam(group.latin1());
    if ( pw == 0L ) {
      kdError(1202) << " ERROR: No user " << owner << endl;
      return;
    }
    if ( g == 0L ) {
      kdError(1202) << " ERROR: No group " << group << endl;
      return;
    }
    QString path = properties->kurl().path();
    if ( chown( QFile::encodeName(path), pw->pw_uid, g->gr_gid ) != 0 )
      KMessageBox::sorry( 0, i18n( "Could not change owner/group\nPerhaps access denied." ));
  }

  kdDebug(1203) << "old permissions : " << permissions << endl;
  kdDebug(1203) << "new permissions : " << p << endl;
  kdDebug(1203) << "url : " << properties->kurl().url() << endl;
  if ( permissions != p )
  {
    KIO::Job * job = KIO::chmod( properties->kurl(), p );
    connect( job, SIGNAL( result( KIO::Job * ) ),
             SLOT( slotChmodResult( KIO::Job * ) ) );
    // Wait for job
    qApp->enter_loop();
  }
}


kdelibs'FilePermissionsPropsPage::slotChmodResult() (./kdelibs/kfile/kpropsdlg.cpp:972)

void FilePermissionsPropsPage::slotChmodResult( KIO::Job * job )
{
  kdDebug(1203) << "FilePermissionsPropsPage::slotChmodResult" << endl;
  if (job->error())
    job->showErrorDialog(this);
  else
  {
    // Force refreshing information about that file if displayed.
    KDirWatch::self()->setFileDirty( properties->kurl().path() );
  }
  // allow apply() to return
  qApp->exit_loop();
}