Logo Search packages:      
Sourcecode: sadms version File versions  Download package

acls.py

#!/usr/bin/python
# -*-coding: UTF-8 -*-
# bbou@ac-toulouse.fr
# GPL license
# 2005-08-07 11:02:32  
# acls.py

import pygtk
pygtk.require("2.0")
from gtk import *
import gtk.glade
import string
import re

import runner
import remote

sysSetting={
      'hasFAcl':'type getfacl',
      'getFAcl':'getfacl "%FSOBJECT%" 2> /dev/null',
      'setFAcl':'setfacl %RECURSE% %MODE%=- "%FSOBJECT%"<<EOF\n%ACLS%\nEOF',
      'remount':'mount "%MOUNT%" -o remount',
      'remount2':'umount "%MOUNT%" && mount "%MOUNT%"',
      'docs':{'default':'file:///usr/share/doc/sadms-%s/%s',
            'redhat':'file:///usr/share/doc/sadms-%s/%s',
            'debian':'file:///usr/share/doc/sadms/%s',
            'suse':'file:///usr/share/doc/packages/sadms/%s',
            'mandriva':'file:///usr/share/doc/sadms-%s/%s'},
      'browser':{'default':'/usr/bin/firefox',
            'redhat':'/usr/bin/firefox',
            'debian':'/usr/bin/firefox',
            'suse':'/usr/bin/firefox',
            'mandriva':'/usr/bin/mozilla-firefox'},

      'getUsers':"getent passwd | grep -v '^$' | cut -f 1 -d ':' | sort",
      'getGroups':"getent group | grep -v '^$' | grep -v '^BUILTIN/' | cut -f 1 -d ':' | sort",
      'getOwnerGroup':"stat -c '%U:%G' \"%FSOBJECT%\"",
      'getUidGid':"stat -c '%u:%g' \"%FSOBJECT%\"",
      'getFstab':'cat /etc/fstab | grep -v "^#" | grep -v "^$"',
      'putFstab':"awk '{if (index($0,\"%DEV%\") && index($0,\"%MOUNT%\")){gsub($4,\"%OPTIONS%\")}; print $0}' /etc/fstab > /tmp/fstab; install -b -o root -g root -m 644 /tmp/fstab /etc ",
      'isDirectory':'sh -c \'if [ -d "%FSOBJECT%" ]; then echo true; else echo false; fi\'',
      'exists':'sh -c \'if [ -e "%FSOBJECT%" ]; then echo true; else echo false; fi\'',
      'getVersion':"cat version | head -n 1",
      'getDistribution':'sh -c \'if [ -f /etc/debian_version ]; then echo "debian"; else if [ -f /etc/SuSE-release ]; then echo "suse"; else if [ -e /etc/mandrake-release -o -e /etc/mandriva-release ]; then echo "mandriva"; else if [ -e /etc/redhat-release ]; then echo "redhat"; else echo "default"; fi; fi; fi; fi\'',
}

#######################################################################
#     ACL
#######################################################################

class Acl(dict):
      READ=0
      WRITE=1
      EXEC=2

      def __init__(self):
            pass

      def find(self,subject):
            for s in self.keys():
                  if s==subject:
                        return self[s]
            return None

      toR={True:'r',False:'-'}
      toW={True:'w',False:'-'}
      toX={True:'x',False:'-'}

      def boolToString(self,r,w,x):
            return '%s%s%s' % (Acl.toR[r],Acl.toW[w],Acl.toX[x])

        def toString(self):
                string=''
                subjects=self.keys()
                subjects.sort()
            for subject in subjects:
                  perms=self[subject]
                  rwx=self.boolToString(perms[Acl.READ],perms[Acl.WRITE],perms[Acl.EXEC])
                        string=string+self.getPath()+subject+":"+rwx+"\n"
                return string
      
class UnixAcl(Acl):
      
        def __init__(self):
                Acl.__init__(self)
                return

        def toString(self):
                string=""
            perms=self.find('user')
                if perms!=None:
                        string=string+self.getPath()+"user"+"::"+self.boolToString(perms[Acl.READ],perms[Acl.WRITE],perms[Acl.EXEC])+"\n"
            perms=self.find('group')
                if perms!=None:
                        string=string+self.getPath()+"group"+"::"+self.boolToString(perms[Acl.READ],perms[Acl.WRITE],perms[Acl.EXEC])+"\n"
            perms=self.find('other')
                if perms!=None:
                         string=string+self.getPath()+"other"+"::"+self.boolToString(perms[Acl.READ],perms[Acl.WRITE],perms[Acl.EXEC])+"\n"
            perms=self.find('mask')
                if perms!=None:
                         string=string+self.getPath()+"mask"+"::"+self.boolToString(perms[Acl.READ],perms[Acl.WRITE],perms[Acl.EXEC])+"\n"
                return string

        def getPath(self):
                return ""
        
class UserAcl(Acl):

        def __init__(self):
                Acl.__init__(self)
                return

        def getPath(self):
                return "user:"
        
class GroupAcl(Acl):

        def __init__(self):
                Acl.__init__(self)
                return

        def getPath(self):
                return "group:"
        
