Files
opensim-helpers/offline.php
T
2024-12-23 11:10:54 -04:00

210 lines
6.2 KiB
PHP

<?php
/**
* offline.php
*
* Handles Instant Messages sent to offline users and deliver them when the user
* comes back online. If the user has enabled Send offline IM by email (in
* viewer preferences), the messages are also forwarded immediately by email.
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*
* Includes portions of code from
* http://opensimulator.org/wiki/Offline_Messaging
* http://www.weberdev.com/get_example-4372.html
**/
require_once 'includes/config.php';
require_once 'includes/databases.php';
if ( ! isset( $OpenSimDB ) ) {
die();
}
$request_xml = file_get_contents( 'php://input' );
if ( empty( $request_xml ) ) {
osXmlResponse( false, 'Invalid request' );
die();
}
$method = @$_SERVER['PATH_INFO)'];
if ( empty( $method ) ) {
$method = '/' . basename( getenv( 'REDIRECT_URL' ) ) . '/';
}
$xml = new SimpleXMLElement( $request_xml );
switch ( $method ) {
case '/SaveMessage/':
if ( strpos( $request_xml, '?>' ) == -1 ) {
osXmlResponse( false );
die;
}
// Save for in-world delivery
$saved = $OpenSimDB->prepareAndExecute(
'INSERT INTO ' . OFFLINE_MESSAGE_TBL . ' (PrincipalID, FromID, Message)
VALUES (:PrincipalID, :FromID, :Message)',
array(
'PrincipalID' => $xml->toAgentID,
'FromID' => $xml->fromAgentID,
'Message' => preg_replace( '/>\n/', '>', $xml->asXML() ),
)
);
osXmlResponse( $saved ); // Output in-world save result
dontWait(); // flush output, continue in background
// Save to mail queue if mail forwarding is set
$emailinfo = $OpenSimDB->prepareAndExecute(
'SELECT imviaemail, email FROM usersettings WHERE useruuid = :useruuid',
array(
'useruuid' => $xml->toAgentID,
),
);
if ( $emailinfo ) {
list($sendmail, $email) = $emailinfo->fetch();
if ( empty( $email ) || $sendmail == 'false' ) {
die();
}
if ( $xml->fromAgentName == 'Server' ) {
$xml->fromAgentName = OPENSIM_GRID_NAME;
}
$headers = "From: $xml->fromAgentName <" . OPENSIM_MAIL_SENDER . ">\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=UTF-8\r\n";
$parts = explode( '|', $xml->message );
if ( count( $parts ) > 1 ) {
$subject = $parts[0];
$body = "<h4>$subject</h4>" . $parts[1];
} else {
$body = $xml->message;
}
if ( ! empty( OPENSIM_GRID_NAME ) ) {
$in = ' in ' . OPENSIM_GRID_NAME;
}
switch ( $xml->dialog ) {
// To complete from http://wiki.secondlife.com/wiki/ImprovedInstantMessage
case '32':
$subject = "Group notice: $subject";
$intro = "$xml->fromAgentName sent a group notice$in:";
break;
case '3':
$subject = "Group invitation from $xml->fromAgentName";
$intro = $body;
$body = 'Log in-world to accept or decline';
break;
case '4':
$subject = "Inventory offer from $xml->fromAgentName";
$intro = "$xml->fromAgentName returned you " . $body;
$body = 'Log in-world to accept or decline';
break;
// case "19":
// $subject = "Message from $xml->fromAgentName";
// $intro = $body;
// break;
case '38':
$subject = "Friendship offer from $xml->fromAgentName";
$intro = $body;
$body = 'Log in-world to accept or decline.';
break;
default:
$subject = "Message from $xml->fromAgentName";
$outro = "Sent by $xml->fromAgentName $in";
}
$body = htmlspecialchars( $body );
$subject = htmlspecialchars( $subject );
$body = str_replace( "\n", "\n<br>", $body );
// $body = str_replace( "\n", "\r\n", $body );
$body = '<html><body>'
. ( empty( $intro ) ? '' : '<p></p>' )
. $body
. "\r\n"
. "\r\n"
. ( empty( $outro ) ? '' : "<blockquote>$outro</blockquote>" )
. '<hr>'
. "<p style='font-size:small'><b>" . OPENSIM_GRID_NAME . '</b> Instant Messages mail forwarding by w4os.'
. '<br>Please log in-world to answer to this message. Emails to the sender address will not be processed.'
. '<br>To disable mail notifications, uncheck option "Send IM to mail" in your viewer preferences (tab "Chat" or "Communications").'
. '</p></body></html>';
if ( defined( 'WPINC' ) ) {
// We're inside WordPress, use wp_mail()
add_action(
'plugins_loaded',
function () use ( $email, $subject, $body, $headers ) {
$result = wp_mail( $email, $subject, $body, $headers );
if ( ! $result ) {
error_log( __FILE__ . "error $result sending IM notification to $email." );
}
die();
},
99
);
} else {
// use standard PHP mail, might need a local smtp server
$result = mail( $email, $subject, $body, $headers );
if ( ! $result ) {
error_log( __FILE__ . "error $result sending IM notification to $email." );
}
die();
}
}
break;
case '/RetrieveMessages/':
if ( opensim_isuuid( $xml->Guid ) ) {
$pendingmessages = $OpenSimDB->prepareAndExecute(
'SELECT ID, Message FROM ' . OFFLINE_MESSAGE_TBL . ' WHERE PrincipalID = :PrincipalID',
array(
'PrincipalID' => $xml->Guid,
),
);
if ( $pendingmessages ) {
$delivered = array();
echo '<?xml version="1.0" encoding="utf-8"?>';
echo '<ArrayOfGridInstantMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">';
while ( list($id, $message) = $pendingmessages->fetch() ) {
$start = strpos( $message, '?>' );
if ( $start != -1 ) {
$message = substr( $message, $start + 2 );
}
echo $message;
$delivered[] = $id;
}
echo '</ArrayOfGridInstantMessage>';
if ( ! empty( $delivered ) ) {
$result = $OpenSimDB->prepareAndExecute(
'DELETE FROM ' . OFFLINE_MESSAGE_TBL . ' WHERE ID=' . join( ' OR ID=', $delivered )
);
}
} else {
error_log( 'error retrieving pending messages' );
osXmlResponse( false );
}
} else {
error_log( $xml->Guid . ' is not a valid UUID' );
}
die();
break;
// '//': die(); // empty request
default:
error_log( "Offline messages: method $method not implemented, please configure OfflineMessageModule = OfflineMessageModule in OpenSim.ini" );
osXmlResponse( false, "method $method not implemented" );
die();
}