/***************************************************************************
                          permission.cpp  -  description
                             -------------------
    begin                : Sun Jan 13 2002
    copyright            : (C) 2002 by Dominik Seichter
    email                : domseichter@web.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "permission.h"

// TQt includes
#include <tqcheckbox.h>
#include <tqgroupbox.h>
#include <tqlabel.h>
#include <tqlayout.h>

// TDE includes
#include <tdeapplication.h>
#include <kcombobox.h>
#include <kiconloader.h>
#include <tdelocale.h>

// OS includes
#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <grp.h>
#include <unistd.h>

const TQString MyPermPlugin::getName() const
{
    return i18n("Permissions");
}

const TQString MyPermPlugin::getAccelName() const
{
    return i18n("&Permissions");
}

const int MyPermPlugin::type() const
{
    return TYPE_FINAL_FILE;
}

bool MyPermPlugin::checkError()
{
    return true;
}

void MyPermPlugin::drawInterface( TQWidget* w, TQVBoxLayout* l )
{
    int i;
    unsigned int uid;   // Maybe this must be signed int ?
    struct passwd *user;
    struct group *ge;
    TQLabel *la, *cl[3];
    TQGridLayout *gl;

    TQString strOwner;

    m_widget = w;

    l->setResizeMode( TQLayout::FreeResize );
    w->setMinimumSize( TQSize( 100, 100 ) );
    
    Layout0 = new TQVBoxLayout( 0, 0, 6 );

    groupPermission = new TQGroupBox ( i18n("Access permissions"), w );
    groupPermission->setEnabled( FALSE );

    gl = new TQGridLayout (groupPermission, 6, 6, 15);
    gl->addRowSpacing(0, 10);

    checkPermissions = new TQCheckBox( i18n("Change &Permissions"), w );

    la = new TQLabel(i18n("Class"), groupPermission);
    gl->addWidget(la, 1, 0);

    la = new TQLabel( i18n("Read"), groupPermission );
    gl->addWidget (la, 1, 1);

    la = new TQLabel( i18n("Write"), groupPermission );
    gl->addWidget (la, 1, 2);

    la = new TQLabel( i18n("Exec"), groupPermission );
    TQSize size = la->sizeHint();
    size.setWidth(size.width() + 15);
    la->setFixedSize(size);
    gl->addWidget (la, 1, 3);

    la = new TQLabel( i18n("Special"), groupPermission );
    gl->addMultiCellWidget(la, 1, 1, 4, 5);

    cl[0] = new TQLabel( i18n("User"), groupPermission );
    gl->addWidget (cl[0], 2, 0);

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

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

    la = new TQLabel(i18n("UID"), groupPermission);
    gl->addWidget(la, 2, 5);

    la = new TQLabel(i18n("GID"), groupPermission);
    gl->addWidget(la, 3, 5);

    la = new TQLabel(i18n("Sticky"), groupPermission);
    gl->addWidget(la, 4, 5);

    for (int row = 0; row < 3 ; ++row) {
        for (int col = 0; col < 4; ++col) {
            TQCheckBox *cb = new TQCheckBox(groupPermission);
            permBox[row][col] = cb;
            gl->addWidget (permBox[row][col], row+2, col+1);

            permBox[row][0]->setChecked( TRUE );
        }
    }
    permBox[0][1]->setChecked( TRUE );

    gl->setColStretch(6, 10);

    checkOwner = new TQCheckBox( i18n("Change &Owner"), w );

    groupOwner = new TQGroupBox ( i18n("Ownership"), w );
    groupOwner->setEnabled( FALSE );
    groupOwner->setColumnLayout(0, TQt::Vertical );
    groupOwner->layout()->setSpacing( 6 );
    groupOwner->layout()->setMargin( 11 );
    groupOwnerLayout = new TQVBoxLayout( groupOwner->layout() );
    groupOwnerLayout->setAlignment( TQt::AlignTop );

    Layout2 = new TQHBoxLayout( 0, 0, 6 );
    Layout3 = new TQHBoxLayout( 0, 0, 6 );
    Layout4 = new TQHBoxLayout( 0, 0, 6 );

    la = new TQLabel( i18n("User:"), groupOwner );
    Layout2->addWidget( la );
    la = new TQLabel( i18n("Group:"), groupOwner );
    Layout3->addWidget( la );

    username = new KComboBox( groupOwner );
    uid = geteuid();

    setpwent();
    for (i=0; ((user = getpwent()) != 0L) && (i < MAXENTRIES); i++) {
        if( uid == 0 )
            username->insertItem(TQString::fromLatin1(user->pw_name));
        else
            if( user->pw_uid == uid )
                username->insertItem(TQString::fromLatin1(user->pw_name));
    }
    endpwent();

    groupname = new KComboBox( groupOwner );
    user = getpwuid(geteuid());
    TQString strUser = user->pw_name;

    setgrent();
    for (i=0; ((ge = getgrent()) != 0L) && (i < MAXENTRIES); i++) {
        if( uid == 0 ) {
            groupname->insertItem(TQString::fromLatin1(ge->gr_name));
        } else {
            char ** members = ge->gr_mem;
            char * member;
           
            while ((member = *members) != 0L) {
                if (strUser == member) {
                    groupname->insertItem(TQString::fromLatin1(ge->gr_name));
                    break;
                }

                ++members;
            }
        }
    }
    endgrent();

    /* add the users group */
    ge = getgrgid (getegid());
    if (ge) {
        TQString name = TQString::fromLatin1(ge->gr_name);
        if (name.isEmpty())
            name.setNum(ge->gr_gid);

        groupname->insertItem( name );
    }

    // make the users group visible
    groupname->setCurrentItem( groupname->count() );

    TQSpacerItem* spacer8 = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
    TQSpacerItem* spacer9 = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );

    Layout2->addWidget( username );
    Layout2->addItem( spacer8 );
    Layout3->addWidget( groupname );
    Layout3->addItem( spacer9 );

    groupOwnerLayout->addLayout( Layout2 );
    groupOwnerLayout->addLayout( Layout3 );

    TQSpacerItem* spacer10 = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );

    Layout4->addWidget( checkPermissions );
    Layout4->addWidget( checkOwner );

    l->addLayout( Layout4 );
    l->addWidget( groupPermission );
    l->addWidget( groupOwner );
    l->addItem( spacer10 );

    connect( checkOwner, TQ_SIGNAL(clicked()), this, TQ_SLOT(enableControls()) );
    connect( checkPermissions, TQ_SIGNAL(clicked()), this, TQ_SLOT(enableControls()) );
}

