Βασίλης Κούλης
T03197
Το Samba φτιάχτηκε από τον Andrew Tridgell για διαμοιρασμό αρχείων και συσκευών μεταξύ των Windows και των Unix το 1991.
Το πρόγραμμα διατίθεται δωρεάν με άδεια GPLv3 και είναι γραμμένο σε C, C++ και σε Python
Οι πιο σημαντικές εκδώσεις είναι οι ακόλουθες:
Το GTK+ είναι μια αντικειμενοστραφής εργαλειοθήκη widget γραμμένη σε C για την δημιουργία γραφικού περιβάλλοντος σε οποιαδήποτε πλατφόρμα.
Φτιάχτηκε το 1998 από τον Spancer Kimball με άδεια ανοιχτού λογισμικού LGPL.
Ξεκίνησα χρησιμοποιώντας το Quickly που είναι ένα πρόγραμμα της Canonical για εύκολο σχεδιασμό και επεξεργασία κώδικα με glade και python. Επίσης μπορεί να δημοσιεύσει εύκολα το project χρησιμοποιώντας το GNU Bazaar ή το Launchpad.
Οι βασικές εντολές του quickly πακέτου είναι οι ακόλουθες:
Το Glade δημιουργεί ένα αρχείο xml.
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="UserOptions">
<property name="transient_for">samba_config_window</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="UserButtonOK">
<property name="label" translatable="yes">OK</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="UserButtonCancel">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<accelerator key="w" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="UserLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">15</property>
<property name="label" translatable="yes">UserName</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="PasswordLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">15</property>
<property name="label" translatable="yes">Password</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="UserEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="invisible_char">•</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="PasswordEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="invisible_char">•</property>
<property name="input_purpose">password</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">UserButtonOK</action-widget>
<action-widget response="0">UserButtonCancel</action-widget>
</action-widgets>
</object>
</interface>
Αντίστοιχες εφαρμογές για διαχείριση του samba είναι οι παρακάτω:
Η εφαρμογή αποτελείται από 4 παράθυρα:
Υπάρχουν 3 κλάσεις:
class Window(WinFunc):
'''Main Class for Signals'''
def __init__(self):
self.MainWindow = builder("SambaConfigWindow.glade","samba_config_window")
self.ui = self.MainWindow.get_ui(self)
PASSWORD = "1"
WinFunc.Initialize(self, PASSWORD)
#Window Signals
def on_samba_config_window_destroy(self, widget, data=None):
Gtk.main_quit()
def on_mnu_close_activate(self, widget, data=None):
Gtk.main_quit()
def on_ShareOptions_delete_event(self, widget, data=None):
self.ui.ShareOptions.hide()
return True
def on_BrowseDialog_delete_event(self, widget, data=None):
self.ui.BrowseDialog.hide()
return True
def on_UserOptions_delete_event(self, widget, data=None):
self.ui.UserOptions.hide()
return True
#Toolbar Main Buttons
def on_SaveButton_clicked(self, widget, data=None):
WinFunc.SaveChanges(self)
def on_RefreshButton_clicked(self, widget, data=None):
WinFunc.Initialize(self, self.ROOTPASS)
#Shares Tab
def on_EditButton_clicked(self, widget, data=None):
WinFunc.EditShares(self)
def on_DeleteButton_clicked(self, widget, data=None):
WinFunc.DeleteShares(self)
def on_AddButton_clicked(self, widget, data=None):
WinFunc.AddShares(self)
def on_SharesTree_focus_out_event(self,widget,gpoint):
self.ui.EditButton.set_sensitive(False)
self.ui.DeleteButton.set_sensitive(False)
self.ui.AddButton.set_sensitive(False)
def on_SharesTree_focus_in_event(self,widget,gpoint):
self.ui.EditButton.set_sensitive(True)
self.ui.DeleteButton.set_sensitive(True)
self.ui.AddButton.set_sensitive(True)
WinFunc.WriteShares(self)
#Users Tab
def on_AddUserButton_clicked(self,widget,data=None):
WinFunc.AddUser(self)
def on_EditUserButton_clicked(self,widget,data=None):
WinFunc.EditUser(self)
def on_DeleteUserButton_clicked(self,widget,data=None):
WinFunc.DeleteUser(self)
#Shares Window
def on_SharesCheckPublic_toggled(self, widget, data=None):
if (self.ui.SharesCheckPublic.get_active()==True):
self.ui.TabsNotebook.set_show_tabs(False)
else:
self.ui.TabsNotebook.set_show_tabs(True)
def on_SharesButtonOK_clicked(self, widget, data=None):
WinFunc.ConfirmShareChanges(self)
def on_SharesButtonBrowse_clicked(self, widget, data=None):
self.MainWindow.ShowWindow("BrowseDialog")
Directory = self.ui.SharesEntryDirectory.get_text()
if(Directory == ""):
self.ui.BrowseDialog.set_current_folder("/home")
else:
self.ui.BrowseDialog.set_current_folder(Directory)
def on_SharesButtonCancel_clicked(self, widget, data=None):
self.ui.ShareOptions.hide()
#BrowseDialog Window
def on_BrowseOK_clicked(self, widget, data=None):
try:
self.ui.SharesEntryDirectory.set_text(self.ui.BrowseDialog.get_current_folder())
self.ui.BrowseDialog.hide()
except:
output = Popen(["notify-send", "This is not a Directory"]).communicate()
def on_BrowseCancel_clicked(self, widget, data=None):
self.ui.BrowseDialog.hide()
#Users Window
def on_UserButtonOK_clicked(self, widget, data=None):
WinFunc.ConfirmUserChanges(self)
def on_UserButtonCancel_clicked(self, widget, data=None):
self.ui.UserOptions.hide()
class WinFunc():
def Initialize(self, ROOTPASS):
'''Define Variables and Call Methods for initialization'''
# DEFINE Variables
...
# CALL Methods
...
# Files-Lists
def __CreateSMBLIST(self):
'''Private Method to READ the smb config file and write to SMBLIST with the proper names'''
...
def __FixSynonyms(self):
'''Fix the names in the SMBLIST'''
...
def __CreateSharesList(self):
''' Search in the SMBLIST for shares and create a new list, SharesList, to store them '''
...
# Append items in List
...
def __WriteConfig(self):
''' Write the whole smb config file in the Configuration Tab of the application GUI'''
...
# Settings Tab
def __GetProperties(self, search):
''' Search in the SMBLIST to for specific configuration '''
...
def __PrintShareExists(self):
''' Search the SMBLIST for printer share '''
...
# Shares Tab
def WriteShares(self):
''' Write all the shares from the SharesList to Shares Tab in the application GUI '''
...
def DeleteShares(self):
''' Get the selected row and delete it from Shares Tab and from SharesList '''
...
def AddShares(self):
''' Open new empty Window for share '''
...
def EditShares(self):
''' Get the selected share and open a new share Window based on the SharesList '''
...
def __OpenShares(self, Name, Directory, Description, Access, Permissions, Title):
''' Write the properties to the Shares Window '''
...
def ConfirmShareChanges(self):
# Get Options from the window
...
# Get Selected Users who have access to the shared directory
...
# Check if Everything is Fine
...
# Update the SharesList with the new Options
...
# Users Tab
def __WriteUsers(self):
''' Write all the Users from the the output of the pdbedit to Users Tab in the application GUI '''
...
def DeleteUser(self):
''' Delete the selected User from the application GUI and from the system '''
...
def AddUser(self):
''' Open new empty Window for UserName and Password '''
...
def EditUser(self):
''' Get the selected User and open a new User Window to edit the user password '''
...
def __OpenUsers(self, UserName, Password, Title):
''' Write the properties to the Users Window '''
...
def ConfirmUserChanges(self):
# Get Options from the window
...
def ChangeUser(self, UserName, Password):
''' Used to add/edit the user of the system '''
# If the User exists then Edit the password only
...
# Add User to the system
...
# Change Password of the User
# If no change is made to the window's password
...
# Ending
def SaveChanges(self):
...
# Write Config from template file
...
# Write Shares
...
# Save the list to the config file
...
class builder():
def __init__(self,filename,window):
self.widgets = {}
self.widgets = {}
self.builder = Gtk.Builder()
self.builder.add_from_file(filename)
self.ShowWindow(window)
tree = ElementTree()
tree.parse(filename)
ele_widgets = tree.getiterator("object")
for ele_widget in ele_widgets:
name = ele_widget.attrib['id']
widget = self.builder.get_object(name)
self.widgets[name] = widget
print dir(widget)
def ShowWindow(self,window):
self.builder.get_object(window).show()
def get_ui(self, callback_obj):
'''Return the attributes of the widgets and Connects to Handler'''
#Get all methods of class window and write them to a dictionary
methods = []
for k in dir(callback_obj):
try:
attr = getattr(callback_obj, k)
except:
continue
if inspect.ismethod(attr):
methods.append((k, attr))
methods.sort()
dict_methods = dict(methods)
callback_handler_dict = {}
callback_handler_dict.update(dict_methods)
for (widget_name, widget) in self.widgets.items():
setattr(self, widget_name, widget) #Return the attribute
signal_names = self.__get_signals(widget) #Get a list of the widget signals
for signal_name in signal_names:
signal_name = signal_name.replace("-", "_")
handler_names = ["on_%s_%s" % (widget_name, signal_name)]
#For every method of the window, connect the signals
for handler_name in handler_names:
target = handler_name in callback_handler_dict.keys()
if target:
widget.connect(signal_name, callback_handler_dict[handler_name])
return self
def __get_signals(self, widget):
'''Return the signals of the widget'''
signal_ids = []
try:
widget_type = type(widget)
while widget_type:
signal_ids.extend(GObject.signal_list_ids(widget_type))
widget_type = GObject.type_parent(widget_type)
except RuntimeError:
pass
signal_names = [GObject.signal_name(sid) for sid in signal_ids]
return signal_names
Βασικές ρυθμίσεις
Επιλέγει ποιους φακέλους να μοιράζεται
Δημιουργεί, διαγράφει χρήστες
Εμφανίζεται το τελικό αποτέλεσμα που θα αποθηκευτεί