Login.py :  » Network » emesene » emesene-1.6.2 » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » emesene 
emesene » emesene 1.6.2 » Login.py
# -*- coding: utf-8 -*-

#   This file is part of emesene.
#
#    Emesene 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.
#
#    emesene 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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with emesene; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import os
import gtk
import gobject
import base64 # yes base64, go out and look how gaim does it :P
import shutil

import paths
import Widgets
import dialog
import stock
import emesenelib.common

class Login(gtk.VBox):
    '''This class represents the login widget where you insert the user,
    pass and status'''

    def __init__(self , controller, interface):
        '''Constructor'''

        gtk.VBox.__init__(self)

        self.controller = controller

        self.set_spacing(20)
        self.set_border_width(20)

        self.buildInterface(interface)

    def buildInterface(self, interface):

        # Load users.dat
        self.users = UserManager(os.path.join(paths.CONFIG_DIR, 'users.dat'))

        self.currentInterface = interface

        lUser = gtk.Label(_('_User:'))
        lPass = gtk.Label(_('_Password:'))
        self.lCaps = gtk.Label('')
        lStatus = gtk.Label(_('_Status:'))

        lUser.set_use_underline(True)
        lPass.set_use_underline(True)
        lStatus.set_use_underline(True)

        # Make a ListStore for users
        self.userListStore = gtk.ListStore(gobject.TYPE_STRING, gtk.gdk.Pixbuf)
        # User entry with combo (from ListStore)
        self.tUser = gtk.ComboBoxEntry(self.userListStore, 0)
        self.tUser.connect("changed", self.on_comboxEntry_changed)
        self.tUser.connect("key-release-event", self.on_comboxEntry_keyrelease)
        # User entry completion (from ListStore)
        self.userCompletion = gtk.EntryCompletion()
        self.userCompletion.set_model(self.userListStore)
        self.tUser.get_children()[0].set_completion(self.userCompletion)
        self.userCompletion.connect('match-selected', self.matchSelected)
        # Add pictures to the completion
        self.userPixbufCell = gtk.CellRendererPixbuf()
        self.userCompletion.pack_start(self.userPixbufCell)
        self.userCompletion.add_attribute(self.userPixbufCell, 'pixbuf', 1)
        self.userCompletion.set_text_column(0)

        # Make a ListStore for Status
        self.statusListStore = gtk.ListStore(gtk.gdk.Pixbuf,
                                              gobject.TYPE_STRING,
                                              gobject.TYPE_STRING)

        self.tStatus = gtk.ComboBox(self.statusListStore)
        self.statusPixbufCell = gtk.CellRendererPixbuf()
        self.statusTextCell = gtk.CellRendererText()
        self.tStatus.pack_start(self.statusPixbufCell, False)
        self.tStatus.pack_start(self.statusTextCell, False)
        self.statusPixbufCell.set_property('xalign', 0.0)
        self.statusPixbufCell.set_property('xpad', 5)
        self.statusTextCell.set_property('xalign', 0.0)
        self.statusTextCell.set_property('xpad', 5)
        self.tStatus.add_attribute(self.statusTextCell, 'text', 2)
        self.tStatus.add_attribute(self.statusPixbufCell, 'pixbuf', 0)

        self.tPass = gtk.Entry(128)
        self.tPass.set_visibility(False)
        self.tPass.connect('activate' , self.bLogin_clicked)
        self.tPass.connect('key-press-event', self.on_password_keypressed)

        lUser.set_mnemonic_widget(self.tUser)
        lPass.set_mnemonic_widget(self.tPass)
        lStatus.set_mnemonic_widget(self.tStatus)

        # fill the status combobox
        self.statusList = []
        j = 0
        for i in self.controller.status_ordered[ 1 ]:
            if i != 'offline' and i not in self.statusList:
                self.statusListStore\
                        .append([ self.controller.theme.statusToPixbuf(
                               emesenelib.common.status_table[i]).scale_simple(20,20,gtk.gdk.INTERP_BILINEAR), i,
                               _(self.controller.status_ordered[2][j]) ])
                self.statusList.append(i)
            j += 1

        self.tStatus.set_active(0)

        pixbuf = self.controller.theme.getImage('login', False)
        self.loginImage = Widgets.avatarHolder()
        self.loginImage.set_from_pixbuf(pixbuf)
        if not self.controller.config.glob['dontShowAvatarInLoginWindow']:
            self.pack_start(self.loginImage , True , False)

        self.fieldsBox = gtk.VBox(spacing=10)

        userBox = gtk.VBox(spacing=4)
        lUser.set_alignment(0.0, 0.5)
        userBox.pack_start(lUser , False , False)
        userBox.pack_start(self.tUser , False , False)

        self.fieldsBox.pack_start(userBox, False, False)

        passBox = gtk.VBox(spacing=4)
        passLBox = gtk.HBox(spacing=6)
        lPass.set_alignment(0.0, 0.5)
        passLBox.pack_start(lPass , False , False)
        passLBox.pack_start(self.lCaps , False , False)
        passBox.pack_start(passLBox , False , False)
        passBox.pack_start(self.tPass , False , False)

        self.fieldsBox.pack_start(passBox, False, False)

        statusBox = gtk.VBox(spacing=4)
        lStatus.set_alignment(0.0, 0.5)
        statusBox.pack_start(lStatus , False , False)
        statusBox.pack_end(self.tStatus, True, True)

        self.fieldsBox.pack_start(statusBox, False, False)

        fieldsAlig = gtk.Alignment(0.5, 0.5, 0.75, 0.0)
        fieldsAlig.add(self.fieldsBox)
        self.pack_start(fieldsAlig, True, False)

        self.lReconnectCounter = None

        buttonBox = gtk.HButtonBox()

        if interface == 'login':
            self.bLogin = gtk.Button(_('_Login'), gtk.STOCK_CONNECT)
            self.bLogin.connect('clicked' , self.bLogin_clicked)
            buttonBox.pack_start(self.bLogin, False, False)

            self.cRemember = gtk.CheckButton(_('_Remember me'), True)
            self.cRemember.connect('toggled' , self.on_cRemember_toggled)

            self.forgetMe = gtk.EventBox()
            self.forgetMe.set_events(gtk.gdk.BUTTON_PRESS_MASK)
            self.forgetMeLabel = gtk.Label('<span foreground="#0000AA">(' + \
                                            _('Forget me') + ')</span>')
            self.forgetMeLabel.set_use_markup(True)
            self.forgetMe.add(self.forgetMeLabel)
            self.forgetMe.connect('button_press_event', self.onForgetMe)
            self.forgetMe.set_child_visible(False)

            self.cRememberPass = gtk.CheckButton(_('R_emember password'), True)
            self.cRememberPass.connect('toggled' , self.on_cRememberPass_toggled)

            # TODO: find a better description and get-text it
            self.cAutoLogin = gtk.CheckButton(_('Auto-Login'), True)
            self.cAutoLogin.connect('toggled' , self.on_cAutoLogin_toggled)

            #this fixes a bug with user config
            current_user = self.controller.config.getCurrentUser()

            if self.controller.config.glob['rememberMe'] and current_user != '':
                self.cRemember.set_active(True)

            if self.controller.config.glob['rememberMyPassword'] and current_user != '':
                self.cRememberPass.set_active(True)

            if self.controller.config.glob['autoLogin'] and current_user != '':
                self.cAutoLogin.set_active(True)

            self.checkBox = gtk.VBox(spacing=4)

            rememberBox = gtk.HBox(spacing=4)
            rememberBox.pack_start(self.cRemember , False , False)
            rememberBox.pack_start(self.forgetMe , False , False)
                
            self.checkBox.pack_start(rememberBox, False, False)
            self.checkBox.pack_start(self.cRememberPass, False, False)
            self.checkBox.pack_start(self.cAutoLogin, False, False)

            try:
                import locale
                link = "http://status.messenger.msn.com/Status.aspx?mkt="
                link += locale.getlocale()[0].replace('_','-')
                serverStatus = gtk.LinkButton(link,_('Service Status'))
                self.checkBox.pack_start(serverStatus, False, False)
            except:
                # some people have really weird python installs
                pass
                            
            checkAlig = gtk.Alignment(0.5, 0.5)
            checkAlig.add(self.checkBox)

            self.pack_start(checkAlig , True , False)

            serverBox = gtk.VBox(spacing=40)
            serverLBox = gtk.HBox(spacing=6)

            serverBox.pack_start(serverLBox , False , False)

            checkAlig1 = gtk.Alignment(0.5, 0.5)
            checkAlig1.add(serverBox)

            self.pack_start(buttonBox, True, False)
        
            self.pack_start(checkAlig1, True, False)

        elif interface == 'reconnect':
            self.fieldsBox.set_sensitive(False)

            self.lConnectionError = gtk.Label()
            self.lConnectionError.set_markup('<b>' + _('Connection error') + '</b>')

            self.lReconnectCounter = gtk.Label()

            self.bCancelReconnect = gtk.Button(_('Cancel'), gtk.STOCK_CANCEL)
            self.bCancelReconnect.connect('clicked', self.onCancelReconnect)
            self.bReconnectNow = gtk.Button(_('Reconnect now'), gtk.STOCK_CONNECT)
            self.bReconnectNow.connect('clicked' , self.onReconnectNow)

            self.pack_start(self.lConnectionError, True, False)
            self.pack_start(self.lReconnectCounter, True, False)
            buttonBox.pack_start(self.bReconnectNow, True, False)
            buttonBox.pack_start(self.bCancelReconnect, False, False)
            self.pack_start(buttonBox, True, False)
        elif interface == 'loading':
            self.fieldsBox.set_sensitive(False)

            pixbuf = self.controller.theme.getImage('loading', True)
            self.loading = gtk.image_new_from_animation(pixbuf)

            cancelButton = gtk.Button(_('Cancel'), gtk.STOCK_CANCEL)
            cancelButton.connect('clicked', self.onCancelLogin)
            buttonBox.pack_start(cancelButton, False, False)

            self.pack_start(self.loading, False, False)
            self.pack_start(buttonBox, True, False)
            # XXX: progress stuff maybe?

        # fill the user list
        self.refreshUserList()
        if self.users.userExists(self.controller.config.glob['lastLoggedAccount']):
                self.tUser.get_children()[0].set_text(self.controller.config.glob['lastLoggedAccount'])

        self.show_all()
        self.tUser.grab_focus()

    def setFieldValues(self, user, password, status):
        self.tUser.prepend_text(user)
        self.tUser.set_active(0)
        self.tPass.set_text(password)

        i = 0
        for item in self.statusListStore:
            if item[1] == status: break
            i += 1
        self.tStatus.set_active(i)

    def onCancelReconnect(self, *args):
        self.controller.cancelReconnect()

    def onCancelLogin(self,*args):
        self.controller.cancelLogin()
        
    def onReconnectNow(self,*args):
        self.lReconnectCounter.set_text(_('Reconnecting...'))
        self.login()
        
    def refreshUserList(self):
        '''fill the user list to the completion and combo'''

        self.userListStore.clear()
        for i in sorted(self.users.getUsers(), key=lambda x: x.lower()):
            self.userListStore.append([ i , self.controller.theme.getImage('online').scale_simple(20,20,gtk.gdk.INTERP_BILINEAR) ])

    def on_cRemember_toggled(self , *args):
        self.controller.config.glob['rememberMe'] = self.cRemember.get_active()
        if not self.cRemember.get_active():
            self.cRememberPass.set_active(False)

    def on_cRememberPass_toggled(self , *args):
        if self.cRememberPass.get_active():
            self.controller.config.glob['rememberMyPassword'] = True
            self.cRemember.set_active(True)
            self.cRemember.set_sensitive(False)
        else:
            self.controller.config.glob['rememberMyPassword'] = False
            self.cAutoLogin.set_active(False)
            self.cRemember.set_sensitive(True)
            # Reset password
            if self.users.userExists(self.getUser()):
                if self.users.getPassword(self.getUser()) != '':
                    self.tPass.set_sensitive(True)
                    self.tPass.set_text('')
                    self.users.resetPassword(self.getUser())
                    self.users.save()

    def on_cAutoLogin_toggled(self , *args):
        if self.cAutoLogin.get_active():
            self.controller.config.glob['autoLogin'] = True
            self.cRememberPass.set_active(True)
            self.cRememberPass.set_sensitive(False)
        else:
            self.controller.config.glob['autoLogin'] = False
            self.cRememberPass.set_sensitive(True)

    def setReconnectCounter(self, seconds):
        if self.lReconnectCounter:
            if seconds > 0:
                self.lReconnectCounter.set_text(_('Reconnecting in %s seconds') % str(seconds))
            else:
                self.lReconnectCounter.set_text(_('Reconnecting...'))

    def login(self):
        if self._control_fields():
            return
        self.controller.login(self.getUser() , self.getPass() , self.getStatus())

    def bLogin_clicked(self , *args):
        if self._control_fields():
            return

        if self.currentInterface == 'login' and self.cRemember.get_active():
            if self.cRememberPass.get_active():
                self.users.addUser(self.getUser(), base64.b16encode(self.getPass()), self.getStatus())
            else:
                self.users.addUser(self.getUser(),'',self.getStatus())
        else:
            self.users.removeUser(self.getUser())

        self.users.save()
        self.login()
 
    def _control_fields(self):
        '''control that all login fields are not empty'''
        if self.getUser() == '' or self.getPass() == '' or self.getStatus() == '':
            self.controller.mainWindow.showNiceBar(_("User or password empty"),
                      self.controller.niceBarWarningColor, gtk.STOCK_DIALOG_WARNING)     
            return True
        else:
            return False

    def getUser(self):
        self.active_user = self.tUser.get_active()

        return self.tUser.get_active_text()

    def getPass(self):
        return self.tPass.get_text()[:16]

    def getStatus(self):
        return self.statusListStore.get(self.tStatus.get_active_iter(), 1)[0]

    def on_comboxEntry_changed(self, *args):
        self.getPreferences(self.getUser())

    def matchSelected(self, completion=None, model=None, iter=None):
        '''this callback is called when a user is selected with autocompletion
        then i check if the password is stored.'''
        userInEntry = model.get(iter, 0)[ 0 ]
        self.getPreferences(userInEntry)

    def getPreferences(self, user):

        if not self.users.userExists(user):
            self.loginImage.set_from_pixbuf(self.controller.theme.getImage('login', False))
            self.tPass.set_text('')
            self.tPass.set_sensitive(True)
            self.tStatus.set_active(self.statusList.index('online'))
            if self.currentInterface == 'login':
                self.cRemember.set_active(False)
                self.forgetMe.set_child_visible(False)

        else:
            password = self.users.getPassword(user)
            status = self.users.getStatus(user)
            avatar = self.getUserAvatarPath(user)

            try:
                self.loginImage.set_from_file(avatar)
            except gobject.GError:
                pass
            except: # everything else, like open() problems
                pass

            if self.currentInterface == 'login':
                self.cRemember.set_active(True)
                self.forgetMe.set_child_visible(True)

            if password != '':
                self.tPass.set_text(base64.b16decode(password))
                if self.currentInterface == 'login':
                    self.cRememberPass.set_active(True)
                    self.tPass.set_sensitive(False)
            else:
                self.tPass.set_text('')
                if self.currentInterface == 'login':
                    self.cRememberPass.set_active(False)
                    self.tPass.set_sensitive(True)

            if status != '':
                try:
                    self.tStatus.set_active(self.statusList.index(status) )
                except:
                    pass
            

    def getUserAvatarPath(arg, user):
        user = user.replace('@', '_').replace('.', '_')
        try:
            s = open(os.path.join(paths.CONFIG_DIR, user, 'config'), 'r').read()
            s.replace(' ', '')
            path = s.split('avatarPath=')[1].split('\n')[0]
        except Exception, e:
            path = paths.DEFAULT_THEME_PATH + 'login.png'

        if os.path.isfile(path):
            return path

        return paths.DEFAULT_THEME_PATH + 'login.png'

    def onForgetMe(self, *args):
        '''This method is called when the user press the forget me event box'''
        def _yes_no_cb(response):
            '''callback from the confirmation dialog'''
            if response == stock.YES:
                try: # Delete user's folder
                    user = self.getUser().replace('@', '_').replace('.', '_')
                    shutil.rmtree(os.path.join(paths.CONFIG_DIR, user))
                except: 
                    pass

                self.users.removeUser(self.getUser())
                self.tUser.get_children()[0].set_text('')
                self.tPass.set_text('')
                self.forgetMe.set_child_visible(False)
                self.refreshUserList()
                self.users.save()

        dialog.yes_no(
            _('Are you sure you want to delete the account %s ?') % self.getUser() , _yes_no_cb)

    def on_comboxEntry_keyrelease(self, widget, event):
        if event.keyval == gtk.keysyms.Tab:
            self.tPass.grab_focus()

        if event.keyval == gtk.keysyms.Return:
            self.login()

    def on_password_keypressed(self, widget, event):
        if (event.state & 0x00000002) == 2: # Verify caps lock state
            warning = _('Attention: Your capslock is enabled!')
            self.lCaps.set_markup(
                '<span foreground="#FF0000">%s</span>' % warning)
        elif self.lCaps.get_text():
            self.lCaps.set_text('')

