# -*- coding: utf-8
# $Id: FLE.py 346 2005-09-19 07:10:55Z vahur $
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA 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.
#
# IVA 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 IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""This is the main module for FLE, containing the FLE class and the Zope factory method for creating a FLE installation inside Zope."""

__version__ = "$Revision: 346 $"[11:-2]
IVA_VERSION = "IVA dev"

import os.path, string, time

try:
    from PIL import Image
    PIL_imported = 1
except ImportError:
    PIL_imported = 0
try:
	from Products.PlacelessTranslationService import getTranslationService
	PLACELESS = 1
except ImportError:
	PLACELESS = 0
try:
	from Products.ZWiki.ZWikiPage import ZWikiPage
	ZWIKI_imported = 1
except ImportError:
	ZWIKI_imported = 0

import Globals
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.StandardCacheManagers import AcceleratedHTTPCacheManager
from Globals import Persistent, Acquisition, HTMLFile, PersistentMapping
import AccessControl
import OFS
from OFS.Folder import Folder
from Products.ZCatalog.ZCatalog import ZCatalog

from TraversableWrapper import TraversableWrapper as TW
from Cruft import Cruft

from ThinkingTypeSetManager import ThinkingTypeSetManager as TTSM
from UserManager import UserManager
from CourseManager import CourseManager
from Timer import Timer
from common import file_path, ui_path, translate
import Acquisition
import YlTest
from string import atoi

from common import add_dtml_obj, new_add_dtml_obj, add_image_obj, \
     reload_dtml, add_dtml, reload_pt, add_pt_obj, add_pt
from common import perm_view, perm_edit, perm_manage, perm_add_lo, perm_access, \
     roles_admin, roles_staff, roles_user
import common
import re

import YlHoidla
from YlHoidla import YlHoidla

try:
	from Products.CMFCore.CookieCrumbler import CookieCrumbler, ATTEMPT_NONE, ATTEMPT_LOGIN, ATTEMPT_RESUME
	CCAware = 1
except:
	CCAware = 0

from Statistics import StatisticsRegister

# This is the class for the FLE installation root object.
class FLE(
    Folder,
    TW,
    Cruft,
    Persistent,
    AccessControl.Role.RoleManager,
    OFS.SimpleItem.Item,
    Timer,
    StatisticsRegister,
    ):
    """FLE product."""
    security = AccessControl.ClassSecurityInfo()
    security.declareObjectPublic()

    meta_type = 'IVA'

    security.declareProtected(perm_manage, 'management_tab')
