<?php
/*
 * PiAnoS (Picture Annotation System), A fingerprint examiner training tool
 * Copyright (C) 2011-2021 University of Lausanne, Switzerland
 * https://ips-labs.unil.ch/pianos
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */
require_once ( "unil/Application.php" );
require_once ( "unil/Node.php" );
require_once ( "unil/SessionManager.php" );
require_once ( "unil/IntlManager.php" );

abstract class ContentDriver extends Driver
{
    protected function printHtml( $content )
    {
        require_once ( "unil/Renderer.php" );
        
        $rs = new RenderStruct();
        
        $rs->getPage()->setTitle( Application::instance()->getName() );
        
        $rs->getPage()->addScript( Application::get( 'jslib_jquery' ) );
        $rs->getPage()->addScript( Application::get( 'jslib_jquery_ui' ) );
        
        $rs->getPage()->addScript( "js/shared.functions.js" );
        
        $content->render( $rs );
        
        $rs->flush();
    }
};

require_once ( "backend/Login.php" );
require_once ( "backend/Intro.php" );
require_once ( "unil/RemoteProcedureCall.php" );

abstract class Pianos4 extends Application
{
    function __construct()
    {
        parent::__construct( false );
        $this->setLocalSettingsPath( 'backend/settings-local.php' );
        $this->_plugins = array ();
    }
    
    public function init()
    {
        $this->setName( 'PiAnoS 4' );
        
        // Drivers will be called in the reverse order that they are installed.
        // The driver chain is traversed from last to first.
        // Each driver may choose to process or ignore the request (through the accept() method).
        // A driver that accepts() a request can be final (when handleRequest() returns true) or pass-through (handleRequest() returns false).
        // Initialization drivers are pass-through, and set up various features (session management, internationalization) made into reusable components.
        // Final drivers deliver the content to the client.
        
        // Last driver: the actual content (HTML+javascript) of the application.
        // This is provided by the actual class (Teaching/Lab Editions).
        $this->registerDrivers();
        
        $rpc = new RemoteProcedureCall();
        $this->registerDriver( $rpc );
        
        $this->registerDriver( new IntroDriver() );
        
        // Checks that the user is logged in and read his preferences.
        // If the user is not logged in, displays a login form and terminates.
        $this->registerDriver( new LoginDriver() );
        
        // Enable gettext internationalization, passing call back for a locale change event.
        $this->registerDriver( new IntlManager( Application::get( 'default_locale' ), 'setlocale' ) );
        
        // Manages the session
        $session = new SessionManager(
            md5( $this->getName() ),
            array (
                'action',
                'logout'
            ),
            Application::get( 'session_lifetime' )
        );
        
        $sessionParams = Application::get( 'cookie_params' );
        if( $sessionParams )
            $session->setCookieParams( $sessionParams );
        $this->registerDriver( $session );
    }
    
    abstract protected function registerDrivers();
    abstract protected function createDatabaseInstance();
    
    protected function createDatabase()
    {
        $db = $this->createDatabaseInstance();
        $db->connect(
            $this->getSetting( 'db_host' ),
            $this->getSetting( 'db_port' ),
            $this->getSetting( 'db_name' ),
            $this->getSetting( 'db_user' ),
            $this->getSetting( 'db_password' )
        );
        return $db;
    }
    
    public function getPlugin( $index )
    {
        return $this->_plugins[ $index ];
    }
    
    public function callPlugins( $event, &$data )
    {
        foreach( $this->_plugins as $plugin )
            $plugin->call( $event, $data );
    }
    
    private $_plugins;
    
