Include slightly modified economy helper
Original by https://github.com/magicoli/opensim-helpers which may provide more functionality for other things
This commit is contained in:
64
helper/economy/addons/gloebit.php
Normal file
64
helper/economy/addons/gloebit.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Gloebit default configuration
|
||||
*
|
||||
* DO NOT EDIT THIS FILE. It will be replaced on next update.
|
||||
* Instead copy the 'define(...)' lines to config.php, before the addons include
|
||||
* command, and customize from there.
|
||||
*
|
||||
* @package magicoli/opensim-helpers
|
||||
* @author Gudule Lapointe <gudule@speculoos.world>
|
||||
* @link https://github.com/magicoli/opensim-helpers
|
||||
* @license AGPLv3
|
||||
*/
|
||||
|
||||
if ( CURRENCY_PROVIDER != 'gloebit' ) {
|
||||
die();
|
||||
}
|
||||
/**
|
||||
* Set to true to activate sandbox mode, during initial installation and tests.
|
||||
* Set to false once ready to go live.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
if ( ! defined( 'GLOEBIT_SANDBOX' ) ) {
|
||||
define( 'GLOEBIT_SANDBOX', false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gloebit currency conversion table
|
||||
*
|
||||
* Used to display a cost estimation when using the viewer Buy Currency feature.
|
||||
* Conversion rate between Gloebit amount and US$ cents. Must match the packages
|
||||
* and prices idsplayed on Gloebit website.
|
||||
* // TODO: fetch conversion values from Gloebit website.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
if ( ! defined( 'GLOEBIT_CONVERSION_TABLE' ) ) {
|
||||
define(
|
||||
'GLOEBIT_CONVERSION_TABLE',
|
||||
array(
|
||||
400 => 199,
|
||||
1050 => 499,
|
||||
2150 => 999,
|
||||
4500 => 1999,
|
||||
11500 => 4999,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Affects the suggested purchase amount. Gloebit only allow predifined amounts
|
||||
* to be purchased.
|
||||
* - Set threshold of 1.0 to switch to the next pack even for 1$G more
|
||||
* (e.g. if user request 401, suggest 1050)
|
||||
* - Set theshold to 1.1 or 1.2 to keep the low pack for small differences.
|
||||
* (e.g. if user request 401, still suggest 400)
|
||||
* The user can still choose another pack on the web purchase page.
|
||||
*
|
||||
* @GLOEBIT_CONVERSION_THRESHOLD float must be >= 1.0
|
||||
*/
|
||||
if ( ! defined( 'GLOEBIT_CONVERSION_THRESHOLD' ) ) {
|
||||
define( 'GLOEBIT_CONVERSION_THRESHOLD', 1.2 );
|
||||
}
|
||||
33
helper/economy/addons/podex.php
Normal file
33
helper/economy/addons/podex.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Podex default configuration file.
|
||||
*
|
||||
* DO NOT EDIT THIS FILE. It will be replaced on next update.
|
||||
* Instead copy the 'define(...)' lines to config.php, before the addons include
|
||||
* command, and customize from there.
|
||||
*
|
||||
* @package magicoli/opensim-helpers
|
||||
* @author Gudule Lapointe <gudule@speculoos.world>
|
||||
* @link https://github.com/magicoli/opensim-helpers
|
||||
* @license AGPLv3
|
||||
*/
|
||||
|
||||
if ( CURRENCY_PROVIDER != 'podex' ) {
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the message displayed to users when they use the viewer "Buy
|
||||
* currency" feature. Podex Buy and sell transactions are actually provided by
|
||||
* in-world terminals. Adjust the message and the url to instruct user to
|
||||
* teleport to the region providing Podex terminals.
|
||||
*
|
||||
* @var [type]
|
||||
*/
|
||||
if ( ! defined( 'PODEX_ERROR_MESSAGE' ) ) {
|
||||
define( 'PODEX_ERROR_MESSAGE', 'Please use our terminals in-world to proceed. Click OK to teleport to terminals region.' );
|
||||
}
|
||||
|
||||
if ( ! defined( 'PODEX_REDIRECT_URL' ) ) {
|
||||
define( 'PODEX_REDIRECT_URL', 'secondlife://Podex Exchange/128/128/21' );
|
||||
}
|
||||
382
helper/economy/currency.php
Normal file
382
helper/economy/currency.php
Normal file
@@ -0,0 +1,382 @@
|
||||
<?php
|
||||
/**
|
||||
* currency.php
|
||||
*
|
||||
* Provides web tools for OpenSim currencies
|
||||
*
|
||||
* 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
|
||||
* Melanie Thielker and Teravus Ovares (http://opensimulator.org/)
|
||||
* Fumi.Iseki for CMS/LMS '09 5/31
|
||||
*/
|
||||
|
||||
// error_reporting(E_ERROR | E_WARNING | E_PARSE);
|
||||
|
||||
require_once 'includes/config.php';
|
||||
require_once 'includes/economy.php';
|
||||
|
||||
//
|
||||
// The XMLRPC server object
|
||||
//
|
||||
$xmlrpc_server = xmlrpc_server_create();
|
||||
|
||||
//
|
||||
// Viewer retrieves currency buy quote
|
||||
//
|
||||
xmlrpc_server_register_method( $xmlrpc_server, 'getCurrencyQuote', 'currency_xmlrpc_quote' );
|
||||
function currency_xmlrpc_quote( $method_name, $params, $app_data ) {
|
||||
$req = $params[0];
|
||||
$agentid = $req['agentId'];
|
||||
$sessionid = $req['secureSessionId'];
|
||||
$amount = $req['currencyBuy'];
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
$ret = opensim_check_secure_session( $agentid, null, $sessionid );
|
||||
|
||||
if ( $ret ) {
|
||||
$confirmvalue = currency_get_confirm_value( $ipAddress );
|
||||
switch ( CURRENCY_PROVIDER ) {
|
||||
case 'gloebit':
|
||||
$cost = 1; // default cost if no table;
|
||||
$conversion_table = GLOEBIT_CONVERSION_TABLE;
|
||||
foreach ( $conversion_table as $key => $value ) {
|
||||
$cost = $value;
|
||||
if ( GLOEBIT_CONVERSION_THRESHOLD > 0 ) {
|
||||
$threshold = GLOEBIT_CONVERSION_THRESHOLD;
|
||||
} else {
|
||||
$threshold = 1;
|
||||
}
|
||||
if ( $key >= $amount / $threshold ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$cost = currency_virtual_to_real( $amount );
|
||||
$realamount = $amount;
|
||||
}
|
||||
|
||||
$currency = array(
|
||||
'estimatedCost' => $cost,
|
||||
'currencyBuy' => $realamount,
|
||||
);
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => true,
|
||||
'currency' => $currency,
|
||||
'confirm' => $confirmvalue,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "Unable to Authenticate\n\nClick URL for more info.",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
// Viewer buys currency
|
||||
//
|
||||
xmlrpc_server_register_method( $xmlrpc_server, 'buyCurrency', 'currency_xmlrpc_buy' );
|
||||
function currency_xmlrpc_buy( $method_name, $params, $app_data ) {
|
||||
$req = $params[0];
|
||||
$agentid = $req['agentId'];
|
||||
$sessionid = $req['secureSessionId'];
|
||||
$amount = $req['currencyBuy'];
|
||||
$confim = $req['confirm'];
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
if ( $confim != currency_get_confirm_value( $ipAddress ) ) {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "\n\nMissmatch Confirm Value!!",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
return '';
|
||||
}
|
||||
|
||||
$checkSecure = opensim_check_secure_session( $agentid, null, $sessionid );
|
||||
if ( ! $checkSecure ) {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "\n\nMissmatch Secure Session ID!!",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
return '';
|
||||
}
|
||||
|
||||
$ret = false;
|
||||
$cost = currency_virtual_to_real( $amount );
|
||||
$transactionPermit = currency_process_transaction( $agentid, $cost, $ipAddress );
|
||||
|
||||
if ( $transactionPermit ) {
|
||||
$res = currency_add_money( $agentid, $amount, $sessionid );
|
||||
if ( $res['success'] ) {
|
||||
$ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $ret ) {
|
||||
$response_xml = xmlrpc_encode( array( 'success' => true ) );
|
||||
} else {
|
||||
switch ( CURRENCY_PROVIDER ) {
|
||||
case 'podex':
|
||||
$errorURI = null; // opensim_format_tp(PODEX_REDIRECT_URL, TPLINK_HOP);
|
||||
$errorMessage = PODEX_ERROR_MESSAGE . ' ' . PODEX_REDIRECT_URL;
|
||||
break;
|
||||
|
||||
case 'gloebit':
|
||||
if ( defined( GLOEBIT_SANDBOX ) && GLOEBIT_SANDBOX ) {
|
||||
$baseurl = 'https://sandbox.gloebit.com/purchase';
|
||||
} else {
|
||||
$baseurl = 'https://www.gloebit.com/purchase';
|
||||
}
|
||||
$server_info = opensim_get_server_info( $agentid );
|
||||
$serverip = $server_info['serverIP'];
|
||||
$httpport = $server_info['serverHttpPort'];
|
||||
|
||||
$informurl = "http://${serverip}:${httpport}/gloebit/buy_complete?agentId=${agentid}";
|
||||
$errorURI = "${baseurl}?reset&r=&inform=$informurl";
|
||||
$errorMessage = 'Click OK to finish the transaction on Gloebit website.';
|
||||
break;
|
||||
|
||||
default:
|
||||
$errorMessage = 'Unable to process the transaction. The gateway denied your charge. Open help page?';
|
||||
$errorURI = empty( W4OS_GRID_INFO['help'] ) ? CURRENCY_HELPER_URL : W4OS_GRID_INFO['help'];
|
||||
}
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => $errorMessage,
|
||||
'errorURI' => $errorURI,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
// Region requests account balance
|
||||
//
|
||||
xmlrpc_server_register_method( $xmlrpc_server, 'simulatorUserBalanceRequest', 'currency_xmlrpc_balance' );
|
||||
function currency_xmlrpc_balance( $method_name, $params, $app_data ) {
|
||||
$req = $params[0];
|
||||
$agentid = $req['agentId'];
|
||||
$sessionid = $req['secureSessionId'];
|
||||
|
||||
$balance = currency_get_balance( $agentid, $sessionid );
|
||||
|
||||
if ( $balance >= 0 ) {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => true,
|
||||
'agentId' => $agentid,
|
||||
'funds' => $balance,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => 'Could not authenticate your avatar. Money operations may be unavailable',
|
||||
'errorURI' => ' ',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
// Region initiates money transfer (Direct DB Operation for security)
|
||||
//
|
||||
xmlrpc_server_register_method( $xmlrpc_server, 'regionMoveMoney', 'currency_xmlrpc_regionMoveMoney' );
|
||||
function currency_xmlrpc_regionMoveMoney( $method_name, $params, $app_data ) {
|
||||
$req = $params[0];
|
||||
$agentid = $req['agentId'];
|
||||
$destid = $req['destId'];
|
||||
$sessionid = $req['secureSessionId'];
|
||||
$regionid = $req['regionId'];
|
||||
$secret = $req['secret'];
|
||||
$currencySecret = $req['currencySecret'];
|
||||
$cash = $req['cash'];
|
||||
$aggregatePermInventory = $req['aggregatePermInventory'];
|
||||
$aggregatePermNextOwner = $req['aggregatePermNextOwner'];
|
||||
$flags = $req['flags'];
|
||||
$transactiontype = $req['transactionType'];
|
||||
$description = $req['description'];
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
$ret = opensim_check_region_secret( $regionid, $secret );
|
||||
|
||||
if ( $ret ) {
|
||||
$ret = opensim_check_secure_session( $agentid, $regionid, $sessionid );
|
||||
|
||||
if ( $ret ) {
|
||||
$balance = currency_get_balance( $agentid, $sessionid );
|
||||
if ( $balance >= $cash ) {
|
||||
currency_move_money(
|
||||
$agentid,
|
||||
$destid,
|
||||
$cash,
|
||||
$transactiontype,
|
||||
$flags,
|
||||
$description,
|
||||
$aggregatePermInventory,
|
||||
$aggregatePermNextOwner,
|
||||
$ipAddress
|
||||
);
|
||||
$sbalance = currency_get_balance( $agentid, $sessionid );
|
||||
$dbalance = currency_get_balance( $destid );
|
||||
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => true,
|
||||
'agentId' => $agentid,
|
||||
'funds' => $balance,
|
||||
'funds2' => $balance,
|
||||
'currencySecret' => ' ',
|
||||
)
|
||||
);
|
||||
|
||||
currency_update_simulator_balance( $agentid, $sbalance, $sessionid );
|
||||
currency_update_simulator_balance( $destid, $dbalance );
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => 'You do not have sufficient funds for this purchase',
|
||||
'errorURI' => ' ',
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => 'Unable to authenticate avatar. Money operations may be unavailable',
|
||||
'errorURI' => ' ',
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => 'This region is not authorized to manage your money.',
|
||||
'errorURI' => ' ',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
// Region claims user
|
||||
//
|
||||
xmlrpc_server_register_method( $xmlrpc_server, 'simulatorClaimUserRequest', 'currency_xmlrpc_claimUserRequest' );
|
||||
function currency_xmlrpc_claimUserRequest( $method_name, $params, $app_data ) {
|
||||
$req = $params[0];
|
||||
$agentid = $req['agentId'];
|
||||
$sessionid = $req['secureSessionId'];
|
||||
$regionid = $req['regionId'];
|
||||
$secret = $req['secret'];
|
||||
|
||||
$ret = opensim_check_region_secret( $regionid, $secret );
|
||||
|
||||
if ( $ret ) {
|
||||
$ret = opensim_check_secure_session( $agentid, null, $sessionid );
|
||||
|
||||
if ( $ret ) {
|
||||
$ret = opensim_set_current_region( $agentid, $regionid );
|
||||
|
||||
if ( $ret ) {
|
||||
$balance = currency_get_balance( $agentid, $sessionid );
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => true,
|
||||
'agentId' => $agentid,
|
||||
'funds' => $balance,
|
||||
'currencySecret' => ' ',
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => 'Error occurred, when DB was updated.',
|
||||
'errorURI' => ' ',
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => 'Unable to authenticate avatar. Money operations may be unavailable.',
|
||||
'errorURI' => ' ',
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => 'This region is not authorized to manage your money.',
|
||||
'errorURI' => ' ',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
// Process the request
|
||||
//
|
||||
$request_xml = file_get_contents( 'php://input' );
|
||||
// error_log(__FILE__ . ' '. $request_xml);
|
||||
|
||||
xmlrpc_server_call_method( $xmlrpc_server, $request_xml, '' );
|
||||
xmlrpc_server_destroy( $xmlrpc_server );
|
||||
die();
|
||||
82
helper/economy/includes/config.example.php
Normal file
82
helper/economy/includes/config.example.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* config.example.php
|
||||
*
|
||||
* Helpers configuration
|
||||
* Rename this file as "config.php" before editing.
|
||||
*
|
||||
* @package magicoli/opensim-helpers
|
||||
* @author Gudule Lapointe <gudule@speculoos.world>
|
||||
* @link https://github.com/magicoli/opensim-helpers
|
||||
* @license AGPLv3
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main database.
|
||||
* For grids, use Robust database credentials.
|
||||
* For standalone simulators, use OpenSim database credentials.
|
||||
*
|
||||
* Access to OpenSim database is required
|
||||
* - for search including classifieds
|
||||
* - for offline messages processing
|
||||
* - for economy
|
||||
* It is not required if only search is needed, without classifieds (e.g. to for
|
||||
* a multi-grid search engine). In this case search will only provide results
|
||||
* for places, land for sale and events.
|
||||
*/
|
||||
define( 'OPENSIM_DB', true ); // Set to false for search only, see above
|
||||
define( 'OPENSIM_DB_HOST', 'localhost' );
|
||||
define( 'OPENSIM_DB_NAME', 'opensim' );
|
||||
define( 'OPENSIM_DB_USER', 'opensim' );
|
||||
define( 'OPENSIM_DB_PASS', 'password' );
|
||||
define( 'SEARCH_TABLE_EVENTS', 'events' );
|
||||
|
||||
/**
|
||||
* Search database credentials and settings.
|
||||
* Needed if you enable search in OpenSim server.
|
||||
*
|
||||
* A dedicated database is:
|
||||
* - strongly recommended if the search engine is shared by several grids
|
||||
* - recommended and more efficient for large and/or hypergrid-enabled grids
|
||||
* - optional for closed grids and standalone simulators
|
||||
* These are recommendations, the Robust database can safely be used instead.
|
||||
*/
|
||||
define( 'SEARCH_DB_HOST', OPENSIM_DB_HOST );
|
||||
define( 'SEARCH_DB_NAME', OPENSIM_DB_NAME );
|
||||
define( 'SEARCH_DB_USER', OPENSIM_DB_USER );
|
||||
define( 'SEARCH_DB_PASS', OPENSIM_DB_PASS );
|
||||
|
||||
/**
|
||||
* Currency database credentials and settings.
|
||||
* Needed if currency is enabled on OpenSim server.
|
||||
* A dedicated database is recommended, but not mandatory.
|
||||
*/
|
||||
define( 'CURRENCY_DB_HOST', OPENSIM_DB_HOST );
|
||||
define( 'CURRENCY_DB_NAME', OPENSIM_DB_NAME );
|
||||
define( 'CURRENCY_DB_USER', OPENSIM_DB_USER );
|
||||
define( 'CURRENCY_DB_PASS', OPENSIM_DB_PASS );
|
||||
define( 'CURRENCY_MONEY_TBL', 'balances' );
|
||||
define( 'CURRENCY_TRANSACTION_TBL', 'transactions' );
|
||||
|
||||
/**
|
||||
* Money Server settings.
|
||||
*/
|
||||
define( 'CURRENCY_USE_MONEYSERVER', false );
|
||||
define( 'CURRENCY_SCRIPT_KEY', '123456789' );
|
||||
define( 'CURRENCY_RATE', 10 ); // amount in dollar...
|
||||
define( 'CURRENCY_RATE_PER', 1000 ); // ... for this amount in virtual currency
|
||||
define( 'CURRENCY_PROVIDER', null ); // NULL, 'podex' or 'gloebit'
|
||||
define( 'CURRENCY_HELPER_URL', 'http://yourgrid.org/helpers/' );
|
||||
// if (!defined('CURRENCY_HELPER_PATH')) define('CURRENCY_HELPER_PATH', dirname(__DIR__));
|
||||
|
||||
/**
|
||||
* DO NOT MAKE CHANGES BELOW THIS
|
||||
* Add your custom values above.
|
||||
*/
|
||||
require_once 'databases.php';
|
||||
require_once 'functions.php';
|
||||
|
||||
$currency_addon = dirname( __DIR__ ) . '/addons/' . CURRENCY_PROVIDER . '.php';
|
||||
if ( file_exists( $currency_addon ) ) {
|
||||
require_once $currency_addon;
|
||||
}
|
||||
98
helper/economy/includes/databases.php
Normal file
98
helper/economy/includes/databases.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* New database class using PDO, replaces DB class using mysqli
|
||||
*
|
||||
* @package magicoli/opensim-helpers
|
||||
* @author Gudule Lapointe <gudule@speculoos.world>
|
||||
* @link https://github.com/magicoli/opensim-helpers
|
||||
* @license AGPLv3
|
||||
*/
|
||||
|
||||
class OSPDO extends PDO {
|
||||
public function __construct( $dsn, $username = null, $password = null, $driver_options = null ) {
|
||||
try {
|
||||
@parent::__construct( $dsn, $username, $password, $driver_options );
|
||||
$this->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
|
||||
$this->connected = true;
|
||||
} catch ( PDOException $e ) {
|
||||
error_log( "Could not connect to database $dsn as $username" );
|
||||
// error_log($e);
|
||||
$this->connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare SQL query, execute with params and log error if any
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $options options passed to prepare()
|
||||
* @param array $params substitute markers passed to execute()
|
||||
* @return PDOstatement if success, false on error
|
||||
*/
|
||||
public function prepareAndExecute( $query, $params = null, $options = array() ) {
|
||||
$trace = debug_backtrace()[0];
|
||||
$trace = $trace['file'] . ':' . $trace['line'];
|
||||
|
||||
try {
|
||||
$statement = $this->prepare( $query, $options );
|
||||
$result = $statement->execute( $params );
|
||||
} catch ( PDOException $e ) {
|
||||
error_log( 'Error ' . $e->getCode() . ' ' . $e->getMessage() . ' query ' . print_r( $query, true ) . ' params ' . print_r( $params, true ) . ' ' . $trace );
|
||||
return false;
|
||||
}
|
||||
// $statement = $this->prepare( $query, $options );
|
||||
// $result = $statement->execute( $params );
|
||||
|
||||
if ( $result ) {
|
||||
return $statement;
|
||||
}
|
||||
|
||||
error_log( 'Error ' . $statement->errorCode() . ' ' . $statement->errorInfo()[2] . ' ' . $trace );
|
||||
return false;
|
||||
}
|
||||
|
||||
public function insert( $table, $values ) {
|
||||
foreach ( $values as $field => $value ) {
|
||||
$markers[] = ':' . $field;
|
||||
}
|
||||
$markers = implode( ',', $markers );
|
||||
$fields = implode( ',', array_keys( $values ) );
|
||||
$sql = "INSERT INTO $table ($fields) VALUES ($markers)";
|
||||
$statement = $this->prepare( $sql );
|
||||
return $statement->execute( $values );
|
||||
}
|
||||
}
|
||||
|
||||
function tableExists( $pdo, $tables ) {
|
||||
if ( ! is_object( $pdo ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( ! $pdo->connected ) {
|
||||
return false;
|
||||
}
|
||||
// error_log("pdo " . print_r($pdo, true));
|
||||
|
||||
if ( is_string( $tables ) ) {
|
||||
$tables = array( $tables );
|
||||
}
|
||||
foreach ( $tables as $table ) {
|
||||
// Try a select statement against the table
|
||||
// Run it in try/catch in case PDO is in ERRMODE_EXCEPTION.
|
||||
try {
|
||||
$result = $pdo->query( "SELECT 1 FROM $table LIMIT 1" );
|
||||
} catch ( Exception $e ) {
|
||||
error_log( __FILE__ . ': ' . SEARCH_DB_NAME . " is missing table $table" );
|
||||
// We got an exception == table not found
|
||||
return false;
|
||||
}
|
||||
if ( $result == false ) {
|
||||
error_log( __FILE__ . ': ' . SEARCH_DB_NAME . " is missing table $table" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( defined( 'OPENSIM_DB' ) && OPENSIM_DB === true ) {
|
||||
$OpenSimDB = new OSPDO( 'mysql:host=' . OPENSIM_DB_HOST . ';dbname=' . OPENSIM_DB_NAME, OPENSIM_DB_USER, OPENSIM_DB_PASS );
|
||||
}
|
||||
581
helper/economy/includes/economy.php
Normal file
581
helper/economy/includes/economy.php
Normal file
@@ -0,0 +1,581 @@
|
||||
<?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;
|
||||
}
|
||||
612
helper/economy/includes/functions.php
Normal file
612
helper/economy/includes/functions.php
Normal file
@@ -0,0 +1,612 @@
|
||||
<?php
|
||||
/**
|
||||
* economy.php
|
||||
*
|
||||
* Provides functions required by helpers
|
||||
*
|
||||
* @package magicoli/opensim-helpers
|
||||
* @author Gudule Lapointe <gudule@speculoos.world>
|
||||
* @link https://github.com/magicoli/opensim-helpers
|
||||
* @license AGPLv3
|
||||
*/
|
||||
|
||||
/**
|
||||
* Verify if given string is an UUID.
|
||||
* In theory, we would check want v4-compliant uuids
|
||||
* (xxxxxxxx-xxxx-4xxx-[89AB]xxx-xxxxxxxxxxxx) but OpenSimulator seems to have
|
||||
* lot of non v4-compliant uuids left, so stict defaults to false.
|
||||
*
|
||||
* @param [type] $uuid string to verify
|
||||
* @param boolean $nullok accept null value or null key as valid (default false)
|
||||
* @param boolean $strict apply strict UUID v4 implentation (default false)
|
||||
* @return boolean
|
||||
*/
|
||||
function opensim_isuuid( $uuid, $nullok = false, $strict = false ) {
|
||||
if ( $uuid == null ) {
|
||||
return $nullok;
|
||||
}
|
||||
if ( defined( 'NULL_KEY' ) && $uuid == NULL_KEY ) {
|
||||
return $nullok;
|
||||
}
|
||||
|
||||
if ( $strict ) {
|
||||
return ( preg_match( '/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i', $uuid ) );
|
||||
} else {
|
||||
return ( preg_match( '/^[0-9A-F]{8,8}-[0-9A-F]{4,4}-[0-9A-F]{4,4}-[0-9A-F]{4,4}-[0-9A-F]{12,12}$/i', $uuid ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a destination URI or URL
|
||||
*
|
||||
* @param string $url url or uri (secondlife:// url, hop:// url, region name...)
|
||||
* @param string $gatekeeperURL default login uri to add to urls sithout host:port
|
||||
* @param boolean $array_outout output as array
|
||||
* @return string (default) $host:$port $region/$pos
|
||||
* or array array($host, $port, $region, $pos)
|
||||
*/
|
||||
function opensim_sanitize_uri( $url, $gatekeeperURL = null, $array_outout = false ) {
|
||||
// $normalized = opensim_format_tp($uri, TPLINK_TXT);
|
||||
$host = null;
|
||||
$port = null;
|
||||
$region = null;
|
||||
$pos = null;
|
||||
$uri = urldecode( trim( $url ) );
|
||||
$uri = preg_replace( '#^(.*://)?(([A-Za-z0-9_-]+\.[A-Za-z0-9\._-]+)([:/ ]+)?)?(([0-9]+)([ /:]))?([^/]+)(/|$)(.*)#', '$3:$6:$8/$10', "$uri" );
|
||||
$uri = preg_replace( '/^([^:]+)::([0-9]+)/', '$1:$2', $uri );
|
||||
$uri = preg_replace( '+[:/]*$+', '', $uri );
|
||||
$split = explode( '/', $uri );
|
||||
$uri = array_shift( $split );
|
||||
if ( count( $split ) == 2 || count( $split ) == 3 ) {
|
||||
$pos = implode( '/', $split );
|
||||
} else {
|
||||
$pos = '';
|
||||
}
|
||||
// $pos = preg_replace('+[^0-9/]+e', '', $pos);
|
||||
$split = explode( ':', $uri );
|
||||
|
||||
if ( count( $split ) == 1 ) {
|
||||
$region = $split[0];
|
||||
} elseif ( count( $split ) == 2 && preg_match( '/ /', $split[1] ) ) {
|
||||
// could probably improve the preg_replace to avoid this
|
||||
$host = $split[0];
|
||||
$split = explode( ' ', $split[1] );
|
||||
$port = $split[0];
|
||||
$region = $split[1];
|
||||
} elseif ( preg_match( '/[a-z].*\.[a-z]/', $split[0] ) ) {
|
||||
$host = array_shift( $split );
|
||||
if ( preg_match( '/^[0-9]+$/', $split[0] ) ) {
|
||||
$port = array_shift( $split );
|
||||
} else {
|
||||
$port = 8002;
|
||||
}
|
||||
$region = preg_replace( ':^/*:', '', @$split[0] );
|
||||
} elseif ( function_exists( 'w4os_grid_login_uri' ) ) {
|
||||
$host = parse_url( w4os_grid_login_uri(), PHP_URL_HOST );
|
||||
$port = parse_url( w4os_grid_login_uri(), PHP_URL_HOST );
|
||||
if ( preg_match( '/^[0-9]+$/', $split[0] ) ) {
|
||||
array_shift( $split );
|
||||
}
|
||||
$region = preg_replace( ':^/*:', '', @$split[0] );
|
||||
} else {
|
||||
if ( empty( $gatekeeperURL ) ) {
|
||||
return false;
|
||||
}
|
||||
$region = $split[2];
|
||||
$split = explode( ':', preg_replace( '#.*://([^/]+)/?.*#', '$1', $gatekeeperURL ) );
|
||||
$host = $split[0];
|
||||
$port = $split[1];
|
||||
}
|
||||
if ( empty( $host ) & ! empty( $gatekeeperURL ) ) {
|
||||
$split = explode( ':', preg_replace( '#.*://([^/]+)/?.*#', '$1', $gatekeeperURL ) );
|
||||
$host = $split[0];
|
||||
$port = $split[1];
|
||||
}
|
||||
if ( empty( $port ) & ! empty( $host ) ) {
|
||||
$port = 80;
|
||||
}
|
||||
$host = strtolower( trim( $host ) );
|
||||
$region = trim( str_replace( '_', ' ', $region ) );
|
||||
if ( is_numeric( $region ) ) {
|
||||
$pos = "$region/$pos";
|
||||
$region = '';
|
||||
}
|
||||
if ( $array_outout ) {
|
||||
return array(
|
||||
'host' => $host,
|
||||
'port' => $port,
|
||||
'region' => $region,
|
||||
'pos' => $pos,
|
||||
'gatekeeper' => "http://$host:$port",
|
||||
'key' => strtolower( "$host:$port/$region" ),
|
||||
);
|
||||
} else {
|
||||
return trim(
|
||||
$host
|
||||
. ( empty( $port ) ? '' : ":$port" )
|
||||
. ( empty( $region ) ? '' : " $region" )
|
||||
. ( empty( $pos ) ? '' : "/$pos" ),
|
||||
":/ \n\r\t\v\x00"
|
||||
);
|
||||
}
|
||||
|
||||
// trim(string $string, string $characters = " \n\r\t\v\x00"): string
|
||||
// return preg_replace('#^[: ]*(.*)/*$#', '$1', "$host:$port $region" . ((empty($pos)) ? '' : "/$pos"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format destination uri as a valid local or hypergrid link url
|
||||
*
|
||||
* @param string $uri Destination uri, as "host:port:Region Name" or already formatted URL
|
||||
* @param integer $format The desired format as binary flags. Several values can be specified with an addition
|
||||
* e.g. TPLINK_V3HG + TPLINK_APPTP
|
||||
* TPLINK_LOCAL or 1: secondlife://Region Name/x/y/z
|
||||
* TPLINK_HG or 2: original HG format (obsolete?)
|
||||
* TPLINK_V3HG or 4: v3 HG format (Singularity)
|
||||
* TPLINK_HOP or 8: hop:// format (FireStorm)
|
||||
* TPLINK_TXT or 16: host:port Region Name
|
||||
* TPLINK_APPTP or 32: secondlife:///app/teleport link
|
||||
* TPLINK_MAP or 64: (not implemented)
|
||||
* 127: output all formats
|
||||
* @param string $sep Separator for multiple formats, default new line
|
||||
* @return string
|
||||
*/
|
||||
function opensim_format_tp( $uri, $format = TPLINK, $sep = "\n" ) {
|
||||
if ( empty( $uri ) ) {
|
||||
return;
|
||||
}
|
||||
$parts = parse_url( $uri );
|
||||
|
||||
// $uri = preg_replace('#!#', '', $uri);
|
||||
// $uri = preg_replace('#.*://+#', '', $uri);
|
||||
// $uri = preg_replace('#[\|:]#', '/', $uri);
|
||||
// $uri = preg_replace('#^([^/]+)/([0-9]+)/#', '$1:$2/', $uri);
|
||||
// $uri = preg_replace('#^[[:blank:]]*#', '', $uri);
|
||||
// echo "$uri ";
|
||||
// // $uri = preg_replace('#(\d{4}):#', '$1/', $uri);
|
||||
// $parts = explode("/", $uri);
|
||||
// $loginuri = array_shift($parts);
|
||||
// $hostparts = explode(":", $loginuri);
|
||||
// $host = $hostparts[0];
|
||||
// $port = (empty($hostparts[1])) ? 80 : $hostparts[1];
|
||||
// $region = urldecode(array_shift($parts));
|
||||
// $pos="";
|
||||
// if(count($parts) >=3 && is_numeric($parts[0]) && is_numeric($parts[1]) && is_numeric($parts[2]) ) {
|
||||
// $posparts = array($parts[0],$parts[1],$parts[2]);
|
||||
// $pos = join('/', $posparts);
|
||||
// $pos_sl = ($parts[0]>=256 || $parts[0]>=256) ? "" : $pos;
|
||||
// }
|
||||
$uri_parts = opensim_sanitize_uri( $uri, '', true );
|
||||
extract( $uri_parts );
|
||||
|
||||
$regionencoded = urlencode( $region );
|
||||
$region_hop = str_replace( ' ', '%20', $region );
|
||||
$pos_mandatory = ( empty( $pos ) ) ? '128/128/25' : $pos;
|
||||
$links = array();
|
||||
if ( $format & TPLINK_TXT ) {
|
||||
$links[ TPLINK_TXT ] = "$host:$port $region/$pos";
|
||||
}
|
||||
if ( $format & TPLINK_LOCAL || ( $format & TPLINK_HG && empty( $host ) ) ) {
|
||||
$links[ TPLINK_LOCAL ] = "secondlife://$region/$pos";
|
||||
}
|
||||
if ( $format & TPLINK_HG ) {
|
||||
$links[ TPLINK_HG ] = "secondlife://$host:$port $region/$pos";
|
||||
}
|
||||
if ( $format & TPLINK_V3HG ) {
|
||||
$links[ TPLINK_V3HG ] = "secondlife://http|!!$host|$port+$region";
|
||||
}
|
||||
if ( $format & TPLINK_HOP ) {
|
||||
$links[ TPLINK_HOP ] = "hop://$host:$port/$region_hop" . ( empty( $pos ) ? '' : "/$pos" );
|
||||
}
|
||||
if ( $format & TPLINK_APPTP ) {
|
||||
$links[ TPLINK_APPTP ] = "secondlife:///app/teleport/$host:$port+$regionencoded/" . ( ( ! empty( $pos_sl ) ) ? "$pos_sl/" : '' );
|
||||
}
|
||||
// if ($format & TPLINK_MAP) $links[TPLINK_MAP] = "secondlife:///app/map/$host:$port+$regionencoded/$pos";
|
||||
$links = preg_replace( '#^[^[:alnum:]]*|[^[:alnum:]]+$#', '', $links );
|
||||
|
||||
return join( $sep, $links );
|
||||
}
|
||||
|
||||
/**
|
||||
* Use xmlrpc link_region method to request link_region data from robust
|
||||
*
|
||||
* @param mixed $args region uri or sanitized region array
|
||||
* @param string $var output a single variable value
|
||||
* @return array (or string if var specified)
|
||||
*/
|
||||
function opensim_link_region( $args, $var = null ) {
|
||||
if ( empty( $args ) ) {
|
||||
return array();
|
||||
}
|
||||
global $OSSEARCH_CACHE;
|
||||
|
||||
if ( is_array( $args ) ) {
|
||||
$region_array = $args;
|
||||
} else {
|
||||
$region_array = opensim_sanitize_uri( $args, '', true );
|
||||
}
|
||||
extract( $region_array ); // $host, $port, $region, $pos, $gatekeeper, $key
|
||||
|
||||
if ( isset( $OSSEARCH_CACHE['link_region'][ $key ] ) ) {
|
||||
$link_region = $OSSEARCH_CACHE['link_region'][ $key ];
|
||||
} else {
|
||||
$link_region = oxXmlRequest( $gatekeeper, 'link_region', array( 'region_name' => "$region" ) );
|
||||
$OSSEARCH_CACHE['link_region'][ $key ] = $link_region;
|
||||
}
|
||||
|
||||
if ( $link_region ) {
|
||||
if ( $var ) {
|
||||
return $link_region[ $var ];
|
||||
} else {
|
||||
return $link_region;
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build region URL from array
|
||||
*
|
||||
* @param array $region sanitized region array
|
||||
* @return string
|
||||
*/
|
||||
function opensim_region_url( $region ) {
|
||||
if ( ! is_array( $region ) ) {
|
||||
return false;
|
||||
}
|
||||
return $region['gatekeeper'] . ( empty( $region['region'] ) ? '' : ':' . $region['region'] ) . ( empty( $region['pos'] ) ? '' : '/' . $region['pos'] );
|
||||
}
|
||||
|
||||
function opensim_get_region( $region_uri, $var = null ) {
|
||||
if ( empty( $region_uri ) ) {
|
||||
return array();
|
||||
}
|
||||
global $OSSEARCH_CACHE;
|
||||
$region = opensim_sanitize_uri( $region_uri, '', true );
|
||||
|
||||
$gatekeeper = $region['gatekeeper'];
|
||||
|
||||
$link_region = opensim_link_region( $region );
|
||||
|
||||
$uuid = @$link_region['uuid'];
|
||||
if ( ! opensim_isuuid( $uuid ) ) {
|
||||
// error_log( "opensim_get_region $region_uri invalid uuid $uuid" );
|
||||
return array();
|
||||
}
|
||||
|
||||
if ( isset( $OSSEARCH_CACHE['get_region'][ $uuid ] ) ) {
|
||||
$get_region = $OSSEARCH_CACHE['get_region'][ $uuid ];
|
||||
} else {
|
||||
$get_region = oxXmlRequest( $gatekeeper, 'get_region', array( 'region_uuid' => "$uuid" ) );
|
||||
// $get_region = oxXmlRequest('http://dev.w4os.org:8402/grid', 'get_region_by_name', ['scopeid' => NULL_KEY,'name'=>"$region"]);
|
||||
$OSSEARCH_CACHE['get_region'][ $uuid ] = $get_region;
|
||||
}
|
||||
$get_region['link_region'] = $link_region;
|
||||
|
||||
if ( $get_region ) {
|
||||
if ( $var ) {
|
||||
return $get_region[ $var ];
|
||||
} else {
|
||||
return $get_region;
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if region is online
|
||||
*
|
||||
* @param mixed $region region uri or sanitized region array
|
||||
* @return boolean true if online
|
||||
*/
|
||||
function opensim_region_is_online( $region ) {
|
||||
$data = opensim_link_region( $region );
|
||||
return ( $data && $data['result'] == 'True' );
|
||||
}
|
||||
|
||||
function opensim_user_alert( $agentID, $message, $secureID = null ) {
|
||||
$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(
|
||||
'UserAlert',
|
||||
array(
|
||||
array(
|
||||
'clientUUID' => $agentID,
|
||||
'clientSessionID' => $sessionID,
|
||||
'clientSecureSessionID' => $secureID,
|
||||
'Description' => $message,
|
||||
),
|
||||
)
|
||||
);
|
||||
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruti, $request );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* [oxXmlRequest description]
|
||||
*
|
||||
* @param string $gatekeeper [description]
|
||||
* @param string $method [description]
|
||||
* @param array $request [description]
|
||||
* @return array received xml response
|
||||
*/
|
||||
function oxXmlRequest( $gatekeeper, $method, $request ) {
|
||||
$xml_request = xmlrpc_encode_request( $method, array( $request ) );
|
||||
|
||||
$context = stream_context_create(
|
||||
array(
|
||||
'http' => array(
|
||||
'method' => 'POST',
|
||||
'header' => 'Content-Type: text/xml' . "\r\n",
|
||||
'timeout' => 3, // most of the time below 1 sec, but leave some time for slow ones
|
||||
'content' => $xml_request,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$response = @file_get_contents( $gatekeeper, false, $context );
|
||||
if ( $response === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$xml_array = xmlrpc_decode( $response );
|
||||
if ( empty( $xml_array ) ) {
|
||||
return;
|
||||
}
|
||||
if ( is_array( $xml_array ) & ! xmlrpc_is_fault( $xml_array ) ) {
|
||||
return $xml_array;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function osXmlResponse( $success = true, $errorMessage = false, $data = false ) {
|
||||
global $request_key;
|
||||
|
||||
// Data given, output as xmlrpc
|
||||
if ( is_array( $data ) ) {
|
||||
if( ! $success && ! empty( $errorMessage ) ) {
|
||||
# Avoid duplicate error messages
|
||||
# TODO: improve to make sure we don't cache error messages for different requests
|
||||
# (currently $request_key only identifies search arguments, client IP and gateway url,
|
||||
# but client IP is the simulator, not the actual user, so in theory, the key could
|
||||
# be identical for two simultaneous requests by different users in the same region,
|
||||
# although this is unlikely to happen)
|
||||
|
||||
$tmp_dir = get_writable_tmp_dir();
|
||||
$cache = $tmp_dir . '/cache-' . $request_key;
|
||||
# Check if file exists and is not older than 5 seconds
|
||||
if ( file_exists( $cache ) && ( time() - filemtime( $cache ) < 1.5 ) ) {
|
||||
$errorMessage = '';
|
||||
} else {
|
||||
file_put_contents( $cache, $errorMessage );
|
||||
}
|
||||
}
|
||||
|
||||
$array = array(
|
||||
'success' => $success,
|
||||
'errorMessage' => $errorMessage,
|
||||
'data' => $data,
|
||||
);
|
||||
|
||||
$response_xml = xmlrpc_encode( $array );
|
||||
|
||||
echo $response_xml;
|
||||
return;
|
||||
}
|
||||
|
||||
// No data given, output simple boolean or error message, no change here
|
||||
if ( $success ) {
|
||||
$answer = new SimpleXMLElement( '<boolean>true</boolean>' );
|
||||
} else {
|
||||
$answer = new SimpleXMLElement( "<error>$errorMessage</error>" );
|
||||
}
|
||||
echo $answer->asXML();
|
||||
}
|
||||
|
||||
function osXmlDie( $message = '' ) {
|
||||
osXmlResponse( false, $message, array() );
|
||||
die;
|
||||
}
|
||||
|
||||
function osNotice( $message ) {
|
||||
echo $message . "\n";
|
||||
}
|
||||
|
||||
function osAdminNotice( $message, $error_code = 0, $die = false ) {
|
||||
// get calling function and file
|
||||
$trace = debug_backtrace();
|
||||
|
||||
if ( isset( $trace[1] ) ) {
|
||||
$caller = $trace[1];
|
||||
} else {
|
||||
$caller = $trace[0];
|
||||
}
|
||||
$file = empty( $caller['file'] ) ? '' : $caller['file'];
|
||||
$function = $caller['function'] . '()' ?? 'main';
|
||||
$line = $caller['line'] ?? 0;
|
||||
$class = $caller['class'] ?? 'main';
|
||||
$type = $caller['type'] ?? '::';
|
||||
if ( $class != 'main' ) {
|
||||
$function = $class . $type . $function;
|
||||
}
|
||||
$file = $file . ':' . $line;
|
||||
$message = sprintf(
|
||||
'%s%s: %s in %s',
|
||||
$function,
|
||||
empty( $error_code ) ? '' : " Error $error_code",
|
||||
$message,
|
||||
$file,
|
||||
);
|
||||
error_log( $message );
|
||||
if ( $die == true ) {
|
||||
die( $error_code );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush output and free client so following commands are executed in background
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function dontWait() {
|
||||
$size = ob_get_length();
|
||||
|
||||
header( "Content-Length:$size" );
|
||||
header( 'Connection:close' );
|
||||
header( 'Content-Encoding: none' );
|
||||
header( 'Content-Type: text/html; charset=utf-8' );
|
||||
|
||||
ob_flush();
|
||||
ob_end_flush();
|
||||
flush();
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'osdebug' ) ) {
|
||||
function osdebug( $message = '' ) {
|
||||
if ( empty( $message ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! is_string( $message ) ) {
|
||||
$message = print_r( $message, true );
|
||||
}
|
||||
error_log( 'osdebug ' . $message );
|
||||
echo $message . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
function set_helpers_locale( $locale = null, $domain = 'messages' ) {
|
||||
mb_internal_encoding( 'UTF-8' );
|
||||
$encoding = mb_internal_encoding();
|
||||
|
||||
if ( isset( $_GET['l'] ) ) {
|
||||
$locale = $_GET['l'];
|
||||
}
|
||||
$languages = array_filter( array_merge( array( $locale ), explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) );
|
||||
|
||||
// $results = putenv("LC_ALL=$locale");
|
||||
// if (!$results) {
|
||||
// exit ('putenv failed');
|
||||
// }
|
||||
|
||||
// $currentLocale = setlocale(LC_ALL, 0);
|
||||
$user_locales = array_unique( array( $locale, $locale . ".$encoding", $locale . '.UTF-8', $locale . '.utf8', $locale, 0 ) );
|
||||
|
||||
$user_locales = array_map(
|
||||
function ( $code ) {
|
||||
return preg_replace(
|
||||
array( '/;.*/', '/-/' ),
|
||||
array( '', '_' ),
|
||||
$code
|
||||
);
|
||||
},
|
||||
$languages
|
||||
);
|
||||
|
||||
// Generate variants with different encodings appended
|
||||
$variants = array();
|
||||
foreach ( $user_locales as $lang ) {
|
||||
$variants[] = $lang;
|
||||
$variants[] = "$lang.$encoding";
|
||||
// $variants[] = "$lang.UTF-8";
|
||||
}
|
||||
|
||||
$variants = array_unique( $variants );
|
||||
if ( ! setlocale( LC_ALL, $variants ) ) {
|
||||
// error_log( "setlocale() failed: none of '" . join( ', ', $variants ) . "' does exist in this environment or setlocale() is not available on this platform" );
|
||||
setlocale( LC_ALL, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
bindtextdomain( $domain, './locales' );
|
||||
textdomain( $domain );
|
||||
}
|
||||
|
||||
function get_writable_tmp_dir() {
|
||||
if(isset($_GLOBALS['tmp_dir'])) {
|
||||
return $_GLOBALS['tmp_dir'];
|
||||
}
|
||||
$dirs = array( sys_get_temp_dir(), ini_get('upload_tmp_dir'), '/tmp', '/var/tmp', '/usr/tmp', '.' );
|
||||
foreach ( $dirs as $dir ) {
|
||||
if ( @is_writable( $dir ) ) {
|
||||
$_GLOBALS['tmp_dir'] = $dir;
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
error_log( __FILE__ . ':' . __LINE__ . ' ERROR - could not find a writable temporary directory, check web server and PHP config' );
|
||||
return false;
|
||||
// return '/tmp';
|
||||
}
|
||||
|
||||
if( ! defined( 'NULL_KEY') ) define( 'NULL_KEY', '00000000-0000-0000-0000-000000000000' );
|
||||
if( ! defined( 'TPLINK_LOCAL') ) {
|
||||
define( 'TPLINK_LOCAL', 1 ); // seconlife://Region/x/y/z
|
||||
define( 'TPLINK_HG', 2 ); // seconlife://yourgrid.org:8002 Region/x/y/z
|
||||
define( 'TPLINK_V3HG', 4 ); // the overcomplicated stuff!
|
||||
define( 'TPLINK_HOP', 8 ); // hop://yourgrid.org:8002:Region/x/y/z
|
||||
define( 'TPLINK_TXT', 16 ); // yourgrid.org:8002:Region/x/y/z
|
||||
define( 'TPLINK_APPTP', 32 ); // secondlife:///app/teleport/yourgrid.org:8002:Region/x/y/z
|
||||
define( 'TPLINK_MAP', 64 ); // secondlife:///app/map/yourgrid.org:8002:Region/x/y/z
|
||||
define( 'TPLINK', pow( 2, 8 ) - 1 ); // all formats
|
||||
define( 'TPLINK_DEFAULT', TPLINK_HOP ); // default
|
||||
}
|
||||
|
||||
define( 'HELPERS_LOCALE_DIR', dirname( __DIR__ ) . '/languages' );
|
||||
|
||||
function os_cache_get( $key, $default = null ) {
|
||||
global $oshelpers_cache;
|
||||
return isset( $oshelpers_cache[$key] ) ? $oshelpers_cache[$key] : $default;
|
||||
}
|
||||
|
||||
function os_cache_set( $key, $value, $expire = 0 ) {
|
||||
global $oshelpers_cache;
|
||||
$oshelpers_cache[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenSim source to help further attempts to allow Hypergrid search results.
|
||||
* Infouuid is a fake parcelid resolving to region handle and (region-level?)
|
||||
* pos which might (or not) give enough information to allow hg results.
|
||||
* 1. Link region locally with link-region (or directly in db?)
|
||||
* 2. Use local link region handle (instead of remote one) to generate infouuid
|
||||
* 3. Use local link Global pos instead of remote one
|
||||
*/
|
||||
//
|
||||
// public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y)
|
||||
// {
|
||||
// byte[] bytes =
|
||||
// {
|
||||
// (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
|
||||
// (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
|
||||
// (byte)x, (byte)(x >> 8), 0, 0,
|
||||
// (byte)y, (byte)(y >> 8), 0, 0 };
|
||||
// return new UUID(bytes, 0);
|
||||
// }
|
||||
//
|
||||
// public static UUID BuildFakeParcelID(ulong regionHandle, uint x, uint y, uint z)
|
||||
// {
|
||||
// byte[] bytes =
|
||||
// {
|
||||
// (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
|
||||
// (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
|
||||
// (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
|
||||
// (byte)y, (byte)(y >> 8), 0, 0 };
|
||||
// return new UUID(bytes, 0);
|
||||
// }
|
||||
1
helper/economy/index.php
Normal file
1
helper/economy/index.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php die();
|
||||
191
helper/economy/landtool.php
Normal file
191
helper/economy/landtool.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
/**
|
||||
* landtool.php
|
||||
*
|
||||
* Provides web tools for land sales operations
|
||||
*
|
||||
* 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
|
||||
* Melanie Thielker and Teravus Ovares (http://opensimulator.org/)
|
||||
* Fumi.Iseki for CMS/LMS '09 5/31
|
||||
*/
|
||||
|
||||
require_once 'includes/config.php';
|
||||
require_once 'includes/economy.php';
|
||||
|
||||
// No user serviceable parts below #####################
|
||||
//
|
||||
// The XMLRPC server object
|
||||
//
|
||||
|
||||
$xmlrpc_server = xmlrpc_server_create();
|
||||
|
||||
//
|
||||
// Land purchase sections
|
||||
//
|
||||
// Functions are called by the viewer directly.
|
||||
//
|
||||
|
||||
//
|
||||
// Land buying functions
|
||||
//
|
||||
|
||||
xmlrpc_server_register_method( $xmlrpc_server, 'preflightBuyLandPrep', 'buy_land_prep' );
|
||||
|
||||
function buy_land_prep( $method_name, $params, $app_data ) {
|
||||
$req = $params[0];
|
||||
$agentid = $req['agentId'];
|
||||
$sessionid = $req['secureSessionId'];
|
||||
$amount = $req['currencyBuy'];
|
||||
$billableArea = $req['billableArea'];
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
$ret = opensim_check_secure_session( $agentid, null, $sessionid );
|
||||
|
||||
if ( $ret ) {
|
||||
$confirmvalue = currency_get_confirm_value( $ipAddress );
|
||||
$membership_levels = array(
|
||||
'levels' => array(
|
||||
'id' => '00000000-0000-0000-0000-000000000000',
|
||||
'description' => 'some level',
|
||||
),
|
||||
);
|
||||
$landUse = array(
|
||||
'upgrade' => false,
|
||||
'action' => '' . CURRENCY_HELPER_URL . '',
|
||||
);
|
||||
$currency = array( 'estimatedCost' => currency_virtual_to_real( $amount ) );
|
||||
$membership = array(
|
||||
'upgrade' => false,
|
||||
'action' => '' . CURRENCY_HELPER_URL . '',
|
||||
'levels' => $membership_levels,
|
||||
);
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => true,
|
||||
'currency' => $currency,
|
||||
'membership' => $membership,
|
||||
'landUse' => $landUse,
|
||||
'currency' => $currency,
|
||||
'confirm' => $confirmvalue,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "Unable to Authenticate\n\nClick URL for more info.",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Perform the buy (所持金が足りないとき)
|
||||
//
|
||||
|
||||
xmlrpc_server_register_method( $xmlrpc_server, 'buyLandPrep', 'buy_land' );
|
||||
|
||||
function buy_land( $method_name, $params, $app_data ) {
|
||||
$req = $params[0];
|
||||
$agentid = $req['agentId'];
|
||||
$sessionid = $req['secureSessionId'];
|
||||
$amount = $req['currencyBuy'];
|
||||
$cost = $req['estimatedCost'];
|
||||
$billableArea = $req['billableArea'];
|
||||
$confim = $req['confirm'];
|
||||
$ipAddress = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
if ( $confim != currency_get_confirm_value( $ipAddress ) ) {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "\n\nMissmatch Confirm Value!!",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
return '';
|
||||
}
|
||||
|
||||
$ret = opensim_check_secure_session( $agentid, null, $sessionid );
|
||||
|
||||
if ( $ret ) {
|
||||
if ( $amount >= 0 ) {
|
||||
if ( ! $cost ) {
|
||||
$cost = currency_virtual_to_real( $amount );
|
||||
}
|
||||
if ( ! currency_process_transaction( $agentid, $cost, $ipAddress ) ) {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "\n\nThe gateway has declined your transaction. Please update your payment method AND try again later.",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
}
|
||||
$enough_money = false;
|
||||
$res = currency_add_money( $agentid, $amount, $sessionid );
|
||||
if ( $res['success'] ) {
|
||||
$enough_money = true;
|
||||
}
|
||||
|
||||
if ( $enough_money ) {
|
||||
$amount += currency_get_balance( $agentid );
|
||||
currency_move_money( $agentid, null, $amount, 5002, 0, 'Land Purchase', 0, 0, $ipAddress );
|
||||
currency_update_simulator_balance( $agentid, -1, $sessionid );
|
||||
$response_xml = xmlrpc_encode( array( 'success' => true ) );
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "\n\nYou do not have sufficient funds for this purchase",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$response_xml = xmlrpc_encode(
|
||||
array(
|
||||
'success' => false,
|
||||
'errorMessage' => "\n\nUnable to Authenticate\n\nClick URL for more info.",
|
||||
'errorURI' => '' . CURRENCY_HELPER_URL . '',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
header( 'Content-type: text/xml' );
|
||||
echo $response_xml;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Process XMLRPC request
|
||||
//
|
||||
|
||||
$request_xml = file_get_contents( 'php://input' );
|
||||
// error_log("landtool.php: ".$request_xml);
|
||||
|
||||
xmlrpc_server_call_method( $xmlrpc_server, $request_xml, '' );
|
||||
xmlrpc_server_destroy( $xmlrpc_server );
|
||||
Reference in New Issue
Block a user