#    management_tab = Globals.DTMLFile('ui/FLE/management_tab', globals())
    management_tab = PageTemplateFile('ui/management_tab', globals())
    management_tab._owner = None
    manage_options=(
        {'label' : 'Tools', 'action' : 'management_tab'},
        ) + OFS.Folder.Folder.manage_options

    dtml_files = (
	('style_css','','ui/style_css'),
	('style_cssWebtop','','ui/style_cssWebtop'),
	('style_cssBookshelf','','ui/style_cssBookshelf'),
	('style_cssWorkshops','','ui/style_cssWorkshops'),
	('style_cssManagement','','ui/style_cssManagement'),
	('style_cssOrganizer','','ui/style_cssOrganizer'),
	('js/checkAll2','','ui/js/checkAll2'),
	('js/tree','','ui/js/tree'),
	('js/ivaeditor', '', 'ui/js/ivaeditor'),
    	)
    #index_html = Globals.HTMLFile("index_html", globals())
    pt_files = ( # ZWiki files
    	('courses_list','list of courses','ui/courses_list'),
	('password_form','','ui/password_form'),
	('backlinks','ZWiki backlinks','ui/Wiki/backlinks.pt'),
	('badtemplate','ZWiki ZPT','ui/Wiki/badtemplate.pt'),
	('contentspage','ZWiki','ui/Wiki/contentspage.pt'),
	('diffform','ZWiki','ui/Wiki/diffform.pt'),
	('editform','ZWiki','ui/Wiki/editform.pt'),
	('filterissues','ZWiki','ui/Wiki/filterissues.pt'),
	('issuetracker','ZWiki ZPT','ui/Wiki/issuetracker.pt'),
	('ratingform','ZWiki ZPT','ui/Wiki/ratingform.pt'),
	('recentchanges','ZWiki','ui/Wiki/recentchanges.pt'),
	('searchwiki','ZWiki','ui/Wiki/searchwiki.pt'),
	('subscribeform','ZWiki','ui/Wiki/subscribeform.pt'),
	('useroptions','ZWiki','ui/Wiki/useroptions.pt'),
	('wikipage_macros','ZWiki','ui/Wiki/wikipage_macros.pt'),
	('wikipage','ZWiki Page','ui/Wiki/wikipage.pt'),

	('index_html','start page','ui/index_html'),
	('start_page','start page','ui/start_page'),
	('defaultRender','dummy page to display custom pages','ui/defaultRender'),
	('changeEvent','','ui/changeEvent'),
	('createMail','','ui/createMail'),
	('event_index','','ui/event_index'),
	('event_list','','ui/event_list'),
	('haldusleht','','ui/haldusleht'),
	('mailbox_index','','ui/mailbox_index'),
	('mail_index','','ui/mail_index'),
	('mailStatus','','ui/mailStatus'),
	('main_macro','','ui/main_macro.zpt'),
	('blog_macro','','ui/blog_macros.zpt'),
	('blog_index','','ui/blog_index'),
	('blog_entry','','ui/blog_entry'),
	('blog_archive','','ui/blog_archive'),
	('blog_addEntryForm','','ui/blog_addEntryForm'),
	('blog_changeEntryForm','','ui/blog_changeEntryForm'),
	('manage_addAssignment','','ui/manage_addAssignment'),
	('manage_addingUsers','','ui/manage_addingUsers'),
	('manage_addIvaUsers','','ui/manage_addIvaUsers'),
	('manage_affiliations','','ui/manage_affiliations'),
	('manage_assignments','','ui/manage_assignments'),
	('manage_changeAssignment','','ui/manage_changeAssignment'),
	('manage_course_info','','ui/manage_course_info'),
	('manage_gradeAssignment','','ui/manage_gradeAssignment'),
	('manage_iva_setup','','ui/manage_iva_setup'),
	('manage_ivaUsers','','ui/manage_ivaUsers'),
	('manage_participants','','ui/manage_participants'),
	('manage_userPermissions','','ui/manage_userPermissions'),
	('manage_pendingUsers','','ui/manage_pendingUsers'),
	('message_dialog','','ui/message_dialog'),
	('message_dialog2','','ui/message_dialog2'),
	('message_dialog_error','','ui/message_dialog_error'),
	('organizer_calendar','','ui/organizer_calendar'),
	('calendar','','ui/calendar.zpt'),
	('organizer_change_course','','ui/organizer_change_course'),
	('organizer_index','','ui/organizer_index'),
	('page_macro','','ui/page_macro.zpt'),
	('sharedDocs','','ui/sharedDocs'),
	('standard_error_message','','ui/standard_error_message'),
	('error_show_traceback','Show traceback to user','ui/error_show_traceback.zpt'),
	('assignmentGrading','','ui/assignmentGrading'),
	('testihaldus', '', 'ui/testihaldus'),
	#('workshop_subgroup','','ui/subgroups/workshop_subgroup'),
	('workshop_subgroup_add','','ui/subgroups/workshop_subgroup_add.zpt'),
	('workshop_subgroup_list','','ui/subgroups/workshop_subgroup_list.zpt'),
	('workshop_subgroup_members','','ui/subgroups/workshop_subgroup_members.zpt'),
	('portfolio_index', '', 'ui/portfolio_index.zpt'),
	#('courses/sg_index_html','','ui/subgroups/sg_index_html.zpt'),
	('hw_index_html', 'Assignment folder index_html', 'ui/webtop/hw_index_html.zpt'),
	('wt_add_folder','','ui/webtop/wt_add_folder.zpt'),
	('wt_add_link','','ui/webtop/wt_add_link.zpt'),
	('wt_add_memo','','ui/webtop/wt_add_memo.zpt'),
	('wt_add_wiki','','ui/webtop/wt_add_wiki.zpt'),
	('wt_index_html','','ui/webtop/wt_index_html.zpt'),
	('wt_itemProperties','','ui/webtop/wt_itemProperties.zpt'),
	('wt_manage','','ui/webtop/wt_manage.zpt'),
	('wt_rename','','ui/webtop/wt_rename.zpt'),
	('wt_upload','','ui/webtop/wt_upload.zpt'),
	('wt_usercomments','','ui/webtop/wt_usercomments.zpt'),
	('wt_userForm','','ui/webtop/wt_userForm.zpt'),
	('wt_view_memo','','ui/webtop/wt_view_memo.zpt'),
	('wt_zip_upload','','ui/webtop/wt_zip_upload.zpt'),
	('wt_visitors','','ui/webtop/wt_visitors.zpt'),
	('wt_macros','','ui/webtop/wt_macros.zpt'),
	('ylAlus_muutmisVorm', '', 'ui/ylAlus_muutmisVorm'),
	('ylMeta_vorm1', '', 'ui/ylMeta_vorm1'),
	('ylesandedMuutmisTabelina', '', 'ui/ylesandedMuutmisTabelina'),
	('ylOtsing', '', 'ui/ylOtsing'),
	('ylOtsinguVorm', '', 'ui/ylOtsinguVorm'),
	('ylTestSettingsForm', '', 'ui/ylTestSettingsForm'),
	('ylBlankQuestion', '', 'ui/ylBlankQuestion'),
	('ylAddPicture', '', 'ui/ylAddPicture'),
	('ylTable', '', 'ui/ylTable'),
	('qtChangeFormMatchingExercise', '', 'ui/qtChangeFormMatchingExercise'),
	('qtChangeFormNumberSpaceExercise', '', 'ui/qtChangeFormNumberSpaceExercise'),
	('qtChangeFormShortAnswerExercise', '', 'ui/qtChangeFormShortAnswerExercise'),
	('qtChangeFormPercentExercise', '', 'ui/qtChangeFormPercentExercise'),
	('qtTimeSettings', '', 'ui/qtTimeSettings'),
	('qtTestAnswerTable', '', 'ui/qtTestAnswerTable'),
	('qtTestAnswerCommentingTable', '', 'ui/qtTestAnswerCommentingTable'),
	('qtTestAnswerStatistics', '', 'ui/qtTestAnswerStatistics'),
	('qtUserResults', '', 'ui/qtUserResults'),
	('qtExplanationQuiz', '', 'ui/qtExplanationQuiz'),
	('qtAnsweringForm', '', 'ui/qtAnsweringForm'),
	('qtAnswersSaved', '', 'ui/qtAnswersSaved'),
	('qtExerciseForm', '', 'ui/qtExerciseForm'),
	('qtExerciseAnswer', '', 'ui/qtExerciseAnswer'),

	('wmapindex', '', 'ui/wmapindex'),
	('wordmaps_word_page', '', 'ui/wordmaps_word_page'),
	('wordmaps_edge_page', '', 'ui/wordmaps_edge_page'),
	('wordmaps_equation_redactor', '', 'ui/wordmaps_equation_redactor'),
	('wordmaps_equation_buttons', '', 'ui/wordmaps_equation_buttons'),
	('wordmaps_index_html', '', 'ui/wordmaps_index_html'),
	('wordmaps_importing_page', '', 'ui/wordmaps_importing_page'),
	('wordmaps_managing_page', '', 'ui/wordmaps_managing_page'),
	('wordmaps_weight_page', '', 'ui/wordmaps_weight_page'),
	('wordmaps_assessment_results', '', 'ui/wordmaps_assessment_results'),
	('wordmaps_toolbox', '', 'ui/wordmaps_toolbox'),
	('wordmaps_hierarhy', '', 'ui/wordmaps_hierarhy'),

	('courses/add_course_context_form','Add Course Context','ui/courses/add_course_context_form'),
	('courses/context_html','Context index','ui/courses/context_html'),
	('courses/course_html','Course Context list','ui/courses/course_html'),
	('courses/course_info','','ui/courses/course_info'),
	('courses/course_setup_roleplay_form','Roleplay setup','ui/courses/course_setup_roleplay_form'),
	('courses/note_edit_form','Note editing form','ui/courses/note_edit_form'),
	('courses/index_html','','ui/courses/index_html'),
	('courses/note_preview_form','Note editing form','ui/courses/note_preview_form'),
	('courses/note_index_html','Note viewing form','ui/courses/note_index_html'),
	('courses/organizer_openCourses','','ui/courses/organizer_openCourses'),
	('courses/printer_macro','Note printers','ui/courses/printer_macro'),
	('courses/note_hide','Note printers','ui/courses/note_hide'),

	('courses/jamming_index_html','Index page of jamming','ui/courses/jamming_index_html'),
	('courses/jam_add_session_form','add jam session','ui/courses/jam_add_session_form'),
	('courses/jamsession_index_html','Index page of jamsession','ui/courses/jamsession_index_html'),
	('courses/jam_add_artefact_form','Add artefact form','ui/courses/jam_add_artefact_form'),
	('courses/jam_artefact_index_html','Artefact index_html','ui/courses/jam_artefact_index_html'),
	('courses/jam_add_annotation_form','Add artefact annotation form','ui/courses/jam_add_annotation_form'),
	('courses/list_readers','Who has read it!?','ui/courses/list_readers'),

	('courses/manage_import_form','Import course','ui/courses/manage_import_form'),
	('courses/teacher_import_form','Import course(for teacher)','ui/courses/teacher_import_form'),
	('courses/manageCategories','manage course categories','ui/courses/manageCategories'),
	('courses/course_index','Welcome page for course','ui/courses/course_index'),
	('courses/courseStatistics','Course statistics','ui/courses/courseStatistics'),
	('courses/describeTTS','Describes thinkingtypeset','ui/courses/describeTTS'),
	('courses/tootubade_leht','','ui/courses/tootubade_leht.zpt'),

	('typesets/edit_form_1_3','','ui/typesets/edit_form_1_3'),
	('typesets/edit_form_2_3','','ui/typesets/edit_form_2_3'),
	('typesets/edit_form_3_3','','ui/typesets/edit_form_3_3'),
	('typesets/index_html','','ui/typesets/index_html'),
	('typesets/tts_index','','ui/typesets/tts_index'),
	('typesets/manage_import_form','Import typesets','ui/typesets/manage_import_form'),

	('register_form','Register form','ui/register_form'),

	('fle_users/course_info_user','Information about user actions','ui/fle_users/course_info_user'),
	('fle_users/user_courses_info','Information about all user courses','ui/fle_users/user_courses_info'),
	('fle_users/show_user_info','','ui/fle_users/show_user_info'),
	('fle_users/edit_user_form','','ui/fle_users/edit_user_form'),

	('sub_manager_index','','ui/subgroups/sub_manager_index.zpt'),

	)

    # NOTE: Since we use a python method index_html to do
    # the redirection to the appropriate DTML method, EVERY FOLDER
    # that the user access must have this index_html method
    # (either through class inheritance or as its own dtml method,
    # but not through acquisition from its containers). Acquisition
    # cannot be used, since the object reference passed to the DTML
    # method will point to the object where index_html was acquired.
    # So all courses, contexts, notes, userinfos, webtops and webtopfolders
    # and any other folderish objects must have this python method.
    #security.declarePublic('index_html')
    #def index_html(self,REQUEST):
    #    return self.ui.FLE.index_html(self,REQUEST)

    # Parameters are received from the creation form at
    # ui/FLE/creation_form.dtml
    def __init__(
        self, _id, title,
        smtp_host, smtp_port=25, 
        _default_lang='en', _quota=3000000, mfrom='iva@htk.tpu.ee',
	def_passwd=0,def_not_change=0,def_not_aff=0):
        """Construct FLE object."""

        self.setup_timer()

        errors = []
        if not _id:
            errors.append('ID not specified')
        if not title:
            errors.append('Title not specified')
        if errors:
            raise 'Insufficient form data',str(errors)

        self.id = _id
        self._default_lang=_default_lang
        self._quota=_quota
        self.title = title
	self.mfrom = mfrom
	
	self.def_asswd= int(def_passwd)
	self.def_ot_change= int(def_not_change)
	self.def_ot_aff= int(def_not_aff)
	self._pending_users = PersistentMapping() # user list 

        self.__fle_root = ''

        if len(smtp_host)>0 and smtp_port:
            from Products.MailHost import MailHost
            mailhost = MailHost.MailHost()
            mailhost._init(smtp_host, int(smtp_port))
            self._setObject('MailHost', mailhost)

        # Add images to images/
        self.manage_addFolder('images', 'Images')
	AcceleratedHTTPCacheManager.manage_addAcceleratedHTTPCacheManager(self.images,'HTTPCache')
	http_cache = getattr(self.images, 'HTTPCache')
	http_cache.manage_editProps('', {'anonymous_only':0, 'interval':3600, 'notify_urls':''})
        from common import image_file_path
        self.add_images(self.images, image_file_path)
	ims = getattr(self, 'images')
	ims.manage_addFolder('courses_imgs', '')
	ims.manage_addFolder('users_imgs', '')

        # ZCatalog for webtop items
        catalog = ZCatalog('catalog_webtop_items', 'ZCatalog for webtop items')

        # indexes
        catalog.addIndex('get_name', 'TextIndex')
        catalog.addIndex('get_content', 'TextIndex')
        catalog.addIndex('get_author', 'FieldIndex')

        # metadata
        catalog.addColumn('get_name')
        catalog.addColumn('get_author')
        catalog.addColumn('absolute_url')

        self._setObject('catalog_webtop_items', catalog)

	# ZCatalog for events
	catalog = ZCatalog('catalog_events','ZCatalog for events')

	# indexes
	catalog.addIndex('meta_type', 'FieldIndex')
	catalog.addIndex('path', 'PathIndex')
	catalog.addIndex('kysiOlek', 'FieldIndex')
	catalog.addIndex('getName', 'FieldIndex')
	catalog.addIndex('asukohaNimi', 'FieldIndex')
	catalog.addIndex('get_start_time', 'DateIndex')
	catalog.addIndex('get_end_time', 'DateIndex')

	# metadata
	catalog.addColumn('getName')
	catalog.addColumn('kysiOlek')
	catalog.addColumn('getContent')
	catalog.addColumn('kysiSiseviide')
	catalog.addColumn('kysiViide')
	catalog.addColumn('kysiAlgus')
	catalog.addColumn('kysiLopp')
	catalog.addColumn('get_start_time')
	catalog.addColumn('get_end_time')
	catalog.addColumn('absolute_url')

	# add object
        self._setObject('catalog_events', catalog)

	# init Statistics
	StatisticsRegister.__init__(self)

    security.declarePrivate('manage_afterAdd')
    # Executes a full FLE import if the export data was
    # passed to the constructor (ie. uploaded via the creation
    # form.
    def manage_afterAdd(self, item, container):
        """Add roles to the root level Fle folder and do other
        initialization tasks."""

	stats = getattr(self, 'Statistics', None)
	if stats is None:
		from Statistics import StatisticsManager
		stats = StatisticsManager()
		self._setObject(stats.id, stats)
	
	if not hasattr(self.aq_self, 'qtCatalog'):
		self._setObject('qtCatalog', YlHoidla())

        if hasattr(self,'typesets'):
            # If the typesets directory already exists, then this
            # isn't the initial installation, but rather a rename
            # or a move operation.
            # Skip everything!
            return

        self.manage_addProperty('Autoregister', 0, 'boolean')
        # add property for FLE version number
        
        self.manage_addProperty('webtop_quota', 1, 'boolean')
        self.manage_addProperty('webtop_quota_amount', self._quota, 'string')
        self.manage_addProperty('default_language', self._default_lang, 'string')
                
        self.manage_addProperty('IVA_VERSION', IVA_VERSION, 'string')
	self.manage_addProperty('MFROM',self.mfrom,'string')
	self.manage_addProperty('def_passwd',int(self.def_asswd),'boolean')
	self.manage_addProperty('def_not_change',int(self.def_ot_change),'boolean')
	self.manage_addProperty('def_not_aff',int(self.def_ot_aff),'boolean')

        tts_manager = TTSM('typesets', '')
        self._setObject('typesets', tts_manager)
        tts_manager=tts_manager.__of__(self)

        from Downloader import Downloader
        self._setObject('download',Downloader())

	self.manage_addFolder('uploads','Wiki uploads')
	self.manage_addFolder('js','JavaScripts')

        from common import fle_roles

        for role in fle_roles:
            self._addRole(role)
	self._addRole('Items')

	self.manage_permission(perm_access, ('Manager','IVAAdmin','Member','Owner') ,0)
	self.manage_permission(perm_view, ('Authenticated','Manager','IVAAdmin','Member','Owner') ,0)
	self.manage_permission(perm_edit, ('Manager',), 0)

        self.manage_permission(perm_manage, roles_admin, 0)
        self.manage_permission(perm_add_lo, roles_admin, 0)
	try:
		self.manage_permission('Zwiki: Add comments', roles_user+('Authenticated','Owner',), 0)
		self.manage_permission('Zwiki: Add pages', ('Owner',), 0)
		self.manage_permission('Zwiki: Add wikis', ('Owner',), 0)
		self.manage_permission('Zwiki: Change page types', ('Owner',), 0)
		self.manage_permission('Zwiki: Delete pages', ('Owner',), 0)
		self.manage_permission('Zwiki: Edit pages', ('Owner',), 0)
		self.manage_permission('Zwiki: Rename pages', ('Owner',), 0)
		self.manage_permission('Zwiki: Reparent pages', ('Owner',), 0)
	except ValueError:
		pass
	self.uploads.manage_permission('Add Documents, Images, and Files', roles_user+('Authenticated','Owner',), 0)

        um_obj = UserManager('fle_users',
                             #'FLE User Manager')
                             '')
        self._setObject('fle_users',
                        um_obj)

        # Create default knowledge type sets, whether importing
        # or not.
        tts_manager.load_default_sets()

        # Let's do courses last, since if we're importing, we
        # need to have the users already in place.
        cm_obj = CourseManager('courses')
        self._setObject('courses', cm_obj)
        
        self.manage_addProduct['OFSP'].manage_addFolder('css')
        #self.css._setObject('style_css', self.style_css)

	self.reload_pt()
        # Set the zope manageable dtml objects of this class.
        self.reload_dtml()

	self.setDefaultPermissions()
	#XXX: migrate me too!?
	if CCAware:
		self.addCookieCrumbler()

    security.declareProtected(perm_manage, 'reload_pt')
    def reload_pt(self, REQUEST=None):
	""" reload ZopePageTemplates """
	reload_pt(self, self.pt_files)
	self.setDefaultPermissions()

        if REQUEST:
            return self.message_dialog(
                self, REQUEST,
                title="Reloaded",
                message="All page templates reloaded",
                action='index_html')
		
    security.declarePublic('setDefaultPermissions')
    def setDefaultPermissions(self):
	""" doc"""
        getattr(self.images,'iva_logo_trans').manage_permission('View',['Authenticated', 'Anonymous',], 1)
        getattr(self.images,'start_top_bg').manage_permission('View',['Authenticated', 'Anonymous',], 1)
        getattr(self.images,'start_bg').manage_permission('View',['Authenticated', 'Anonymous',], 1)
        getattr(self,'register_form').manage_permission('View',['Authenticated', 'Anonymous',], 1)
        getattr(self,'courses_list').manage_permission('View',['Authenticated', 'Anonymous',], 1)
	try:
	        getattr(self,'style_css').manage_permission('View',['Authenticated', 'Anonymous',], 1)
	except:
		pass
        getattr(self,'index_html').manage_permission('View',['Authenticated', 'Anonymous',], 1)
        getattr(self,'start_page').manage_permission('View',['Authenticated', 'Anonymous',], 1)
	getattr(self,'password_form').manage_permission(perm_view,['Authenticated', 'Anonymous',], 1)
