FLO-appStore/apps/Aterna-Love/include/db.inc.php
sairajzero bf43539e3d update
2018-08-19 22:06:29 +05:30

260 lines
8.5 KiB
PHP

<?
/*
TODO: add error codes
*/
if (!defined('SECURITY')) exit('404');
// return a database handle given user credentials
function get_dbh($setup) {
// setup database using user credentials stored in $setup
try {
$dbh = new PDO("mysql:host=" . $setup['DB_HOST'] . ";dbport=" . $setup['DB_PORT'] . ";dbname=" . $setup['DB_NAME'], $setup['DB_USER'], $setup['DB_PASS'], array(
PDO::ATTR_PERSISTENT => true
));
}
catch (PDOException $e) {
api_exit(JSON_ENCODE(array('error'=>"Error connecting to database.", 'success'=>0)));
}
return $dbh;
}
function check_user_info(&$array) {
$accepted_length = array(
'email' => 100,
'remail' => 100,
'name' => 20,
'rname' => 20,
'message' => 380
);
$missing = null;
$too_long = null;
// check if values are missing or too long
foreach ($array as $key=>$val) { if (!$val || $val == '') $missing[] = $key; }
foreach ($array as $key=>$val) { if (strlen($val) > $accepted_length[$key]) $too_long[] = $key; }
if ($missing || $too_long) api_exit(JSON_ENCODE(array('error'=>array(array('missing'=>$missing), array('too_long'=>$too_long)), 'success'=>0)));
// check for special chars
$string_to_check = array($array['name'], $array['email'], $array['message'], $array['rname'], $array['remail']);
check_chars($string_to_check);
// rebuild array and set values
$array['name'] = $string_to_check[0];
$array['email'] = $string_to_check[1];
$array['message'] = $string_to_check[2];
$array['rname'] = $string_to_check[3];
$array['remail'] = $string_to_check[4];
}
// check array of strings for invalid chars, replace with another char
function check_chars(&$array) {
$string_to_check = array($name, $rname, $message);
$strcheck = array('|', '>');
$strinto = ' ';
foreach ($strcheck as $check) {
foreach ($array as $key=>$val) { $array[$key] = str_replace($strcheck, $strinto, $val); }
}
}
// handle user first creating a message from the preliminary form
function write_love_row($dbh, $userinfo) {
// check userinfo for weird characters, empty strings, etc
check_user_info($userinfo);
extract($userinfo);
// replace special chars with harmless chars
// create unique token
$uniq = $email . $remail . $name . $rname . $message . microtime(true) . 'jklasjf((9@jkL@@2lllLLlLK@KJopPE))]]nnenenenq29@(928(@*@##89';
$secret= hash_hmac('sha256', $uniq, 0, 0);
try {
// check if user already began a love note
$q = $dbh->prepare("select count(*) from love where email = ? and (verified = 0 or done = 0 or confirmed = 0)");
$q->bindParam(1, $email, strlen($email), PDO::PARAM_STR);
if (!$q->execute()) { api_exit(JSON_ENCODE(array('error'=>"Sorry, we're experiencing technical difficulties. Please contact support@aterna.org (code# AL101-$secret)", 'success'=>0))); }
$resp = $q->fetchAll(PDO::FETCH_COLUMN, 0);
if ($resp[0] > 0) {api_exit(JSON_ENCODE(array('error'=>"Sorry $name, you've already begun a love note.", 'success'=>0)));}
// insert new user into database
$q = $dbh->prepare("insert into love (email, remail, name, rname, message, token) values (?, ?, ?, ?, ?, ?)");
$q->bindParam(1, $email, strlen($email), PDO::PARAM_STR);
$q->bindParam(2, $remail, strlen($remail), PDO::PARAM_STR);
$q->bindParam(3, $name, strlen($name), PDO::PARAM_STR);
$q->bindParam(4, $rname, strlen($rname), PDO::PARAM_STR);
$q->bindParam(5, $message, strlen($message), PDO::PARAM_STR);
$q->bindParam(6, $secret, strlen($secret), PDO::PARAM_STR);
if (!$q->execute()) { api_exit(JSON_ENCODE(array('error'=>"Sorry, we're experiencing technical difficulties. Please contact support@aterna.org (code# AL102-$secret)", 'success'=>0))); }
}
catch (PDOException $e) {
api_exit(JSON_ENCODE(array('error'=>"Sorry, we're experiencing technical difficulties. Please contact support@aterna.org (error code #AL103-$secret)", 'success'=>0)));
}
// success!
api_exit(JSON_ENCODE(array('error'=>0, 'success'=>1)));
}
// user has verified his email, set database into next state
function email_verify($dbh, $secret) {
$q = $dbh->prepare("update love set verified = 1 where token = ?");
$q->bindParam(1, $secret, strlen($secret), PDO::PARAM_STR);
if ($q->execute()) {
api_exit(JSON_ENCODE(array('error'=>0, 'success'=>1)));
}
else {
api_exit(JSON_ENCODE(array('error'=>"Sorry, we're experiencing technical difficulties. Please contact support@aterna.org (error code #AL200-$secret)", 'success'=>0)));
}
}
// check for an available transaction given account, address, and confirms
function check_available_transaction($r, $ACCOUNT, $ADDRESS, $confirms) {
// get unspent transactions
$unspent = $r->call('listunspent', $confirms);
$unspent_tx = null;
foreach ($unspent as $u) { $unspent_tx[] = $u['txid']; }
// list transactions under this account
$listtx = $r->call('listtransactions', $ACCOUNT);
$listtx_tx = null;
foreach ($listtx as $l) { $listtx_tx[] = $l['txid']; }
// find a transaction we can use that's unspent
$unspent_final = array_intersect($unspent_tx, $listtx_tx);
if (count($unspent_final) == 0) {
// check mempool for transactions
$mempool = $r->call('getrawmempool');
$unspent_final_mempool = array_intersect($mempool, $listtx_tx);
if (count($unspent_final_mempool) > 0) exit("* * * WARNING: our last transaction is still in the mempool\n");
else{exit("***** FATAL ERROR: We have NO UNSPENT TRANSACTIONS. HUGE PROBLEM\n");}
}
$txid = null;
foreach ($unspent_final as $key=>$tx) { if (strlen($tx) == 64) $txid = $tx; }
return $txid;
}
// write transaction
function write_transaction_with_message($txid, $message, $r, $ADDRESS) {
$rawtx_encoded = $r->call('getrawtransaction', $txid);
$rawtx = $r->call('decoderawtransaction', $rawtx_encoded);
// make sure the last transaction id has an output to this user
$vouts = $rawtx['vout'];
foreach ($vouts as $vout) {
if ($vout['scriptPubKey']['addresses'][0] === $ADDRESS) {
$coins = $vout['value'];
$n = $vout['n'];
}
}
//echo "^^ found coins: $coins\n";
//echo "^^ found vout: $n\n";
// TODO: ADD A CONDITION THAT ENSURES THIS IS THE *ONLY* OUTPUT (FOR PROTOCOL)
if (!isset($coins) || !isset($n)) {
exit("***** FATAL ERROR: couldn't find the coins or vout of previous transaction $txid\n");
}
/* at this point, there are few relevant vars:
$tx = transaction ID of the transaction we will use
$ADDRESS = address to send to
$TXCOMMENT = tx-comment */
// build json for createrawtransaction
$json1 = array(array( "txid"=>$txid, "vout"=>$n));
$json2 = array($ADDRESS=>$coins);
$args = array($json1, $json2, $message);
// send to rpc
$myrawtx = ($r->call('createrawtransaction', $args));
$signedtx = $r->call('signrawtransaction', $myrawtx);
$signedtx_hex = $signedtx['hex'];
$decodetx = $r->call('decoderawtransaction', $signedtx_hex);
$newtx = $r->call('sendrawtransaction', $signedtx_hex);
if (!$myrawtx || !$signedtx || !$signedtx_hex /*|| !$newtx*/) {
exit("***** FATAL ERROR: couldn't write transaction $txid to network\n");
}
echo "!! $newtx\n\n";
return($newtx);
}
function check_tx_confirms_rpc($dbh, $r, $txid) {
$q = $dbh->query("select block from tx where hash = '$txid' and inactive != 1");
$block = null;
if ($q) {
$z = $q->fetchAll(PDO::FETCH_COLUMN, 0);
if ($z[0]) {
$block= (int)$z[0];
}
}
$confirms = 0;
if ($block) {
$hash = $r->call('getblockhash', $block);
$block_array = $r->call('getblock', $hash);
$confirms = $block_array['confirmations'];
}
if ($confirms > 5) {
return true;
}
}
function email($to, $subject, $from, $body, $name = null, $rname = null, $message = null, $txid = null, $id = null) {
require_once("postmark.php");
$postmark = new Postmark("key",'support@aterna.org');
$result = $postmark->to($to)
->subject($subject)
->plain_message($body)
->send();
if($result === true) {
echo "## sent a message to $to from $from\n";
return true;
} //else echo "* * * WARNING: message to $to from $from failed (id# $id)\n";
}
function send_final_email($data) {
return email($data['remail'], "A love message from " . $data['name'] . " to " . $data['rname'], $data['email'], $body, $data['name'], $data['rname'], $data['message'], $data['txid'], $data['id']);
}
?>