class UserManager(object):
    '''This class manages the file that hold the user:password data
    the format of users.dat is:
    mail:password:status
    the password is encrypted in a magic way :P'''

    def __init__(self, path):
        '''Contructor'''

        self.path = path
        self.users = {}

        self.load()

    def getUsers(self):
        '''return a list of users'''

        return self.users.keys()

    def getPassword(self, user):
        '''return the password of the user'''

        if user in self.users:
            return self.users[user][0]
        else:
            return ''

    def getStatus(self, user):
        '''return the status of the user'''

        if user in self.users:
            return self.users[user][1]
        else:
            return 'NLN'

    def addUser(self, user, password = '', status = 'online'):
        '''add a user to the dictionary'''

        # if no password provided and we already have an user saved
        # with a password, we keep it
        # INFO: iAgree -- Why????!!!
        if password == '' and \
           user in self.users and \
           self.users[user][0] != '':
            password = self.users[user][0]

        self.users[user] = (password, status)

    def removeUser(self, user):
        '''remove the user from the dictionary'''

        if user in self.users:
            del self.users[user]

    def userExists(self, user):
        '''checks if the user exists'''

        if user in self.users:
            return True
        return False

    def resetPassword(self, user):
        '''reset the user password'''

        if user in self.users:
            self.users[user] = ('', self.users[user][1])

    def save(self):
        '''save the values to the file'''

        users = file(self.path, 'w')

        for user in self.users.keys():
            users.write(user + ':')
            users.write(self.users[ user ][ 0 ] + ':')
            users.write(self.users[ user ][ 1 ] + '\n')

        users.close()

    def load(self):
        '''load the content of the file'''
        try:
            usersListRead = open(self.path, 'r')
            for line in usersListRead.readlines():
                (user,password,status) = line.strip().split(':')
                self.users[ user ] = (password, status)
            usersListRead.close()
        except:
            usersList = open(self.path , 'w')
            usersList.close()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.