<commit_before><?php

require_once "db.php";
require_once "util.php";
require_once "mtgox_api.php";

function random_voucher_string($len)
{
    $voucher_chars_str = VOUCHER_CHARS;
    $voucher_chars_length = strlen(VOUCHER_CHARS);

    if (@is_readable('/dev/urandom')) {
        $fp = fopen('/dev/urandom', 'r');
        $urandom = fread($fp, $len);
        fclose($fp);
    }

    $return='';

    for ($i = 0; $i < $len; $i++) {
        if (!isset($urandom)) {
            echo "no urandom?\n";
            if ($i % 2 == 0)
                mt_srand(time() % 2147 * 1000000 + (double)microtime() * 1000000);
            $rand = mt_rand() % $voucher_chars_length;
        } else
            $rand = ord($urandom[$i]) % $voucher_chars_length;

        $return .= $voucher_chars_str[$rand];
    }

    return $return;
}

function voucher_code_prefix($code)
{
    $length = strlen(VOUCHER_PREFIX . "-BTC-XXXXX");

    return substr($code, 0, $length);
}

function encrypt_voucher_code($code, $salt)
{
    $hash = hash('sha256', $salt . $code);
    return $hash;
}

function voucher_code_exists($code)
{
    $prefix = voucher_code_prefix($code);

    $query = "
        SELECT reqid, redeem_reqid, salt, hash, uid, amount, curr_type, status
        FROM voucher_requests
        JOIN requests
        USING(reqid)
        WHERE prefix = '$prefix'
    ";

    $result = do_query($query);

    usleep(rand(1e6, 2e6)); // don't give any timing clues as to whether that's a valid prefix; be too slow to brute-force

    while ($row = mysql_fetch_array($result))
        if (encrypt_voucher_code($code, $row['salt']) == $row['hash'])
            return $row;

    return false;
}

function check_voucher_code($code)
{
    $from = array();
    $to = array();
    foreach (explode(',', VOUCHER_REPLACE) as $pair) {
        array_push($from, $pair[0]);
        array_push($to  , $pair[1]);
    }

    if (VOUCHER_FORCE_UPPERCASE)
        $code = strtoupper($code);
    $code = str_replace($from, $to, $code);

    $row = voucher_code_exists($code);
    if (!$row)
        throw new Exception(_("no such voucher exists"));

    $reqid = $row['reqid'];
    $redeem_reqid = $row['redeem_reqid'];
    $uid = $row['uid'];
    $amount = $row['amount'];
    $curr_type = $row['curr_type'];
    $status = $row['status'];

    // echo "reqid: '$reqid'; redeem_reqid: '$redeem_reqid'; uid: $uid; amount: $amount; curr_type: $curr_type; status: $status<br/>\n";

    if ($redeem_reqid)
        throw new Exception(_("this voucher has already been redeemed"));

    if ($status == 'CANCEL')
        throw new Exception(_("this voucher has been cancelled by the user who issued it"));

    if ($status != 'VERIFY')
        throw new Exception(_("coding error; voucher wasn't redeemed or cancelled, but isn't in state 'VERIFY'"));

    return array($reqid, $uid, $amount, $curr_type);
}

function random_voucher_salt()
{
    return random_voucher_string(5);
}

function store_new_voucher_code($reqid, $type)
{
    // $nonce = 0;

    do {
        $code = sprintf("%s-%s-%s-%s-%s-%s",
                        VOUCHER_PREFIX,
                        $type,
                        random_voucher_string(5),
                        random_voucher_string(5),
                        random_voucher_string(5),
                        random_voucher_string(5));<commit_msg>Use new 'random_string() code to generate voucher strings.<commit_after><?php

require_once "db.php";
require_once "util.php";
require_once "mtgox_api.php";

function random_voucher_string($length_per_block, $num_blocks = 1)
{
    return random_string($length_per_block, $num_blocks, VOUCHER_CHARS);
}

function voucher_code_prefix($code)
{
    $length = strlen(VOUCHER_PREFIX . "-BTC-XXXXX");

    return substr($code, 0, $length);
}

function encrypt_voucher_code($code, $salt)
{
    $hash = hash('sha256', $salt . $code);
    return $hash;
}

function voucher_code_exists($code)
{
    $prefix = voucher_code_prefix($code);

    $query = "
        SELECT reqid, redeem_reqid, salt, hash, uid, amount, curr_type, status
        FROM voucher_requests
        JOIN requests
        USING(reqid)
        WHERE prefix = '$prefix'
    ";

    $result = do_query($query);

    usleep(rand(1e6, 2e6)); // don't give any timing clues as to whether that's a valid prefix; be too slow to brute-force

    while ($row = mysql_fetch_array($result))
        if (encrypt_voucher_code($code, $row['salt']) == $row['hash'])
            return $row;

    return false;
}

function check_voucher_code($code)
{
    $from = array();
    $to = array();
    foreach (explode(',', VOUCHER_REPLACE) as $pair) {
        array_push($from, $pair[0]);
        array_push($to  , $pair[1]);
    }

    if (VOUCHER_FORCE_UPPERCASE)
        $code = strtoupper($code);
    $code = str_replace($from, $to, $code);

    $row = voucher_code_exists($code);
    if (!$row)
        throw new Exception(_("no such voucher exists"));

    $reqid = $row['reqid'];
    $redeem_reqid = $row['redeem_reqid'];
    $uid = $row['uid'];
    $amount = $row['amount'];
    $curr_type = $row['curr_type'];
    $status = $row['status'];

    // echo "reqid: '$reqid'; redeem_reqid: '$redeem_reqid'; uid: $uid; amount: $amount; curr_type: $curr_type; status: $status<br/>\n";

    if ($redeem_reqid)
        throw new Exception(_("this voucher has already been redeemed"));

    if ($status == 'CANCEL')
        throw new Exception(_("this voucher has been cancelled by the user who issued it"));

    if ($status != 'VERIFY')
        throw new Exception(_("coding error; voucher wasn't redeemed or cancelled, but isn't in state 'VERIFY'"));

    return array($reqid, $uid, $amount, $curr_type);
}

function random_voucher_salt()
{
    return random_string(5);
}

function store_new_voucher_code($reqid, $type)
{
    // $nonce = 0;

    do {
        $code = sprintf("%s-%s-%s",
                        VOUCHER_PREFIX,
                        $type,
                        random_voucher_string(5, 4));
{'fraction_non_alphanumeric': 0.15389751293607076, 'fraction_numerical': 0.008679686195960608, 'mean_word_length': 2.845956354300385, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4278972', 'n_tokens_mistral': 2165, 'n_tokens_neox': 2034, 'n_words': 465}