<?php
/*******************************************************************************
 *
 * LEIDEN OPEN VARIATION DATABASE (LOVD)
 *
 * Created     : 2006-10-23
 * Modified    : 2010-08-09
 * For LOVD    : 2.0-29
 *
 * Access      : Administrator and managers.
 * Purpose     : Create and manage LOVD submitters.
 *
 * Copyright   : 2004-2010 Leiden University Medical Center; http://www.LUMC.nl/
 * Programmers : Ing. Ivo F.A.C. Fokkema <I.F.A.C.Fokkema@LUMC.nl>
 *               Ir. Gerard C.P. Schaafsma <G.C.P.Schaafsma@LUMC.nl>
 * Last edited : Ing. Ivo F.A.C. Fokkema <I.F.A.C.Fokkema@LUMC.nl>
 *
 *
 * This file is part of LOVD.
 *
 * LOVD 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.
 *
 * LOVD 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 LOVD; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *************/

define('ROOT_PATH', './');
require ROOT_PATH . 'inc-init.php';

if (HAS_AUTH) {
    // If authorized, check for updates.
    require ROOT_PATH . 'inc-upgrade.php';
}

// Require manager clearance.
lovd_requireAUTH(LEVEL_MANAGER);





if ($_GET['action'] == 'view_all') {
    // View all submitters.

    require ROOT_PATH . 'inc-lib-list.php';
    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');

    // Check if there are submitters at all.
    list($nTotal) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_SUBS));
    if (!$nTotal) {
        print('      There are no submitters with this system.<BR>' . "\n");
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Standard query, will be extended later on.
    $sQ = 'SELECT s.*, CONCAT(s.firstname, " ", s.lastname) AS name, c.country AS country_, (s.login_attempts >= 3) AS locked, COUNT(p2v.variantid) AS submits FROM ' . TABLE_SUBS . ' AS s LEFT JOIN ' . TABLE_COUNTRIES . ' AS c ON (s.country = c.code) LEFT OUTER JOIN ' . TABLE_PATIENTS . ' AS p ON (s.submitterid = p.submitterid) LEFT JOIN ' . TABLE_PAT2VAR . ' AS p2v ON (p.patientid = p2v.patientid) WHERE 1=1';

    // 2008-10-22; 2.0-13; Added searching through the submitter list.
    // Here starts the actual building of the query.
    // Implement XSS check on search terms.
    foreach ($_GET as $key => $val) {
        if (!is_array($val) && $val != strip_tags($val)) {
            $_GET[$key] = '';
        }
    }

    // SEARCH: Advanced text search.
    $aSearchText =
         array(
                'search_submitterid' => 's.submitterid',
                'search_name' => 'CONCAT(s.firstname, " ", s.lastname)',
                'search_institute' => 's.institute',
                'search_country_' => 'c.country',
                'search_last_login' => 's.last_login',
                'search_created_date' => 's.created_date',
              );

    foreach ($aSearchText as $key => $val) {
        if (isset($_GET[$key]) && trim($_GET[$key])) {
            // 2010; 2.0-28; Allow for searches where the order of words is forced by enclosing the values with double quotes; ["Fokkema et al 2005"] will only
            // return hits with these words in exactly this order while [Fokkema et al 2005] will return hits with all of these words, in whatever order.
            $sSearch = preg_replace_callback('/\\\"([^"]+)\\\"/', create_function('$aRegs', 'return str_replace(\' \', \'{{SPACE}}\', $aRegs[1]);'), trim($_GET[$key]));
            $a = explode(' ', $sSearch);
            foreach ($a as $sTerm) {
                if ($sTerm) {
                    if (substr_count($sTerm, '|') && preg_match('/^[^|]+(\|[^|]+)+$/', $sTerm)) {
                        // OR.
                        $aOR = explode('|', $sTerm);
                        $sQ .= ' AND (';
                        foreach ($aOR as $nTerm => $sTerm) {
                            // 2009-03-03; 2.0-17; Advanced searching did not allow to combine NOT and OR searches.
                            if (substr($sTerm, 0, 1) == '!') {
                                // NOT.
                                $sQ .= ($nTerm? ' OR ' : '') . $val . ' NOT LIKE "%' . lovd_escapeSearchTerm(substr($sTerm, 1)) . '%"';
                            } else {
                                // Common search term.
                                $sQ .= ($nTerm? ' OR ' : '') . $val . ' LIKE "%' . lovd_escapeSearchTerm($sTerm) . '%"';
                            }
                        }
                        $sQ .= ')';
                    } elseif (substr($sTerm, 0, 1) == '!') {
                        // NOT.
                        $sQ .= ' AND ' . $val . ' NOT LIKE "%' . lovd_escapeSearchTerm(substr($sTerm, 1)) . '%"';
                    } else {
                        // Common search term.
                        $sQ .= ' AND ' . $val . ' LIKE "%' . lovd_escapeSearchTerm($sTerm) . '%"';
                    }
                }
            }
        }
    }

    $sQ .= ' GROUP BY s.submitterid';

    $nResults = mysql_num_rows(mysql_query($sQ));

    // SORT: Current settings.
    if (!empty($_GET['order'])) {
        $aOrder = explode(',', $_GET['order']);
    } else {
        $aOrder = array('', '');
    }

    // SORT: Column data.
    $aOrderList = array('submitterid' => array('s.submitterid', 'ASC'), 'name' => array('name', 'ASC'), 'institute' => array('institute', 'ASC'), 'country_' => array('c.country', 'ASC'), 'submits' => array('submits', 'DESC'), 'last_login' => array('s.last_login', 'DESC'), 'created_date' => array('s.created_date', 'ASC'));
    if (!array_key_exists($aOrder[0], $aOrderList)) {
        $aOrder[0] = 'country_';
    }
    if ($aOrder[1] != 'ASC' && $aOrder[1] != 'DESC') {
        $aOrder[1] = $aOrderList[$aOrder[0]][1];
    }

    $sQueryLimit = lovd_pagesplitInit(($nResults > 0? $nResults : $nTotal), 25);
    $sQ .= ' ORDER BY s.deleted ASC, ' . $aOrderList[$aOrder[0]][0] . ' ' . $aOrder[1] . ', c.country, name ' . $sQueryLimit;



    // Show form; required for sorting and searching.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '" method="get" style="margin : 0px;">' . "\n" .
          '        <INPUT type="hidden" name="action" value="' . $_GET['action'] . '">' . "\n" .
          '        <INPUT type="hidden" name="order" value="' . implode(',', $aOrder) . '">' . "\n\n");

    if (!$nResults) {
        // Searched, but no results.
        print('      No results have been found that match your criteria.<BR><BR>' . "\n\n");
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    $q = mysql_query($sQ);
    if (!$q) {
        lovd_dbFout('Subs' . ucfirst($_GET['action']), $sQ, mysql_error());
    }

    $n = (isset($nResults)? $nResults : $nTotal);
    print('      <SPAN class="S11">' . $n . ' entr' . ($n == 1? 'y' : 'ies') . '</SPAN><BR>' . "\n");

    // Array which will make up the table (header and data).
    $aTable =
             array(
                    'submitterid' => array('ID', '40'),
                    'name' => array('Name', '*'),
                    'institute' => array('Institute', '*'),
                    'country_' => array('Country', '*'),
                    'submits' => array('Submits', '70', 'align="right"'),
                    'status_' => array('Status', '50', 'align="center"'),
                    'last_login' => array('Last login', '80'),
                    'created_date' => array('Registered', '80'),
                  );

    // Table.
    print('      <TABLE border="0" cellpadding="0" cellspacing="1" width="950" class="data">' . "\n" .
          '        <TR>');

    foreach ($aTable as $sField => $aCol) {
        // Location onclick changed because of the search fields within the same <TH>. Clicking on the field triggers a sort.
        print("\n" . '          <TH valign="top"' . (!empty($aCol[2])? ' ' . $aCol[2] : '') . (is_numeric($aCol[1])? ' width="' . $aCol[1] . '"' : '') . (array_key_exists($sField, $aOrderList)? ' class="order' . ($aOrder[0] == $sField? 'ed' : '') . '"' : '') . '>' .
              (array_key_exists($sField, $aOrderList)? "\n" .
                                                           '            <TABLE border="0" cellpadding="0" cellspacing="0" width="100%" class="S11">' . "\n" .
                                                           '              <TR' . (array_key_exists($sField, $aOrderList)? ' onclick="document.forms[0].order.value=\'' . $sField . ',' . ($aOrder[0] == $sField? ($aOrder[1] == 'ASC'? 'DESC' : 'ASC') : $aOrderList[$sField][1]) . '\';document.forms[0].submit();"' : '') . '>' . "\n" .
                                                           '                <TH>' . str_replace(' ', '&nbsp;', $aCol[0]) . '</TH>' . "\n" .
                                                           '                <TD align="right" width="13"><IMG src="' . ROOT_PATH . 'gfx/order_arrow_desc' . ($aOrder[0] == $sField && $aOrder[1] == 'DESC'? '_sel' : '') . '.png" alt="Descending" title="Descending" width="13" height="6"><BR><IMG src="' . ROOT_PATH . 'gfx/order_arrow_asc' . ($aOrder[0] == $sField && $aOrder[1] == 'ASC'? '_sel' : '') . '.png" alt="Ascending" title="Ascending" width="13" height="6"></TD></TR>' .
                                                           (array_key_exists('search_' . $sField, $aSearchText)? "\n" .
                                                                                         '              <TR>' . "\n" .
                                                                                         '                <TD colspan="3"><INPUT type="text" name="search_' . $sField . '" value="' . (isset($_GET['search_' . $sField])? htmlspecialchars(stripslashes($_GET['search_' . $sField])) : '') . '" title="' . $aCol[0] . ' field should contain..." style="width : ' . ($aCol[1] - 8) . 'px; font-weight : normal;" onchange="document.forms[0].submit();"></TD></TR>' : '') .
                                                           '</TABLE>' : $aCol[0]) . '</TH>');
    }
    print('</TR>');

    while ($zData = mysql_fetch_assoc($q)) {
        print("\n" .
              '        <TR' . ($zData['deleted']? ' class="del"' : '') . ' style="cursor : pointer; cursor : hand;" onmouseover="this.className = \'' . ($zData['deleted']? 'del_' : '') . 'hover\';" onmouseout="this.className = \'' . ($zData['deleted']? 'del' : '') . '\';" onclick="window.location.href = \'' . $_SERVER['PHP_SELF'] . '?action=view&amp;view=' . $zData['submitterid'] . lovd_showSID(true, true) . '\';">');

        $zData['name']         = '<A href="' . $_SERVER['PHP_SELF'] . '?action=view&amp;view=' . $zData['submitterid'] . '" class="data">' . $zData['name'] . '</A>';
        $zData['status_']      = ($zData['locked']? '<IMG src="' . ROOT_PATH . 'gfx/status_locked.png" alt="Locked" title="Locked" width="14" height="14">' : '');
        $zData['last_login']   = substr($zData['last_login'], 0, 10);
        $zData['created_date'] = substr($zData['created_date'], 0, 10);

        foreach ($aTable as $sField => $aCol) {
            print("\n" . '          <TD' . (!empty($aCol[2])? ' ' . $aCol[2] : '') . (is_numeric($aCol[1])? ' width="' . $aCol[1] . '"' : '') . ($aOrder[0] == $sField? ' class="ordered"' : '') . '>' . (!$zData[$sField]? '-' : $zData[$sField]) . '</TD>');
        }
        print('</TR>');
    }
    print('</TABLE>' . "\n" .
          '</FORM>' . "\n\n");

    // URL pagelink.
    $sPageLink = 'order=' . rawurlencode(implode(',', $aOrder));

    // SEARCH: Simple text search.
    foreach ($aSearchText as $key => $val) {
        if (isset($_GET[$key]) && $_GET[$key]) {
            // 2009-04-23; 2.0-18; Added stripslashes to allow search terms to include quotes.
            $sPageLink .= ($sPageLink? '&amp;' : '') . $key . '=' . rawurlencode(stripslashes($_GET[$key]));
        }
    }

    lovd_pagesplitShowNav($sPageLink);

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'view' && is_numeric($_GET['view'])) {
    // View specific submitter.

    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');

    $zData = @mysql_fetch_assoc(mysql_query('SELECT s.*, CONCAT(s.firstname, " ", s.lastname) AS name, c.country AS country_, (s.login_attempts >= 3) AS locked, COUNT(p2v.variantid) AS submits, u_c.name AS created_by_, u_e.name AS edited_by_ FROM ' . TABLE_SUBS . ' AS s LEFT JOIN ' . TABLE_COUNTRIES . ' AS c ON (s.country = c.code) LEFT OUTER JOIN ' . TABLE_PATIENTS . ' AS p ON (s.submitterid = p.submitterid) LEFT JOIN ' . TABLE_PAT2VAR . ' AS p2v USING (patientid) LEFT OUTER JOIN ' . TABLE_USERS . ' AS u_c ON (s.created_by = u_c.userid) LEFT OUTER JOIN ' . TABLE_USERS . ' AS u_e ON (s.edited_by = u_e.userid) WHERE s.submitterid = "' . $_GET['view'] . '" GROUP BY s.submitterid'));
    if (!$zData) {
        // Wrong ID, apparently.
        print('      No such ID!<BR>' . "\n");
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Array which will make up the data table.
    $aTable =
             array(
                    'submitterid' => 'Submitter ID',
                    'firstname' => 'First name',
                    'lastname' => 'Last name',
                    'institute' => 'Institute',
                    'department' => 'Department',
                    'address' => 'Address',
                    'city' => 'City',
                    'country_' => 'Country',
                    'email' => 'Email address',
                    'telephone' => 'Telephone',
                    'reference' => 'Reference',
                    'username' => 'Username',
                    'submits_' => 'Submits',
                    'password_force_change_' => 'Force change password',
                    'locked_' => 'Locked',
                    'last_login' => 'Last login',
                    'deleted_' => 'Deleted',
                    'created_by_' => 'Created by',
                    'created_date' => 'Date created',
                    'edited_by_' => 'Last edited by',
                    'edited_date' => 'Date last edited',
                  );

    // Prepare information for created by column.
    if (!$zData['created_by_']) {
        // Self-registration.
        $zData['created_by_'] = $zData['name'];
    }

    // Remove unnecessary columns.
    if ($zData['edited_by'] == NULL) {
        // Never been edited.
        unset($aTable['edited_by_'], $aTable['edited_date']);
    } elseif (!$zData['edited_by']) {
        $zData['edited_by_'] = $zData['name'];
    }

    // Table.
    print('      <TABLE border="0" cellpadding="0" cellspacing="1" width="600" class="data">');

    $zData['address']  = str_replace(array("\r\n", "\r", "\n"), '<BR>', $zData['address']);
    $zData['email']    = str_replace(array("\r\n", "\r", "\n"), ', ', trim($zData['email']));
    $zData['submits_'] = $zData['submits'] . ($zData['submits']? ' in total (<A href="' . ROOT_PATH . 'submitters_variants.php?submitterid=' . $zData['submitterid'] . '&amp;all_genes">view</A>)' : '');
    // 2010-07-26; 2.0-28; Also show the number of submitted variants per gene.
    if ($zData['submits']) {
        // 2010-08-09; 2.0-29; On older MySQL versions this query returned an "ERROR 1111: Invalid use of group function" error when not aliasing the COUNT() and using the alias for the ORDER BY. How weird...
        $sQ = 'SELECT COUNT(p2v.variantid) AS submits, p2v.symbol FROM ' . TABLE_SUBS . ' AS s LEFT JOIN ' . TABLE_PATIENTS . ' AS p USING (submitterid) LEFT JOIN ' . TABLE_PAT2VAR . ' AS p2v USING (patientid) WHERE s.submitterid =  "' . $zData['submitterid'] . '" GROUP BY p2v.symbol ORDER BY submits DESC';
        $q = mysql_query($sQ);
        $i = 0;
        while ($r = mysql_fetch_row($q)) {
            $zData['submits_'] .= ($i == 0 ? '<BR>' : ', ') . $r[0] . ' (<A href="' . ROOT_PATH . 'variants.php?select_db=' . $r[1] . '&amp;action=search_all&amp;search_submitterid=' . $zData['submitterid'] . '">' . $r[1] . '</A>)';
            $i++;
        }
    }
    $zData['password_force_change_'] = ($zData['password_force_change']? '<IMG src="gfx/mark_1.png" alt="" width="11" height="11"> Yes' : 'No');
    $zData['locked_']  = ($zData['locked']? '<IMG src="gfx/status_locked.png" alt="Locked" title="Locked" width="14" height="14" align="top"> Locked' : 'No');
    $zData['deleted_'] = ($zData['deleted']? '<IMG src="gfx/light_1_r.png" alt="" width="11" height="11"> Yes' : 'No');

    foreach ($aTable as $sField => $sHeader) {
        print("\n" .
              '        <TR>' . "\n" .
              '          <TH valign="top">' . str_replace(' ', '&nbsp;', $sHeader) . '</TH>' . "\n" .
              '          <TD>' . (!$zData[$sField]? '-' : $zData[$sField]) . '</TD></TR>');
    }
    print('</TABLE>' . "\n\n");

    $sNavigation = '';
    // Authorized user (admin or manager) is logged in. Provide tools.
    $sNavigation = '<A href="' . $_SERVER['PHP_SELF'] . '?action=edit&amp;edit=' . $zData['submitterid'] . '">Edit submitter</A>';
    if (!$zData['deleted']) {
        $sNavigation .= ' | <A href="' . $_SERVER['PHP_SELF'] . '?action=drop&amp;drop=' . $zData['submitterid'] . '">Delete submitter</A>';
    } else {
        // Check for associated patients; if none, include purge link.
        list($nPatients) = @mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_PATIENTS . ' WHERE submitterid = "' . $zData['submitterid'] . '"'));
        if (!$nPatients) {
            $sNavigation .= ' | <A href="' . $_SERVER['PHP_SELF'] . '?action=purge&amp;drop=' . $zData['submitterid'] . '">Permanently delete submitter</A>';
        } else {
            $sNavigation .= ' | <A style="color : #999999;">Permanently delete submitter</A>';
        }
    }

    if ($sNavigation) {
        print('      <IMG src="gfx/trans.png" alt="" width="1" height="5"><BR>' . "\n");
        lovd_viewNavigation($sNavigation);
    }

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'create') {
    // Create new submitter.

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheck =
                 array(
                        'firstname' => 'First name',
                        'lastname' => 'Last name',
                        'institute' => 'Institute',
                        'address' => 'Address',
                        'city' => 'City',
                        'country' => 'Country',
                        'email' => 'Email address',
                        'username' => 'Username',
                        'password_1' => 'Password',
                        'password_2' => 'Password (confirm)',
                      );

        foreach ($aCheck as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // Check username format.
        if ($_POST['username'] && !lovd_matchUsername($_POST['username'])) {
            lovd_errorAdd('Please fill in a correct username; 4 to 20 characters and starting with a letter followed by letters, numbers, dots, underscores and dashes only.');
        }

        // Does the username exist already?
        // We check in both tables to be able to provide one login form.
        if ($_POST['username']) {
            list($nSubs) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_SUBS . ' WHERE username = "' . $_POST['username'] . '"'));
            list($nUsers) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_USERS . ' WHERE username = "' . $_POST['username'] . '"'));
            
            if ($nSubs || $nUsers) {
                lovd_errorAdd('There is already a user with this username. Please choose another one.');
            }
        }

        // Email address.
        if ($_POST['email']) {
            $aEmail = explode("\r\n", trim($_POST['email']));
            foreach ($aEmail as $sEmail) {
                if (!lovd_matchEmail($sEmail)) {
                    lovd_errorAdd('Email "' . $sEmail . '" is not a correct email address.');
                }
            }
        }

        // One of two password fields entered... check 'em.
        if ($_POST['password_1'] || $_POST['password_2']) {
            if ($_POST['password_1'] && $_POST['password_2']) {
                // Both entered.
                if ($_POST['password_1'] != $_POST['password_2']) {
                    lovd_errorAdd('The \'Password\' fields are not equal. Please try again.');
                } else {
                    // 2008-11-21; 2.0-14; Added password quality check for submitters, also.
                    // Password quality.
                    if (!lovd_matchPassword($_POST['password_1'])) {
                        lovd_errorAdd('Your password is found too weak. Please fill in a proper password; at least 4 characters long and containing at least one number or special character.');
                    }
                }
            } else {
                lovd_errorAdd('Please fill in both \'Password\' fields.');
            }
        }

        // 2006-12-07; 2.0-alpha-02
        // XSS attack prevention. Simply deny input of HTML, PHP other stuff blocked by strip_tags().
        lovd_checkXSS();

        if (!lovd_error()) {
            // Query text.
            $sQ = 'INSERT INTO ' . TABLE_SUBS . ' VALUES (NULL, ';

            // 2008-11-21; 2.0-14; Fixed bug, this query should have been here.
            // Fetching country name.
            list($_POST['country_']) = mysql_fetch_row(mysql_query('SELECT country FROM ' . TABLE_COUNTRIES . ' WHERE code = "' . $_POST['country'] . '"'));

            $_POST['password'] = md5($_POST['password_1']);
            $_POST['password_autogen'] = '';
            if (empty($_POST['reference'])) {
                $_POST['reference'] = $_POST['country_'] . ':' . $_POST['city'];
            }

            // Standard fields to be used.
            $aQ = array('firstname', 'lastname', 'institute', 'department', 'address', 'city', 'country', 'email', 'telephone', 'reference', 'username', 'password', 'password_autogen', 'password_force_change', 'login_attempts');

            // Lock / Unlock user.
            $_POST['login_attempts'] = ($_POST['locked']? 3 : 0);

            foreach ($aQ as $key => $val) {
                $sQ .= ($key? ', ' : '') . '"' . $_POST[$val] . '"';
            }

            $sQ .= ', NULL, ' . (int) $_POST['deleted'] . ', ' . $_AUTH['userid'] . ', NOW(), NULL, NULL)';

            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_submitters_create', 'LOVD Setup - Create new submitter');
                lovd_dbFout('SubmitterCreate', $sQ, $sError);
            }

            $nID = str_pad(mysql_insert_id(), 3, '0', STR_PAD_LEFT);

            // Write to log...
            lovd_writeLog('MySQL:Event', 'SubmitterCreate', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully created submitter ' . $_POST['username'] . ' (' . $_POST['firstname'] . ' ' . $_POST['lastname'] . ')');

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view&view=' . $nID . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_submitters_create', 'LOVD Setup - Create new submitter');
            lovd_showInfoTable('Registration \'' . stripslashes($_POST['firstname'] . ' ' . $_POST['lastname']) . '\' has successfully been created!', 'success');

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password_1'], $_POST['password_2']);
        }
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_submitters_create', 'LOVD Setup - Create new submitter');

    if (!isset($_GET['sent'])) {
        print('      To create a new submitter registration, please fill out the form below.<BR>' . "\n" .
              '      <BR>' . "\n\n");
    }

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;sent=true" method="post">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Retrieve country list.
    $qCountryList = mysql_query('SELECT code, country FROM ' . TABLE_COUNTRIES . ' ORDER BY country');

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('', 'print', '<B>Submitter details</B>'),
                    array('First name', 'text', 'firstname', 30),
                    array('Last name', 'text', 'lastname', 30),
                    array('Institute', 'text', 'institute', 40),
                    array('Department (optional)', 'text', 'department', 40),
                    array('Full address', 'textarea', 'address', 35, 3),
                    array('City', 'text', 'city', 30),
                    array('', 'print', '<SPAN class="form_note">In addition to your full address, please enter the city for sorting purposes.</SPAN>'),
                    array('Country', 'select', 'country', 1, $qCountryList, true, false, false),
                    array('Email address(es), one per line', 'textarea', 'email', 30, 3),
                    array('Telephone (optional)', 'text', 'telephone', 20),
                    array('Reference (optional)', 'text', 'reference', 30),
                    array('', 'print', '<SPAN class="form_note">Your submissions will contain a reference to you in the format "Country:City" by default. You may change this to your preferred reference here.</SPAN>'),
                    array('Username', 'text', 'username', 20),
                    array('Password', 'password', 'password_1', 20),
                    array('Password (confirm)', 'password', 'password_2', 20),
                    array('Must change password at next logon', 'checkbox', 'password_force_change', 1),
                    'skip',
                    array('', 'print', '<B>Security</B>'),
                    array('Locked', 'checkbox', 'locked', 0),
                    array('Deleted', 'checkbox', 'deleted', 0),
                    'skip',
                    array('', 'submit', 'Create submitter account'),
                  );
    $_MODULES->processForm('SetupSubmittersCreate', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'edit' && is_numeric($_GET['edit'])) {
    // Edit specific submitter.

    $zData = @mysql_fetch_assoc(mysql_query('SELECT s.*, (s.login_attempts >= 3) AS locked FROM ' . TABLE_SUBS . ' AS s WHERE s.submitterid = "' . $_GET['edit'] . '"'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
        print('      No such ID!<BR>' . "\n");
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheck =
                 array(
                        'firstname' => 'First name',
                        'lastname' => 'Last name',
                        'institute' => 'Institute',
                        'address' => 'Address',
                        'city' => 'City',
                        'country' => 'Country',
                        'email' => 'Email address',
                        'password' => 'Enter your password for authorization',
                      );

        foreach ($aCheck as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // Email address.
        if ($_POST['email']) {
            $aEmail = explode("\r\n", trim($_POST['email']));
            foreach ($aEmail as $sEmail) {
                if (!lovd_matchEmail($sEmail)) {
                    lovd_errorAdd('Email "' . $sEmail . '" is not a correct email address.');
                }
            }
        }

        // One of two password fields entered... check 'em.
        if ($_POST['password_1'] || $_POST['password_2']) {
            if ($_POST['password_1'] && $_POST['password_2']) {
                // Both entered.
                if ($_POST['password_1'] != $_POST['password_2']) {
                    lovd_errorAdd('The \'New password\' fields are not equal. Please try again.');
                } else {
                    // 2008-11-21; 2.0-14; Added password quality check for submitters, also.
                    // Password quality.
                    if (!lovd_matchPassword($_POST['password_1'])) {
                        lovd_errorAdd('Your password is found too weak. Please fill in a proper password; at least 4 characters long and containing at least one number or special character.');
                    }
                }
            } else {
                lovd_errorAdd('If you want to change the current password, please fill in both \'New password\' fields.');
            }
        }

        // User had to enter his/her password for authorization.
        if ($_POST['password'] && md5($_POST['password']) != $_AUTH['password']) {
            lovd_errorAdd('Please enter your correct password for authorization.');
        }

        // 2006-12-07; 2.0-alpha-02
        // XSS attack prevention. Simply deny input of HTML, PHP other stuff blocked by strip_tags().
        lovd_checkXSS();

        if (!lovd_error()) {
            // Query text.
            $sQ = 'UPDATE ' . TABLE_SUBS . ' SET ';

            // Standard fields to be used.
            $aQ = array('firstname', 'lastname', 'institute', 'department', 'address', 'city', 'country', 'email', 'telephone', 'reference', 'password_force_change', 'login_attempts', 'deleted');

            // In case the password is getting changed...
            if ($_POST['password_1']) {
                $_POST['password'] = md5($_POST['password_1']);
                $aQ[] = 'password';
            }

            // Lock / Unlock user.
            $_POST['login_attempts'] = ($_POST['locked']? 3 : 0);

            foreach ($aQ as $key => $val) {
                $sQ .= ($key? ', ' : '') . $val . ' = "' . $_POST[$val] . '"';
            }

            $sQ .= ', edited_by = "' . $_AUTH['userid'] . '", edited_date = NOW() WHERE submitterid = ' . $zData['submitterid'];

            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
                lovd_dbFout('SubmitterEdit', $sQ, $sError);
            }

            // Write to log...
            lovd_writeLog('MySQL:Event', 'SubmitterEdit', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully edited submitter ' . $zData['username'] . ' (' . $_POST['firstname'] . ' ' . $_POST['lastname'] . ')');

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view&view=' . $_GET['edit'] . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
            lovd_showInfoTable('Successfully updated registration \'' . stripslashes($_POST['firstname'] . ' ' . $_POST['lastname']) . '\'!', 'success');

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password'], $_POST['password_1'], $_POST['password_2']);
        }

    } else {
        foreach ($zData as $key => $val) {
            if (!isset($_POST[$key]) || !$_POST[$key]) {
                $_POST[$key] = $val;
            }
        }
        $_POST['password'] = '';
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;edit=' . $zData['submitterid'] . '&amp;sent=true" method="post">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Retrieve country list.
    $qCountryList = mysql_query('SELECT code, country FROM ' . TABLE_COUNTRIES . ' ORDER BY country');

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('', 'print', '<B>Submitter details</B>'),
                    array('First name', 'text', 'firstname', 30),
                    array('Last name', 'text', 'lastname', 30),
                    array('Institute', 'text', 'institute', 40),
                    array('Department (optional)', 'text', 'department', 40),
                    array('Full address', 'textarea', 'address', 35, 3),
                    array('City', 'text', 'city', 30),
                    array('', 'print', '<SPAN class="form_note">In addition to your full address, please enter the city for sorting purposes.</SPAN>'),
                    array('Country', 'select', 'country', 1, $qCountryList, true, false, false),
                    array('Email address(es), one per line', 'textarea', 'email', 30, 3),
                    array('Telephone (optional)', 'text', 'telephone', 20),
                    array('Reference (optional)', 'text', 'reference', 30),
                    array('', 'print', '<SPAN class="form_note">Your submissions will contain a reference to you in the format "Country:City" by default. You may change this to your preferred reference here.</SPAN>'),
                    array('New password (optional)', 'password', 'password_1', 20),
                    array('New password (confirm, optional)', 'password', 'password_2', 20),
                    array('Must change password at next logon', 'checkbox', 'password_force_change', 1),
                    'skip',
                    array('', 'print', '<B>Security</B>'),
                    array('Locked', 'checkbox', 'locked', 0),
                    array('Deleted', 'checkbox', 'deleted', 0),
                    'skip',
                    array('Enter your password for authorization', 'password', 'password', 20),
                    array('', 'submit', 'Edit registration'),
                  );
    $_MODULES->processForm('SetupSubmittersEdit', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'drop' && is_numeric($_GET['drop'])) {
    // Drop specific submitter.

    $zData = @mysql_fetch_assoc(mysql_query('SELECT *, CONCAT(firstname, " ", lastname) AS name FROM ' . TABLE_SUBS . ' WHERE submitterid = "' . $_GET['drop'] . '" AND deleted = 0'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
        print('      No such ID!<BR>' . "\n");
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheck =
                 array(
                        'password' => 'Enter your password for authorization',
                      );

        foreach ($aCheck as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // User had to enter his/her password for authorization.
        if ($_POST['password'] && md5($_POST['password']) != $_AUTH['password']) {
            lovd_errorAdd('Please enter your correct password for authorization.');
        }

        if (!lovd_error()) {
            // Query text.
            $sQ = 'UPDATE ' . TABLE_SUBS . ' SET deleted = 1 WHERE submitterid = "' . $zData['submitterid'] . '"';

            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
                lovd_dbFout('SubmitterDrop', $sQ, $sError);
            }

            // Write to log...
            lovd_writeLog('MySQL:Event', 'SubmitterDrop', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully deleted submitter ' . $zData['username'] . ' (' . mysql_real_escape_string($zData['firstname'] . ' ' . $zData['lastname']) . ')');

            // 2008-11-21; 2.0-14; Automatically purge the submitter, if requested.
            if ($_POST['purge']) {
                // Automatically authorize the next step.
                $_SESSION['auto_auth'] = array('/setup_submitters?action=purge', time());
                header('Location: ' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=purge&drop=' . $zData['submitterid'] . '&sent=true' . lovd_showSID(true));
                exit;
            }

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view&view=' . $zData['submitterid'] . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
            lovd_showInfoTable('Successfully deleted registration \'' . stripslashes($zData['firstname'] . ' ' . $zData['lastname']) . '\'!', 'success');

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password']);
        }
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitter');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;drop=' . $zData['submitterid'] . '&amp;sent=true" method="post">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('Deleting submitter registration', 'print', $zData['username'] . ' (' . $zData['name'] . ')'),
                    array('Permanently delete the submitter', 'checkbox', 'purge', 1),
                    'skip',
                    array('Enter your password for authorization', 'password', 'password', 20),
                    array('', 'submit', 'Delete submitter'),
                  );
    $_MODULES->processForm('SetupSubmittersDelete', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'purge' && is_numeric($_GET['drop'])) {
    // Drop (permanently) specific submitter.

    $zData = @mysql_fetch_assoc(mysql_query('SELECT *, CONCAT(firstname, " ", lastname) AS name FROM ' . TABLE_SUBS . ' WHERE submitterid = "' . $_GET['drop'] . '" AND deleted = 1'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
        print('      No such ID!<BR>' . "\n");
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Check for associated patients.
    list($nPatients) = @mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_PATIENTS . ' WHERE submitterid = "' . $_GET['drop'] . '"'));
    if ($nPatients) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
        lovd_showInfoTable('This submitter still has patients assigned! Cannot permanently delete submitter!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // 2008-11-21; 2.0-14; Automatically purge the submitter, if requested.
        if (!(!empty($_SESSION['auto_auth']) && $_SESSION['auto_auth'][0] == '/setup_submitters?action=purge' && time() - $_SESSION['auto_auth'][1] < 3)) {
            // Mandatory fields.
            $aCheck =
                     array(
                            'password' => 'Enter your password for authorization',
                          );

            foreach ($aCheck as $key => $val) {
                if (empty($_POST[$key])) {
                    lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
                }
            }

            // User had to enter his/her password for authorization.
            if ($_POST['password'] && md5($_POST['password']) != $_AUTH['password']) {
                lovd_errorAdd('Please enter your correct password for authorization.');
            }
        }

        if (!lovd_error()) {
            // Query text.
            $sQ = 'DELETE FROM ' . TABLE_SUBS . ' WHERE submitterid = "' . $zData['submitterid'] . '"';

            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
                lovd_dbFout('SubmitterPurge', $sQ, $sError);
            }

            // Write to log...
            lovd_writeLog('MySQL:Event', 'SubmitterPurge', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully purged submitter ' . $zData['username'] . ' (' . mysql_real_escape_string($zData['firstname'] . ' ' . $zData['lastname']) . ')');

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view_all' . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitters');
            lovd_showInfoTable('Successfully purged registration \'' . stripslashes($zData['firstname'] . ' ' . $zData['lastname']) . '\'!', 'success');

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password']);
        }
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_submitters_manage', 'LOVD Setup - Manage submitter');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;drop=' . $zData['submitterid'] . '&amp;sent=true" method="post">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('Purging submitter registration', 'print', $zData['username'] . ' (' . $zData['name'] . ')'),
                    'skip',
                    array('Enter your password for authorization', 'password', 'password', 20),
                    array('', 'submit', 'Permanently delete submitter'),
                  );
    $_MODULES->processForm('SetupSubmittersPurge', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} else {
    // Default action:
    header('Location: ' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view_all' . lovd_showSID(true));
    exit;
}
?>