class DefaultUnixAcl(UnixAcl):

        def __init__(self):
                UnixAcl.__init__(self)
                return

        def getPath(self):
                return "default:"
        
class DefaultUserAcl(Acl):

        def __init__(self):
                Acl.__init__(self)
                return

        def getPath(self):
                return "default:user:"
        
class DefaultGroupAcl(Acl):

        def __init__(self):
                Acl.__init__(self)
                return

        def getPath(self):
                return "default:group:"
      
#######################################################################
#     ACLS (6-tuple of acls)
#######################################################################

class Acls:
      def __init__(self,unixAcl,userAcl,groupAcl,defaultUnixAcl,defaultUserAcl,defaultGroupAcl):
              self.unixAcl=unixAcl
              self.userAcl=userAcl
              self.groupAcl=groupAcl
              self.defaultUnixAcl=defaultUnixAcl
              self.defaultUserAcl=defaultUserAcl
              self.defaultGroupAcl=defaultGroupAcl
            return
      
      # split global acl into 6-tuple of typed acls (unix,user,group,default unix,default user, default group)
      def parse(self,s):
            lines=string.split(s,"\n")
            for l in lines[3:]:
                  if l=="":
                        continue
                  f=string.split(l,":")
                  n=len(f)
                  p=f[n-1]
                  perms=self.toBooleans(p)
                  if f[0]=='user':
                        if f[1]=='':
                              self.unixAcl['user']=perms
                        else:
                              self.userAcl[f[1]]=perms
                  elif f[0]=='group':
                        if f[1]=='':
                              self.unixAcl['group']=perms
                        else:
                              self.groupAcl[f[1]]=perms
                  elif f[0]=='other':
                        self.unixAcl['other']=perms
                  elif f[0]=='mask':
                        self.unixAcl['mask']=perms
                  elif f[0]=='default':
                        if f[1]=='user':
                              if f[2]=='':
                                    self.defaultUnixAcl['user']=perms
                              else:
                                    self.defaultUserAcl[f[2]]=perms
                        elif f[1]=='group':
                              if f[2]=='':
                                    self.defaultUnixAcl['group']=perms
                              else:
                                    self.defaultGroupAcl[f[2]]=perms
                        elif f[1]=='other':
                              if f[2]=='':
                                    self.defaultUnixAcl['other']=perms
                        elif f[1]=='mask':
                              if f[2]=='':
                                    self.defaultUnixAcl['mask']=perms
              return

        RToBoolean={'r':True,'-':False}
        WToBoolean={'w':True,'-':False}
        XToBoolean={'x':True,'-':False}

      def toBooleans(self,perms):
            return Acls.RToBoolean[perms[Acl.READ]],Acls.WToBoolean[perms[Acl.WRITE]],Acls.XToBoolean[perms[Acl.EXEC]]

      def toString(self):
            return self.unixAcl.toString()+self.userAcl.toString()+self.groupAcl.toString()+self.defaultUnixAcl.toString()+self.defaultUserAcl.toString()+self.defaultGroupAcl.toString()

#######################################################################
#     ACLVIEWS
#######################################################################

