Files
2023-08-03 08:10:45 -04:00

582 lines
14 KiB
PHP

<?php
/**
* economy.php
*
* Provides functions required only by currency.php and landtool.php
*
* Requires an OpenSimulator Money Server
* [DTL/NSL Money Server for OpenSim](http://www.nsl.tuis.ac.jp/xoops/modules/xpwiki/?OpenSim%2FMoneyServer)
* or [Gloebit module](http://dev.gloebit.com/opensim/configuration-instructions/)
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*
* Includes portions of code from original DTLS/NLS Money Server, by:
* Melanie Thielker and Teravus Ovares (http://opensimulator.org/)
* Fumi.Iseki for CMS/LMS '09 5/31
**/
require_once 'functions.php';
if ( defined( 'CURRENCY_DB_HOST' ) ) {
$CurrencyDB = new OSPDO( 'mysql:host=' . CURRENCY_DB_HOST . ';dbname=' . CURRENCY_DB_NAME, CURRENCY_DB_USER, CURRENCY_DB_PASS );
} else {
$CurrencyDB = &$OpenSimDB;
}
function noserver_save_transaction( $sourceId, $destId, $amount, $type, $flags, $desc, $prminvent, $nxtowner, $ip ) {
global $CurrencyDB;
if ( ! is_numeric( $amount ) ) {
return;
}
if ( ! opensim_isuuid( $sourceId ) ) {
$sourceId = NULL_KEY;
}
if ( ! opensim_isuuid( $destId ) ) {
$destId = NULL_KEY;
}
$region = NULL_KEY;
$client = $sourceId;
if ( $client == NULL_KEY ) {
$client = $destId;
}
$avt = opensim_get_avatar_session( $client );
if ( $avt != null ) {
$region = $avt['regionID'];
}
$CurrencyDB->insert(
CURRENCY_TRANSACTION_TBL,
array(
'sourceId' => $sourceId,
'destId' => $destId,
'amount' => $amount,
'flags' => $flags,
'aggregatePermInventory' => $prminvent,
'aggregatePermNextOwner' => $nxtowner,
'description' => $desc,
'transactionType' => $type,
'timeOccurred' => time(),
'RegionGenerated' => $region,
'ipGenerated' => $ip,
)
);
}
function noserver_get_balance( $agentID ) {
global $CurrencyDB;
if ( ! opensim_isuuid( $agentID ) ) {
return -1;
}
$sent_sum = 0;
$received_sum = 0;
$credits = $CurrencyDB->prepareAndExecute(
'SELECT SUM(amount) FROM ' . CURRENCY_TRANSACTION_TBL . ' WHERE destId = :destId',
array( 'destId' => $agentID )
);
if ( $credits ) {
list($received_sum) = $credits->fetch();
}
$debits = $CurrencyDB->prepareAndExecute(
'SELECT SUM(amount) FROM ' . CURRENCY_TRANSACTION_TBL . ' WHERE sourceId = :sourceId',
array( 'sourceId' => $agentID )
);
if ( $debits ) {
list($sent_sum) = $debits->fetch();
}
$cash = (int) $received_sum - (int) $sent_sum;
return $cash;
}
function currency_save_transaction( $sourceId, $destId, $amount, $type, $flags, $description, &$deprecated = null ) {
global $CurrencyDB;
if ( ! is_numeric( $amount ) ) {
return;
}
if ( ! opensim_isuuid( $sourceId ) ) {
$sourceId = NULL_KEY;
}
if ( ! opensim_isuuid( $destId ) ) {
$destId = NULL_KEY;
}
$handle = 0;
$secure = NULL_KEY;
$client = $sourceId;
$UUID = make_random_guid();
$sourceID = $sourceId;
$destID = $destId;
if ( $client == NULL_KEY ) {
$client = $destId;
}
$avt = opensim_get_avatar_session( $client );
if ( $avt != null ) {
$region = $avt['regionID'];
$secure = $avt['secureID'];
$rgn = opensim_get_region_info( $region );
if ( $rgn != null ) {
$handle = $rgn['regionHandle'];
}
}
$CurrencyDB->insert(
CURRENCY_TRANSACTION_TBL,
array(
'UUID' => $UUID,
'sender' => $sourceID,
'receiver' => $destID,
'amount' => $amount,
'objectUUID' => NULL_KEY,
'regionHandle' => $handle,
'type' => $type,
'time' => time(),
'secure' => $secure,
'status' => $flags,
'description' => $description,
)
);
}
function currency_set_currency_balance( $agentID, $amount, &$deprecated = null ) {
if ( ! opensim_isuuid( $agentID ) or ! is_numeric( $amount ) ) {
return false;
}
global $CurrencyDB;
$balances_table = CURRENCY_MONEY_TBL;
$CurrencyDB->query( "LOCK TABLES $balances_table" );
$currentbalance = $CurrencyDB->prepareAndExecute(
"SELECT balance FROM $balances_table WHERE user = :user",
array(
'user' => $agentID,
)
);
if ( $currentbalance ) {
list($cash) = $currentbalance->fetch();
$balance = (int) $cash + (int) $amount;
$result = $CurrencyDB->prepareAndExecute(
"UPDATE $balances_table SET balance = :balance WHERE user = :user",
array(
'balance' => $balance,
'user' => $agentID,
)
);
} else {
$result = false;
}
$CurrencyDB->query( "UNLOCK TABLES $balances_table" );
return $result;
}
function currency_update_simulator_balance( $agentID, $amount = -1, $secureID = null ) {
if ( ! opensim_isuuid( $agentID ) ) {
return false;
}
if ( $amount < 0 ) {
$amount = currency_get_balance( $agentID, $secureID );
if ( $amount < 0 ) {
return false;
}
}
// XML RPC to Region Server
if ( ! opensim_isuuid( $secureID, true ) ) {
return false;
}
$agentServer = opensim_get_server_info( $agentID );
if ( ! $agentServer ) {
return false;
}
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
$avatarSession = opensim_get_avatar_session( $agentID );
if ( ! $avatarSession ) {
return false;
}
$sessionID = $avatarSession['sessionID'];
if ( $secureID == null ) {
$secureID = $avatarSession['secureID'];
}
$request = xmlrpc_encode_request(
'UpdateBalance',
array(
array(
'clientUUID' => $agentID,
'clientSessionID' => $sessionID,
'clientSecureSessionID' => $secureID,
'Balance' => $amount,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
return $response;
}
function currency_move_money( $agentID, $destID, $amount, $type, $flags, $desc, $prminvent = 0, $nxtowner = 0, $ip = '' ) {
if ( ! CURRENCY_USE_MONEYSERVER ) {
noserver_save_transaction( $agentID, $destID, $amount, $type, $flags, $desc, $prminvent, $nxtowner, $ip );
return true;
}
// Direct DB access for security
// $url = preg_split("/[:\/]/", USER_SERVER_URI);
// $userip = $url[3];
currency_save_transaction( $agentID, $destID, $amount, $type, $flags, $desc );
// TODO: Shouldn't we execute both balance updates only if all of the four
// conditions are met and none of them if any of the checks fails?
if ( opensim_isuuid( $agentID ) and $agentID != NULL_KEY ) {
currency_set_currency_balance( $agentID, -$amount );
}
if ( opensim_isuuid( $destID ) and $destID != NULL_KEY ) {
currency_set_currency_balance( $destID, $amount );
}
return true;
}
function currency_add_money( $agentID, $amount, $secureID = null ) {
if ( ! opensim_isuuid( $agentID ) ) {
return false;
}
if ( ! CURRENCY_USE_MONEYSERVER ) {
noserver_save_transaction( null, $agentID, $amount, 5010, 0, 'Add Money', 0, 0, '' );
$response = array( 'success' => true );
return $response;
}
//
// XML RPC to Region Server
//
if ( ! opensim_isuuid( $secureID, true ) ) {
return false;
}
$agentServer = opensim_get_server_info( $agentID );
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
if ( $serverip == '' ) {
return false;
}
$avatarSession = opensim_get_avatar_session( $agentID );
$sessionID = $avatarSession['sessionID'];
// if ($sessionID=="") return false;
if ( $secureID == null ) {
$secureID = $avatarSession['secureID'];
}
$request = xmlrpc_encode_request(
'AddBankerMoney',
array(
array(
'clientUUID' => $agentID,
'clientSessionID' => $sessionID,
'clientSecureSessionID' => $secureID,
'amount' => $amount,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
return $response;
}
//
// Send the money to avatar for bonus
// by Milo
//
function currency_send_money( $agentID, $amount, $secretCode = null ) {
if ( ! opensim_isuuid( $agentID ) ) {
return false;
}
if ( ! CURRENCY_USE_MONEYSERVER ) {
noserver_save_transaction( null, $agentID, $amount, 5003, 0, 'Send Money', 0, 0, '' );
$response = array( 'success' => true );
return $response;
}
//
// XML RPC to Region Server
//
$agentServer = opensim_get_server_info( $agentID );
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
if ( $serverip == '' ) {
return false;
}
$serverip = gethostbyname( $serverip );
if ( $secretCode != null ) {
$secretCode = md5( $secretCode . '_' . $serverip );
} else {
$secretCode = currency_get_confirm_value( $serverip );
}
$request = xmlrpc_encode_request(
'SendMoneyBalance',
array(
array(
'clientUUID' => $agentID,
'secretAccessCode' => $secretCode,
'amount' => $amount,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
return $response;
}
function currency_get_balance( $agentID, $secureID = null ) {
$cash = -1;
if ( ! opensim_isuuid( $agentID ) ) {
return (int) $cash;
}
if ( ! CURRENCY_USE_MONEYSERVER ) {
$cash = noserver_get_balance( $agentID );
return (int) $cash;
}
if ( ! opensim_isuuid( $secureID, true ) ) {
return (int) $cash;
}
$agentServer = opensim_get_server_info( $agentID );
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
if ( $serverip == '' ) {
return (int) $cash;
}
$avatarSession = opensim_get_avatar_session( $agentID );
$sessionID = $avatarSession['sessionID'];
if ( $sessionID == '' ) {
return (int) $cash;
}
if ( $secureID == null ) {
$secureID = $avatarSession['secureID'];
}
$request = xmlrpc_encode_request(
'GetBalance',
array(
array(
'clientUUID' => $agentID,
'clientSessionID' => $sessionID,
'clientSecureSessionID' => $secureID,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
if ( $response ) {
$cash = $response['balance'];
}
return (int) $cash;
}
function currency_get_confirm_value( $ipAddress ) {
// TODO:
// Option to force key to be something else than default
$key = empty( CURRENCY_SCRIPT_KEY ) ? '1234567883789' : CURRENCY_SCRIPT_KEY;
$confirmvalue = md5( $key . '_' . $ipAddress );
return $confirmvalue;
}
function currency_process_transaction( $avatarID, $cost, $ipAddress ) {
// Do external processing here! (credit card, paypal, any money system)
// Return False if it fails!
// Remember, $amount is stored without decimal places, however it's assumed
// that the transaction amount is in Cents and has two decimal places
// 5 dollars will be 500
// 15 dollars will be 1500
// if ($avatarID==CURRENCY_BANKER) return true;
// return false;
return true;
}
function currency_virtual_to_real( $amount ) {
$cost = (int) ( CURRENCY_RATE / CURRENCY_RATE_PER * 100 * $amount );
return $cost;
}
// XML RPC
function currency_xmlrpc_call( $host, $port, $uri, $request ) {
$url = '';
if ( $uri != '' ) {
$dec = explode( ':', $uri );
if ( ! strncasecmp( $dec[0], 'http', 4 ) ) {
$url = "$dec[0]:$dec[1]";
}
}
if ( $url == '' ) {
$url = "http://$host";
}
$url = "$url:$port/";
// TODO: use file_get_contents() instead of over complicate curl procedure
$header[] = 'Content-type: text/xml';
$header[] = 'Content-length: ' . strlen( $request );
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_TIMEOUT, 3 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $header );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $request );
$data = curl_exec( $ch );
if ( ! curl_errno( $ch ) ) {
curl_close( $ch );
}
$ret = false;
if ( $data ) {
$ret = xmlrpc_decode( $data );
}
return $ret;
}
/**
* Following functions are not specific to money and could be useful in other
* helpers. However, they are not: they are currently only used in currency
* scripts, so I leave them here, hence the opensim_ prefix.
*/
function opensim_get_avatar_session( $agentID, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $agentID ) ) {
return null;
}
$result = $OpenSimDB->query( "SELECT RegionID,SessionID,SecureSessionID FROM Presence WHERE UserID='$agentID'" );
if ( $result ) {
list($RegionID, $SessionID, $SecureSessionID) = $result->fetch();
} else {
return array();
}
$av_session['regionID'] = $RegionID;
$av_session['sessionID'] = $SessionID;
$av_session['secureID'] = $SecureSessionID;
return $av_session;
}
function opensim_set_current_region( $agentID, $regionid, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $agentID ) or ! opensim_isuuid( $regionid ) ) {
return false;
}
$sql = "UPDATE Presence SET RegionID='$regionid' WHERE UserID='$agentID'";
$result = $OpenSimDB->query( $sql );
if ( ! $result ) {
return false;
}
return true;
}
function opensim_get_server_info( $userid, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $userid ) ) {
return array();
}
$result = $OpenSimDB->query(
"SELECT serverIP,serverHttpPort,serverURI,regionSecret
FROM GridUser INNER JOIN regions ON regions.uuid=GridUser.LastRegionID
WHERE GridUser.UserID='$userid'"
);
if ( $result ) {
list($serverip, $httpport, $serveruri, $secret) = $result->fetch();
} else {
return array();
}
$serverinfo['serverIP'] = $serverip;
$serverinfo['serverHttpPort'] = $httpport;
$serverinfo['serverURI'] = $serveruri;
$serverinfo['regionSecret'] = $secret;
return $serverinfo;
}
function opensim_check_secure_session( $agentID, $regionid, $secure, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $agentID ) or ! opensim_isuuid( $secure ) ) {
return false;
}
$sql = "SELECT UserID FROM Presence WHERE UserID='$agentID' AND SecureSessionID='$secure'";
if ( opensim_isuuid( $regionid ) ) {
$sql = $sql . " AND RegionID='$regionid'";
}
$result = $OpenSimDB->query( $sql );
if ( ! $result ) {
return false;
}
list($UUID) = $result->fetch();
if ( $UUID != $agentID ) {
return false;
}
return true;
}
function opensim_check_region_secret( $regionID, $secret, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $regionID ) ) {
return false;
}
$result = $OpenSimDB->prepareAndExecute(
'SELECT UUID FROM regions WHERE UUID=:uuid AND regionSecret=:regionSecret',
array(
'uuid' => $regionID,
'regionSecret' => $secret,
)
);
if ( $result ) {
list($UUID) = $result->fetch();
if ( $UUID == $regionID ) {
return true;
}
}
return false;
}