#
# Copyright 2001, 2002 by Fle3 Team and contributors
#
# This file is part of Fle3.
#
# Fle3 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.
#
# Fle3 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 Fle3; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""Contains class UserInfo, which contains the FLE specific details
of registered users."""

__version__ = "$Revision: 1.7 $"[11:-2]

import time, string, types
import os.path

try:
    from PIL import Image
    PIL_imported = 1
except ImportError:
    PIL_imported = 0
import cStringIO

import Globals
import OFS
from Globals import Persistent, Acquisition
import AccessControl
from AccessControl import ClassSecurityInfo
from IUserInfo import IUserInfo
import TraversableWrapper
from Cruft import Cruft
from Webtop import Webtop
from CourseManager import IDManager
from common import add_dtml_obj, reload_dtml, add_dtml, get_url, styles_path, \
     image_file_path, add_image_obj, make_action, get_roles, get_local_roles
#from common import user_timeout_delay
#from TempObjectManager import TempObjectManager
from input_checks import render, is_valid_title, is_valid_url, normal_entry_tags
from common import perm_view, perm_edit, perm_manage, perm_add_lo
from XmlRpcApi import UserInfoXMLRPC
from Globals import PersistentMapping
from Products.ZWiki.ZWikiPage import ZWikiPage


bg_stuff = {
    'bgcolor_rd': ('rd', 'cc3333'),
    'wt_bg_bl': ('bl','3f82b5'),
    'wt_bg_gray1': ('gray', 'c0c0c0'),
    'wt_bg_gray2': ('gray', '99af73'),
    'wt_bg_tq': ('tq', '93bdb6'),
    'wt_bg_yl': ('yl', 'c2c32e'),
    }

# An instance of this class holds all user specific information
# with the exception of access control, which is handled by the
# standard Zope objects in acl_users. Fle3 no longer has global
# roles, but rather local roles attached to the FLE root object.
#
# Some acl information is handled here (like password changing),
# but those functions transfer to Zope internals as fast as possible.
class UserInfo(
    OFS.Folder.Folder,
    Persistent,
    TraversableWrapper.TraversableWrapper,
    Cruft,
    AccessControl.Role.RoleManager,
    OFS.SimpleItem.Item,
    IDManager,
    UserInfoXMLRPC,
    ):
    """FLE user information."""
    meta_type = 'UserInfo'

    security = ClassSecurityInfo()
    security.declareObjectPublic()

    __implements__ = IUserInfo

    dtml_files = (
        )


    def __init__(self, id_):
        """Construct UserInfo object."""
        self.id = id_
        #self.title = title
        self.title = ''
        self.uname = id_
        self.id=id_
        self.jooksev_kursus=0;
        self.__last_active = {}
        self.__frozen = 0

        self.__edit_tbl = PersistentMapping()

        IDManager.__init__(self)

        # Set permissions:
        # We iterate first over all set_* methods in this class, and protect them
        # with the Edit permission (see manage_afterAdd), and then we set the
        # View permissions for all get_* methods.
        for prefix in ['set_', 'get_']:
            for func in filter(lambda x,p=prefix:x[:len(p)] == p, dir(self)):
                if prefix == 'set_':
                    security.declareProtected('Edit', func)
                elif prefix == 'get_':
                    security.declareProtected('View', func)

        #self.set_first_name(first_name)
        #self.set_last_name(last_name)
        #self.set_email(email)
        #self.set_language(language)
        ## NOTE: Wrong. Stuff like this should have their own container classes.
        #self.set_photo(photo) # This is picture binary data
        self.set_group('')
        self.set_address1('')
        self.set_address2('')
        self.set_city('')
        self.set_country('Estonia')
        self.set_homepage('')
        self.set_phone('')
        self.set_gsm('')
        self.set_quote('')
        self.set_background('')
        self.set_personal_interests('')
        self.set_professional_interests('')
        self.set_language('et_ee') # Dirty hack ..
#        try:
#        self.set_language(self.get_default_language())
#        except:
#          pass
        self.set_organization('')

        for tup in self.dtml_files:
            add_dtml(self, tup)

    security.declarePrivate('manage_afterAdd')
    def manage_afterAdd(self, item, container):
        """Set default permissions for roles."""
#        wt = Webtop().__of__(self)
        wt=Webtop()
        wt.id='webtop'
        self._setObject('webtop', wt)
        wt2 = Webtop('sahtel').__of__(self) #Jaagup
        self._setObject('sahtel', wt2)

        self.set_language(self.get_default_language())
        
        #self.manage_addProduct['OFSP'].manage_addFolder('omawiki');
        #wikiobj=ZWikiPage(source_string='algus', __name__='AlgusLeht')
        #wikiobj.title='pealkiri'
        #wikiobj._deleteOwnershipAfterAdd()
        #self.omawiki._setObject('AlgusLeht', wikiobj)

 
        for obj in (self, self.get_child('webtop')):
            obj.manage_delLocalRoles([t[0] for t in obj.get_local_roles()])
            obj.manage_setLocalRoles(self.get_uname(), ('Owner',))

        for obj in (self, self.get_child('sahtel')):
            obj.manage_delLocalRoles([t[0] for t in obj.get_local_roles()])
            obj.manage_setLocalRoles(self.get_uname(), ('Owner',))

        self.manage_addFolder('own_styles')
        f = open(os.path.join(styles_path, 'personal_style_sheet.dtml'))
        code = f.read()
        f.close()

        code = code.replace('own_styles',
                            'fle_users/' + self.get_uname() + '/own_styles',
                            1)

        self.own_styles.manage_addFile(
            id='my_style_sheet',
            file=code,
            title='',
            content_type='text/css')

        self.set_webtop_bg_from_default_image('bgcolor_rd')

        from common import roles_admin, roles_staff, roles_user

        self.manage_permission(perm_manage, roles_admin, 0)
        self.manage_permission(perm_edit, roles_admin+('Owner',), 0)
        self.manage_permission(perm_view, roles_user, 0)

    security.declareProtected(perm_manage, 'reload_dtml')
    def reload_dtml(self, REQUEST=None):
        """Reload dtml files from the file system."""
        reload_dtml(self, self.dtml_files)

        if REQUEST:
            self.get_lang(('common',),REQUEST)
            return self.message_dialog(
                self, REQUEST,
                title=REQUEST['L_dtml_reloaded'],
                message=REQUEST['L_dtml_files_reloaded'],
                action='index_html')

    # Each person has two personal stylesheets:
    #  -  my_style_sheet modifies webtop background
    #  -  my_style_sheet_tab modifies webtop tab background
    security.declarePrivate('modify_style_sheet')
    def modify_stylesheet(self, colour, image_path):
        """Modify personal stylesheets to use given colour
        and background image."""

        f = open(os.path.join(styles_path, 'personal_style_sheet.dtml'))
        code = f.read()
        f.close()

        code = code.replace('XXXXXX', colour)
        code = code.replace('YYYYYY', image_path)

        try:
            self.own_styles._delObject('my_style_sheet')
            self.own_styles._delObject('my_style_sheet_tab')
        except:
            pass

        code = str(code) # for some reason, code is sometimes unicode
        self.own_styles.manage_addFile(
            id='my_style_sheet',
            file=code,
            title='',
            content_type='text/css')

        code = code.replace('.mainbg ', '.wtbg-tab ')
        code = code.replace('.main ', '.wt-tab ')
        self.own_styles.manage_addFile(
            id='my_style_sheet_tab',
            file=code,
            title='',
            content_type='text/css')

    security.declareProtected(perm_view, 'get_photo_tag')
    # Our (simple) version of the tag() method of Zope's Image class.
    def get_photo_tag(self, REQUEST, **args):
        """Return HTML img tag for user's photo."""
        if self.has_photo():
            url = self.find_URL_of_fle_root(REQUEST) + \
                  '/fle_users/' + self.uname + '/get_photo'
            extra_params = ''
            arg_keys_lower = map(string.lower, args.keys())

            if not 'alt' in arg_keys_lower:
                extra_params += ' alt=""'