class AclsView:

      # datatype
      UNIX=0
      USER=1
      GROUP=2

      # column info = rank, type, header, expand, render callback
      IMAGE=0
      SUBJECT=1
      READ=2
      WRITE=3
      EXEC=4
      DIFF=5

      columns=(
            [IMAGE,gtk.gdk.Pixbuf,'',True,None],
            [SUBJECT,str,'subject',True,None],
            [READ,bool,'r',False,True],
            [WRITE,bool,'w',False,True],
            [EXEC,bool,'x',False,True],
            [DIFF,str,'',False,None])

      pixbufs=[]

        def __init__(self,listview,subjecttype):

            # widget from glade
            self.listview=listview

            # subjecttype
            self.subjecttype=subjecttype

            # selection
            self.listview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

            # type of alc it represents
            self.aclType=None

            # model
            types=[t[1] for t in AclsView.columns]
            self.model=gtk.ListStore(*types)
            self.listview.set_model(self.model)       
            
            # columns
            self.setupColumns()
      
            # images
            if AclsView.pixbufs==[]:
                  AclsView.pixbufs=self.setupImages()
                return
        
      def setupImages(self):
            imageFile=['unix.png','user.png','group.png']
            pixbufs=[]
            for i in range(len(imageFile)):
                  pixbufs.append(gtk.gdk.pixbuf_new_from_file('pixmaps/'+imageFile[i]))
            return pixbufs

      def setupColumns(self): 
            types=[t[1] for t in AclsView.columns]
            for rank,datatype,header,expand,render in AclsView.columns:
                  column=gtk.TreeViewColumn(header)
                  if datatype==str:
                        column.set_min_width(300)
                        cell=gtk.CellRendererText()
                        attr='text'
                  elif datatype==bool:
                        cell=gtk.CellRendererToggle()
                        cell.set_property('activatable',True)
                        cell.set_property('cell-background','lightGray')            
                        cell.connect('toggled',self.toggle_acl_callback,(rank))
                        attr='active'
                  elif datatype==gtk.gdk.Pixbuf:
                        cell=gtk.CellRendererPixbuf()
                        attr='pixbuf'           
                  else:
                        cell=gtk.CellRendererText()
                        attr='text' 
                  column.pack_start(cell,expand)
                  column.add_attribute(cell,attr,rank)
                  if render!=None:
                        column.set_cell_data_func(cell,self.renderPerm)
                  self.listview.append_column(column)
            return

      # render callback
      def renderPerm(self,column,cell,model,iter):
            s=model.get_value(iter,AclsView.SUBJECT)
            if s in ['user','group','other']:
                  cell.set_property('cell-background','gray')
            elif s in ['mask']:
                  cell.set_property('cell-background','pink')
            else:       
                  cell.set_property('cell-background','lightGray')
            return

      # toggle callback
      def toggle_acl_callback(self,cell,r,(c)):
            #print "path=%s,%s" % (r,c)
            self.model[r][c]=not self.model[r][c]
            return       

      # find subject (returns TreeModelRow)
      def find(self,subject):
            for i in self.model:
                  if i[AclsView.SUBJECT]==subject:
                        return i
            return None

        # addition/removal

      def setAcl(self,acl):
                subjects=acl.keys()
                subjects.sort()
                for subject in subjects:
                  self.addAce(subject,acl[subject][Acl.READ],acl[subject][Acl.WRITE],acl[subject][Acl.EXEC])
                return
            
      def addAce(self,subject,r,w,x):
            #print subject,r,w,x
            if self.find(subject)==None:
                  self.model.append([AclsView.pixbufs[self.subjecttype],subject,r,w,x,''])
                return
            
        def removeSelectedAces(self):
            selection=self.listview.get_selection()
            (model,pathlist)=selection.get_selected_rows()
            pathlist.reverse()
            for path in pathlist:
                        model.remove(model.get_iter(path))
            return

        def clear(self):
            self.model.clear()
            return

        # retrieval

      def getAcl(self):
                acl=self.aclType()
            for i in self.model:
                  subject=i[AclsView.SUBJECT]
                  r=i[AclsView.READ]
                  w=i[AclsView.WRITE]
                  x=i[AclsView.EXEC]
                        acl[subject]=r,w,x
                return acl

        # diff from other view
      
      def diff(self,aclView,*options):
            for i in self.model:
                  subject=i[AclsView.SUBJECT]
                  j=aclView.find(subject)
                  if j!=None:
                        if i[AclsView.READ]==j[AclsView.READ] and i[AclsView.WRITE]==j[AclsView.WRITE] and i[AclsView.EXEC]==j[AclsView.EXEC]:
                              i[AclsView.DIFF]=''
                        else:
                              message=''
                              if i[AclsView.READ]!=j[AclsView.READ]:
                                    message=message+'r'
                              if i[AclsView.WRITE]!=j[AclsView.WRITE]:
                                    message=message+'w'
                              if i[AclsView.EXEC]!=j[AclsView.EXEC]:
                                    message=message+'x'
                              i[AclsView.DIFF]=message
                        else:
                        i[AclsView.DIFF]='+'
                return

class UnixAclsView(AclsView):
      
        def __init__(self,widget):
                AclsView.__init__(self,widget,AclsView.UNIX)
            self.aclType=UnixAcl
                return

        def setAcl(self,acl):
                for subject in ['user','group','other','mask']:
                  if acl.has_key(subject):
                        self.addAce(subject,acl[subject][Acl.READ],acl[subject][Acl.WRITE],acl[subject][Acl.EXEC])
                return
        
class UserAclsView(AclsView):

        def __init__(self,widget):
                AclsView.__init__(self,widget,AclsView.USER)
            self.aclType=UserAcl
                return
        
class GroupAclsView(AclsView):

        def __init__(self,widget):
                AclsView.__init__(self,widget,AclsView.GROUP)
            self.aclType=GroupAcl
                return
        
class DefaultUnixAclsView(UnixAclsView):

        def __init__(self,widget):
                UnixAclsView.__init__(self,widget)
            self.aclType=DefaultUnixAcl
                return
        
class DefaultUserAclsView(AclsView):

        def __init__(self,widget):
                AclsView.__init__(self,widget,AclsView.USER)
            self.aclType=DefaultUserAcl
                return
        
class DefaultGroupAclsView(AclsView):

        def __init__(self,widget):
                AclsView.__init__(self,widget,AclsView.GROUP)
            self.aclType=DefaultGroupAcl
                return
       
#######################################################################
#     ACLMANAGER CLASSES
#######################################################################