#	getattr(self,'style_css').manage_permission(perm_view,['Anonymous'],0)
	getattr(self,'register_form').manage_permission(perm_view,['Anonymous'],0)
	getattr(self,'images').manage_permission('View',['Anonymous',],1)
	try:
		getattr(getattr(self,'js'), 'tree').manage_permission('View',['Anonymous',],1)
	except AttributeError:
		pass
	getattr(self, 'main_macro').manage_permission('View',['Anonymous',],1)

    security.declareProtected(perm_manage, 'reload_dtml')
    def reload_dtml(self, REQUEST=None):
        """Reloads dtml stuff."""
        reload_dtml(self, self.dtml_files)
	self.setDefaultPermissions()

        if REQUEST:
            return self.message_dialog(
                self, REQUEST,
                title='Reloaded',
                message='dtml files reloaded',
                action='index_html')

    security.declareProtected(perm_manage, 'reload_typesets')
    def reload_typesets(self,REQUEST=None):
        """Reload typesets."""
        self.typesets.load_default_sets()
        if REQUEST:
            return self.message_dialog(
                self, REQUEST,
                title='Reloaded',
                message='Knowledge type sets reloaded',
                action='index_html')


    security.declareProtected(perm_manage, 'reload_images')
    def reload_images(self,REQUEST=None):
        """Reload images."""
        for e in self.images.objectIds():
	    if e in ('courses_imgs', 'users_imgs', 'HTTPCache'):
		    continue
            self.images.manage_delObjects(e)

        from common import image_file_path
        self.add_images(self.images, image_file_path)

        if REQUEST:
            return self.message_dialog(
                self, REQUEST,
                title='Reloaded',
                message='Images reloaded',
                action='index_html')

    security.declarePrivate('add_images')
    # fs_path is CVS path
    def add_images(self, zope_path, fs_path):
        """Add images recursively."""
        for e in os.listdir(fs_path):
            full_path = os.path.join(fs_path, e)

            if os.path.isdir(full_path):
                if e == 'CVS': continue
		if e == '.svn': continue
                zope_path.manage_addFolder(e, '')
                self.add_images(getattr(zope_path, e), full_path)
            else:
                # title (3rd parameter) will be used as an alt parameter
                # inside HTML <img> tag. (Override in DTML code when you
                # want some alt text (i.e. almost always...))

                # This can be like this for now .... -granbo
                import re
                m = re.match("^(.*)\.", e)

                add_image_obj(zope_path, m.group(1), '', full_path)

    security.declareProtected(perm_manage, 'reload_all')
    def reload_all(self, REQUEST=None):
        """Reload all dtml, style sheet, image, printer, and
        translation files."""
	self.IVA_VERSION = IVA_VERSION