#            if not 'height' in arg_keys_lower:
#                extra_params += ' height="32"'
#            if not 'width' in arg_keys_lower:
#             #   extra_params += ' width="32"'
#            if not 'border' in arg_keys_lower:
#             #   extra_params += ' border="0"'

            for key in args.keys():
                extra_params += ' %s="%s"' % (key, args[key])

            return '<img src="%s"%s />' % (url, extra_params)
        else:
            # User has no photo -> show default user image.

            # NOTE: At the moment default image is not 32x32... find
            # NOTE: out if there is any reason for that?
            args['width']='32'
            args['height']='32'
            return apply(self.fle_root().images.user.tag, [], args)

    security.declareProtected(perm_view, 'has_photo')
    def has_photo(self):
        """Return whether user has photo."""
        return not not self.get_photo()

    security.declareProtected(perm_view, 'get_webtop')
    def get_webtop(self):
        """Return the webtop of the user."""
        return self.get_child('webtop')

    security.declarePrivate('freeze_me')
    def freeze_me(self):
        """Freeze the user."""
        fle=self.parent().parent()
        uname=self.get_uname()
        self.__roles = get_local_roles(fle,self.get_uname())
        fle.manage_delLocalRoles((uname,))
        self.__frozen = 1
        self._p_changed = 1

    security.declarePrivate('unfreeze_me')
    def unfreeze_me(self):
        """Unfreeze the user."""
        fle=self.parent().parent()
        uname=self.get_uname()
        fle.manage_setLocalRoles(uname,self.__roles)
        del self.__roles
        self.__frozen = 0
        self._p_changed = 1

    security.declarePublic('is_frozen')
    def is_frozen(self):
        """Am I frozen?"""
        try:
            return self.__frozen
        except:
            return 0

    def getPassword(self):
        return self.acl_users.getUser(self.get_uname())._getPassword()

    def getFrozenPassword(self):
        return self.__password

    def getDomains(self):
        return self.acl_users.getUser(self.get_uname()).getDomains()

    def getFrozenDomains(self):
      try:
        return self.__domains
      except:
        return []

    # Get "global" roles, eg. the roles given for the FLE root object.
    def getRoles(self):
        return get_roles(self.parent().parent(),self.get_uname())

    def getFrozenRoles(self):
        return self.__roles

    # Get roles specified for just one object, and not acquired from above.
    def getRolesInObject(self,object):
        return get_local_roles(object,self.get_uname())

    security.declareProtected(perm_view, 'user_courses')
    def user_courses(self, REQUEST=None):
        """Return a list of the courses the user is on."""
        ac = []
        uname = self.get_uname()
        for course in self.fle_root().courses.get_courses():
            if uname in [u.get_uname() for u in course.get_all_users()]:
                ac.append(course)
        return ac

    security.declarePublic('set_jooksev_kursus')
    def set_jooksev_kursus(self, kursus):
       "kursus"
       self.jooksev_kursus=kursus


    security.declarePublic('get_jooksev_kursus')
    def get_jooksev_kursus(self):
       "kursusvalja"
       return self.jooksev_kursus
       
    def kysiJooksvaKursuseObjekt(self):
      "Kursus kasutatava objektina"
      try:
	      return getattr(self.fle_root().courses, self.get_jooksev_kursus())
      except:
	      return "viga"

    def kysiJooksvaKursuseSisegrupid(self):
      "Sisegruppide loetelu"
      k=self.kysiJooksvaKursuseObjekt()
      return self.kysiKursuseSisegrupid(k)
      
    def kysiKursuseSisegrupid(self, kursus):
      "Kursusel olevad grupid"
      m=kursus.sisegrupid.objectValues()
      loetelu=[]
      for x in m:
        r=x.get_local_roles()
        for paar in r:
          if paar[0]==self.id and 'Student' in paar[1]:
            loetelu.append(x)
      return loetelu
      
    def kysiKasutajaKoikSisegrupid(self):
      "Kõikide gruppide loetelu kursuste peale kokku"
      kursused=self.user_courses()
      tulemus=[]
      for kursus in kursused:
        grupid=self.kysiKursuseSisegrupid(kursus)
        for grupp in grupid:
          tulemus.append(grupp)
      return tulemus
      
      
      
    def kasKasutajalSisegruppe(self):
      "jah/ei"
      return len(self.kysiJooksvaKursuseSisegrupid())>0

    security.declarePrivate('set_state')
    def set_state(self, state):
        """Set state."""
        self.__state = state

    security.declarePrivate('get_state')
    def get_state(self):
        """Get state."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__state'):
            return ""
        else:
            return self.__state
            
    def kasKeelBrauserist(self):
      "kas arvestatakse brauseri määranguid"
      if hasattr(self, 'keelBrauserist'):
        return self.keelBrauserist
      return 0
      
    def seaKeelBrauserist(self, seisund):
      "Soovitu seadmine"
      if seisund:
        self.keelBrauserist=1
      else:
        self.keelBrauserist=0

    security.declareProtected(perm_edit, 'set_language')
    def set_language(self, lang):
        """Set language."""
        if lang in get_languages():
            self.language = lang

    security.declareProtected(perm_view, 'get_language')
    def get_language(self):
        """Get language."""
        if self.language is None:
            raise 'FLE Error', 'No language set.'
        return self.language

    security.declareProtected(perm_edit, 'set_first_name')
    def set_first_name(self, name):
        """Set first name."""
        self.__first_name = name

    security.declareProtected(perm_edit, 'set_last_name')
    def set_last_name(self, name):
        """Set last name."""
        self.__last_name = name

    security.declareProtected(perm_edit, 'set_email')
    def set_email(self, email):
        """Set email."""
        self.__email = email

    security.declareProtected(perm_edit, 'set_language')
    def set_language(self, language):
        """Set language."""
        self.__language = language

    security.declareProtected(perm_edit, 'set_photo')
    def set_photo(self, photo, content_type=None):
        """Set photo."""

        try:
            # Try to crop and scale image to 32x32 pixels and
            # convert it into JPEG format...
            if not PIL_imported:
                print "Can't scale user's photo. PIL not installed."
                raise ''

            s = cStringIO.StringIO(photo)
            im = Image.open(s)
            (width, height) = im.size

            if width == 32 and height == 32 and im.format == 'JPEG':
                # If the image is already 32x32 JPEG image, we want to
                # avoid doing JPEG compression again (lossy!)
                # This is important when exporting/importing FLE.
                raise ''

            if im.mode != 'RGB':
                im = im.convert('RGB')

            if width != height:
                smaller = min(width, height)
                bigger = max(width, height)

                if width == smaller:
                    # Tall image: save top part of the image
                    im = im.crop(( 0, 0, smaller, smaller))
                else:
                    # Wide image: save center part of the image
                    im = im.crop(( (width-height)/2, 0, smaller, smaller))

            im = im.resize((32,32), Image.BICUBIC)

            s = cStringIO.StringIO()
            im.save(s, "JPEG", quality=100)
            s.seek(0)
            self.__photo = s.read()
            self.__photo_type = 'image/jpeg'
        except:
            # ... or failing that just use the original image.
            # (The failure happens if the system has not PIL installed,
            #  or if the PIL can't read the image format, or if the PIL
            #  was compiled without JPEG support, or then something
            #  completely different...)
            self.__photo = photo
            self.__photo_type = content_type

    # FIXME: user can change his own group!
    # We can do this by calling this method from another
    # method that does custom access checking.
    security.declareProtected(perm_edit, 'set_group')
    def set_group(self, group):
        """Set group."""
        self.__group = group

    security.declareProtected(perm_edit, 'set_address1')
    def set_address1(self, address1):
        """Set address.1 (street address)"""
        self.__address1 = address1

    security.declareProtected(perm_edit, 'set_address2')
    def set_address2(self, address2):
        """Set address.2 (postal address)"""
        self.__address2 = address2

    security.declareProtected(perm_edit, 'set_city')
    def set_city(self, city):
        """Set city."""
        self.__city = city

    security.declareProtected(perm_edit, 'set_country')
    def set_country(self, country):
        """Set country."""
        self.__country = country

    security.declareProtected(perm_edit, 'set_homepage')
    def set_homepage(self, homepage):
        """Set homepage."""
        self.__homepage = homepage

    security.declareProtected(perm_edit, 'set_phone')
    def set_phone(self, phone):
        """Set phone."""
        self.__phone = phone

    security.declareProtected(perm_edit, 'set_gsm')
    def set_gsm(self, gsm):
        """Set gsm."""
        self.__gsm = gsm

    security.declarePrivate('get_webtop_bg_image_path')
    # Used in exportUser() in ImportExport
    def get_webtop_bg_image_path(self):
        """Get webtop image path used in the style sheet."""
        if self.__webtop_bg_name in bg_stuff.keys():
            return 'images/'+ self.__webtop_bg_name
        else:
            return 'fle_users/' + self.get_uname() + \
                   '/own_styles/' + self.__webtop_bg_name

    security.declareProtected(perm_view, 'get_webtop_bg_colour_name')
    def get_webtop_bg_colour_name(self):
        """Get webtop background name."""
        if hasattr(self,
                   '_' + self.__class__.__name__+ '__webtop_bg_name'):
            if self.__webtop_bg_name in bg_stuff.keys():
                return bg_stuff[self.__webtop_bg_name][0]

        return 'rd'

    security.declareProtected(perm_view, 'get_webtop_bg_name')
    def get_webtop_bg_name(self):
        """Get webtop background name."""
        if not hasattr(self,
                       '_' + self.__class__.__name__+ '__webtop_bg_name'):
            return ""
        return self.__webtop_bg_name

    # FIXME:
    security.declareProtected(perm_view, 'get_bg_colour_name')
    def get_bg_colour_name(self):
        """..."""
        return self.get_webtop_bg_colour_name()

    security.declarePrivate('set_webtop_bg_from_image_data')
    def set_webtop_bg_from_image_data(self, image_data):
        """Set Webtop background image."""
        try: self.own_styles._delObject(self.__webtop_bg_name)
        except: pass

        # Change name every time, making it easier for web browser to detect
        # that the image has changed.
        name = 'own_bg' + self.generate_id()
        self.own_styles.manage_addImage(name, image_data,
                                        'Webtop background')
        self.__webtop_bg_name = name
        self.modify_stylesheet('cc3333', 'fle_users/' + self.get_uname() + \
                               '/own_styles/' + name)

    security.declarePrivate('set_webtop_bg_from_default_image')
    def set_webtop_bg_from_default_image(self, image_name):
        """Set Webtop background image."""
        try: self.own_styles._delObject(self.__webtop_bg_name)
        except: pass
        self.__webtop_bg_name = image_name
        self.modify_stylesheet(bg_stuff[image_name][1], 'images/' + image_name)

    security.declareProtected(perm_edit, 'set_quote')
    def set_quote(self, quote):
        """Set quote."""
        self.__quote = quote

    security.declareProtected(perm_edit, 'set_background')
    def set_background(self, background):
        """Set background."""
        self.__background = background

    security.declareProtected(perm_edit, 'set_personal_interests')
    def set_personal_interests(self, p_i):
        """Set personal interests."""
        self.__personal_interests = p_i

    security.declareProtected(perm_edit, 'set_professional_interests')
    def set_professional_interests(self, p_i):
        """Set professional interests."""
        self.__professional_interests = p_i

    security.declareProtected(perm_edit, 'set_organization')
    def set_organization(self, p_i):
        """Set organization."""
        self.__organization = p_i
        
    security.declarePublic('kysi_omadus')
    def kysi_omadus(self, omadus):
       "Teatab vastava omaduse väärtuse"
       if omadus=="kasutajanimi": return self.get_uname()
       if omadus=="eesnimi": return self.get_first_name()
       if omadus=="epost": return self.get_email()
       raise "Probleem", "tundmatu omadus"

    

    security.declarePublic('get_uname')
    def get_uname(self):
        """Get user name."""
        return self.uname

    security.declarePublic('get_nickname')
    def get_nickname(self):
        """Get user's visible nick name."""
        try:
            return self.nickname
        except AttributeError:
            return self.uname

    security.declareProtected(perm_view,'get_first_name')
    def get_first_name(self):
        """Get first name."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__first_name'):
            return ""
        else:
            return self.__first_name.upper()

    security.declareProtected(perm_view,'get_last_name')
    def get_last_name(self):
        """Get last name."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__last_name'):
            return ""
        else:
            return self.__last_name

    security.declareProtected(perm_view, 'get_email')
    def get_email(self):
        """Get email."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__email'):
            return ""
        else:
            return self.__email
    security.declareProtected(perm_view, 'get_language')
    def get_language(self):
        """Get language."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__language'):
            return ""
        else:
            return self.__language
    security.declareProtected(perm_view, 'get_photo')
    def get_photo(self, REQUEST=None):
        """Get photo."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__photo'):
            return ""
        else:
            if REQUEST and self.__photo_type:
                REQUEST.RESPONSE.setHeader('content-type',self.__photo_type)
            return self.__photo

    security.declareProtected(perm_view, 'get_photo_type')
    def get_photo_type(self):
        """Get photo's content type."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__photo_type'):
            return ""
        else:
            return self.__photo_type

    security.declareProtected(perm_view, 'get_group')
    def get_group(self):
        """Get group."""
        # FIXME: This can't be defined here.
        if not hasattr(self, '_' + self.__class__.__name__+ '__group'):
            return ""
        else:
            return self.__group
    security.declareProtected(perm_view, 'get_address1')
    def get_address1(self):
        """Get address1. (street address)"""
        if not hasattr(self, '_' + self.__class__.__name__+ '__address1'):
            return ""
        else:
            return self.__address1
    security.declareProtected(perm_view, 'get_address2')
    def get_address2(self):
        """Get address2. (postal address2)"""
        if not hasattr(self, '_' + self.__class__.__name__+ '__address2'):
            return ""
        else:
            return self.__address2
    security.declareProtected(perm_view, 'get_country')
    def get_country(self):
        """Get country."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__country'):
            return ""
        else:
            return self.__country
    security.declareProtected(perm_view, 'get_homepage')
    def get_homepage(self):
        """Get homepage."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__homepage'):
            return ""
        else:
            return self.__homepage
    security.declareProtected(perm_view, 'get_phone')
    def get_phone(self):
        """Get phone."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__phone'):
            return ""
        else:
            return self.__phone
    security.declareProtected(perm_view, 'get_gsm')
    def get_gsm(self):
        """Get gsm."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__gsm'):
            return ""
        else:
            return self.__gsm
    security.declareProtected(perm_view, 'get_quote')
    def get_quote(self):
        """Get quote."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__quote'):
            return ""
        else:
            return self.__quote

    security.declareProtected(perm_view, 'render_quote')
    def render_quote(self):
        """Render quote."""
        return render(
            self.get_quote(),
            legal_tags=normal_entry_tags)

    security.declareProtected(perm_view, 'get_background')
    def get_background(self):
        """Get background."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__background'):
            return ""
        else:
            return self.__background

    security.declareProtected(perm_view, 'render_background')
    def render_background(self):
        """Render background."""
        return render(
            self.get_background(),
            legal_tags=normal_entry_tags)


    security.declareProtected(perm_view, 'get_personal_interests')
    def get_personal_interests(self):
        """Get personal interests."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__personal_interests'):
            return ""
        else:
            return self.__personal_interests

    security.declareProtected(perm_view, 'render_personal_interests')
    def render_personal_interests(self):
        """Render personal interests."""
        return render(
            self.get_personal_interests(),
            legal_tags=normal_entry_tags)

    security.declareProtected(perm_view, 'get_professional_interests')
    def get_professional_interests(self):
        """Get professional interests."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__professional_interests'):
            return ""
        else:
            return self.__professional_interests

    security.declareProtected(perm_view, 'render_professional_interests')
    def render_professional_interests(self):
        """Render professional interests."""
        return render(
            self.get_professional_interests(),
            legal_tags=normal_entry_tags)

    security.declareProtected(perm_view, 'get_organization')
    def get_organization(self):
        """Get organization."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__organization'):
            return ""
        else:
            return self.__organization

    security.declareProtected(perm_view, 'get_city')
    def get_city(self):
        """Get city."""
        if not hasattr(self, '_' + self.__class__.__name__+ '__city'):
            return ""
        else:
            return self.__city

    security.declareProtected(perm_view, 'get_default_webtop_bgs')
    def get_default_webtop_bgs(self):
        """Return a list of default Image objects."""

        names = bg_stuff.keys()
        names.sort()
        return [eval('self.images.%s' % x) for x in names]

    security.declarePrivate('update_active')
    def update_active(self, course_id):
        """Update the user activity record."""
        self.__last_active[course_id] = time.time()
        self._p_changed = 1

#    security.declarePrivate('last_active')
    def last_active(self, course_id):
        """Return time when user was last active."""
        try:
          return self.__last_active[course_id]
        except:
          return 0
          
    def global_last_active(self):
       "Kõigist viimane"
       viimane=0
       for nr in self.__last_active.values():
         if nr>viimane:viimane=nr
       return viimane
    

    def global_last_active_time(self, REQUEST):
       "Tekstina"
       import time
       self.get_lang(('common',), REQUEST)
       if self.global_last_active()==0:return "-" 
       return time.strftime(REQUEST['L_timestamp_format'], time.localtime(self.global_last_active()))
          
    def vaikimisAeg(self, course_id):
        "Aeg, mis mööda läinud viimatisest külastusest kursusel"
        return time.time()-self.last_active(course_id)
        
    def kasSees(self, course_id):
        "Tõene, kui pole ületanud viimasest külastusest määratud aega"
        import common
        return self.vaikimisAeg(course_id)<common.user_timeout_delay
        


#    security.declareProtected(perm_edit, 'empty_pwd')
    def empty_pwd(self):
        """Return default empty password. Note, user can't use
        this password."""
        return 'eightchr'

    security.declareProtected(perm_edit, 'set_password')
    def set_password(self, pwd):
        roles = self.acl_users.data.get(self.get_id()).roles
        self.acl_users._doChangeUser(self.getId(), pwd, roles, [])
        
    security.declareProtected(perm_edit, 'muuda_parool')
    def muuda_parool(self, uusparool):
        "Püütakse kasutajal parool muuta, väljund 1/0"
#       try:
        kataloog=self.leiaKasutajaKataloog(self.get_id())
        if kataloog:
         rollid=kataloog.data.get(self.get_id()).roles
         kataloog._doChangeUser(self.getId(), uusparool, rollid, [])
         return "muudetud"
#       except:
#        return 0   

    security.declareProtected(perm_edit, 'set_roles')
    def set_roles(self, roles):
        """Set user's Fle global roles."""
        if type(roles) == types.StringType: roles = [roles]
        else: roles = list(roles)
        fle=self.parent().parent()
        person=self.get_uname()
        fle.manage_delLocalRoles((person,))
        fle.manage_setLocalRoles(person,roles)

    security.declareProtected(perm_view, 'has_role')
    def has_role(self, role):
        """Has user given role."""
        return role in get_roles(self.parent().parent(),self.get_uname())

    security.declareProtected(perm_view, 'has_any_role')
    def has_any_role(self, roles):
        """Has user any of given role."""
        real_roles = get_roles(self.parent().parent(),self.get_uname())
        for role in roles:
            if role in real_roles: return 1

        return 0

    security.declareProtected('View', 'has_right_to_edit')
    def has_right_to_edit(self, REQUEST):
        logged_user = self.parent().get_user_info(self.get_current_user(REQUEST))
        if self.has_role('FLEAdmin'):
            if not logged_user.has_role('FLEAdmin'):
                return 0
            else:
                # a user with FLEAdmin role can edit do anything (even edit
                # other user with FLEAdmin role.
                return 1
        elif self.get_id() == logged_user.get_id():
            return 1
        else:
            return self.is_power_user(
                self.get_current_user(REQUEST))


    security.declareProtected(perm_edit, 'edit_user_form_handler')
    def edit_user_form_handler(
        self,
        REQUEST,

        # actual user info data from forms
        pwd = '',               # password
        pwd_confirm = '',       # password confirmation
        nickname = None,
        first_name = None,
        last_name = None,
        email = None,
        organization = None,
        language = None,
        role = None,
        photo_upload = None,
        photo_url = None,
        group = None,
        address1 = None,
        address2 = None,
        city = None,
        country = None,
        homepage = None,
        phone = None,
        gsm = None,
        quote = None,
        background = None,
        personal_interests = None,
        professional_interests = None,
        webtop_bg_upload=None,
        default_webtop_bg=None,
        keel_brauserist=0,

        cancel = '',
        commit = '',
        ):
        """User info edit form handler."""

        if cancel:
            if REQUEST:
                REQUEST.RESPONSE.redirect(
                    self.state_href(REQUEST, 'show_user_info'))
            return

        if not self.has_right_to_edit(REQUEST):
            raise 'FLE Error', \
                  'I am sorry Dave. I am afraid I cannot do that.'

        errors = []
        self.get_lang(('common', 'ivacommon','usermgmnt'), REQUEST)

        for s in ('first_name', 'last_name', 'email', 'organization',
                  'photo_url', 'address1', 'address2', 'city', 'homepage',
                  'phone', 'gsm'):
            e = REQUEST.get(s)
            if e:
                e = e.strip()
                REQUEST.set(s, e)

        # Mandatory
        for x in ('first_name', 'last_name'):
            e = REQUEST.get(x)
            if e and not is_valid_title(e):
                errors.append(REQUEST['L_' + x])

        # Optional
        for x in ('nickname', 'email', 'organization', 'language', 'address1',
                  'address2', 'city', 'phone', 'gsm'):
            e = REQUEST.get(x)
            if e and not is_valid_title(e):
                errors.append(REQUEST['L_' + x])

        # These are optional, too.
        if photo_url and not is_valid_url(photo_url):
            errors.append(REQUEST['L_url_to_photo'])
        if homepage and not is_valid_url(homepage):
            homepage='http://'+homepage
        if homepage and not is_valid_url(homepage):
            errors.append(REQUEST['L_homepage'])

        # FIXME: input_checks: group

        for x in ('quote', 'background', 'personal_interests',
                  'professional_interests'):
            value = REQUEST.get(x)
            if value and ('<' in value or '>' in value):
                errors.append(REQUEST['L_' + x])

        # Check that the nick name isn't already taken
        if nickname:
            if nickname in \
               [x.get_uname() for x in self.fle_users.get_users()]\
               or nickname in \
               [x.get_nickname() for x in self.fle_users.get_users()]:
                errors.append(REQUEST['L_nickname'])

        if len(errors) > 0:
            # Update photo, because we can't save that to URL.
            if photo_upload and len(photo_upload.filename) > 0:
                self.set_photo(photo_upload.read(),
                               photo_upload.headers['content-type'])
            action = apply(
                make_action,
                ['edit_user_form'] +
                [(x, REQUEST.get(x)) for x in
                 ('first_name', 'last_name', 'email', 'homepage',
                  'organization', 'language', 'role',
                  'photo_url', 'address1', 'address2', 'city',
                  'country', 'phone', 'gsm',
                  'quote', 'background', 'personal_interests',
                  'professional_interests')])

            return self.message_dialog(
                self, REQUEST,
                title=REQUEST['L_invalid_input'],
                message=REQUEST['L_invalid_fields'] + ": '" + \
                "' , '".join(errors) + "'",
                action=action)

        if nickname and not hasattr(self,'nickname'):
            self.nickname=nickname

        self.seaKeelBrauserist(keel_brauserist)

        if webtop_bg_upload and len(webtop_bg_upload.filename) > 0:
            self.webtop.set_webtop_bg_from_image_data(webtop_bg_upload.read())
        elif default_webtop_bg:
            self.webtop.set_webtop_bg_from_default_image(default_webtop_bg)

        self.edit_info(
            first_name, last_name, email, organization, language,
            photo_upload, photo_url, group, address1, address2, city,
            country, homepage, phone, gsm, quote,
            background, personal_interests,
            professional_interests)

        if role:
            if role == 'User':
                self.set_roles(('User',))
            elif role in ('Staff', 'FLEAdmin'):
                self.set_roles(('User', role))
            else:
                raise 'FLE Error', 'Invalid role'
	muutis_parooli = 0
        if pwd and (pwd != self.empty_pwd()):
            # change password
            if pwd == pwd_confirm:
                #self.set_password(pwd)
                self.muuda_parool(pwd)
                if hasattr(self,'perm_must_change'):
			if self.perm_must_change == 1:
				muutis_parooli = 1
				self.perm_must_change = 0
                # If user changed her own password, return a message dialog
                # (with info that the browser will ask for username/password).