class FsViewer:

      IMAGE=0
      TEXT=1

      USER=0
      GROUP=1

      pixbufs=[]

      IMAGE=0
      DEV=1
      MOUNT=2
      FSTYPE=3
      OPTIONS=4
      FREQ=5
      PASSNO=6

      pixbufs=[]

      columns=(
            [IMAGE,gtk.gdk.Pixbuf,'',False],
            [DEV,str,'fs',True],
            [MOUNT,str,'dev',True],
            [FSTYPE,str,'dev',True],
            [OPTIONS,str,'options',True],
            [FREQ,str,'freq',True],
            [PASSNO,str,'pass',True]
            )

      def __init__(self,dialog,listview):
            self.dialog=dialog
            self.listview=listview
            
            # header
            self.listview.set_headers_visible(True)

            # selection
            self.listview.get_selection().set_mode(gtk.SELECTION_SINGLE)

            # model
            self.model=ListStore(gtk.gdk.Pixbuf,str)
            self.listview.set_model(self.model)

            # setup
            self.setup(FsViewer.columns)

            # images
            if FsViewer.pixbufs==[]:
                  FsViewer.pixbufs=self.setupImages()
                return
        
      def setup(self,columns):      

            types=[t[1] for t in columns]

            # model
            self.model=ListStore(*types)
            self.listview.set_model(self.model)

            # columns
            for rank,datatype,header,expand in columns:
                  column=gtk.TreeViewColumn(header)
                  if datatype==str:
                        column.set_sort_column_id(rank)
                        column.connect('clicked',self.columnClicked,self.listview)
                        cell=gtk.CellRendererText()
                        attr='text'
                  if datatype==int:
                        column.set_sort_column_id(rank)
                        column.connect('clicked',self.columnClicked,self.listview)
                        cell=gtk.CellRendererText()
                        attr='text'
                  elif datatype==bool:
                        cell=gtk.CellRendererToggle()
                        cell.set_property('activatable',True)
                        cell.connect('toggled',self.toggle_acl_callback,(rank))
                        attr='active'
                  elif datatype==gtk.gdk.Pixbuf:
                        cell=gtk.CellRendererPixbuf()
                        attr='pixbuf'
                  else:
                        cell=gtk.CellRendererText()
                        attr='text' 
                  column.pack_start(cell,expand)
                  column.add_attribute(cell,attr,rank)
                  column.set_cell_data_func(cell,self.render)
                  self.listview.append_column(column)
            return

      def setupImages(self):
            imageFile=['disk-hidden.png','disk.png']
            pixbufs=[]
            for i in range(len(imageFile)):
                  pixbufs.append(gtk.gdk.pixbuf_new_from_file('pixmaps/'+imageFile[i]))
            return pixbufs

      # render callback
      def render(self,column,cell,model,i):
            r=model.get_path(i)
            toggle=r[0] % 2 == 0
            if toggle:
                  cell.set_property('cell-background','lightGray')
            else:
                  cell.set_property('cell-background','white')
            return

      # toggle callback
      def toggle_acl_callback(self,cell,r,(c)):
            #print "path=%s,%s" % (r,c)
            self.model[r][c]=not self.model[r][c]
            return       
      
      # click column call back
      def columnClicked(self,c,data):     
            pass

      def set(self,fss):
            self.model.clear()
            for fs in fss:
                  dev,mount,fstype,opts,freq,passno=fs
                  if fstype=='ext3':
                        pixbufIndex=0
                        if opts.find('acl')!=-1:
                              pixbufIndex=1
                        self.model.append([FsViewer.pixbufs[pixbufIndex],dev,mount,fstype,opts,freq,passno])
            return

      def getSelection(self):
            selection=self.listview.get_selection()
            (model,pathlist)=selection.get_selected_rows()
            if pathlist==[]:
                  return None
            path=pathlist[0]
            row=model[model.get_iter(path)]
            return [row[FsViewer.DEV],row[FsViewer.MOUNT],row[FsViewer.FSTYPE],row[FsViewer.OPTIONS],row[FsViewer.FREQ],row[FsViewer.PASSNO]]

      # wrappers 
      
      def run(self):
            return self.dialog.run()

      def hide(self):
            self.dialog.hide()
            return

class SubjectChooser:

      IMAGE=0
      TEXT=1

      USER=0
      GROUP=1

      pixbufs=[]

      def __init__(self,dialog,listview):
            self.dialog=dialog
            self.listview=listview
            
            # header
            self.listview.set_headers_visible(False)

            # selection
            self.listview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

            # model
            self.model=ListStore(gtk.gdk.Pixbuf,str)
            self.listview.set_model(self.model)

            # columns
            column=gtk.TreeViewColumn('')
            cell=gtk.CellRendererPixbuf()
            column.pack_start(cell,True)
            column.add_attribute(cell,'pixbuf',SubjectChooser.IMAGE)
            self.listview.append_column(column)

            column=gtk.TreeViewColumn('subject')
            cell=gtk.CellRendererText()
            column.pack_start(cell,True)
            column.add_attribute(cell,'text',SubjectChooser.TEXT)
            self.listview.append_column(column)

            # images
            if SubjectChooser.pixbufs==[]:
                  SubjectChooser.pixbufs=self.setupImages()
                return
        
      def setupImages(self):
            imageFile=['user-hidden.png','group-hidden.png']
            pixbufs=[]
            for i in range(len(imageFile)):
                  pixbufs.append(gtk.gdk.pixbuf_new_from_file('pixmaps/'+imageFile[i]))
            return pixbufs

      def set(self,subjects,subjecttype):
            self.model.clear()
            for i in subjects:
                  self.model.append([SubjectChooser.pixbufs[subjecttype],i])
            return

      def getSelection(self):
            selection=self.listview.get_selection()
            (model,pathlist)=selection.get_selected_rows()
            return [model[model.get_iter(path)][SubjectChooser.TEXT] for path in pathlist]

      # wrappers 
      
      def run(self):
            return self.dialog.run()

      def hide(self):
            self.dialog.hide()
            return