#        self.reload_all_dtml()
        self.reload_images()
	self.reload_pt()
        self.reload_typesets()
	self.reload_all_dtml()

        if REQUEST:
            return self.message_dialog(
                self, REQUEST,
                title='Reloaded',
                message='Reloaded all dtml, css, images, and knowledge type sets',
                action='index_html')

    security.declareProtected(perm_manage, 'reload_all_dtml')
    def reload_all_dtml(self, REQUEST=None):
        """Reload _all_ dtml files."""
        from common import tree_reload_dtml
        reload_dtml(self, self.dtml_files)
	self.setDefaultPermissions()

        if REQUEST:
            return self.message_dialog(
                self, REQUEST,
                title='Reloaded',
                message='dtml files reloaded',
                action='index_html')
                
#    security.declareProtected(perm_view, 'get_version')
    security.declarePublic('get_version')
    def get_version(self):
	""" return IVA version """
	return getattr(self, 'IVA_VERSION', 'IVA')

    # FIXME: What should we do if self.webtop_quota_amount is invalid?
    security.declareProtected(perm_view, 'get_quota')
    def get_quota(self):
        """Return quota limit in bytes (-1 if no quota in use)."""
        if not hasattr(self, 'webtop_quota'):
          return -1
        if not hasattr(self, 'webtop_quota_amount'):
          return -1
        if not self.webtop_quota:
            return -1 # no quota
        s = self.webtop_quota_amount.strip()
        if s[-1].lower() == 'k':
            return int(s[:-1]) * 1024
        elif s[-1].lower() == 'm':
            return int(s[:-1]) * 1024 * 1024
        else:
            return int(s)