# M6ttetu return kuna kasutajanime ja parooli kysitakse ikkagi ennem kui seda n2idatakse
#                if repr(REQUEST.AUTHENTICATED_USER) == self.get_uname():
#                    self.get_lang(('common','usermgmnt'),REQUEST)
#                    return self.message_dialog(
#                        self, REQUEST,
#                        title=REQUEST['L_passwd_changed'],
#                        message=REQUEST['L_passwd_changed_explanation'],
#                        action='show_user_info')

            else:
                if REQUEST:
                    self.get_lang(('common','usermgmnt'),REQUEST)
                    return self.message_dialog(
                        self, REQUEST,
                        title=REQUEST['L_error'],
                        message=REQUEST['L_password_mismatch'],
                        action='edit_user_form')

	if first_name == '':
		return self.message_dialog(
			self,REQUEST,
			title=REQUEST['L_error'],
			message=REQUEST['L_ic_enter_correct']+REQUEST['L_first_name'],
			action='edit_user_form')
	if last_name == '':
		return self.message_dialog(
			self,REQUEST,
			title=REQUEST['L_error'],
			message=REQUEST['L_ic_enter_correct']+REQUEST['L_last_name'],
			action='edit_user_form')

        if REQUEST:
		if muutis_parooli:
			REQUEST.RESPONSE.redirect(self.state_href(REQUEST, 'paevikuleht'))
		else:
	            REQUEST.RESPONSE.redirect(
        	        self.state_href(REQUEST, 'show_user_info'))



    # Implementation of edit_user_form_handler without http code.
    security.declarePrivate('edit_info')
    def edit_info(
        self,

        first_name = None,
        last_name = None,
        email = None,
        organization = None,
        language = None,
        photo_upload = None,
        photo_url = None,
        group = None,
        address1 = None,
        address2 = None,
        city = None,
        country = None,
        homepage = None,
        phone = None,
        gsm = None,
        quote = None,
        background = None,
        personal_interests = None,
        professional_interests = None,
        ):
        """Commits changes in userinfo object."""

        if first_name != None: self.set_first_name(first_name)
        if last_name != None: self.set_last_name(last_name)
        if email != None: self.set_email(email)
        if organization != None: self.set_organization(organization)
        if language != None: self.set_language(language)
        if group != None: self.set_group(group)
        if address1 != None: self.set_address1(address1)
        if address2 != None: self.set_address2(address2)
        if city != None: self.set_city(city)
        if country != None: self.set_country(country)
        if homepage != None: self.set_homepage(homepage)
        if phone != None: self.set_phone(phone)
        if gsm != None: self.set_gsm(gsm)
        if quote != None: self.set_quote(quote)
        if background != None: self.set_background(background)
        if personal_interests != None:
            self.set_personal_interests(personal_interests)
        if professional_interests != None:
            self.set_professional_interests(professional_interests)

        if photo_upload != None:
            if hasattr(photo_upload,'filename') and \
               len(photo_upload.filename) > 0:
                photo_data = photo_upload.read()
                self.set_photo(photo_data,photo_upload.headers['content-type'])
                return
        if photo_url != None and photo_url != '' and photo_url != 'http://':
            photo_data = get_url(photo_url)
            self.set_photo(photo_data)


    def kysiSyndmusteKataloog(self):
      "Lisatakse kui pole"
      import Kalender
      if not hasattr(self, 'syndmused'):
        self._setObject('syndmused', Kalender.KalendriSyndmusteKataloog())
        self.syndmused.id='syndmused'
