<?php
/*******************************************************************************
 *
 * LEIDEN OPEN VARIATION DATABASE (LOVD)
 *
 * Created     : 2006-11-20
 * Modified    : 2010-04-12
 * For LOVD    : 2.0-26
 *
 * Access      : Submitters and up.
 * Purpose     : Edit & drop variant selected gene's variants.
 *
 * 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 : Ir. Gerard C.P. Schaafsma <G.C.P.Schaafsma@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 curator clearance.
// 2008-04-21; 2.0-06; Allow submitters to access the edit form.
if (!(!empty($_GET['action']) && $_GET['action'] == 'edit' && HAS_SUBS && $_CONF['my_submissions'])) {
    lovd_requireAUTH(LEVEL_CURATOR);
}

// If no gene selected, forward to the select list.
if (!$_SESSION['currdb']) {
    header('Location: ' . PROTOCOL . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/home.php' . lovd_showSID());
    exit;
}

if (HAS_SUBS) {
    // 2008-04-22; 2.0-06 Submitters can now also edit variants when My Submissions is activated.
    $aIDs = explode(',', $_GET['edit']);
    $nPatientID = $aIDs[0];
    list($nSubmitterID) = mysql_fetch_row(mysql_query('SELECT submitterid FROM ' . TABLE_PATIENTS . ' WHERE patientid = "' . $nPatientID . '"'));
    if ($nSubmitterID != $_SUBS['submitterid']) {
        // In stead of the default error, throw in a specific one.
        require ROOT_PATH . 'inc-top.php';
        lovd_showInfoTable('This patient has not been submitted by you!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }
}

// Whether or not a user can see non-public data.
if (lovd_isCurator($_SESSION['currdb'])) {
    define('IS_CURATOR', true);
} else {
    define('IS_CURATOR', false);
}

// Non-curators do not belong here.
if (!IS_CURATOR && !HAS_SUBS) {
    require ROOT_PATH . 'inc-top.php';
    lovd_showInfoTable('You are not allowed access to this gene database. Please contact your manager or the administrator to grant you access.', 'stop');
    require ROOT_PATH . 'inc-bot.php';
    exit;
}





if ($_GET['action'] == 'edit' && preg_match('/^([0-9]{1,7})\,([0-9]{1,7})\,([0-9]{1,2})$/', $_GET['edit'], $aRegs) && list(, $_GET['patientid'], $_GET['variantid'], $_GET['allele']) = $aRegs) {
    // Edit sequence variant incl. specific variant/patient link.

    $zData = @mysql_fetch_assoc(mysql_query('SELECT p2v.*, v.* FROM ' . TABLE_PAT2VAR . ' AS p2v LEFT JOIN ' . TABLE_CURRDB_VARS . ' AS v ON (p2v.variantid = v.variantid) WHERE p2v.symbol = "' . $_SESSION['currdb'] . '" AND v.variantid = "' . $_GET['variantid'] . '" AND p2v.patientid = "' . $_GET['patientid'] . '" AND p2v.allele = "' . $_GET['allele'] . '"'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');
        lovd_showInfoTable('No such ID!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // 2008-03-26; 2.0-05; If variant is shared over multiple patients, warn user.
    $nPatients = @mysql_num_rows(mysql_query('SELECT DISTINCT patientid FROM ' . TABLE_PAT2VAR . ' WHERE symbol = "' . $_SESSION['currdb'] . '" AND variantid = "' . $_GET['variantid'] . '"'));
    $aFormMultiplePat = array();
    if ($nPatients > 1) {
        // 2008-12-12; 2.0-15; Choose what to do with multiple patients added.
        $aFormMultiplePat =
                 array(
                        array('', 'print', '<I>Warning: this variant entry is connected to ' . $nPatients . ' patients. Please select if you want the changes to this variant (except allele, pathogenicity or status) to show on all patients, or just this one.</I>'),
                        array('Edit variant for all patients?', 'select', 'update_all', 1, array('update' => 'Edit variant for all patients', 'insert' => 'Edit variant only for this patient'), true, false, false),
                        'skip',
                      );
    }

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';
    require ROOT_PATH . 'class/currdb.php';
    $_CURRDB = new CurrDB();
    $sMutationCol = $_CURRDB->getMutationCol();
    // 2008-04-22; 2.0-06; Submitters can now also edit variants when My Submissions is activated.
    if (HAS_SUBS) {
        $_CURRDB->hideCols('public_form');
        $aFormMultiplePat = array();
        $_POST['update_all'] = 'insert';
    }

    // 2007-09-04; 2.0-beta-08; Add quick-curate option.
    // 2008-10-16; 2.0-13; Add agree to submitter's changes option.
    if ((isset($_GET['curate']) || isset($_GET['agree'])) && !isset($_GET['sent'])) {
        // Curate this entry... nothing edited (except for the status, if curating).
        foreach ($zData as $key => $val) {
            // 2009-04-29; 2.0-18; Added mysql_real_escape_string() to prevent MySQL errors and SQL injection problem.
            $_POST[$key] = mysql_real_escape_string($val);
        }
        // 2009-01-23; 2.0-15; Curating will not change any fields; edit all.
        $_POST['update_all'] = 'update';
        // Transform select lists' values.
        $_CURRDB->transformSelectValues($_POST, true);
        $_POST['pathogenic_reported'] = $_POST['pathogenic']{0};
        $_POST['pathogenic_concluded'] = $_POST['pathogenic']{1};
        if (isset($_GET['curate'])) {
            $_POST['status'] = STATUS_OK;
        }
        $_POST['password'] = $_AUTH['password'];
        $_GET['sent'] = true;
    }

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

        // 2008-04-24; 2.0-06; Check Variant/DBID field to make sure it's consistent with the variant.
        // Submitters don't see this DBID column. Possibly, this LOVD has been configured to hide it anyway. So:
        $_CURRDBtmp = new CurrDB(true, $_SESSION['currdb']);
        if ($_CURRDBtmp->colExists('Variant/DBID')) {
            if (!empty($_POST[$sMutationCol])) {
                // 2008-05-19; 2.0-07; Some modifications here to apply new function that checks if
                // the given ID matches the given variant and predict the ID only when left empty.
                if (empty($_POST['Variant/DBID'])) {
                    // Submitters who don't have this field AND curators who left this field open.
                    $sIDGenerated = lovd_fetchDBID($_SESSION['currdb'], $_POST[$sMutationCol], $sMutationCol);
                    $_POST['Variant/DBID'] = $sIDGenerated;
                } else {
                    // 2008-10-13; 2.0-13; The DBID check allowed invalid DBID values if the DBID field contained more than just the ID.
                    $sDBID = substr($_POST['Variant/DBID'], 0, strlen($_SESSION['currsymb']) + 6);
                    if (!lovd_checkDBID($_SESSION['currdb'], $_POST[$sMutationCol], $sMutationCol, $sDBID, $_GET['variantid'])) {
                        lovd_errorAdd('The given variant ID "' . strip_tags($sDBID) . '" does not match the variant "' . strip_tags($_POST[$sMutationCol]) . '".');
                    }
                }
            }
        }

        // Mandatory fields.
        if ((HAS_AUTH && $_POST['status'] >= STATUS_MARKED) || (HAS_SUBS && $zData['status'] >= STATUS_MARKED)) {
            $_CURRDB->checkMandatory('Variant');
        }

        // Field lengths.
        $_CURRDB->checkInputLength();

        // Field types.
        $_CURRDB->checkInputType();

        // Regular expressions.
        $_CURRDB->checkInputRegExp();

        // Mandatory fields.
        // 2008-12-17; 2.0-15; Force user to choose how to edit the variant.
        $aCheck = array();
        if ($nPatients > 1) {
            $aCheck =
                 array(
                        'update_all' => 'Edit variant for all patients?',
                      );
        }
        $aCheck['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 ((isset($_GET['curate']) || isset($_GET['agree'])) && $_POST['password'] && $_POST['password'] != $_AUTH['password']) {
            lovd_errorAdd('Please enter your correct password for authorization.');
        } elseif (!(isset($_GET['curate']) || isset($_GET['agree'])) && $_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();

        // 2008-10-09; 2.0-13; Deny this entry, if the allele is changed but the exact combination is already present in the database. Otherwise, an SQL error would show up.
        if (!lovd_error() && $zData['allele'] != $_POST['allele']) {
            // Check database.
            // 2009-07-02; 2.0-19; Of course, we need to check the patientid field here, too.
            list($n) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_PAT2VAR . ' WHERE symbol = "' . $_SESSION['currdb'] . '" AND variantid = "' . $_GET['variantid'] . '" AND allele = "' . $_POST['allele'] . '" AND patientid = "' . $_GET['patientid'] . '"'));
            if ($n) {
                // This is bad... we should not allow this!
                lovd_errorAdd('An entry in the database exactly like this already exists! Are you sure you don\'t want a different value for the \'Variant allele\' field?');
            }
        }

        if (!lovd_error()) {
            // 2009-07-02; 2.0-19; Don't do anything when a submitter edits, and nothing is changed.
            if (HAS_SUBS) {
                // Check if something changed.
                $bChanged = false;

                // Get columns to update in the database.
                $aCols = $_CURRDB->getColList('Variant');

                // Then, add pat2var columns that submitters can change!
                $aCols[] = 'allele';
                $aCols[] = 'pathogenic';
                $_POST['pathogenic'] = $_POST['pathogenic_reported'] . $zData['pathogenic']{1};

                foreach ($aCols as $sCol) {
                    $sVal = (empty($_POST[$sCol])? '' : $_POST[$sCol]);
                    // Selection list to value.
                    if (is_array($sVal)) {
                        $sVal = implode(';', $sVal);
                    }
                    if ($sVal != $zData[$sCol]) {
                        $bChanged = true;
                        break;
                    }
                }

                // Now, if nothing changed, just kick the user out right here.
                if (!$bChanged) {
                    header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/variants.php?action=view&view=' . $_GET['patientid'] . '%2C' . $_GET['variantid'] . '%2C' . $_POST['allele'] . lovd_showSID(true));

                    require ROOT_PATH . 'inc-top.php';
                    lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');

                    lovd_showInfoTable('There were no changes submitted!', 'success');

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



            // Get columns to update in the database.
            $aCols = $_CURRDB->getColList('Variant');

            if ($sMutationCol && in_array($sMutationCol, array('Variant/DNA', 'Variant/RNA'))) {
                // Find mutation column, include sort column in list.
                $aCols[] = 'sort';
                // 2009-06-12; 2.0-19; Added exon column for better search results.
                // A bit crude; we're not checking if Variant/Exon exists, we just suppress a possible notice.
                $_POST['sort'] = @lovd_sort($_POST[$sMutationCol], $_POST['Variant/Exon']);
            }

            // 2008-04-24; 2.0-06; Include auto generated Variant/DBID field for submitters.
            if (array_search('Variant/DBID', $aCols) === false && !empty($_POST['Variant/DBID'])) {
                // Variant/DBID was hidden, but value is filled in.
                $aCols[] = 'Variant/DBID';
            }

            // FIXME; if there are no actual changes to any of the Variant/* fields, it would be better not to do anything in this code block.
            // 2009-01-23; 2.0-15; What kind of update? Update existing variant for sure, if there is simply one patient associated.
            if ($nPatients < 2 || $_POST['update_all'] == 'update') {
                // Query text.
                $sQ = 'UPDATE ' . TABLE_CURRDB_VARS . ' SET ';

                // 2009-11-25; 2.0-23; Make sure variant gets mapped again.
                $aCols[] = 'c_position_start';
                $_POST['c_position_start'] = NULL; // So it will be remapped.

                foreach ($aCols as $key => $val) {
                    // 2007-06-28; 2.0-beta-05; sometimes fields are not sent. HTTP posting faked or empty selection list?
                    // This one is different because we don't want to use isset(). isset() will return false for a variable set to NULL (see 5 lines up).
                    if (!array_key_exists($val, $_POST)) {
                        $_POST[$val] = '';
                    }

                    // Selection list to value.
                    if (is_array($_POST[$val])) {
                        $_POST[$val] = implode(';', $_POST[$val]);
                    }
                    $sQ .= ($key? ', ' : '') . '`' . $val . '` = ' . ($_POST[$val] === NULL? 'NULL' : '"' . $_POST[$val] . '"');
                }

                $sQ .= ' WHERE variantid = ' . $_GET['variantid'];

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

                // We need to update *all* edited_by and edited_date fields if the fields of the mutation itself were actually changed.
                $bUpdateAll = mysql_affected_rows();

                if ($bUpdateAll) {
                    $sQ = 'UPDATE ' . TABLE_PAT2VAR . ' SET edited_by = "' . (HAS_AUTH? $_AUTH['userid'] : 0) . '", edited_date = NOW() WHERE symbol = "' . $_SESSION['currdb'] . '" AND variantid = "' . $_GET['variantid'] . '"';
                    $q = mysql_query($sQ);
                    if (!$q) {
                        $sError = mysql_error(); // Save the mysql_error before it disappears.
                        require ROOT_PATH . 'inc-top.php';
                        lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');
                        lovd_dbFout('VariantEditB1', $sQ, $sError);
                    }
                }

            } else {
                // Create the insert query.
                $sQ = 'INSERT INTO ' . TABLE_CURRDB_VARS . ' (';

                // Determine which columns to insert into.
                $aCol = array();
                foreach ($aCols as $sCol) {
                    if (isset($_POST[$sCol])) {
                        $sQ .= (substr($sQ, -1) == '('? '' : ', ') . '`' . $sCol . '`';
                        $aCol[] = $_POST[$sCol];
                    }
                }
                $sQ .= ') VALUES (';
                // Determine the values to insert
                foreach ($aCol as $key => $val) {
                    // 2009-06-11; 2.0-19; Fixed bug when $val is array.
                    // Selection list to value.
                    if (is_array($val)) {
                        $val = implode(';', $val);
                    }
                    $sQ .= ($key? ', ' : '') . '"' . $val . '"';
                }
                $sQ .= ')';
                $q = mysql_query($sQ);
                if (!$q) {
                    $sError = mysql_error(); // Save the mysql_error before it disappears.
                    require ROOT_PATH . 'inc-top.php';
                    lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');
                    lovd_dbFout('VariantEditA2', $sQ, $sError);
                }

                // Remember variant id.
                $nVariantID = str_pad(mysql_insert_id(), 7, '0', STR_PAD_LEFT);

                // Now connect the newly created variant entry with the patient entry, and change the edited_* fields for this variant in this patient (2 if homozygous!).
                $sQ = 'UPDATE ' . TABLE_PAT2VAR . ' SET edited_by = "' . (HAS_AUTH? $_AUTH['userid'] : 0) . '", edited_date = NOW(), variantid = "' . $nVariantID . '" WHERE symbol = "' . $_SESSION['currdb'] . '" AND variantid = "' . $_GET['variantid'] . '" AND patientid = "' . $_GET['patientid'] . '"';
                $q = mysql_query($sQ);
                if (!$q) {
                    $sError = mysql_error(); // Save the mysql_error before it disappears.
                    require ROOT_PATH . 'inc-top.php';
                    lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');
                    lovd_dbFout('VariantEditB2', $sQ, $sError);
                    // Delete the variant already inserted before
                    @mysql_query('DELETE FROM ' . TABLE_CURRDB_VARS . ' WHERE variantid = "' . $nVariantID . '"');
                }

                // 2009-02-23; 2.0-16; Moved this statement (was in the wrong place).
                $_GET['variantid'] = $nVariantID;
            }

            // 2010-04-12; 2.0-26; Start remapping the variants every time a variant has been edited.
            $_SESSION['mapping']['time_complete'] = 0;

            // Variant pathogenicity.
            if (HAS_AUTH) {
                // Curator and up.
                $_POST['pathogenic'] = $_POST['pathogenic_reported'] . $_POST['pathogenic_concluded'];
            } else {
                // 2008-04-22; 2.0-06; Submitters can now also edit variants when My Submissions is activated.
                // Submitter... keep concluded pathogenicity to what it was.
                if (!array_key_exists($_POST['pathogenic_reported'], $_SETT['var_pathogenic'])) {
                    $_POST['pathogenic_reported'] = 5;
                }
                $_POST['pathogenic'] = $_POST['pathogenic_reported'] . $zData['pathogenic']{1};

                // Also change status, just maybe.
                if ($zData['status'] > 7) {
                    $_POST['status'] = 7;
                } else {
                    $_POST['status'] = $zData['status'];
                }
            }

            // Update PAT2VAR table. Also update edited_* fields, as it may not have been updated up there.
            $sQ = 'UPDATE ' . TABLE_PAT2VAR . ' SET allele = "' . $_POST['allele'] . '", pathogenic = "' . $_POST['pathogenic'] . '", status = "' . $_POST['status'] . '", edited_by = "' . (HAS_AUTH? $_AUTH['userid'] : 0) . '", edited_date = NOW() WHERE symbol = "' . $_SESSION['currdb'] . '" AND variantid = "' . $_GET['variantid'] . '" AND patientid = "' . $_GET['patientid'] . '" AND allele = "' . $_GET['allele'] . '"';
            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');
                lovd_dbFout('VariantEditC', $sQ, $sError);
            }

            // 2007-12-05; 2.0-02; Fixed bug #20 - Gene's "Last update" field not updated.
            lovd_setUpdatedDate($_SESSION['currdb']);

            // Write to log...
            lovd_writeLog('MySQL:Event', 'VariantEdit', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully ' . (isset($_GET['curate'])? 'curat' : (isset($_GET['agree'])? 'agreed to ' : '') . 'edit') . 'ed variant #' . $zData['variantid'] . ' (' . $_SESSION['currdb'] . ')');



            // 2008-04-22; 2.0-06; Submitters can now also edit variants when My Submissions is activated.
            if (HAS_SUBS) {
                // This was a submitter's work. Send email to curator(s).

                // Grab email adresses of addressees, to prevent double emails.
                $aEmails = array();

                // Find me the curator of this gene...
                $qCurators = mysql_query('SELECT u.name, u.email FROM ' . TABLE_CURATES . ' AS c, ' . TABLE_USERS . ' AS u WHERE c.userid = u.userid AND c.symbol = "' . $_SESSION['currdb'] . '" ORDER BY u.level DESC, u.name');
                $nCurators = mysql_num_rows($qCurators);
                $sCurators = '';
                while ($r = mysql_fetch_row($qCurators)) {
                    // If email hasn't been added before, add it.
                    if (!in_array($r[1], $aEmails)) {
                        // 2009-02-27; 2.0-16; Sending emails on Windows requires removal of names from the email addresses.
                        $sCurators .= ($sCurators? ', ' : '') . (ON_WINDOWS? '' : '"' . $r[0] . '" ') . '<' . $r[1] . '>';
                        $aEmails[] = $r[1];
                    }
                }

                // 2009-02-27; 2.0-16; Sending emails on Windows requires removal of names from the email addresses.
                $sSubmitter = (ON_WINDOWS? '' : '"' . $_AUTH['name'] . '" ') . '<' . str_replace(array("\r\n", "\r", "\n"), '>, <', trim($_AUTH['email'])) . '>';

                $sBody = 'LOVD ' . $_SETT['system']['version'] . ' @ ' . $_CONF['location_name'] . ' for ' . $_SESSION['currdb'] . "\n" .
                         'To Curator' . ($nCurators == 1? ' ' : 's') . '  : ' . str_replace('"', '', $sCurators) . "\n" .
                         'CC Submitter : ' . str_replace('"', '', $sSubmitter) . "\n\n" .
                         'Dear Curator' . ($nCurators == 1? '' : 's') . ',' . "\n\n" .
                         $_AUTH['name'] . ' has edited a variant entry in the ' . $_SESSION['currdb'] . ' database.' . "\n" .
                         'If the submission was public, the status has been set to Marked. ' .
                         'Below is a copy of the updated variant information.' . "\n\n";
                // 2009-04-06; 2.0-17; Add the location of the entry, so that the curator can just click the link.
                if ($_CONF['location_url']) {
                    $sBody .= 'To view the entry, click this link (you may need to log in first):' . "\n" .
                              $_CONF['location_url'] . 'variants.php?select_db=' . $_SESSION['currdb'] . '&action=view&view=' . $zData['patientid'] . '%2C' . $zData['variantid'] . '%2C' . $_POST['allele'] . "\n\n";
                }
                $sBody .= 'Regards,' . "\n" .
                          '    LOVD system at ' . $_CONF['location_name'] . "\n\n";

                // Submitter information.
                $sBody .= str_repeat('-', 80) . "\n" .
                          '  SUBMITTER DETAILS' . "\n" .
                          str_repeat('-', 80) . "\n";

                // Array containing the fields.
                $aMail =
                         array(
                                'submitterid' => 'Submitter ID',
                                'name' => 'Name',
                                'institute' => 'Institute',
                                'department' => 'Department',
                                'address' => 'Address',
                                'city' => 'City',
                                'country_' => 'Country',
                                'email' => 'Email address',
                                'telephone' => 'Telephone',
                              );

                // Fetching country name.
                list($_AUTH['country_']) = mysql_fetch_row(mysql_query('SELECT country FROM ' . TABLE_COUNTRIES . ' WHERE code = "' . $_AUTH['country'] . '"'));

                // Padding to...
                $lPad = 0;
                foreach ($aMail as $val) {
                    $l = strlen($val);
                    if ($l > $lPad) {
                        $lPad = $l;
                    }
                }

                foreach ($aMail as $key => $val) {
                    $sBody .= str_pad($val, $lPad) . ' : ' . str_replace("\n", "\n" . str_repeat(' ', $lPad + 3), lovd_wrapText($_AUTH[$key], 80 - $lPad - 3)) . "\n";
                }
                $sBody .= str_repeat('-', 80) . "\n\n";

                // Variant information.
                $sBody .= str_repeat('-', 80) . "\n" .
                          '  VARIANT DETAILS' . "\n" .
                          str_repeat('-', 80) . "\n";

                // Array containing the fields.
                $aMail = $_CURRDB->buildTable('detail');

                // Remove columns not for variants.
                $aCols = $_CURRDB->getColList('Variant');
                foreach ($aMail as $sCol => $aCol) {
                    if (!in_array($sCol, $aCols)) {
                        unset($aMail[$sCol]);
                    }
                }

                // Add columns.
                $aMail = array_merge(
                         array(
                                'pathogenic_' => 'Pathogenic',
                                'allele_' => 'Allele',
                              ),
                         $aMail);

                // Padding to...
                $lPad = 0;
                foreach ($aMail as $val) {
                    $l = strlen($val);
                    if ($l > $lPad) {
                        $lPad = $l;
                    }
                }

                // Good practice when mailing and printing.
                lovd_magicUnquote($_POST);

                $_POST['pathogenic_'] = $_SETT['var_pathogenic'][$_POST['pathogenic']{0}];
                $zData['pathogenic_'] = $_SETT['var_pathogenic'][$zData['pathogenic']{0}]; // So we can match the two to track changes.
                $_POST['allele_']     = $_SETT['var_allele'][$_POST['allele']];
                $zData['allele_']     = $_SETT['var_allele'][$zData['allele']]; // So we can match the two to track changes.

                // Transform select lists' values.
                $_CURRDB->transformSelectValues($_POST);
                $_CURRDB->transformSelectValues($zData); // So we can match the two to track changes.

                foreach ($aMail as $key => $val) {
                    // $lPad '± 2' specific for editing!
                    $sBody .= str_pad($val, $lPad) . (isset($_POST[$key]) && $zData[$key] != $_POST[$key]? ' *' : '  ') . ' : ' . str_replace("\n", "\n" . str_repeat(' ', $lPad + 3 + 2), lovd_wrapText($_POST[$key], 80 - $lPad - 3 - 2)) . "\n";
                }
                $sBody .= str_repeat('-', 80) . "\n";

                // Set proper subject.
                $sSubject = 'LOVD submission update (' . $_SESSION['currdb'] . ')';

                // Send mail.
                $bMail = @mail($sCurators,
                               $sSubject,
                               lovd_wrapText($sBody),
                               $_SETT['headers'] .
                               $sEol . 'Cc: ' . $sSubmitter);



                // Mail the database admin if he's not the curator(s).
                if ($bMail) {
                    if ($_CONF['send_fwd'] && !in_array($_SETT['admin']['email'], $aEmails)) {
                        // Sent mail to curator(s), send copy to database administrator.
                        $sBody = 'Dear ' . $_SETT['admin']['name'] . ",\n\n" .
                                 'As requested, a copy of the message I\'ve just sent.' . "\n\n" .
                                 str_repeat('-', 30) . ' Forwarded  Message ' . str_repeat('-', 30) . "\n\n" .
                                 rtrim($sBody) . "\n\n" .
                                 str_repeat('-', 27) . ' End of Forwarded Message ' . str_repeat('-', 27) . "\n";

                        // Send mail.
                        $bMailA = @mail((ON_WINDOWS? '' : '"' . $_SETT['admin']['name'] . '" ') . '<' . $_SETT['admin']['email'] . '>',
                                        'Fw: ' . $sSubject,
                                        lovd_wrapText($sBody),
                                        $_SETT['headers']);

                        if (!$bMailA) {
                            // Couldn't sent confirmation to admin...
                            lovd_writeLog('MySQL:Error', 'EmailNotify', $_SERVER['PHP_SELF'] . ' returned SubmitUpdateNotifyAdmin error for submitter ' . $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ')');
                        }
                    }

                } else {
                    // Couldn't sent confirmation...
                    lovd_writeLog('MySQL:Error', 'EmailNotify', $_SERVER['PHP_SELF'] . ' returned SubmitUpdateNotify error for submitter ' . $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ')');
                }
            }



            // Thank the user...
            header('Refresh: ' . (isset($_GET['curate'])? '1' : (isset($_GET['agree'])? '0' : '3')) . '; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/variants.php?action=view&view=' . $_GET['patientid'] . '%2C' . $_GET['variantid'] . '%2C' . $_POST['allele'] . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');




            $sMessage = 'Successfully ' . (isset($_GET['curate'])? 'curat' : 'edit') . 'ed variant!';
            if (HAS_SUBS) {
                if ($bMail) {
                    $sMessage .= '<BR>The curator' . ($nCurators == 1? '' : 's') . ' of the ' . $_SESSION['currdb'] . ' database ha' . ($nCurators == 1? 's' : 've') . ' been sent an email containing your changes. A copy has been sent to you.';
                } else {
                    $sMessage .= '<BR>Due to an unknown error, no email regarding the submission could be sent to the curator' . ($nCurators == 1? '' : 's') . ' of the ' . $_SESSION['currdb'] . ' database. Your changes have successfully been added to the database.';
                }
            }
            lovd_showInfoTable($sMessage, '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']);
        }

    } else {
        foreach ($zData as $key => $val) {
            if (!isset($_POST[$key]) || !$_POST[$key]) {
                $_POST[$key] = $val;
            }
        }
        // Transform select lists' values.
        $_CURRDB->transformSelectValues($_POST, true);
        $_POST['pathogenic_reported'] = $_POST['pathogenic']{0};
        $_POST['pathogenic_concluded'] = $_POST['pathogenic']{1};
        $_POST['password'] = '';
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');

    if (!isset($_GET['sent'])) {
        print('      To edit the sequence variant, please fill out the form below.<BR>' . "\n" .
              '      <BR>' . "\n\n");
    }

    lovd_errorPrint();

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

    // 2008-10-09; 2.0-13; Remove "Both (homozygous)" since it serves no purpose here.
    unset($_SETT['var_allele'][3]);

    // 2010-01-14; 2.0-24; Added link to either the coding DNA reference sequence or the mRNA sequence at NCBI, depending on their availability.
    list($sRefType, $sURL, $smRNA) = @mysql_fetch_row(mysql_query('SELECT refseq, refseq_url, refseq_mrna FROM ' . TABLE_DBS . ' WHERE symbol = "' . $_POST['symbol'] . '"'));
    $sLinkText = '';
    if ($sURL) {
        $sLinkText = 'To check your numbering, please check the <A href="' . $sURL .'" target="_blank">' . ($sRefType == 'c' ? 'coding' : 'genomic') . ' DNA reference sequence</A> used in the ' . $_POST['symbol'] . ' database.';
    } elseif ($_SETT['currdb']['refseq_mrna']) {
        $sLinkText = 'To check your numbering, please check the <A href="' . lovd_getExternalSource('genbank', $smRNA, true) . '" target="_blank">' . $smRNA . ' mRNA reference sequence</A>.';
    }
    $_CURRDB->aColList['Variant/DNA']['description_form'] .= ($_CURRDB->aColList['Variant/DNA']['description_form'] && $sLinkText? '<BR>' : '') . $sLinkText;

    // Array which will make up the form table.
    $aForm = array_merge(
                         array(
                                array('POST', '', '', '40%', '60%'),
                                array('Variant allele', 'select', 'allele', 1, $_SETT['var_allele'], false, false, false),
                              ),
                         $_CURRDB->buildFormTable('Variant'),
                         array(
                                'skip',
                                array('Pathogenicity (reported)', 'select', 'pathogenic_reported', 1, $_SETT['var_pathogenic'], false, false, false),
                              ));

    // 2008-04-22; 2.0-06; Submitters can now also edit variants when My Submissions is activated.
    if (IS_CURATOR) {
        // Authorized user logged in; provide status control.
        $aForm = array_merge($aForm,
                             array(
                                    array('Pathogenicity (concluded)', 'select', 'pathogenic_concluded', 1, $_SETT['var_pathogenic'], false, false, false),
                                    array('Variant status', 'select', 'status', 1, $_SETT['var_status'], false, false, false),
                                  ));
    }

    $aForm = array_merge($aForm,
                         array(
                                'skip',
                              ),
                         // 2008-03-26; 2.0-05; If variant is shared over multiple patients, warn user.
                         $aFormMultiplePat,
                         array(
                                array('Enter your password for authorization', 'password', 'password', 20),
                                array('', 'submit', 'Edit variant data'),
                              ));
    $_MODULES->processForm('SubmitVariantsEdit', $aForm);
    lovd_viewForm($aForm);

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

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





} elseif ($_GET['action'] == 'drop' && preg_match('/^([0-9]{1,7})\,([0-9]{1,7})\,([0-9]{1,2})$/', $_GET['drop'], $aRegs) && list(, $_GET['patientid'], $_GET['variantid'], $_GET['allele']) = $aRegs) {
    // Drop specific variant/patient link.

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';
    require ROOT_PATH . 'class/currdb.php';
    $_CURRDB = new CurrDB();
    $sMutationCol = $_CURRDB->getMutationCol();

    $zData = @mysql_fetch_assoc(mysql_query('SELECT p2v.*' . (!$sMutationCol? '' : ', v.`' . $sMutationCol . '`') . ' FROM ' . TABLE_PAT2VAR . ' AS p2v LEFT JOIN ' . TABLE_CURRDB_VARS . ' AS v ON (p2v.variantid = v.variantid) WHERE p2v.symbol = "' . $_SESSION['currdb'] . '" AND v.variantid = "' . $_GET['variantid'] . '" AND p2v.patientid = "' . $_GET['patientid'] . '" AND p2v.allele = "' . $_GET['allele'] . '"'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');
        lovd_showInfoTable('No such ID!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    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()) {
            // Drop Variant link, Remove orphaned patients from TABLE_PATIENTS and orphaned variants from TABLE_CURRDB_VARS.

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('variant_manage', 'LOVD Manage sequence variants');

            // If using transactional tables; begin transaction.
            if ($_INI['database']['engine'] == 'InnoDB') {
                // FIXME; It's better to use 'START TRANSACTION', but that's only available from 4.0.11.
                //   This works from the introduction of InnoDB in 3.23
                @mysql_query('BEGIN WORK');
            }

            // Start with the variant's connection.
            print('      Removing variant...<BR>' . "\n" .
                  '      Removing variant <-> patient link ... ');
            flush();
            $sQ = 'DELETE FROM ' . TABLE_PAT2VAR . ' WHERE patientid = "' . $_GET['patientid'] . '" AND allele = "' . $_GET['allele'] . '" AND symbol = "' . $_SESSION['currdb'] . '" AND variantid = "' . $_GET['variantid'] . '"';
            $q = mysql_query($sQ);
            if (!$q) {
                lovd_dbFout('VariantDropA', $sQ, mysql_error());
            }
            print('OK<BR>' . "\n");

            // Orphaned patients.
            print('      Removing obsolete patients ... ');
            flush();
            // Backwards compatible with MySQL 4.0 and earlier. These versions do not support subqueries, which would really come in handy now.
            // First, determine the ID's of the orphaned patients. Then construct the DELETE query.
            $aOrphaned = array();
            $qOrphaned = mysql_query('SELECT p.patientid FROM ' . TABLE_PATIENTS . ' AS p LEFT OUTER JOIN ' . TABLE_PAT2VAR . ' AS p2v USING (patientid) WHERE p2v.symbol IS NULL');
            while ($rOrphaned = mysql_fetch_row($qOrphaned)) {
                $aOrphaned[] = $rOrphaned[0];
            }
            $bDeleted = in_array($zData['patientid'], $aOrphaned);
            if (count($aOrphaned)) {
                // Construct DELETE query.
                $sQ = 'DELETE FROM ' . TABLE_PATIENTS . ' WHERE patientid IN (' . implode(', ', $aOrphaned) . ')';
                $q = mysql_query($sQ);
                if (!$q) {
                    lovd_dbFout('VariantDropB', $sQ, mysql_error());
                }
                print('OK<BR>' . "\n");
            } else {
                print('N/A<BR>' . "\n");
            }

            // Orphaned variants.
            print('      Removing obsolete variants ... ');
            flush();
            // Backwards compatible with MySQL 4.0 and earlier. These versions do not support subqueries, which would really come in handy now.
            // Fist, determine the ID's of the orphaned patients. Then construct the DELETE query.
            $aOrphaned = array();
            $qOrphaned = mysql_query('SELECT v.variantid FROM ' . TABLE_CURRDB_VARS . ' AS v LEFT OUTER JOIN ' . TABLE_PAT2VAR . ' AS p2v ON (v.variantid = p2v.variantid AND p2v.symbol = "' . $_SESSION['currdb'] . '") WHERE p2v.symbol IS NULL');
            while ($rOrphaned = mysql_fetch_row($qOrphaned)) {
                $aOrphaned[] = $rOrphaned[0];
            }
            if (count($aOrphaned)) {
                // Construct DELETE query.
                $sQ = 'DELETE FROM ' . TABLE_CURRDB_VARS . ' WHERE variantid IN (' . implode(', ', $aOrphaned) . ')';
                $q = mysql_query($sQ);
                if (!$q) {
                    lovd_dbFout('VariantDropC', $sQ, mysql_error());
                }
                print('OK<BR><BR>' . "\n\n");
            } else {
                print('N/A<BR><BR>' . "\n\n");
            }

            // If we don't do this, we haven't got anything in the DB... duh!
            if ($_INI['database']['engine'] == 'InnoDB') {
                // Could this actually fail?!!??
                @mysql_query('COMMIT');
            }

            // 2007-12-05; 2.0-02; Fixed bug #20 - Gene's "Last update" field not updated.
            lovd_setUpdatedDate($_SESSION['currdb']);

            // Write to log...
            lovd_writeLog('MySQL:Event', 'VariantDrop', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully deleted variant for ' . $_SESSION['currdb'] . ' (Patient #' . $_GET['patientid'] . '; Mutation #' . $_GET['variantid'] . '; Allele #' . $_GET['allele'] . ')');

            // Thank the user...
            print('      Successfully deleted variant!<BR><BR>' . "\n\n");

            // Alternate refresh; since we can't send a HTTP header...
            print('      <SCRIPT type="text/javascript">' . "\n" .
                  '      <!--' . "\n");
            // 2007-08-09; 2.0-beta-07; View patient information without considering any variants is now possible.
            if ($bDeleted) {
                print('        setTimeout(\'window.location.href = "' . PROTOCOL . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/variants.php?action=view_all' . lovd_showSID(true, true) . '"\', 3000);' . "\n");
            } else {
                print('        setTimeout(\'window.location.href = "' . PROTOCOL . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/variants.php?select_db=' . $_SESSION['currdb'] . '&action=view&view=' . $zData['patientid'] . lovd_showSID(true, true) . '"\', 3000);' . "\n");
            }
            print('      // -->' . "\n" .
                  '      </SCRIPT>' . "\n\n");

            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('variant_manage', 'LOVD Manage sequence variants');

    lovd_errorPrint();

    // Table.
    // 2009-09-17; 2.022; added ?select_db=' . $_SESSION['currdb'] to stay in the right database
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?select_db=' . $_SESSION['currdb'] . '&amp;action=' . $_GET['action'] . '&amp;drop=' . $_GET['drop'] . '&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 variant', 'print', ($sMutationCol? $zData[$sMutationCol] . ' (allele: ' . $_SETT['var_allele'][$zData['allele']] . ')' : 'Variant in allele: ' . $_SETT['var_allele'][$zData['allele']])),
                    'skip',
                    array('Enter your password for authorization', 'password', 'password', 20),
                    array('', 'submit', 'Delete variant'),
                  );
    $_MODULES->processForm('SubmitVariantsDelete', $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'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/variants.php?action=view_all' . lovd_showSID(true));
    exit;
}
?>