#XXX: security check!
#    security.declareProtected(perm_view, 'get_languages')
    security.declarePublic('get_languages')
    def get_languages(self):
	""" return list of languages available """
	lang_list = ['et','en','fi','ru']
	return lang_list
            
    def get_default_language(self):
        "Vaikimisi keel"
	return getattr(self, 'default_language', 'en')

    # This is used by message_dialog.dtml.
    def message_dialog_handler(self, action, REQUEST):
        """Redirects to the given URL, preserving the
        state information in the url."""
        REQUEST.RESPONSE.redirect(action)

    security.declareProtected(perm_view, 'redirect_to_webtop')
    def redirect_to_webtop(self, REQUEST):
        """Redirect to webtop."""
        uname = str(REQUEST.AUTHENTICATED_USER)
        if (not hasattr(self.fle_users.aq_self, uname)):
        	result = self.fle_users.add_user_fle(uname, ('Member',))

	user = self.fle_users.get_user_info(uname)
	if self.getUseFinger():
		user.fingerNames()
	
	jnr = user.get_jooksev_kursus()
	self.courses.change_course(REQUEST, jnr)

	user.kontrolliKasutajaKodutood(REQUEST)
	if user.get_first_name()=='' or user.get_last_name()=='':
			return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/fle_users/' + uname + '/webtop/edit_user_form')
	if hasattr(user, 'perm_must_change'):
		if user.perm_must_change == 1:
	        	return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/fle_users/' + uname + '/webtop/edit_user_form')
		else:
	        	return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/organizer_index')
	else:
	        return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/organizer_index')

    security.declareProtected(perm_manage, 'manage_workspace')
    def manage_workspace(self,REQUEST):
        """This makes sure that ZCatalog doesn't override manage_workspace
        and make it point to index_html, when we actually want manage_main"""
        REQUEST.RESPONSE.redirect('manage_main')

    def logout(self,REQUEST):
        """This is the logout instruction page."""
        return self.message_dialog2(
            self, REQUEST,
            title= 'Logout',
            message="To log out, either close your browser or press the <b>Logout</b> button below. When your browser asks for a username and password, just press <b>Cancel</b>. This will clear your login information from your browser's cache",
            extra_value_name = '',
            extra_values = (),
            option1_value = 'Cancel',
            option1_name = 'cancel',
            option2_value = 'Logout',
            option2_name = 'logout',
            handler = 'clear_password')

    security.declarePublic('clear_password')
    def clear_password(
        self,
        cancel=None,
        logout=None,
        REQUEST=None):
        """This will clear the password cache."""
        if logout:
	    #XXX: take care of session somehow, invalidating doesn't seem to work
	    #REQUEST.SESSION.invalidate()
            REQUEST.RESPONSE.setStatus(401)
            REQUEST.RESPONSE.setHeader("WWW-Authenticate", 'basic realm="Zope"')
	    try:
		    self.login.logout()
	    except AttributeError:
		    pass
            return self.message_dialog(
                self, REQUEST,
                title='Logout',
                message='You have been logged out.',
                action = 'index_html')
        else:
            return self.redirect_to_webtop(REQUEST)

    def has_PIL(self):
        """Has the system PIL (Python Image Library) installed?"""
        return PIL_imported

    def has_PLACELESS(self):
	""" is PlacelessTranslationService installed? """
	return PLACELESS

    def has_CMF(self):
	""" is CMF installed? """
	return CCAware

    def getId(self):
	""" Return object id. Hack XXX """
	return self.id

    security.declarePublic('register_form_handler')
    def register_form_handler(self, REQUEST, 
    	regB='', cancelB='', # buttons
	username='', fname='', lname='', email='', preflang='en',optmess='', numbercheck=0):
	""" registers user """
	if regB and self.get_allow_autoregister():
		ok = 1
		inv_val = ''
		if username and fname and lname and email:
			ok = 1
		if not '@' in email and not '.' in email:
			ok = 0
			inv_val+= ' email'
		else:
			#XXX check email!?
			pass
		if not fname:
			ok = 0
			if inv_val: inv_val+=','
			inv_val+=' first name'
		if not lname:
			ok = 0
			if inv_val: inv_val+=','
			inv_val+=' last name'
		if numbercheck != REQUEST.SESSION.get('securenr'):
			ok = 0
			if inv_val: inv_val+=','
			inv_val+= ' number'
		if not username:
			ok = 0
			if inv_val: inv_val+=','
			inv_val+=' username'
		else:
			if self.fle_users.is_valid_uname(username):
				ok = 0
				if inv_val: inv_val+=','
				inv_val+=' username'
				# XXX: maybe we don't want that!
				# XXX: also check in fle_users folder for user record
				# XXX: check for lowlevel acl_users?
		if not ok:
			return self.register_form(username=username, fname=fname, lname=lname, email=email, optmess=optmess,mess='invalid values: '+inv_val)
		#do queueing
		self._queue_user(username=username, fname=fname, lname=lname, email=email, preflang=preflang,optmess=optmess)
		#XXX: subject of email. Translation!
		message = translate(self,"registrant_waiting", target=preflang)
		if self.saadaEmail(email,'useraccount request', message):
			return translate(self,"You have been registered, check e-mail",target=self.giveLanguage(REQUEST))
		else:
			return translate(self,"You have been registered but some problems occured when sending email.",target=self.giveLanguage(REQUEST))
	elif cancelB:
		return REQUEST.RESPONSE.redirect('index_html')
	raise "IVA Error", "unknown button in register_form_handler"

    def lostPassword(self,REQUEST, send=0,knimi='', give_email=0):
	if give_email:
		if not knimi: return 0
		try:
			kasutaja = self.fle_users.get_user_info(knimi)
		except:
			return 0
		if kasutaja.get_email() != '':
			return 1
		else:
			return 0
		return 0 # should never reach here
	#if not hasattr(self.aq_self,'MailHost'):
	if not getattr(aq_base(self), 'MailHost', None):
		return ""
	if send:
		try:
			kasutaja = self.fle_users.get_user_info(knimi)
		except:
			return 0
		if kasutaja.get_email() == '':
			return 0
		sisu = '\nContent-Type:text/plain; charset=utf-8\n\n\n'
		sisu += "\n"+translate(self,'Message from IVA server',target=self.giveLanguage(REQUEST))
		sisu += "\n"+translate(self,'IVA server aadress:',target=self.giveLanguage(REQUEST))+" "+self.fle_root().absolute_url()
		sisu += "\n"+translate(self,'Username:',target=self.giveLanguage(REQUEST))+" "+knimi
		sisu += "\n"+translate(self,'Password:',target=self.giveLanguage(REQUEST))+" "
		try:
			sisu += kasutaja.getPassword()
		except:
			sisu += translate(self,"Error fetching password",target=self.giveLanguage(REQUEST))
		self.saadaEmail(kasutaja.get_email(),'Lost password',sisu, kasutaja.get_email())
	return "Recover password"

    security.declarePublic('randomImage')
    def randomImage(self):
	""" chooses 3/4 images to place on frontpage """
	imgs = self.images.frontpage.objectValues()
	from random import shuffle
	shuffle(imgs)
	if self.get_allow_autoregister(): count=3 
	else: count = 4
	return imgs[0:count]

    security.declareProtected(perm_manage,'manage_iva_setup_pictures')
    def manage_iva_setup_pictures(self, REQUEST, uploadB='', deleteB='',dele='', newimage=''):
	""" upload picture, delete picture """
	imgContainer = getattr(self.images, 'frontpage')
	if deleteB:
		from types import StringType
		if type(dele) == StringType: dele = (dele,)
		for x in dele:
			imgContainer._delObject(x)
				
	if uploadB and newimage:
		import random
		nid = ""
		for x in range(15):
			nr = 95
			while 90<nr<97:
				nr = random.randint(65,122)
			nid += chr(nr)		
		imgContainer.manage_addImage(nid,newimage, '')
	return REQUEST.RESPONSE.redirect('manage_iva_setup')
	    

    security.declareProtected(perm_manage,'manage_iva_setup_handler')
    def manage_iva_setup_handler(self, REQUEST, 
    	saveB='', # save button
	autoregister=0,
	useQuota=0,
	quota=3000000,
	smtp_host='localhost',
	smtp_port=25,
	mailfrom='',
	lang='en',
	def_passwd=0,
	def_not_change=0,
	def_not_aff=0,
	useFinger = 0,
	fingerHost = '',
	fingerPort = 79
	):
	""" saves IVA settings"""
	if saveB:
		self.Autoregister = autoregister
		self.default_language=lang
		self.webtop_quota = int(useQuota)
		self.webtop_quota_amount = quota
		#if not hasattr(self,'MailHost'):
