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

shares.py

#!/usr/bin/python
# -*-coding: UTF-8 -*-
# bbou@ac-toulouse.fr
# GPL license
# 2005-10-01 18:10:38  
# shares.py

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

import sharesparser
import runner
import acls
import share

#######################################################################
#     GLOBALS
#######################################################################

sysSetting={
      'testparm':'testparm -vs 2> /dev/null',
      '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'},

      'userId':'id -un',
      'groupId':'id -gn',
      'signal':'kill -SIGHUP `pidof smbd`',
      'readFile':'cat "%FILE%"',
      'writeFile':'cat - > "%FILE%" <<EOF\n%TEXT%\nEOF',
      '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\'',
}

#######################################################################
#     SHARESVIEW
#######################################################################

class SharesView:

      OK=0
      ERROR=1

      # column info = rank, type, header, expand
      IMAGE=0
      SHARE=1
      PATH=2
      READONLY=3
      BROWEABLE=4
      GUESTOK=5
      PERMS=6
      FSOWNERGROUPPERMS=7
      COMMENT=8

      columns=(
            [IMAGE,gtk.gdk.Pixbuf,'',False],
            [SHARE,str,'share',True],
            [PATH,str,'path',True],
            [READONLY,bool,'ro',False],
            [BROWEABLE,bool,'b',False],
            [GUESTOK,bool,'g',False],
            [PERMS,str,'perms',True],
            [FSOWNERGROUPPERMS,str,'fs',True],
            [COMMENT,str,'comment',False])

      pixbufs=[]

        def __init__(self,listview):

            # widget from glade
            self.listview=listview

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

            # model
            types=[t[1] for t in SharesView.columns]
            self.model=gtk.ListStore(*types)
            self.listview.set_model(self.model)       
            
            # columns
            self.setupColumns()     

            # images
            if SharesView.pixbufs==[]:
                  SharesView.pixbufs=self.setupImages()
                return
        
      def setupColumns(self): 
            types=[t[1] for t in SharesView.columns]
            for rank,datatype,header,expand in SharesView.columns:
                  column=gtk.TreeViewColumn(header)
                  if datatype==str:
                        cell=gtk.CellRendererText()
                        attr='text'
                  elif datatype==bool:
                        cell=gtk.CellRendererToggle()
                        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=['directory.png','directory-hidden.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

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

      def addShares(self,shares):
            for k in shares.keys():
                  self.addShare(shares[k])
            return

      def addShare(self,share):
            # data
            path=''
            if share.props.has_key('path'):
                  path=share.props['path']
            comment=''
            if share.props.has_key('comment'):
                  comment=share.props['comment']
            readonly=True
            if share.props.has_key('read only'):
                  readonly=share.props['read only']=='Yes'
            browseable=True
            if share.props.has_key('browseable'):
                  browseable=share.props['browseable']=='Yes'
            guest=False
            if share.props.has_key('guest ok'):
                  guest=share.props['guest ok']=='Yes'
            # perms
            perms=''
            if share.props.has_key('valid users'):
                  perms=perms+'valid=['+self.trimSubjects(share.props['valid users'])+']\n'
            if share.props.has_key('read list'):
                  perms=perms+'read=['+self.trimSubjects(share.props['read list'])+']\n'
            if share.props.has_key('write list'):
                  perms=perms+'write=['+self.trimSubjects(share.props['write list'])+']\n'
            if share.props.has_key('admin users'):
                  perms=perms+'admin=['+self.trimSubjects(share.props['admin users'])+']\n'
            if share.props.has_key('force user'):
                  perms=perms+'force user=['+self.trimSubjects(share.props['force user'])+']\n'
            if share.props.has_key('force group'):
                  perms=perms+'force group=['+self.trimSubjects(share.props['force group'])+']\n'
            perms=perms.rstrip('\n')
            
            # fsPerms
            ownerGroup='?.?'
            if hasattr(share,'fsOwnerGroup'):
                  ownerGroup='%s.%s' % (share.fsOwnerGroup[0],share.fsOwnerGroup[1])
            fsPerms='-'
            if hasattr(share,'fsPerms'):
                  fsPerms=share.fsPerms
            fsOwnerGroupPerms='%s\n%s' % (ownerGroup,fsPerms)

            # image
            imageIndex=SharesView.ERROR
            if share.pathExists:
                  imageIndex=SharesView.OK

            # insert data
            data=[self.pixbufs[imageIndex],share.name,path,readonly,browseable,guest,perms,fsOwnerGroupPerms,comment]
            self.model.append(data)
            return

      def trimSubjects(self,subjects):
            subjects=subjects.split(',')
            subjects=[s.strip('\'" ') for s in subjects]
            subjects=','.join(subjects)
            return subjects

#######################################################################
#     SHARES
#######################################################################

class SharesManager:
      
      def __init__(self):

            handlers={
                  'on_destroy':           self.exit,
                  'on_cancel_clicked':    self.exit,

                  'on_add_clicked': self.add,
                  'on_remove_clicked':    self.remove,
                  'on_properties_clicked':self.properties,
                  'on_select':            self.select,
                  'on_refresh_clicked':   self.forceRefresh,

                  'on_help_clicked':      self.help,
            }

            self.runner=runner.GtkRunner();
            self.parser=sharesparser.SharesParser(self.runner)
            self.shares={}

            self.widgets=gtk.glade.XML('shares.glade')
            self.widgets.signal_autoconnect(handlers)
            self.window=self['shares']
            self.sharesView=SharesView(self['sharesView'])
            self.aboutDialog=self['aboutDialog']
            return

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

      # termination
      
      def exit(self,*options):
            if __name__ == "__main__":
                  gtk.main_quit()
            else:
                  self.window.destroy()   
            return
                        
      # refresh

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

      def refresh(self):
            self.sharesView.clear()
            cl=sysSetting['testparm']
            status,output=self.runToString(cl)
            if not status:
                  return
            self.shares=self.parser.parse(output)
            self.sharesView.addShares(self.shares)
            return

      # add/remove

      def add(self,*options):
            s=share.ShareManager(self)
            s.shareName.set_text('myshare')
            s.sharePath.set_text('/mypath')
            s.shareComment.set_text('description')
            s.shareReadOnly.set_active(True)
            s.shareBrowseable.set_active(True)
            s.shareGuestOk.set_active(True)
            s.fsOwnerRead.set_active(True)
            s.fsOwnerWrite.set_active(True)
            s.fsOwnerExec.set_active(True)
            s.fsGroupRead.set_active(True)
            s.fsGroupWrite.set_active(False)
            s.fsGroupExec.set_active(True)
            s.fsOtherRead.set_active(True)
            s.fsOtherWrite.set_active(False)
            s.fsOtherExec.set_active(True)
            user=self.runToString(sysSetting['userId'])[1].strip('\n\r ')
            group=self.runToString(sysSetting['groupId'])[1].strip('\n\r ')
            s.fsOwner.put([user])
            s.fsGroup.put([group])
            s.dialog.run()
            self.refresh()
            return

      def remove(self,*options):
            selection=self.sharesView.listview.get_selection()
            (model,pathlist)=selection.get_selected_rows()
            pathlist.reverse()
            lines=self.getConf()
            for path in pathlist:
                  i=model.get_iter(path)
                  begin,end=self.parser.clip(lines,model.get_value(i,SharesView.SHARE))
                  if begin!=-1 and end!=-1:
                        #print [begin,end]
                        #print 'vvv'
                        #for line in lines[begin:end]:
                        #     print line,
                        #print '^^^'
                        lines[begin:end]=[]
                        self.setConf(lines)
                              model.remove(model.get_iter(path))
            return

      # select

      def properties(self,w,*options):
            self.select(w)
            return

      def select(self,w,*options):
            sharename=self.getSelectedShare()
            if sharename!=None:
                  selectedShare=self.shares[sharename]
                  m=share.ShareManager(self)
                  m.put(selectedShare)
                  #m.dialog.run()
                  #self.refresh()
            return

      # helpers

      def getSelectedShare(self):
            selection=self.sharesView.listview.get_selection()
            (model,pathlist)=selection.get_selected_rows()
            if pathlist!=[]:
                  iter=self.sharesView.model.get_iter(pathlist[0])
                  name=self.sharesView.model.get_value(iter,SharesView.SHARE)
                  return name
            return None

      def getSelectedPath(self):
            selection=self.sharesView.listview.get_selection()
            (model,pathlist)=selection.get_selected_rows()
            if pathlist!=[]:
                  iter=self.sharesView.model.get_iter(pathlist[0])
                  name=self.sharesView.model.get_value(iter,SharesView.PATH)
                  return name
            return None

      # acls

      def acls0(self,*options):
            m=acls.AclManager()
            path=self.getSelectedPath()
            if path!=None:
                  m.pathEdit.set_text(path)
                  m.refresh()
            return

      def acls(self,*options):
            os.spawnv(os.P_NOWAIT,'./acls.py',['./acls.py'])
            return

      # debug

      def printShares(self,shares):
            for k in shares.keys():
                  shares[k].printShare()

      def printConf(self,lines):
            for line in lines:
                  print line,
            return

      # help

      def help(self,*options):
            distribution=self.getDistribution()
            browser=sysSetting['browser'][distribution]
            urlbase=sysSetting['docs'][distribution]
            if distribution=="suse" or distribution=="debian":
                  url=urlbase % ('shares.html')
            else:
                  url=urlbase % (self.getVersion(),'shares.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):
            status,output=self.runner.runToString(cl)
            return status,output

      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 getConf(self):
            cl=sysSetting['readFile']
            cl=cl.replace('%FILE%','/etc/samba/smb.conf')
            status,output=self.runToString(cl)
            if not status:
                  return []
            output=output.strip('\n\r ')
            return output.splitlines()

      def setConf(self,lines):
            text='\n'.join(lines)
            cl=sysSetting['writeFile']
            cl=cl.replace('%TEXT%',text)
            cl=cl.replace('%FILE%','/etc/samba/smb.conf')
            status,output=self.runToString(cl)
            return

      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=SharesManager()
      m.refresh()

      gtk.main()

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

Generated by  Doxygen 1.6.0   Back to index