#        return "uus"
#      return "vana"
      return self.syndmused

    def lisaKirjadeKataloog(self):
      "Lisab kasutajale kataloogi kirjade hoidmiseks"
      if not hasattr(self, 'kirjad'):
        import Kirjad
        self._setObject('kirjad', Kirjad.KirjadeKataloog())
        self.kirjad.id='kirjad'
        return "Kataloog lisatud"
      return "Juba olemas"
    
    def lisaSobraList(self):
      "Lisab kasutajale kataloogi sõprade hoidmiseks"
      if not hasattr(self, 'sobrad'):
        import SobraList
        self._setObject('sobrad', SobraList.SobraList())
        self.sobrad.id='sobrad'
        return "Sõbralist lisatud"
      return "Sõbralist olemas"
          
    def syndmusteKogum(self):
      "Kasutaja sündmused nii kursustel kui enese omad"
      k=self.kysiSyndmusteKataloog()
      m=[]
      for x in k.objectValues():
        m.append(x)
      for c in self.user_courses():
        k=c.kysiSyndmusteKataloog()
        for x in k.objectValues():
          m.append(x)
      for grupp in self.kysiKasutajaKoikSisegrupid():
        if hasattr(grupp, 'syndmused'):
          for x in grupp.syndmused.objectValues():
            m.append(x)
      return m
      
    def sorteeritudSyndmusteKogum(self, REQUEST):
      "Algusaegade järgi reas"
      import random
      algrida=self.syndmusteKogum()
      sorttulp="aeg"
      sortsuund="edasi"
      if hasattr(REQUEST, 'syndmustesorttulp'):
        if REQUEST.syndmustesorttulp=="asukoht":
          sorttulp="asukoht"
      if hasattr(REQUEST, 'syndmustesortsuund'):
        if REQUEST.syndmustesortsuund=="tagasi":
          sortsuund="tagasi"
      ajam=[]
      d={}
      for x in algrida:
#        s='%012.4f' % x.kysiAlgus() + str(random.randint(0, 1000000))
        s=""
        if sorttulp=="asukoht":
          s=s+x.asukohtTekstina(REQUEST)      
        s=s+'%012.4f' % x.kysiAlgus() + x.absolute_url()
        ajam.append(s)
        d[s]=x
      ajam.sort()
      uusrida=[]
      for x in ajam:
        uusrida.append(d[x])
      if sortsuund=="tagasi":
        uusrida.reverse()
      return uusrida
      
    def filtreeritudSyndmusteKogum(self, REQUEST):
      "Esiotsa päevikulehe tarbeks"
      return self.sorteeritudSyndmusteKogum(REQUEST)
      
    def paevikuleheSyndmusteTabel(self, REQUEST):
      "Tabel sündmuste näitamiseks"
      self.get_lang(('ivacommon',), REQUEST)
      uussuund="edasi"
      if getattr(REQUEST, 'syndmustesortsuund', '')=="edasi":
        uussuund="tagasi"
      tulemus="<table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"1\" bgcolor=\"#EEEEEE\">\n"
      tulemus=tulemus+"<tr>\n<td>\n"
      tulemus=tulemus+"<a href=\"paevikuleht?syndmustesorttulp=asukoht&syndmustesortsuund="+uussuund+"\" class=\"link2\">"+REQUEST['L_ic_author']+"</a>\n</td>\n"
      tulemus=tulemus+"<td>\n<a href=\"paevikuleht?syndmustesorttulp=aeg&syndmustesortsuund="+uussuund+"\" class=\"link2\">"+REQUEST['L_ic_time']+"</a>\n</td>\n</tr>\n"
      for x in self.filtreeritudSyndmusteKogum(REQUEST):
        tulemus=tulemus+x.paevikuTabeliRida(REQUEST)
      tulemus=tulemus+"</table>\n"
      return tulemus

    def syndmusedPaevas(self, kogum, aasta, kuu, paev):
     "Kas viitena kalendris"      
     m=[]
     aasta=int(aasta)
     kuu=int(kuu)
     paev=int(paev)
     for x in kogum:
       if x.kasSyndmusPaeval(aasta, kuu, paev):
         m.append(x)
     return m
     
    def paevadeArv(self, aasta, kuu):
     "Mitu päeva vastavas kuus"
     p=[0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
     if aasta%4==0 and kuu==2: return 29
     return p[kuu]
     
    def nadalateArv(self, aasta, kuu):
     "Mitu nädalat kalendrisse vaja"
     n=self.paevadeArv(aasta, kuu)
     p=n+self.esiPaev(aasta, kuu)
     if p==28: return 4
     if p<=35: return 5
     return 6
     
    def esiPaev(self, aasta, kuu):
     "Kuu esimese päeva järjekorranumber"
#     return time.localtime(time.mktime((aasta, kuu, 1, 0, 0, 0, 0, 0, 1)))[6]
     import calendar
     return calendar.weekday(aasta, kuu, 1)
     
    def kalendriAastaJooniseLeht(self, REQUEST, kogum=None, kaasta=time.localtime()[0], tulpadeArv=3):
      "Terve aasta kalender"
      if kogum==None: kogum=self.syndmusteKogum()
      kaasta=int(kaasta)
      tulpadeArv=int(tulpadeArv)
      tulemus=self.hdr(self, REQUEST)+"<table cellspacing='10'>"
      tulemus=tulemus+"<tr><td colspan='"+str(tulpadeArv)+"' align='center' />"+\
        "<a href='"+REQUEST.URL0+"?kaasta="+str(kaasta-1)+"'>&lt;-</a> &nbsp;"+str(kaasta)+\
         "&nbsp; <a href='"+REQUEST.URL0+"?kaasta="+str(kaasta+1)+"'>-&gt;</a></td></tr>\n"
      kuu=1
      while kuu<=12:
        tulemus=tulemus+"<tr>"
        for tulp in range(tulpadeArv):
          tulemus=tulemus+"<td valign='top'>"
          if kuu<=12:
            tulemus=tulemus+self.kalendriKuuJoonis(REQUEST, 0, kogum, kaasta, kuu)
            kuu=kuu+1
          tulemus=tulemus+"</td>"
        tulemus=tulemus+"</tr>"
      tulemus=tulemus+"</table>"+self.fle_html_footer(self, REQUEST)
      return tulemus
     

    def jooksvaKalendrikuuJoonis(self, REQUEST):
      "Tabel"
      k=self.syndmusteKogum()
      aeg=time.localtime()
      aasta=aeg[0]
      kuu=aeg[1]
      if hasattr(REQUEST, 'aasta'): aasta=int(getattr(REQUEST, 'aasta'))
      if hasattr(REQUEST, 'kuu'): kuu=int(getattr(REQUEST, 'kuu'))
      return self.kalendriKuuJoonis(REQUEST, 1, k, aasta, kuu)
   
    def kalendriKuuJoonis(self, REQUEST, kasYksikKuu, kogum, aasta, kuu):
     "Joonisena"
     self.get_lang(('ivacommon','ivaevents',), REQUEST)
     kuunimed=('',REQUEST["L_ic_month_jan"],REQUEST["L_ic_month_feb"],REQUEST["L_ic_month_mar"],
                  REQUEST["L_ic_month_apr"],REQUEST["L_ic_month_may"],REQUEST["L_ic_month_jun"],
                  REQUEST["L_ic_month_jul"],REQUEST["L_ic_month_aug"],REQUEST["L_ic_month_sep"],
                  REQUEST["L_ic_month_oct"],REQUEST["L_ic_month_nov"],REQUEST["L_ic_month_dec"])
     tulemus="<table width=\"180\" border=\"0\" cellpadding=\"2\" cellspacing=\"1\" bgcolor=\"#EEEEEE\">"
     tulemus=tulemus+"<tr>\n"
     if kasYksikKuu:
       eelmineaasta=aasta
       eelminekuu=kuu-1
       if eelminekuu<1:
        eelmineaasta=aasta-1
        eelminekuu=eelminekuu+12
       jargmineaasta=aasta
       jargminekuu=kuu+1
       if jargminekuu>12:
        jargmineaasta=aasta+1
        jargminekuu=jargminekuu-12
       tulemus=tulemus+"<td align=\"center\"><a href='"+REQUEST.URL0+"?aasta="+str(eelmineaasta)+"&kuu="+\
               str(eelminekuu)+"'><img src=\"images/arrow_left1\" border=\"0\" alt=\"\" /></a></td>\n"
       tulemus=tulemus+"<td colspan=\"5\" align=\"center\">"+kuunimed[kuu]+" "
       tulemus=tulemus+"<a href=\""+self.absolute_url()+"/kalendriAastaJooniseLeht\">"+str(aasta)+"</a></td>\n"
       tulemus=tulemus+"<td align=\"center\"><a href='"+REQUEST.URL0+"?aasta="+str(jargmineaasta)+"&kuu="+\
               str(jargminekuu)+"'><img src=\"images/arrow_right1\" border=\"0\" alt=\"\" /></a></td>\n"
     else:
       tulemus=tulemus+"<td colspan=\"7\" align=\"center\">"+kuunimed[kuu]+"</td>"
     tulemus=tulemus+"</tr>\n"
     kp=0
     ep=self.esiPaev(aasta, kuu)
     pa=self.paevadeArv(aasta, kuu)
     for n in range(self.nadalateArv(aasta, kuu)):
       tulemus=tulemus+"<tr>\n"
       for p in range(7):
         if n==0 and p==ep: kp=1
         if kp>pa:kp=0
         tulemus=tulemus+"<td class=\"t3\">"
         if kp>0: 
           tulemus=tulemus+self.kalendriPaevaLahtriSisu(kogum, aasta, kuu, kp)
           kp=kp+1
         tulemus=tulemus+"</td>\n"
       tulemus=tulemus+"</tr>\n"
     if kasYksikKuu:
       tulemus=tulemus+"<tr>\n<td colspan=\"7\" class=\"t1\" align=\"center\">\n"
       tulemus=tulemus+"<a href='"+self.absolute_url()+"/syndmused/syndmusteMuutmisVorm'>"+REQUEST['L_ie_change']+"</a>\n"
       tulemus=tulemus+"</td>\n</tr>\n"
     tulemus=tulemus+"</table>\n"
     return tulemus
       
    def kalendriPaevaLahtriSisu(self, kogum, aasta, kuu, paev):
      "Viide vastavalt sündmuste arvule"
      m=self.syndmusedPaevas(kogum, aasta, kuu, paev)
      if len(m)==0: return str(paev)
      if len(m)==1: 
        return "<a href='"+m[0].absolute_url()+"'>"+str(paev)+"</a>"
      return ("<a href='kalendriPaevaSyndmusteLoetelu?aasta=%s&kuu=%s&paev=%s'>"%(aasta, kuu, paev))+str(paev)+"</a>"

    def kalendriPaevaSyndmusteLoetelu(self, REQUEST, aasta, kuu, paev):
      "Väljund kasutajale"      
      tulemus=self.hdr(self, REQUEST)
      m=self.syndmusedPaevas(self.syndmusteKogum(), aasta, kuu, paev)
      if len(m)==0:
       tulemus=tulemus+"Sündmused puuduvad"
      else:
       tulemus=tulemus+"<table>"
       for x in m:
         tulemus=tulemus+x.tabeliRida(REQUEST)
       tulemus=tulemus+"</table>"
      return tulemus+self.fle_html_footer(self, REQUEST)
      
      

    def muudetudAladePlokk(self, REQUEST):
      "Värvilaigud päevikulauale"
      k=self.kysiJooksvaKursuseObjekt()
      tulemus=""
      if k == 'viga':
	 return tulemus
      if k.gf.kasMuudetudParastKylastust(REQUEST) or getattr(self.webtop, 'c'+self.get_jooksev_kursus()).kasMuudetudParastKylastust(REQUEST):
        tulemus=tulemus+"<table border=\"0\" cellpadding=\"2\" cellspacing=\"1\" width=\"160\" bgcolor=\"#EEEEEE\">\n"
        tulemus=tulemus+"<tr>\n<th>Muudetud</th>\n</tr>\n"
        tulemus=tulemus+"<tr>\n<td class=\"t1\">\n"
      if getattr(self.webtop, 'c'+self.get_jooksev_kursus()).kasMuudetudParastKylastust(REQUEST):
        tulemus=tulemus+"<a href='"+self.absolute_url()+"/webtop/c"+self.get_jooksev_kursus()+"'>"+REQUEST['L_webtop']+"</a><br />" 
      if k.gf.kasMuudetudParastKylastust(REQUEST):
        tulemus=tulemus+"<a href='"+k.absolute_url()+"/gf'>"+REQUEST['L_bookshelf']+"</a><br />" 
      if k.gf.kasMuudetudParastKylastust(REQUEST) or getattr(self.webtop, 'c'+self.get_jooksev_kursus()).kasMuudetudParastKylastust(REQUEST):
        tulemus=tulemus+"</td>\n</tr>\n</table>\n"
      return tulemus


Globals.InitializeClass(UserInfo)

# EOF