#		if not getattr(aq_base(self), 'MailHost', None):
		if not getattr(self.aq_self, 'MailHost', None):
			if len(smtp_host)>0 and smtp_port:
				from Products.MailHost import MailHost
				mailhost = MailHost.MailHost()
				mailhost._init(smtp_host, atoi(smtp_port))
				self._setObject('MailHost', mailhost)
		else:
			if len(smtp_host)>0 and smtp_port:
				mailhost = getattr(self, 'MailHost')
				mailhost.smtp_host = smtp_host
				mailhost.smtp_port = smtp_port
		self.MFROM = mailfrom
		self.def_passwd = def_passwd
		self.def_not_change = def_not_change
		self.def_not_aff = def_not_aff
		self.setUseFinger(useFinger)
		self.setFingerHost(fingerHost)
		self.setFingerPort(fingerPort)
		return self.manage_iva_setup(mess='settings saved succesfully!')
	return

    security.declareProtected(perm_manage, 'unqueue_user')
    def unqueue_user(self, uname):
	del self._pending_users[uname]

    security.declarePrivate('_queue_user')
    def _queue_user(self,username='', fname='', lname='', email='', preflang='en',optmess=''):
	# _pending_users
	if not getattr(aq_base(self), '_pending_users', None):
		self._pending_users = PersistentMapping()
	#if not hasattr(self.aq_self, '_pending_users'):
	#	self._pending_users = PersistentMapping()
	while self._pending_users.has_key(username):
		username+='x'
	self._pending_users[username] = {'fname':fname,'lname':lname,'email':email,'preflang':preflang,'optmess':optmess}

    security.declareProtected(perm_manage,'get_pending_users')
    def get_pending_users(self):
	""" get pending users """
	return self._pending_users.keys()

    security.declareProtected(perm_manage,'get_pending_details')
    def get_pending_details(self, uname):
	""" get details of pending user """
	return self._pending_users[uname]

    security.declarePrivate('make_random_number')
    def make_random_number(self, REQUEST):
	# generates number and stores in in SESSION
	import random
	rnr = int(random.random()*10000000)
	REQUEST.SESSION.set('securenr',rnr)
	return rnr

    def get_allow_autoregister(self):
	return self.Autoregister
    
    security.declarePublic('generate_picture')
    def generate_picture(self, REQUEST, RESPONSE):
	""" test"""
	srnr = self.make_random_number(REQUEST)
	import PIL
	from PIL import Image, ImageDraw
	import cStringIO
	s = cStringIO.StringIO()
	pilt = Image.new('RGB',(100,30),(255,255,255))
	pil2 = ImageDraw.Draw(pilt)

	tekst = str(srnr)
	pil2.text((10,10),tekst,fill=(30,30,128))
	
	pilt.save(s,'jpeg')
	s.seek(0)
	RESPONSE.setHeader('Content-Type','image/jpeg')
	return s.read()

    def tolgi(self, sona, REQUEST):
        "Tőlgib etteantud jupi. Abifunktsioon DTML-ist tőlkimisel"
        return translate(self, sona, target=self.giveLanguage(REQUEST))

    security.declareProtected(perm_manage,'exportIMail')
    def exportIMail(self,REQUEST):
	""" export mailmessages """
	from ImportExportIMS import Kirjutus
	from ImportExportIMS import kirjutaYldM
	import tempfile, os
        name = 'ivamessages.zip'
        path = os.path.join(Globals.INSTANCE_HOME,'var')
        fname = os.path.join(path,name)
        #fname = tempfile.mktemp()
        yld = kirjutaYldM()
        yld.kirjutaYldmanifest('innermail','Innermail messages',base='',href='messages.xml')
        yld.lisaFaili(fname)
        k = Kirjutus(self.fle_root(), self.get_id())
        k.exportMail(fname)
        #os.remove(fname)
        return "Done! Zip-file is located at %s" % fname

    security.declareProtected(perm_manage, 'exportServerSettings')
    def exportServerSettings(self, REQUEST):
        """ export server settings and course categories """
        from ImportExportIMS import Kirjutus
        from ImportExportIMS import kirjutaYldM
        import tempfile, os
        name = 'iva_settings.zip'
        path = os.path.join(Globals.INSTANCE_HOME,'var')
        fname = os.path.join(path,name)
        yld = kirjutaYldM()
        yld.kirjutaYldmanifest('IVA_C','IVA course categories',base='',href='course_cat.xml')
        yld.kirjutaYldmanifest('IVA_S','IVA server settings',base='',href='settings.xml')
        yld.kirjutaYldmanifest('IVA_A','IVA affiliation codes',base='',href='affiliations.xml')
        yld.lisaFaili(fname)
        k = Kirjutus(self.fle_root(), self.get_id())
        k.looKursuseFail(0)

        #... do stuff
        k.exportCourseCategories(fname)
	k.exportServerSettings(fname)
	k.exportAffiliations(fname)

        return "Done! Zip-file is located at %s" % fname

    security.declareProtected(perm_manage,'exportICAL')
    def exportICAL(self,REQUEST):
	""" export user events """
        from ImportExportIMS import Kirjutus
        from ImportExportIMS import kirjutaYldM
        import tempfile, os
        name = 'iva_events.zip'
        path = os.path.join(Globals.INSTANCE_HOME,'var')
        fname = os.path.join(path,name)
        #fname = tempfile.mktemp()
        yld = kirjutaYldM()
        yld.kirjutaYldmanifest('IVA','IVA user events',base='IVA/',href='imsmanifest.xml')