class TextViewer:

      def __init__(self,dialog,textview):
            self.dialog=dialog
            self.textview=textview
            self.buffer=gtk.TextBuffer(None)
            self.endmark=self.buffer.create_mark('end',self.buffer.get_start_iter(),left_gravity=False)
            self.unixTag=self.buffer.create_tag('unix',foreground='darkBlue')
            self.maskTag=self.buffer.create_tag('mask',foreground='blue')
            self.userTag=self.buffer.create_tag('user',foreground='black')
            self.groupTag=self.buffer.create_tag('group',foreground='darkGray')
            self.errorTag=self.buffer.create_tag('error',foreground='red')
            self.textview.set_property('editable',False)
            self.textview.set_wrap_mode(gtk.WRAP_NONE)
            self.textview.set_buffer(self.buffer)
            return

      def set(self,text):
            self.buffer.delete(self.buffer.get_start_iter(),self.buffer.get_end_iter())
            lines=text.splitlines()
            for line in lines:
                  tag='error'
                  if re.match('^user::',line) or re.match('^default:user::',line):
                        tag='unix'
                  elif re.match('^group::',line) or re.match('^default:group::',line):
                        tag='unix'
                  elif re.match('^other::',line) or re.match('^default:other::',line):
                        tag='unix'
                  elif re.match('^mask::',line) or re.match('^default:mask:',line):
                        tag='mask'
                  elif re.match('^user:',line) or re.match('^default:user:',line):
                        tag='user'
                  elif re.match('^group:',line) or re.match('^default:group:',line):
                        tag='group'
                  
                  i=self.buffer.get_end_iter()
                  self.buffer.insert_with_tags_by_name(i,line+'\n',tag)
            #self.textview.scroll_to_mark(self.endmark,0,use_align=False)
            return

      # wrappers 
      
      def run(self):
            return self.dialog.run()

      def hide(self):
            self.dialog.hide()
            return

#######################################################################
#     ACLMANAGER
#######################################################################