void MyPermPlugin::fillStructure()
{
    perm.changeOwner = checkOwner->isChecked();
    perm.changePermissions = checkPermissions->isChecked();
    if( perm.changeOwner ) {
        perm.group = groupname->currentText();
        perm.owner = username->currentText();
    }

    if( perm.changePermissions )
        perm.newPermission = getPermissions();

}

TQString MyPermPlugin::processFile( BatchRenamer* b, int i, TQString, int )
{
    TQString filename = b->files()[i].dst.name;
    if( perm.changePermissions )
        if (chmod(filename.local8Bit(), (mode_t)perm.newPermission) == -1)
            return i18n("Can't chmod %1.").arg(filename);

    if( perm.changeOwner )
        if (chown(filename.local8Bit(), getUid(perm.owner), getGid(perm.group)))
            return i18n("Can't chown %1.").arg(filename);

    return TQString();
}

void MyPermPlugin::finished()
{
    // We don't care about this event!
    return;
}

int MyPermPlugin::getPermissions()
{
    int fperm[3][4] = {
        {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
        {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
        {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
    };

    int permissions = 0, mask = 0;

    for (int row = 0;row < 3; ++row)
        for (int col = 0; col < 4; ++col)
        {
            switch (permBox[row][col]->state())
            {
                case TQCheckBox::On:
                    permissions |= fperm[row][col];
                    //fall through
                case TQCheckBox::Off:
                    mask |= fperm[row][col];
                    break;
                default:
                    break;
            }
        }

    return permissions;
}

int MyPermPlugin::getGid( TQString group )
{
    int i, r;
    struct group *ge;
    setgrent();
    for (i=0; ((ge = getgrent()) != 0L) && (i < MAXENTRIES); i++)
        if (!strcmp(ge->gr_name, group.local8Bit()))
            break;
    r = ge->gr_gid;
    endgrent();
    return r;
}

int MyPermPlugin::getUid( TQString owner )
{
    int i, r;
    struct passwd *user;
    setpwent();
    for (i=0; ((user = getpwent()) != 0L) && (i < MAXENTRIES); i++)
        if (!strcmp(user->pw_name, owner.local8Bit()))
            break;
    r = user->pw_uid;
    endpwent();
    return r;
}

void MyPermPlugin::enableControls()
{
    groupOwner->setEnabled( checkOwner->isChecked() );
    groupPermission->setEnabled( checkPermissions->isChecked() );
}

const TQPixmap MyPermPlugin::getIcon() const
{
    return kapp->iconLoader()->loadIcon( "clanbomber", TDEIcon::Small );
}

#include "permission.moc"