#       yld.kirjutaYldmanifest()
        yld.lisaFaili(fname)
        k = Kirjutus(self.fle_root(), self.get_id())
        k.looKursuseFail(0)
        k.kirjutaKasutajaSyndmus(self.fle_users.get_users())
        k.pakiKursusFaili(fname)
        #os.remove(fname)
        return "Done! Zip-file is located at %s" % fname

    security.declareProtected(perm_view,'getUseFinger')
    def getUseFinger(self):
	""" return if user information should be pulled via finger """
	if not hasattr(self, 'useFinger'):
		return 0
	return self.useFinger

    security.declareProtected(perm_manage,'setUseFinger')
    def setUseFinger(self, state):
	""" set if we should use finger """
	self.useFinger = int(state)

    security.declareProtected(perm_view,'getFingerPort')
    def getFingerPort(self):
	""" return finger port """
	if not hasattr(self, 'fingerPort'):
		return "79"
	return self.fingerPort

    security.declareProtected(perm_manage,'setFingerPort')
    def setFingerPort(self, port):
	""" set finger daemon port """
	self.fingerPort = int(port)

    security.declareProtected(perm_view,'getFingerHost')
    def getFingerHost(self):
	""" return finger daemon host """
	if not hasattr(self, 'fingerHost'):
		return ""
	return self.fingerHost

    security.declareProtected(perm_manage,'setFingerHost')
    def setFingerHost(self, host):
	""" set fingerdaemon host """
	self.fingerHost = host

    def getCourseForID(self, REQUEST, course_id, curUser):
	""" return course instance or set current course id to 0 """
	#if not hasattr(self.courses.aq_self, course_id):
	course = getattr(self.courses, course_id, '')
	if course == '' and int(course_id) != 0:
		curUser.jooksev_kursus = 0
		return REQUEST.RESPONSE.redirect('organizer_index')
	return course
    
    security.declareProtected(perm_manage,'addCookieCrumbler')
    def addCookieCrumbler(self):
	""" xxx """
	if hasattr(self.aq_self, 'login'):
		return
	cc = CookieCrumbler()
	cc.id = 'login'
	self._setObject('login', cc)
	
	#XXX: picture location!!!
	login_form = """
<html>
<script>
<!---
function fookus(){document.post.__iva_name.focus();}
// -->
</script>
<head></head>
<body onLoad=fookus()>
<img src="images/logo_gif"><br />
<dtml-let came_from="REQUEST.get('came_from', 'http://htk.tpu.ee:8080/IVA/IVA')"
action_url="came_from or 'http://htk.tpu.ee:8080/IVA/IVA'">
<form action="&dtml-action_url;" method="POST" name="post">
<dtml-if expr="REQUEST.get('retry', 0)">
<font color="red">Please try again.</font><br />
<a href="IVA/IVA/password_form?knimi=">Forgot Password?</a>
</dtml-if>
<dtml-if came_from>
<input type="hidden" name="came_from" value="&dtml-came_from;">
</dtml-if>
<table>
<tr>
<td align="left" valign="top">
<strong>Name</strong>
</td>
<td align="left" valign="top">
<input type="TEXT" name="__iva_name" size="20"
value="<dtml-var "REQUEST.get('__iva_name', '')">">
</td>
</tr>
<tr>
<td align="left" valign="top">
<strong>Password</strong>
</td>
<td align="left" valign="top">
<input type="PASSWORD" name="__iva_password" size="20">
</td>
</tr>
<tr valign="top" align="left">
<td></td>
<td><input type="checkbox" name="__iva_persistent" value="1" id="cb_remember" />
<label for="cb_remember">Remember my name.</label>
</td></tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<input type="submit" name="submit" value=" Login ">
</td>
</tr>
</table>
</form>
</dtml-let>
</body>
</html>
	"""
	self.manage_addDTMLMethod('login_form','CookieCruymblers login form',login_form)
        getattr(self,'login_form').manage_permission('View',['Authenticated', 'Anonymous',], 1)
	cc = getattr(self, 'login')
	cc.auth_cookie = '__iva'
	cc.name_cookie = '__iva_name'
	cc.pw_cookie = '__iva_password'
	cc.persist_cookie = '__iva_persistent'

	return "ok"

    security.declarePublic('verifyUserLocation')
    def verifyUserLocation(self, userLocation):
	""" asd """
	if userLocation not in ('Organizer','Workshops','Management','Bookshelf','Webtop'):
		return 1
	return 0

    # XXX:Course: move teatetekst -> self.__quote

