Example #1
0
 def network_setup(self):
     dict = {}
     self.net_mtime = self.network_connect()
     if self.net_mtime != None:
         if os.path.exists( self.user_data_file ):
             self.network_update()
             local_mtime = int(os.stat( self.user_data_file ).st_mtime)
             if local_mtime > self.net_mtime:
                 self.network_upload()
             elif local_mtime < self.net_mtime:
                 self.network_download()
         else:
             self.network_download()
     if os.path.exists( self.user_data_file ):
         ph = open( self.user_data_file )
         dict = Unpickler( ph ).load()[-1]
     if not os.path.exists( self.user_data_file ) and self.net_mtime == None:
         ph = open( self.user_data_file, 'w+' )
         Pickler( ph ).dump( dict )
         ph.close()
         os.utime( self.user_data_file, (0,0) )
     last_month = dateDelta( date.today() ).get_last_month()
     keys = dict.keys()
     keys.sort()
     for key in keys:
         if key[:7] < '%0.4d-%0.2d' % (last_month.year,last_month.month):
             dict.pop( key )
         else:
             break
     self.freetime.update( dict )
Example #2
0
class freetimeConfig(myConfigParser):

    def __init__(self):
        self.error = None
        self.groups_pos = 0
        defaults_dir = os.path.join( sys.prefix, 'share', 'nugsl-freetime')
        path = homeDir( topdir='FreeTime' )
        path = os.path.join( path, 'FreeTime')
        if not os.path.exists( path ):
            os.makedirs( path )
        config_path = os.path.join( path, 'Config')
        if not os.path.exists( config_path ):
            os.makedirs( config_path )
        data_path = os.path.join( path, 'Calendars')
        if not os.path.exists( data_path ):
            os.makedirs( data_path )
        self.data_path = data_path
        self.category_path = {}
        p = os.path.join( data_path, 'Staff')
        if not os.path.exists( p ):
            os.makedirs( p )
        self.category_path[ 'Staff' ] = p
        p = os.path.join( data_path, 'Student')
        if not os.path.exists( p ):
            os.makedirs( p )
        self.category_path[ 'Student' ] = p
        config_file = os.path.join( config_path, 'profile.txt' )
        if not os.path.exists( config_file ):
            default_file = os.path.join( defaults_dir, 'profile-default.txt')
            default = open( default_file ).read()
            open( config_file, 'w+' ).write( default )
            self.error = 'Please edit your profile at %s.' % config_file
            return
        myConfigParser.__init__(self, {'language': 'en'})
        self.paranoid_read( config_file )

        if not 'User' in self.sections():
            self.error = 'Missing section [User] in config file %s' % config_file
            return
        elif not self.has_option('User','name'):
            self.error = 'Missing option "name:" in section [User] of config file %s' % config_file
            return
        elif not self.has_option('User','email'):
            self.error = 'Missing option "email:" in section [User] of config file %s' % config_file
            return
        elif not self.has_option('User','telephone'):
            self.error = 'Missing option "telephone:" in section [User] of config file %s' % config_file
            return

        lang = self.get('User','language')

        self.name = self.get('User', 'name')
        if self.name == 'Unknown User':
            self.error = 'Please edit your profile at %s.' % config_file
            return
        self.email = self.get('User', 'email')
        self.telephone = self.get('User', 'telephone')

        repeat_icon_file = os.path.join( defaults_dir, 'repeat.png')
        img = Image.open( repeat_icon_file, 'r' )
        self.repeat_icon = ImageTk.PhotoImage( img )

        empty_icon_file = os.path.join( defaults_dir, 'empty.png')
        img = Image.open( empty_icon_file, 'r' )
        self.empty_icon = ImageTk.PhotoImage( img )

        right_file =  os.path.join( defaults_dir, 'right.png')
        img = Image.open( right_file, 'r' )
        self.right = ImageTk.PhotoImage( img )

        left_file =  os.path.join( defaults_dir, 'left.png')
        img = Image.open( left_file, 'r' )
        self.left = ImageTk.PhotoImage( img )

        self.times = freetimeTimes( defaults_dir, lang=lang ).times
        self.weekdays = freetimeWeekdays( defaults_dir, lang=lang ).weekdays

        self.month = monthConfig( self.weekdays )

        userkey = userkeyConfig( defaults_dir, config_path )
        self.error = userkey.error
        if self.error:
            self.error = 'Please add your Freetime key to use the calendar.'
            return
        self.userkey = userkey.get('UserKey', 'userkey')
        if self.userkey == 'UnknownUser':
            self.error = 'Please add your Freetime key to use the calendar.'
            return
        self.category = userkey.get('UserKey', 'category')
        pkey = StringIO()
        pkey.write( userkey.get('UserKey','rsa').lstrip() )
        pkey.seek(0)
        self.pkey = RSAKey.from_private_key( pkey )
        self.server = userkey.get('UserKey', 'server')
        self.server_account = userkey.get('UserKey','account')

        groups_file = os.path.join( config_path, 'groups.txt' )
        if os.path.exists( groups_file ):
            text = open( groups_file ).read()
            try:
                text = text.decode('utf8')
            except:
                text = text.decode('shift_jis')
                print 'Barfed on groups file, using shift-jis encoding'
            self.groups = [x[1:-1] for x in re.findall('\[[^]]+\]'.decode('utf8'), text )]
        else:
            self.groups = []
        if self.groups:
            self.groups.insert(0, 'Personal')
        ##print self.groups
        #
        # Reconcile old group data and current groups configuration
        self.groups_data_file = os.path.join( config_path, 'groups.pkl' )
        if os.path.exists( self.groups_data_file ):
            ph = open( self.groups_data_file )
            self.groups_data = Unpickler( ph ).load()
            ph.close()
        else:
            self.groups_data = {}
        for key in self.groups_data.keys():
            if not key in self.groups:
                self.groups_data.pop(key)
        for group in self.groups:
            if not self.groups_data.has_key( group ):
                self.groups_data[ group ] = []

        self.build_user_info()

        self.known_hosts_file = os.path.join( defaults_dir, 'known_hosts')
        self.user_data_file = os.path.join( data_path, self.category, self.userkey )
        self.freetime = freeTime()


    def build_user_info(self):
        self.users = {'Staff': [], 'Student': []}
        today = date.today()
        self.user_index = {}
        for category in ['Staff','Student']:
            ids = os.listdir( self.category_path[ category ] )
            for userid in ids:
                userfile = os.path.join( self.category_path[ category ], userid )
                ph = open( userfile )
                try:
                    userdata = Unpickler( ph ).load()
                    doit = True
                except EOFError:
                    ph.close()
                    os.unlink( userfile )
                    doit = False
                if doit:
                    ph.close()
                    fullname = userdata[1].strip()
                    email = userdata[2].strip()
                    telephone = userdata[3].strip()
                    mtime = os.stat( userfile ).st_mtime
                    filedate = date.fromtimestamp( mtime )
                    delta = today - filedate
                    age = delta.days
                    self.users[ category ].append( (userid, fullname, email, telephone, age) )
            self.users[ category ].sort( self.sort_ids )
            for pos in range(0, len(self.users[ category ]),1):
                #
                # Ugly but effective.  We'll need a wrapper function to keep the
                # usage of this unified key straight.
                self.user_index[ category + '::' + self.users[ category][pos][0] ] = pos



    def sort_ids(self, a, b):
        a = a[0].split('_')[-1]
        b = b[0].split('_')[-1]
        if a > b:
            return 1
        elif a == b:
            return 0
        else:
            return -1

    def network_setup(self):
        dict = {}
        self.net_mtime = self.network_connect()
        if self.net_mtime != None:
            if os.path.exists( self.user_data_file ):
                self.network_update()
                local_mtime = int(os.stat( self.user_data_file ).st_mtime)
                if local_mtime > self.net_mtime:
                    self.network_upload()
                elif local_mtime < self.net_mtime:
                    self.network_download()
            else:
                self.network_download()
        if os.path.exists( self.user_data_file ):
            ph = open( self.user_data_file )
            dict = Unpickler( ph ).load()[-1]
        if not os.path.exists( self.user_data_file ) and self.net_mtime == None:
            ph = open( self.user_data_file, 'w+' )
            Pickler( ph ).dump( dict )
            ph.close()
            os.utime( self.user_data_file, (0,0) )
        last_month = dateDelta( date.today() ).get_last_month()
        keys = dict.keys()
        keys.sort()
        for key in keys:
            if key[:7] < '%0.4d-%0.2d' % (last_month.year,last_month.month):
                dict.pop( key )
            else:
                break
        self.freetime.update( dict )

    def groups_save(self):
        ph = open(self.groups_data_file, 'w+' )
        Pickler( ph ).dump( self.groups_data )
        ph.close()

    def network_connect(self):
        self.sshclient = SSHClient()
        self.sshclient.set_missing_host_key_policy(AutoAddPolicy)
        self.sshclient.load_host_keys( self.known_hosts_file  )
        try:
            self.sshclient.connect( self.server, username=self.server_account, pkey=self.pkey, timeout=20 )
        except:
            # Should have logging for this.
            self.sshclient.close()
            self.sshclient = None
            return None
        self.sftp = self.sshclient.open_sftp()
        if self.userkey in self.sftp.listdir( self.category ):
            return self.sftp.stat( self.category + '/' + self.userkey ).st_mtime
        else:
            return 0

    def network_close(self):
        if self.sshclient:
            self.sftp.close()
            self.sshclient.close()
        else:
            #
            # Setting the mtime to zero will force a merge, rather
            # than an overwrite, when the Net is next accessed.
            os.utime( self.user_data_file, (0,0))

    def network_upload(self):
        #if self.sshclient and self.userkey in self.sftp.listdir( self.category ):
        if self.sshclient and self.userkey in os.listdir( os.path.join( self.data_path, self.category ) ):
            self.sftp.put( self.user_data_file, self.category + '/' + self.userkey )
            mtime = self.sftp.stat( self.category + '/' + self.userkey ).st_mtime
            os.utime( self.user_data_file, (mtime,mtime) )

    def network_download(self):
        if self.sshclient and self.userkey in self.sftp.listdir( self.category ):
            self.sftp.get( self.category + '/' + self.userkey, self.user_data_file )
            mtime = self.sftp.stat( self.category + '/' + self.userkey ).st_mtime
            os.utime( self.user_data_file, (mtime,mtime) )
    #
    # The mtime of the local file is held at zero until
    # the first network connection from this instance.
    # If the local mtime is zero when network is available,
    # update from the server rather than overwriting, to
    # avoid losing data.
    def network_update(self):
        #
        # We have network, we have local file, we may not have
        # remote file.
        if self.userkey in self.sftp.listdir( self.category ):
            local_mtime = os.stat( self.user_data_file ).st_mtime
            if int(local_mtime) == 0:
                self.sftp.get( self.category + '/' + self.userkey, self.user_data_file + '.tmp' )
                ph = open( self.user_data_file + '.tmp' )
                net_data = Unpickler( ph ).load()[-1]
                ph.close()
                os.unlink( self.user_data_file + '.tmp' )

                ph = open( self.user_data_file )
                local_data = Unpickler( ph ).load()[-1]
                ph.close()

                local_data.update( net_data )
                self.freetime = freeTime( dict=local_data )

                ph = open( self.user_data_file, 'w+' )
                Pickler( ph ).dump( self.bundle_data() )
                ph.close()
        else:
            self.sftp.put( self.user_data_file, self.category + '/' + self.userkey )
            mtime = self.sftp.stat( self.category + '/' + self.userkey ).st_mtime
            os.utime( self.user_data_file, (mtime,mtime) )

    def network_update_others(self, category):
        """ Download files of other users for use in coordinating group schedules
        """
        for file in self.sftp.listdir( category ):
            if category == self.category and file == self.userkey:
                continue
            self.sftp.get( category + '/' + file, os.path.join( self.data_path, category, file ) )
            mtime = self.sftp.stat( category + '/' + file ).st_mtime
            os.utime( os.path.join( self.data_path, category, file ), (mtime,mtime) )
            self.build_user_info()

    def bundle_data(self):
        bundle = []
        bundle.append( self.userkey )
        bundle.append( self.name )
        bundle.append( self.email )
        bundle.append( self.telephone )
        bundle.append( self.freetime.copy() )
        return bundle