#!/usr/bin/python

####
# File: gnome-password-generator
# Author: Chris Ladd
# Created: September 30, 2003
####

####
# Copyright (c) 2004 Chris Ladd
#
# 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
####

import random
import string
import time
import gtk
import pango
import gnome
import gnome.ui

VERSION = "1.4"
PIXMAPDIR = "/usr/share/pixmaps"

class Application(gnome.ui.App) :

    def DeleteCallback(self, widget, event, data = None) :
        return gtk.FALSE

    def DestroyCallback(self, widget, data = None) :
        gtk.main_quit()
    
    def ClickedCallback(self, widget, data = None) :
        # Clear the textview
        buffer = self.textview.get_buffer()
        buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
        
        # Generate the passwords
        self.GeneratePasswords(self.length_spin_button.get_value_as_int(), self.count_spin_button.get_value_as_int())
    
    def AboutCallback(self, widget, data = None) :
        gnome.ui.About("Gnome Password Generator", VERSION, "Copyright 2004 Chris Ladd", "Secure Password Generator", ["Chris Ladd <caladd@particlestorm.net>"], None, None, self.image.get_pixbuf()).show()
    
    def GeneratePasswords(self, password_length, password_count) :
        random.seed()
        
        for current_password in range(password_count) :
            password = []
            
            for current_character in range(password_length) :
                random_number = random.randint(0, 61)
                
                if random_number >= 0 and random_number < 10 :
                    password.append(chr(48 + random_number))
                elif random_number >= 10 and random_number < 36 :
                    password.append(chr(55 + random_number))
                else :
                    password.append(chr(61 + random_number))
            
            self.PrintMessage(string.join(password, "")+"\n")
        
    def PrintMessage(self, message) :
        # Add the text at the end
        buffer = self.textview.get_buffer()
        iter = buffer.get_end_iter()
        buffer.insert(iter, message)
        self.textview.scroll_to_iter(iter, 0.0, gtk.FALSE, 0.0, 0.0)
        
        # Do any needed events
        while gtk.events_pending() :
            gtk.main_iteration_do(gtk.FALSE)
      
    def __init__(self) :
        # Setup the application
        gnome.ui.App.__init__(self, "Gnome Password Generator", "Gnome Password Generator")
        
		# Setup the main window
        self.image = gtk.Image();
        self.image.set_from_file(PIXMAPDIR + "/gnome-password-generator.png");

        self.set_icon(self.image.get_pixbuf());
        
        self.connect("delete_event", self.DeleteCallback)
        self.connect("destroy", self.DestroyCallback)
        
        vbox = gtk.VBox(gtk.FALSE, 0)
        
        # Setup the main menubar
        menu_items = (
            ("/_File", None, None, 0, "<Branch>"),
            ("/File/_Quit", "<control>Q", self.DestroyCallback, 0, "<StockItem>", gtk.STOCK_QUIT),
            ("/_Help", None, None, 0, "<Branch>"),
            ("/_Help/_About", None, self.AboutCallback, 0, "<StockItem>", "gnome-stock-about")
        )
    
        accel_group = gtk.AccelGroup()
        item_factory = gtk.ItemFactory(gtk.MenuBar, "<main>", accel_group)
        item_factory.create_items(menu_items)
        self.add_accel_group(accel_group)
    
        menubar = item_factory.get_widget("<main>")
        self.set_menus(menubar)
    
        # Setup the layout controls
        inner_vbox = gtk.VBox(gtk.FALSE, 0)
        
        hbox_top = gtk.HBox(gtk.FALSE, 0)
        top_vbox = gtk.VBox(gtk.FALSE, 0)
        top_frame = gtk.Frame()
        
        top_vbox.pack_start(hbox_top, gtk.TRUE, gtk.TRUE, 6)
        top_frame.add(top_vbox)
        hbox = gtk.HBox(gtk.FALSE, 0)
        hbox.pack_start(top_frame, gtk.TRUE, gtk.TRUE, 4)
        inner_vbox.pack_start(hbox, gtk.FALSE, gtk.FALSE, 6)
        
        hbox_bottom = gtk.HBox(gtk.FALSE, 0)
        bottom_vbox = gtk.VBox(gtk.FALSE, 0)
        
        bottom_vbox.pack_start(hbox_bottom, gtk.TRUE, gtk.TRUE, 6)
        inner_vbox.pack_start(bottom_vbox, gtk.TRUE, gtk.TRUE, 0)
        
        vbox.pack_start(inner_vbox, gtk.TRUE, gtk.TRUE, 0)
        
        # Setup the length label
        length_hbox = gtk.HBox(gtk.FALSE, 0)
        self.length_label = gtk.Label("Length:")
        length_hbox.pack_start(self.length_label, gtk.FALSE, gtk.FALSE, 0)
        
        # Setup the length spin button
        adjustment = gtk.Adjustment(10, 6, 64, 1, 1, 0)
        self.length_spin_button = gtk.SpinButton(adjustment, 0, 0)
        length_hbox.pack_start(self.length_spin_button, gtk.FALSE, gtk.FALSE, 6)
        hbox_top.pack_start(length_hbox, gtk.FALSE, gtk.FALSE, 6)
        
        # Setup the count label
        count_hbox = gtk.HBox(gtk.FALSE, 0)
        self.count_label = gtk.Label("Count:")
        count_hbox.pack_start(self.count_label, gtk.FALSE, gtk.FALSE, 0)
        
        # Setup the count spin button
        adjustment = gtk.Adjustment(1, 1, 100, 1, 1, 0)
        self.count_spin_button = gtk.SpinButton(adjustment, 0, 0)
        count_hbox.pack_start(self.count_spin_button, gtk.FALSE, gtk.FALSE, 6)
        hbox_top.pack_start(count_hbox, gtk.FALSE, gtk.FALSE, 20)
        
        # Setup the start button
        self.button = gtk.Button("", gtk.STOCK_EXECUTE)
        self.button.connect("clicked", self.ClickedCallback) 
        hbox_top.pack_end(self.button, gtk.FALSE, gtk.FALSE, 6)
        
        # Setup the status window
        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)
        self.scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
        self.textview = gtk.TextView()
        self.textview.set_editable(gtk.FALSE)
        self.textview.modify_font(pango.FontDescription("Monospace 12"))
        self.textview.set_left_margin(10)
        self.scrolledwindow.add(self.textview)
        hbox_bottom.pack_start(self.scrolledwindow, gtk.TRUE, gtk.TRUE, 4)

        # Show everything
        self.set_contents(vbox)
        self.set_default_size(400, 300)
        self.set_focus(self.button)
        self.show_all()
    
def Main() :
    program = gnome.init("gnome-password-generator", VERSION)
	
    # Check to make sure the right version of PyGTK is installed
    if gtk.pygtk_version[0] is 1 :
        message = "You appear to be running PyGTK version %i.%i.%i but this program requires version 2.0 or greater.\n\nPlease upgrade to a newer version." % gtk.pygtk_version
        dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, message)
        dialog.run()
    else :
        application = Application()
    
        gtk.main()

# Start the program
if __name__ == "__main__" :
    Main()