Globals.InitializeClass(FLE)


# FIXME: input_checks (some checks done in FLE.__init__)
def manage_addFLE(
    self, id='', title='',
    try_it = 0, shere='',
    smtp_host='', smtp_port=25, 
    lang='en', quota=3000000, mfrom='iva@htk.tpu.ee',def_passwd=0,
    def_not_change=0,def_not_aff=0):
    """Create a FLE object. (Product Factory Method)."""

    if try_it:
	    warnings = []
	    errors = []
	    if not CCAware:
		    warnings.append('CMF not installed - CookieCrumbler not available')
	    if not PIL_imported:
		    warnings.append('PIL not installed - image manipulations disabled')
	    if not PLACELESS:
		    warnings.append('PlacelessTranslationService not installed - translation disabled')
	    if not ZWIKI_imported:
		    warnings.append('ZWiki not installed - some parts of IVA might even not work.')
	    if not id:
		    errors.append('No id specified')
	    if id:
		    used = getattr(shere.aq_inner, id, 0)
		    #print self
		    if used:
			    errors.append('ID is already in use')
		    if not used:
			    from input_checks import is_valid_id
			    valid = is_valid_id(id)
			    if not valid:
				    errors.append('ID is not valid - do not use any special symbols')
	    return {'errors':errors, 'warnings':warnings}

    #def_passwd = REQUEST.get('def_passwd',0)
    #def_not_change = REQUEST.get('def_not_change',0)
    #def_not_aff = REQUEST.get('def_not_aff',0)

    fle = FLE(
        id, title, 
        smtp_host, smtp_port, lang, quota, mfrom,
	def_passwd,def_not_change,def_not_aff)
    self._setObject(id, fle)
    return 1

#manage_addFLEForm = Globals.HTMLFile('ui/IVA_creation_form', globals())
manage_addFLEForm = PageTemplateFile('ui/IVA_creation_form.zpt', globals())

# EOF

