<?php
/*******************************************************************************
 *
 * LEIDEN OPEN VARIATION DATABASE (LOVD)
 *
 * Created     : 2006-10-27
 * Modified    : 2013-02-20
 * For LOVD    : 2.0-35
 *
 * Access      : Public
 * Purpose     : Allow submitters to register themselves and provide the public
 *               listing of submitters.
 *
 * Copyright   : 2004-2013 Leiden University Medical Center; http://www.LUMC.nl/
 * Programmer  : Ing. Ivo F.A.C. Fokkema <I.F.A.C.Fokkema@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';
}

// Because this page is currently the only page needing this function, I've put it here.
function lovd_hideEmail ($s)
{
    // Function kindly provided by Ileos.nl in the interest of Open Source.
    // Obscure email addresses from spambots.
    $a_replace = array(45 => '-', '.',
                       48 => '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                       64 => '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
                       95 => '_',
                       97 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                      );

    $s_return = '';
    for ($i = 0; $i < strlen($s); $i ++) {
        $s_sub = substr($s, $i, 1);
        if ($key = array_search($s_sub, $a_replace)) {
            $s_return .= '&#' . str_pad($key, 3, '0', STR_PAD_LEFT) . ';';
        } else {
            $s_return .= $s_sub;
        }
    }

    return $s_return;
}





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

    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('submitters_public_listing', 'LOVD - Public submitter listing');

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

    list($nTotalSubmits) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_PAT2VAR . ' AS p2v LEFT JOIN ' . TABLE_PATIENTS . ' AS p USING (patientid) WHERE p.submitterid != ""'));

    print('      <B>Total submitters</B> : ' . $nTotal . '<BR>' . "\n" .
          '      <B>Total submissions</B> : ' . $nTotalSubmits . '<BR><BR>' . "\n");

    // Standard query, will be extended later on.
    $sQ = 'SELECT s.*, CONCAT(s.firstname, " ", s.lastname) AS name, c.country AS country_ FROM ' . TABLE_SUBS . ' AS s LEFT JOIN ' . TABLE_COUNTRIES . ' AS c ON (s.country = c.code) WHERE s.deleted = 0 ORDER BY c.country, s.city, name';
    $q = mysql_query($sQ);
    if (!$q) {
        lovd_dbFout('SubsPublic', $sQ, mysql_error());
    }



    $sPrevious = '';

    while ($zData = mysql_fetch_assoc($q)) {
        $sCurrent = $zData['country'];

        if ($sPrevious != $sCurrent) {
            print(($sPrevious? '</TABLE><BR>' . "\n\n" : '') .
                  '      <HR>' . "\n" .
                  '      <SPAN style="font-size : 20px;"><B>' . $zData['country_'] . '</B></SPAN><BR>' . "\n" .
                  '      <HR><BR>' . "\n" .
                  '      <TABLE border="0" cellspacing="0" cellpadding="0">');
            $sPrevious = $sCurrent;
        }

        print("\n" .
              '        <TR>' . "\n" .
              '          <TD valign="top" width="250">' . "\n" .
              '            <A name="' . $zData['submitterid'] . '"></A>' . "\n" .
              '            <B>' . ucwords($zData['city']) . '</B></TD>' . "\n" .
              '          <TD valign="top" class="S11">' . "\n" .
              '            <B class="S13">' . $zData['name'] . '</B><BR>' . "\n" .
              '            <SPAN class="S13">' . $zData['institute'] . '</SPAN><BR>' . "\n" .
              '            ' . $zData['department'] . '<BR>' . "\n" .
              '            ' . str_replace(array("\r\n", "\r", "\n"), '<BR>', trim($zData['address'])) . '<BR>' . "\n" .
              '<BR><BR></TD></TR>');
    }
    print('</TABLE><BR>' . "\n\n");

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





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

    require ROOT_PATH . 'inc-top-clean.php';

    $zData = @mysql_fetch_assoc(mysql_query('SELECT s.*, CONCAT(s.firstname, " ", s.lastname) AS name, c.country AS country_ FROM ' . TABLE_SUBS . ' AS s LEFT JOIN ' . TABLE_COUNTRIES . ' AS c ON (s.country = c.code) WHERE s.submitterid = "' . $_GET['view'] . '"'));
    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&nbsp;ID',
                    'name' => 'Name',
                    'email' => 'Email&nbsp;address',
                    'institute' => 'Institute',
                    'department' => 'Department',
                    'address' => 'Address',
                    'country_' => 'Country',
                  );

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

    $zData['address']  = str_replace(array("\r\n", "\r", "\n"), '<BR>', $zData['address']);
    $zData['email']    = lovd_hideEmail(str_replace(array("\r\n", "\r", "\n"), ', ', trim($zData['email'])));

    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");

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





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

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

    // 2008-12-05; 2.0-15; Agreed, this should be in the module itself... but currently a module can do nothing more than change the forms.
    // Adding CAPTCHA check on registration form.
    if ($_MODULES->isLoaded('recaptcha')) {
        require MODULE_PATH . 'recaptcha/inc-lib-recaptcha.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.');
            }
        }

        // 2008-08-07; 2.0-10; Block newlines to prevent registration form from being used as a spam sender.
        // Fields not allowed to contain newlines (hack attempt - sending spam using the form).
        $aCheck =
                 array(
                        'firstname' => 'First name',
                        'lastname' => 'Last name',
                      );

        foreach ($aCheck as $key => $val) {
            if (substr_count($_POST[$key], "\n")) {
                lovd_errorAdd('Disallowed newline found in form field "' . $val . '". SPAM attack?');
            }
        }

        // 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.');
            }
        }

        // 2008-12-05; 2.0-15; Agreed, this should be in the module itself... but currently a module can do nothing more than change the forms.
        // Adding CAPTCHA check on registration form.
        if ($_MODULES->isLoaded('recaptcha')) {
            // If no response has been filled in, we need to complain. Otherwise, we should check the answer.
            $sCAPTCHAerror = '';
            if (empty($_POST['recaptcha_response_field'])) {
                lovd_errorAdd('Please fill in the two words that you see in the image, at the bottom of the form.');
            } else {
                // Check answer!
                $response = recaptcha_check_answer ('6Le0JQQAAAAAAB-iLSVi81tR5s8zTajluFFxkTPL', $_SERVER['REMOTE_ADDR'], $_POST['recaptcha_challenge_field'], $_POST['recaptcha_response_field']);
                if (!($response->is_valid)) {
                    lovd_errorAdd('The verification failed. Please try again by filling in the two words that you see in the image, at the bottom of the form.');
                    $sCAPTCHAerror = $response->error;
                }
            }
        }

        // 2013-02-20; 2.0-35; This function checks the given data for use by spammers. Based on LOVD3 code.
        if (!lovd_error()) {
            // 2013-09-02; LOVD 2.0-36; LOVD2 allows for multiple email addresses. Check only the last, as we have that prepared in the $sEmail variable.
            $aOutput = lovd_php_file('http://www.stopforumspam.com/api?ip=' . $_SERVER['REMOTE_ADDR'] . '&email=' . $sEmail . '&username=' . $_POST['username'] . '&f=serial');
            if ($aOutput) {
                $aStopSpamResponse = unserialize(implode('', $aOutput));
                foreach (array('ip', 'email', 'username') as $sCategory) {
                    if (!isset($aStopSpamResponse[$sCategory]['confidence'])) {
                        $aStopSpamResponse[$sCategory]['confidence'] = 0;
                    }
                }

                if ($aStopSpamResponse['success']) {
                    $nFrequency = ($aStopSpamResponse['ip']['frequency'] + $aStopSpamResponse['email']['frequency'] + $aStopSpamResponse['username']['frequency']);
                    $nConfidence = max($aStopSpamResponse['ip']['confidence'], $aStopSpamResponse['email']['confidence'], $aStopSpamResponse['username']['confidence']);
                    if ($nFrequency >= 10 || $nConfidence >= 75) {
                        lovd_writeLog('MySQL:Event', 'SubmitterRegister', 'User registration blocked based on frequency (' . $nFrequency . ') and confidence (' . $nConfidence . ') in spam database: ' . $_SERVER['REMOTE_ADDR'] . ', ' . $_POST['email'] . ', ' . $_POST['username']);
                        lovd_errorAdd('Your registration has been blocked based on suspicion of spamming. If you feel this is an error, please contact us.');
                        $_POST = array(); // Empty all 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, ';

            // 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');

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

            $sQ .= ', 0, 0, NOW(), 0, 0, 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('submitters_register', 'LOVD - Register as new submitter');
                lovd_dbFout('SubCreate', $sQ, $sError);
            }

            $_POST['submitterid'] = str_pad(mysql_insert_id(), 5, '0', STR_PAD_LEFT);
            $_POST['name']        = $_POST['firstname'] . ' ' . $_POST['lastname'];

            // Write to log...
            lovd_writeLog('MySQL:Event', 'SubmitterRegister', $_POST['username'] . ' (' . $_POST['name'] . ') successfully created own account with ID ' . $_POST['submitterid']);



            // Mail submitter.
            // Good practice when mailing and printing.
            lovd_magicUnquoteAll();

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

            $sBody = 'LOVD ' . $_SETT['system']['version'] . ' @ ' . $_CONF['location_name'] . "\n" .
                     'To : ' . str_replace('"', '', $sSubmitter) . "\n\n" .
                     'Dear ' . $_POST['firstname'] . ' ' . $_POST['lastname'] . ',' . "\n\n" .
                     'You have registered as a submitter of sequence variations for this LOVD system.' . "\n" .
                     'Below is a copy of your registration information.' . "\n\n";
            // 2009-04-06; 2.0-17; Add the location of the database, so that the submitter can just click the link.
            if ($_CONF['location_url']) {
                $sBody .= 'To log in to LOVD, click this link:' . "\n" .
                          $_CONF['location_url'] . 'account_login.php' . "\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',
                            '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',
                            'password_1' => 'Password',
                          );

            // 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($_POST[$key], 80 - $lPad - 3)) . "\n";
            }
            $sBody .= str_repeat('-', 80) . "\n\n";

            // Set proper subject.
            $sSubject = 'LOVD registration';

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



            // Possibly, mail the database admin.
            if ($bMail) {
                if ($_CONF['send_fwd']) {
                    // Sent mail to submitter, send copy to database administrator.
                    $sBody = preg_replace('/^(Password[\s*]+: )' . preg_quote($_POST['password_1']) . '/m', "$1" . '<password hidden>', $sBody);
                    $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.
                    // 2009-02-27; 2.0-16; Sending emails on Windows requires removal of names from the email addresses.
                    $bMail = @mail((ON_WINDOWS? '' : '"' . $_SETT['admin']['name'] . '" ') . '<' . $_SETT['admin']['email'] . '>',
                                   'Fw: ' . $sSubject,
                                   lovd_wrapText($sBody),
                                   $_SETT['headers'] . $sEol .
                                   'Reply-To: ' . $sSubmitter);

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

                // Thank the user...
                header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . lovd_cleanDirName(dirname($_SERVER['PHP_SELF']) . '/' . ROOT_PATH) . 'account_update.php' . lovd_showSID());

                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('submitters_register', 'LOVD - Register as new submitter');
                print('      Your account has successfully been created!<BR>' . "\n" .
                      '      We\'ve sent you an email containing your account information.<BR><BR>' . "\n\n");

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

                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('submitters_register', 'LOVD - Register as new submitter');
                print('      Your account has successfully been created!<BR>' . "\n" .
                      '      Due to an error, we couldn\'t send you an email containing your account information. Our apologies for the inconvenience.<BR><BR>' . "\n\n");
            }

            // Log user in.
            $_SESSION['subs'] = mysql_fetch_assoc(mysql_query('SELECT * FROM ' . TABLE_SUBS . ' WHERE username = "' . $_POST['username'] . '" AND password = "' . $_POST['password'] . '"'));

            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('submitters_register', 'LOVD - Register as new submitter');

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

    lovd_showInfoTable('Please note that you do <B>NOT</B> need to register to view the data available at these pages. You only need an account for submitting new variants.', 'warning');

    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),
                    'skip',
                    array('', 'submit', 'Create submitter account'),
                  );
    $_MODULES->processForm('SubmittersRegister', $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=public_list' . lovd_showSID(true));
    exit;
}
?>