    protected function createDefaultSettings()
    {
        return array (
                // General parameters
                // ==================
                
                // The version is stored as a configuration parameter (thus, changeable) but is not really meant to be changed - use this at your own risk.
                'version' => 'dev',
                
                // Session cookie parameters
                // While these can be left to NULL on development servers production installation should set them appropriately.
                // There is a security risk if they are not set: 2 installations on the same server and/or domain will potentially use the same cookie (e.g. log on as 'admin' on /pianos-a, go to /pianos-b and you are still logged on as admin!)
                // This can be set to:
                //     - NULL (development only): no session cookie parameters are set
                //     - a string: the base path of the installation (e.g. '/pianos4')
                //     - an array of 2 strings: the base path and the domain (e.g. array('/pianos4','.unil.ch'))
                'cookie_params' => NULL,
                
                // Session timeout.
                // If not set (i.e. set to NULL), let PHP manage the session lifetime (set through the session.gc_maxlifetime parameter).
                // If set to a value (number of seconds), overrides the session lifetime locally, using session variables and access timestamps.
                // Since the session might be let unmodified for a long time while the user is working, setting this is a preferred method over configuring PHP to manage the session lifetime.
                'session_lifetime' => NULL,
                
                // The locale to use by default - may be overriden by users when setting their prefered language.
                // On Linux systems, this will probably be suffixed by '.UTF-8' e.g. 'en_US.UTF-8'.
                // On Windows, the suffix is not necessary - e.g. 'en_US'
                'default_locale' => 'en_US.UTF-8',
                
                // Use Shibboleth login mechanism.
                // Set to 'false' or 'NULL' to disable.
                // Set to an array with the following keys to enable:
                // 'url': URL to the shibboleth-protected area. The file pointed to must perform the appropriate redirect once the login has been performed (i.e. returning to index.php). Note: use 'shibboleth-simulate.php' to simulate a login on a development machine that is not Shibboleth-enabled.
                // 'login_prompt': title of the login form e.g. 'Students login with Shibboleth'
                // 'login_image': URL to the image to display in the login box itself. Do not set or set to NULL when no image should be displayed
                // 'login_text': text inside the login form. Do not set or set to NULL when no text should be displayed
                // 'username':the $_SERVER field containing the username
                // 'display_name': array of 2 $_SERVER fields containing the first and last names
                // 'email': the email
                // 'groups': array of 3-tuples: ($_SERVER field, regexp, target group name). If this is set, users will be accepted only if the specified field matches the regexp, and they will be assigned the target group.
                // 'return': the URL to return to after successfull authentication
                'shibboleth_login' => false,
                
                // Minified scripts. Set these to the name of the minified versions of PiAnoS 4 (main and backend) and microDB javascript files.
                'use_minified_pianos4' => false,
                'use_minified_pianos4_backend' => false,
                
                // URL to the user manual. If left to NULL, no link to the user manual will be shown. Otherwise, it will appear under the help menu.
                'user_manual_url' => NULL,
                
                // Database parameters
                // ===================
                
                // Hostname to connect to
                'db_host' => 'localhost',
                
                // Port
                'db_port' => 5432,
                
                // Name of the database
                'db_name' => 'pianos4',
                
                // Username of the database role
                'db_user' => 'pianos',
                
                // Password for this role
                'db_password' => 'pianos',
                
                // usernameDefaultPasswordSalt
                // This option is used by the "multiple user create" dialog box to add a salt to the password.
                // This value should not be changed after the use of the multi user create or it will report a false default password.
                // This option can (and should) be changed to a unique value at installation time.
                'usernameDefaultPasswordSalt' => "pianos",
                
                // Visual parameters
                // =================
                
                // Path to the jQuery UI folder where the theme is located.
                // The name of the CSS will always be 'theme-backend.css' in that folder.
                // This file may very well contain a single @import statement (e.g. @import "jquery-ui-1.8.12.custom.css"; )
                // You will normally want to include also the file css/common-backend.css which overrides a few of jQuery UI's defaults (such as the text size) and then specify theme-related styles of the app.
                'jqueryui_theme' => 'css/smoothness',
                
                // Application behaviour
                // =====================
                
                // Additionnal parameters to pass to the Javascript constructor of the PiAnoS application.
                // If specified, must be an associative array that can be turned into a JSON object (only POD data inside).
                'pianos_app_settings' => NULL,
                
                // Same for the backend application.
                'backend_app_settings' => NULL,
                
                // Some features require ImageMagick, which can be provided by PHP itself, or by external scripts (e.g. convert[.exe], mogrify[.exe], etc.).
                // If this variable is unset, or set to anything else but a string, it means that PHP Imagick is to be used.
                // If set to a string, it is the base path to the utilities of ImageMagick (e.g. 'c:\\program files\\imagemagick')
                'imagick' => NULL,
                
                // IMPORTANT: this feature requires ImageMagick PHP extension (see the 'imagick' option above).
                // Convert image types before storage.
                // This is needed e.g. because although PiAnoS can accept TIFFs on upload, some browsers (Firefox!) will not accept them (but IE will).
                // Set to false to disable image conversion.
                // Set to an associative array to enable - keys are "from" mimetypes, and values are "to" extensions.
                // E.g. to enable on-the-fly conversion for TIFFs to PNGs, set to array('image/tiff'=>'png')
                // Implementation note: the values will be used as argument to ImageMagick::setImageFormat
                'convert_images' => false,
                
                // There exist the possibility to log ALL saved results to a dedicated table - result_history.
                // By default (set to 'false'), this table will not be used.
                // If set to 'true', results will be continuously inserted into the table.
                // It is your responsibility to manage this table (delete rows, etc.)
                'archive_results' => false,
                
                // When a user is about to start an exercise with a trace image she has already analyzed in a prior exercise, she is given the option to re-use the entire analysis phase from (one of) the said exercise(s).
                // This setting is ON by default.
                // Set to false or NULL to disable.
                'users_can_reuse_analysis' => true,
                
                // The user can create an exercise in his personal folder.
                'can_create_personnal_folder' => true,
                'can_view_personnal_folder_summary' => true,
                
                // Show to the user the upload multiples files button
                'can_upload_images' => true,
                
                // Allow to skip the mendatory fields (quality annotation and the questions at the bottom)
                'skip_mendatory_fields_and_set_default' => false,
                'skip_quality_and_minutiae_checks' => false,
                
                // Show the subfolders
                'subfolders' => true,
                
                // The homeData (fist page open at login) shows the todo-list.
                'homeData_as_todo_list' => false,
                'homeData_show_all_exercises_for_admin' => true,
                
                // Show the progressbar on the home page
                'progress_bar' => false,
                
                // Allow the tutors to switch to an other user (User impresonate).
                'show_switchUser' => true,
                
                // Show the button to make an anonymous review
                'anonymous_review' => true,
                
                // Default values for the markers size (minutiae and pairing)
                'show_marker_size_slider' => true,
                'makerSizeMin' => 0.25,
                'makerSizeMax' => 1.75,
                
                // Show the opacity slider for the minutiae
                'show_marker_opacity_slider' => true,
                
                // Can the mark have a core annotated ?
                'markCanHaveCenter' => true,
                
                // Inital tool to load
                'initialTool' => 'edit',
                
                // Show dialog in comparison phase for no-value marks
                'novalue_comparison_startup_dialog' => true,
                
                // JS force reloader
                // This option has to be set in the settings-local file to be usefull, and should be set to the git revision.
                // This options appends the git version of the requested files (in particular js files) in the GET query to prevent client side caching.
                // This option should be set in a environment where we want to update the server while users are using it.
                'jsforcereload' => false,
                
                // Image editor
                // Display the simple client-side image editor.
                'imageeditor' => true,
                
                // Javascript and CSS dependencies (3rd party)
                // =====================
                
                // The defaults provided here are really meant to work out-of-the-box only when using the distribution tarball. Otherwise, the paths will probably need to be adapted to the actual location and versions of the 3rd party libraries.
                
                // The comment indicates which version the release has been tested with. Feel free to upgrade or downgrade to another version (e.g. jquery-1.8.2 instead of 1.7.1) but know that this may break the build.
                
                // When customizing the dependencies or installing from SVN, you can either
                //     - modify settings-local.php to point to the actual files
                //     - symlink the default values to the actual files
                
                'jslib_jquery' => '/cdn/jquery/js/jquery-1.8.2.min.js',
                'jslib_jquery_ui' => '/cdn/jquery/js/jquery-ui-1.9.1.custom.min.js',
                
                'jslib_md5' => '/cdn/misc/md5-min.js',
                'jslib_jquery_layout' => '/cdn/jquery/js/jquery.layout-1.4.4.js',
                'jslib_jquery_hashchange' => '/cdn/jquery/js/jquery.ba-hashchange-1.3.min.js',
                'jslib_jquery_cookie' => '/cdn/jquery/js/jquery.cookie-1.4.0.js',
                'jslib_microdb' => '/cdn/udb/udb.min.js',
                'jslib_ajaxupload' => '/cdn/misc/ajaxupload.js',
                'jslib_jquery_hotkeys' => '/cdn/jquery/js/jquery.hotkeys-0.8.min.js',
                'jslib_jquery_mousewheel' => '/cdn/jquery/js/jquery.mousewheel-3.0.6.js',
                'jslib_d3' => '/cdn/misc/d3.min.js',
                
                'csslib_jquery_ui' => '/cdn/jquery/css/smoothness/jquery-ui-1.9.1.custom.css',
                'csslib_jquery_layout' => '/cdn/jquery/css/layout.css',
                'csslib_microdb' => '/cdn/udb/css/udb.css',
                    
                'jslib_toastr' => '/cdn/toastr/toastr.min.js',
                'csslib_toastr' => '/cdn/toastr/toastr.min.css',
                'jslib_easing' => '/cdn/jquery/js/jquery.easing.1.3.js',
                
                'jslib_dropzone' => '/cdn/dropzone/dropzone.js',
            
                'jslib_chosen' => '/cdn/chosen/chosen.js',
                'csslib_chosen' => '/cdn/chosen/chosen.css',
            
                // If set to non-NULL, must point to the microDB source directory where the js/ and css/ directories exist.
                // This is used to import the "debug" versions (non-miminized) of microDB, and will override the 'jslib_microdb' and 'css_microdb' settings.
                'microdb_path' => NULL,
                
                // TPS libary
                'TPS' => '/cdn/TPSjs/TPS.js',
                'TPS_grid_url' => NULL,
                'TPS_scale_limit_notification' => 10,
                
                // View Tracking
                'viewTracker' => false,
            
                // Misc parameters
                // ====================
                
                // Path to the 'pwgen' command used by the system to create users with strong random passwords.
                // If set to false, the functionality is disabled and trying to create a user with a random password will raise an exception.
                // Otherwise, set to the full system command that will generate *one* password e.g. if using GNU pwgen:
                // - Linux: 'pwgen_path' => '/usr/bin/pwgen -cn 8 1'
                // - Windows/Cygwin: 'pwgen_path' => 'c:\\cygwin\\bin\\bash.exe -c "/usr/bin/pwgen.exe -cn 8 1"'
                'pwgen_path' => false
        );
    }
}