class AclManager:
      
      NONE=0
      OK=1
      ERROR=2

      pixbufs=[]

      def __init__(self,runner=runner.GtkRunner()):

            handlers={
                  'on_destroy':                 self.exit,
                  'on_cancel_clicked':          self.exit,
                  'on_browseFile_clicked':      self.browseFile,
                  'on_browseFolder_clicked':    self.browseFolder,
                  'on_readAcl_clicked':         self.forceRefresh,

                  'on_addUsers_clicked':        self.addUsers,
                  'on_addGroups_clicked':       self.addGroups,
                  'on_remove_clicked':          self.remove,

                  'on_apply_clicked':           self.applyAcls,
                  'on_ok_clicked':        self.exitOk,

                  'on_copyToDefault_clicked':   self.copyToDefault,
                  'on_diff_clicked':            self.diff,
                  'on_text_clicked':            self.view,
                  'on_remote_clicked':          self.setRemote,
                  'on_fs_clicked':        self.fileSystem,
                  'on_toggleAcls_clicked':      self.toggleAcls,
                  'on_fs_selectrow':            self.selectFs,
                  'on_help_clicked':            self.help,
            }

            self.runner=runner;

            self.widgets=gtk.glade.XML('acls.glade')
            self.widgets.signal_autoconnect(handlers)
            self.dialog=self['acls']

            # widgets
            self.pathEdit=self['targetPath']
            self.pathImage=self['targetPathImage']
            self.ownerLabel=self['ownerLabel']
            self.groupLabel=self['groupLabel']
            self.uidLabel=self['uidLabel']
            self.gidLabel=self['gidLabel']
            self.notebook=self['notebook']
            self.recurseCheck=self['recurseCheck']
            self.remoteStatusImage=self['remoteButtonStatusImage']
            self.setRadio=self['setRadio']
            self.modifyRadio=self['modifyRadio']
            self.copyToDefaultButton=self['copyToDefaultButton']
            self.diffButton=self['diffButton']
            self.toggleAclImage=self['fsDialogToggleAclButtonImage']

            self.unixAclsView=UnixAclsView(self['unixAclList'])
            self.userAclsView=UserAclsView(self['userAclList'])
            self.groupAclsView=GroupAclsView(self['groupAclList'])
            self.defaultUnixAclsView=DefaultUnixAclsView(self['defaultUnixAclList'])
            self.defaultUserAclsView=DefaultUserAclsView(self['defaultUserAclList'])
            self.defaultGroupAclsView=DefaultGroupAclsView(self['defaultGroupAclList'])

            self.subjectChooser=SubjectChooser(self['subjectDialog'],self['subjectDialogView'])
            self.viewer=TextViewer(self['textDialog'],self['textDialogTextView'])
            self.fsviewer=FsViewer(self['fsDialog'],self['fsDialogView'])
            self.aboutDialog=self['aboutDialog']
            self.isDirectoryFlag=False

            self.refreshRemote()
            self.pathEdit.grab_focus()

            # images
            if AclManager.pixbufs==[]:
                  AclManager.pixbufs=self.setupImages()

            return

      # widget access

      def __getitem__(self, key):
            return self.widgets.get_widget(key)

      # images

      def setupImages(self):
            imageFile=['grey.png','green.png','red.png']
            pixbufs=[]
            for i in range(len(imageFile)):
                  pixbufs.append(gtk.gdk.pixbuf_new_from_file('pixmaps/'+imageFile[i]))
            return pixbufs

      # termination

      def exit(self,*options):
            if __name__ == "__main__":
                  gtk.main_quit()
            else:
                  self.dialog.destroy()   
            return
                        
      def exitOk(self,*options):
            self.applyAcls()
            self.exit() 
            return
                        
      #clear

      def clear(self):
            self.unixAclsView.clear()
            self.userAclsView.clear()
            self.groupAclsView.clear()
            self.defaultUnixAclsView.clear()
            self.defaultUserAclsView.clear()
            self.defaultGroupAclsView.clear()
            return

      # get/set

      def setAcls(self,fsobject):
            acls=self.getPerms(fsobject)
            if acls==None:
                  print 'Error while retrieving acls for %s' % fsobject
                  return
              #print 'READ=\n%s' % (acls.toString())
            self.unixAclsView.setAcl(acls.unixAcl)
            self.userAclsView.setAcl(acls.userAcl)
            self.groupAclsView.setAcl(acls.groupAcl)
            self.defaultUnixAclsView.setAcl(acls.defaultUnixAcl)
            self.defaultUserAclsView.setAcl(acls.defaultUserAcl)
            self.defaultGroupAclsView.setAcl(acls.defaultGroupAcl)
            return

      def getAcls(self):
            unixAcl=self.unixAclsView.getAcl()
            userAcl=self.userAclsView.getAcl()
            groupAcl=self.groupAclsView.getAcl()
            defaultUnixAcl=self.defaultUnixAclsView.getAcl()
            defaultUserAcl=self.defaultUserAclsView.getAcl()
            defaultGroupAcl=self.defaultGroupAclsView.getAcl()
            r=Acls(unixAcl,userAcl,groupAcl,defaultUnixAcl,defaultUserAcl,defaultGroupAcl)
            return r

      # refresh

      def forceRefresh(self,*options):
            self.refresh()
            return

      def refresh(self):
                fsobject=self.pathEdit.get_text()
                  self.clear()
            if self.exists(fsobject):
                  self.pathImage.set_from_pixbuf(AclManager.pixbufs[AclManager.OK])

                  self.isDirectoryFlag=self.isDirectory(fsobject)
                  owner,group=self.getOwnerGroup(fsobject)
                  self.ownerLabel.set_text(owner)
                  self.groupLabel.set_text(group)
                  uid,gid=self.getUidGid(fsobject)
                  self.uidLabel.set_text(str(uid))
                  self.gidLabel.set_text(str(gid))
                  self.setAcls(fsobject)  
                  self.adjustToType()
            else:
                  self.pathImage.set_from_pixbuf(AclManager.pixbufs[AclManager.ERROR])
                  
            return

      def adjustToType(self):
            page=self.notebook.get_nth_page(1)
            tab=self.notebook.get_tab_label(page)
            if self.isDirectoryFlag:
                  label="list"
                  tab.show_all()
                  page.show_all()
                  self.copyToDefaultButton.show()
                  self.diffButton.show()
            else:
                  label="execute"
                  tab.hide_all()
                  page.hide_all()
                  self.copyToDefaultButton.hide()
                  self.diffButton.hide()
            return

      # add/removal
      
      def addUsers(self,*options):
            aclview=self.userAclsView
            if self.notebook.get_current_page()==1:
                  aclview=self.defaultUserAclsView
            self.subjectChooser.set(self.getUsers(),SubjectChooser.USER)
            response=self.subjectChooser.run()
            self.subjectChooser.hide()
            if response==gtk.RESPONSE_OK:
                  for u in self.subjectChooser.getSelection():
                        aclview.addAce(u,False,False,False)
          
      def addGroups(self,*options):
            aclview=self.groupAclsView
            if self.notebook.get_current_page()==1:
                  aclview=self.defaultGroupAclsView   
            self.subjectChooser.set(self.getGroups(),SubjectChooser.GROUP)
            response=self.subjectChooser.run()
            self.subjectChooser.hide()
            if response==gtk.RESPONSE_OK:
                  for g in self.subjectChooser.getSelection():
                        aclview.addAce(g,False,False,False)
            return

      def remove(self,*options):
            self.userAclsView.removeSelectedAces()
            self.groupAclsView.removeSelectedAces()
            self.defaultUserAclsView.removeSelectedAces()
            self.defaultGroupAclsView.removeSelectedAces()
            return

      # apply

      def applyAcls(self,*options):
            fsobject=self.pathEdit.get_text()
            if not self.exists(fsobject):
                  return
            owner,group=self.getOwnerGroup(fsobject)
            acls=self.getAcls()
            aclsString='# file: '+fsobject+'\n'+\
                  '# owner: '+owner+'\n'+\
                  '# group: '+group+'\n'+\
                  acls.toString()
            recurse=''
            if self.isDirectoryFlag and self.recurseCheck.get_active():
                  recurse='-R'
            mode='--set-file'
            if self.modifyRadio.get_active():
                  mode='--modify-file'

            cl=sysSetting['setFAcl']
            cl=cl.replace('%RECURSE%',recurse)
            cl=cl.replace('%MODE%',mode)
            cl=cl.replace('%ACLS%',aclsString)
            cl=cl.replace('%FSOBJECT%',fsobject)
            status,output=self.runToString(cl)
            if not status:
                  print '<%s> failed' % (cl)
            return

      # other ops

      def copyToDefault(self,*options):
            self.defaultUnixAclsView.clear()
            self.defaultUserAclsView.clear()
            self.defaultGroupAclsView.clear()
            self.defaultUnixAclsView.setAcl(self.unixAclsView.getAcl())
            self.defaultUserAclsView.setAcl(self.userAclsView.getAcl())
            self.defaultGroupAclsView.setAcl(self.groupAclsView.getAcl())
            return

      def diff(self,*options):
            self.defaultUnixAclsView.diff(self.unixAclsView)
            self.defaultUserAclsView.diff(self.userAclsView)
            self.defaultGroupAclsView.diff(self.groupAclsView)
            self.unixAclsView.diff(self.defaultUnixAclsView)
            self.userAclsView.diff(self.defaultUserAclsView)
            self.groupAclsView.diff(self.defaultGroupAclsView)
            return

      def view(self,*options):
            acls=self.getAcls()
            s=acls.toString()
            self.viewer.set(s)
            response=self.viewer.run()
            self.viewer.hide()
            return

      # browse

      import os.path
      
      def browseFile(self,*options):
            path=self.pathEdit.get_text()
            path=os.path.dirname(path)
            dialog=gtk.FileChooserDialog("Open file...",None,gtk.FILE_CHOOSER_ACTION_OPEN,(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
            dialog.set_default_response(gtk.RESPONSE_OK)
            if os.path.exists(path):
                  dialog.set_current_folder(path)
            filter=gtk.FileFilter()
            filter.set_name("All files")
            filter.add_pattern("*")
            dialog.add_filter(filter)
            response = dialog.run()
            if response == gtk.RESPONSE_OK:
                  self.pathEdit.set_text(dialog.get_filename())
                  self.refresh()
            dialog.destroy()
            return

      def browseFolder(self,*options):
            path=self.pathEdit.get_text()
            path=os.path.dirname(path)
            dialog=gtk.FileChooserDialog("Open folder...",None,gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
            dialog.set_default_response(gtk.RESPONSE_OK)
            if os.path.exists(path):
                  dialog.set_current_folder(path)
            response = dialog.run()
            if response == gtk.RESPONSE_OK:
                  self.pathEdit.set_text(dialog.get_filename())
                  self.refresh()
            dialog.destroy()
            return

      # file system

      def fileSystem(self,*options):
            self.fileSystemRefresh()
            response=self.fsviewer.run()
            self.fsviewer.hide()
            return

      def fileSystemRefresh(self):
            fss=self.getFstab()
            fss=[fs.split() for fs in fss]
            for i in range(0,len(fss)):
                  for j in range(0,len(fss[i])):
                        fss[i][j]=fss[i][j].strip()
            self.fsviewer.set(fss)
            return

      def fileSystemMessage(self,message):
            dialog=gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_WARNING,gtk.BUTTONS_CLOSE,message)
            dialog.run()
            dialog.destroy()
            return

      def toggleAcls(self,*options):
            s=self.fsviewer.getSelection()
            if s==None:
                  return
            dev,mount,fstype,options,freq,passno=s
            if options.find('acl')!=-1:
                  options=options.replace('acl','')
                  remountTag='remount2'
            else:
                  options=options+',acl'
                  remountTag='remount'
            options=options.strip(',')
            cl=sysSetting['putFstab']
            cl=cl.replace('%DEV%',dev)
            cl=cl.replace("%MOUNT%",mount)
            cl=cl.replace("%OPTIONS%",options) 
            status,output=self.runToString(cl)
            if status:
                  cl=sysSetting[remountTag]
                  cl=cl.replace('%MOUNT%',mount)
                  status,output=self.runToString(cl)
                  if not status:
                        message="Remount failed"
                        self.fileSystemMessage(message)
            else:
                  message="Failed to modify /etc/fstab"
                  self.fileSystemMessage(message)
            self.fileSystemRefresh()
            self.refresh()
            self.toggleAclImage.set_from_stock(gtk.STOCK_HARDDISK,gtk.ICON_SIZE_BUTTON)
            return

      def selectFs(self,*options):
            dev,mount,fstype,options,freq,passno=self.fsviewer.getSelection()
            if options.find('acl')!=-1:
                  self.toggleAclImage.set_from_stock(gtk.STOCK_NO,gtk.ICON_SIZE_BUTTON)
            else:
                  self.toggleAclImage.set_from_stock(gtk.STOCK_YES,gtk.ICON_SIZE_BUTTON)
            return

      # remote

      def setRemote(self,*options):
            m=remote.RemoteManager()
            m.remoteCheck.set_active(self.runner.runRemote)
            host=self.runner.remoteHost
            if host==None:
                  host='localhost'
            user=self.runner.remoteUser
            if user==None:
                  user='root'
            wdir=self.runner.remoteDir
            if wdir==None:
                  wdir='~'

            m.hostEntry.set_text(host)
            m.userEntry.set_text(user)
            m.dirEntry.set_text(wdir)
            m.keyPathEntry.set_text('~/.ssh/id_dsa')
            m.refresh()
            response=m.dialog.run()
            m.dialog.hide()
            if response==gtk.RESPONSE_OK:
                  remoteFlag=m.remoteCheck.get_active()
                  host= m.hostEntry.get_text()
                  user=m.userEntry.get_text()
                  wdir=m.dirEntry.get_text()
                  if remoteFlag and m.canRun():
                        self.runner.setRemote(host,user,wdir)
                  else:
                        self.runner.setLocal(host,user,wdir)
                  self.refreshRemote()
            return

      def refreshRemote(self,*options):
            if self.runner.runRemote:
                  self.remoteStatusImage.set_from_stock(gtk.STOCK_YES,gtk.ICON_SIZE_BUTTON)
            else:
                  self.remoteStatusImage.set_from_stock(gtk.STOCK_NO,gtk.ICON_SIZE_BUTTON)
            return

      def help(self,*options):
            distribution=self.getDistribution()
            browser=sysSetting['browser'][distribution]
            urlbase=sysSetting['docs'][distribution]
            if distribution=="suse" or distribution=="debian":
                  url=urlbase % ('acls.html')
            else:
                  url=urlbase % (self.getVersion(),'acls.html')
            os.spawnv(os.P_NOWAIT,browser,[browser,url])
            return

      def getVersion(self):
            cl=sysSetting['getVersion']
            status,output=self.runToString(cl)
            return output

      def about(self,*options):
            self.aboutDialog.show()
            return

      #######################################################################
      #     HELPERS
      #######################################################################
      
      def runToString(self,cl):
            output,status=self.runner.runToString(cl)
            return output,status
            
      def exists(self,path):
            cl=sysSetting['exists']
            cl=cl.replace('%FSOBJECT%',path)
            status,output=self.runToString(cl)
            if not status:
                  return False
            output=output.strip('\n\r ')
            return output=='true'
            
      def isDirectory(self,fsobject):
            cl=sysSetting['isDirectory']
            cl=cl.replace('%FSOBJECT%',fsobject)
            status,output=self.runToString(cl)
            if not status:
                  return False
            output=output.strip('\n\r ')
            return output=='true'
      
      def getUidGid(self,fsobject):
            cl=sysSetting['getUidGid']
            cl=cl.replace('%FSOBJECT%',fsobject)
            status,output=self.runToString(cl)
            if not status:
                  return None,None
            output=output.strip('\n\r ')
            return output.split(":")

      def getOwnerGroup(self,fsobject):
            cl=sysSetting['getOwnerGroup']
            cl=cl.replace('%FSOBJECT%',fsobject)
            status,output=self.runToString(cl)
            if not status:
                  return None,None
            output=output.strip('\n\r ')
            return output.split(":")

      def getPerms(self,fsobject):
            cl=sysSetting['getFAcl']
            cl=cl.replace('%FSOBJECT%',fsobject)
            status,output=self.runToString(cl)
            if not status:
                  return None
            # quirk in getfacl output
            #output=output.encode('raw_unicode_escape').decode('string_escape')
            output=output.encode('utf8').decode('string_escape')

            acls=Acls(UnixAcl(),UserAcl(),GroupAcl(),DefaultUnixAcl(),DefaultUserAcl(),DefaultGroupAcl())
              acls.parse(output)
            return acls

      def getUsers(self):
            cl=sysSetting['getUsers']
            status,output=self.runToString(cl)
            if not status:
                  return []
            output=output.strip('\n\r ')
            users=output.splitlines()
            return users
      
      def getGroups(self):
            cl=sysSetting['getGroups']
            status,output=self.runToString(cl)
            if not status:
                  return []
            output=output.strip('\n\r ')
            groups=output.splitlines()
            return groups
      
      def getFstab(self):
            cl=sysSetting['getFstab']
            status,output=self.runToString(cl)
            if not status:
                  return []
            output=output.strip('\n\r ')
            fss=output.splitlines()
            return fss
      
      def getDistribution(self):
            cl=sysSetting['getDistribution']
            status,output=self.runToString(cl)
            if status:
                  return output.strip('\n\r ')
            return 'default'

#######################################################################
#     MAIN
#######################################################################

import sys
import os

if __name__ == "__main__":
      e=sys.argv[0]
      e=os.path.realpath(e)
      d=os.path.dirname(e)
      os.chdir(d)
      m=AclManager()
      if len(sys.argv)>1:
            path=sys.argv[1]
            m.pathEdit.set_text(path)
            m.refresh()
      gtk.main()


__author__='Bernard Bou <bou@ac-toulouse.fr>'

Generated by  Doxygen 1.6.0   Back to index