Source for file DpUser.php
Documentation is available at DpUser.php
* A user object, the object representing a real user
* DutchPIPE version 0.4; PHP version 5
* LICENSE: This source file is subject to version 1.0 of the DutchPIPE license.
* If you did not receive a copy of the DutchPIPE license, you can obtain one at
* http://dutchpipe.org/license/1_0.txt or by sending a note to
* license@dutchpipe.org, in which case you will be mailed a copy immediately.
* @subpackage dpuniverse_std
* @author Lennert Stock <ls@dutchpipe.org>
* @copyright 2006, 2007 Lennert Stock
* @license http://dutchpipe.org/license/1_0.txt DutchPIPE License
* @version Subversion: $Id: DpUser.php 311 2007-09-03 12:48:09Z ls $
* @link http://dutchpipe.org/manual/package/DutchPIPE
* Builts upon the standard DpLiving class
* Gets title type constants
* A user object, the object representing a real user
* Currently the only differerence with a NPC (which shares the same DpLiving
* class) is the passing of the user's last HTTP request's server, request and
* cookie variables, and the tell method (NPCs don't have a browser).
* See the DpLiving class for most functionality.
* Creates the following DutchPIPE properties:<br />
* - boolean <b>isUser</b> - Set to TRUE
* - boolean <b>isRegistered</b> - TRUE if this is a registered user, FALSE
* - boolean <b>isAdmin</b> - TRUE if this user is an administrator, FALSE
* - boolean <b>noCookies</b> - TRUE if the user's browser didn't accept our
* - boolean <b>isKnownBot</b> - TRUE if this is a known search engine bot,
* - boolean <b>isAjaxCapable</b> - TRUE if the user's browser is AJAX-capable,
* - string <b>age</b> - Descriptive age of the user
* - string <b>inactive</b> - Descriptive inactive time of the user, empty
* - boolean <b>isInactive</b> - TRUE if the user in inactive, FALSE otherwise
* - integer <b>avatarNr</b> - Avatar image number, 0 for custom avatar
* - string <b>avatarCustom</b> - File name of custom avatar, if any
* - status <b>browseAvatarCustom</b> - TRUE if the user is browsing on his
* computer for an image to upload (which causes scripts to halt), unset
* - mixed <b>status</b> - FALSE for no special status, otherwise a descriptive
* - string <b>inputMode</b> - Input field mode, "say" or "cmd"
* - string <b>inputEnabled</b> - Is input field visibile? Either "on" or "off"
* - string <b>inputPersistent</b> - Input field options
* @subpackage dpuniverse_std
* @author Lennert Stock <ls@dutchpipe.org>
* @copyright 2006, 2007 Lennert Stock
* @license http://dutchpipe.org/license/1_0.txt DutchPIPE License
* @version Release: 0.2.1
* @link http://dutchpipe.org/manual/package/DutchPIPE
* Variables set by the web server of related to dpclient.php's environment
* This environment is the execution environment of the current dpclient.php
* Variables which are currently registered to a script's session
* Variables provided via HTTP cookies
* Variables provided via URL query string
* Variables provided via HTTP POST
* Variables provided via HTTP post file uploads
* Counter for AJAX events, increased with each event
private $mEventCount = 0;
* Status of last connection, for example 'busy', used to detect change
private $mLastStatus = FALSE;
* Events this user will be alerted of, such as people entering the site
* History of input field actions, can be accesed by up and down arrow keys
$this->inputMode = 'say';
. $avatar_nr . '_body.gif" border="0" alt="" align="left" '
. 'style="margin-right: 15px" />' . dp_text('A user.') . '<br />';
/* Actions for everybody */
/* Actions for admin only */
/* Last action in menu */
* Gets the user's age in a string
* Returns the user's age in a format like "1 day, 6 hours and 14 minutes".
* @return string user's age
* @see getInactive, isInactive, getStatus, DpLiving::getSessionAge()
if (!$this->isRegistered) {
$result = dp_db_query('SELECT userAge FROM Users WHERE '
* Gets inactive time of the user in a string
* Returns how long the user is inactive in a format like "2 hours and 14
* @return string user's inactivity
* @see getAge, isInactive, getStatus, DpLiving::getSessionAge()
$inactive_time = time() - (!isset ($this->lastActionTime)
? $this->creationTime : $this->lastActionTime);
if ($inactive_time < 300) {
* Inactive is defined as a user who hasn't shown activity in the last 5
* @return status TRUE if the user is inactive, FALSE if active
* @see getAge, getInactive, getStatus, DpLiving::getSessionAge()
$inactive_time = time() - (!isset ($this->lastActionTime)
? $this->creationTime : $this->lastActionTime);
return $inactive_time >= 300;
* Gets a descriptive user status string
* If the user has a special status like inactive, returns a string like
* "away", to use in user titles and such. If there is no special status,
* returns an empty string.
* @return string status description
* @see getAge, getInactive, isInactive, DpLiving::getSessionAge()
* Calls itself every "heartbeat"
* Redefine this method to make timed stuff happen.
if ($this->status === $this->mLastStatus) {
$this->mLastStatus = $this->status;
$this->tell(array('abstract' => '<changeDpElement id="'
. $this->getUniqueId() . '"><b>'
'graphical' => '<changeDpElement id="'
. $this->getUniqueId() . '"><b>'
. '</b></changeDpElement>'));
'abstract' => '<changeDpElement id="' . $this->getUniqueId() . '">'
'graphical' => '<changeDpElement id="'
. $this->getUniqueId() . '">'
. '</changeDpElement>'), $this);
* Sets various PHP global variables passed on from the DutchPIPE server
* Called each time a user's browser does a normal page or AJAX request.
* Several variables are passed which represent their corresponding PHP
* global arrays: $_SERVER, $_COOKIE, etc.
* @param array &$rServerVars User server variables
* @param array &$rSessionVars User session variables
* @param array &$rCookieVars User cookie variables
* @param array &$rGetVars User get variables
* @param array &$rPostVars User post variables
* @param array &$rFilesVars User files variables
function setVars(&$rServerVars, &$rSessionVars, &$rCookieVars, &$rGetVars,
&$rPostVars, &$rFilesVars)
$this->_POST = $rPostVars;
* Sends something to dpclient-js.php running on the user's browser
* Sends the given data to the user's browser. It's up the user's DutchPIPE
* Javascript client, dpclient-js.php by default, what to do with the
* received content. dpclient-js.php can be send data like
* '<message>hello world</message>' and '<window>hello world</window>',
* to show something in the message area and pop up a window respectively.
* Can be binded to an environment. This is useful for locations producing
* messages: the user could be moving to another location before the client
* catches the new message with AJAX, in which case the user should not get
* @param string $data message string
* @param object &$binded_env optional binded environment
function tell($data, &$binded_env = NULL)
|| $env !== $binded_env)) {
echo dp_text("Message skipped, no longer in page\n");
// If this user is the same user doing the current HTTP request, tell
// straight away. Otherwise, store the message for the next time we get
// a HTTP request from the user.
//echo sprintf(dp_text("Storing %s: %s\n"), $this->title,
// (dp_strlen($data) > 512 ? dp_substr($data, 0, 512) : $data));
$data = $data[$this->displayMode];
// Gets the message type from $data which holds a string with the format
// <type>tellstuff</type>. If no type was given in the $data string, we
// consider it type 'message':
list ($mtype_start, $data, $mtype_end) = $this->_tellParseTag($data);
$this->_tellDoTell($mtype_start, $data, $mtype_end);
private function _tellParseTag($data)
&& FALSE !== ($pos = dp_strpos($data, '>'))) {
$mtype_start = dp_substr($data, 1, $pos - 1);
$mtype_end = dp_substr($data, $endpos + 2, - 1);
$endpos - dp_strlen($mtype_start) - 2) . ']]>';
$mtype_start = $mtype_end = 'message';
$data = "<![CDATA[$data]]>";
return array($mtype_start, $data, $mtype_end);
private function _tellDoTell($mtype_start, $data, $mtype_end)
if (isset ($this->_GET['ajax'])) {
if ($mtype_end === 'message' && $data === '<![CDATA[empty]]>') {
$mtype_start = $mtype_end = '';
if ($data !== '1' || !$universe->isToldSomething()) {
if ($mtype_start !== '') {
$data = "<$mtype_start>$data</$mtype_end>";
echo sprintf(dp_text("Telling %s: %s\n"), $this->title,
(dp_strlen($data) > 236 ? dp_substr($data, 0, 236)
if ($mtype_end === '' || $mtype_end === 'header'
|| $mtype_end === 'cookie' || $mtype_end === 'location') {
$universe->tellCurrentDpUserRequest($data);
$universe->tellCurrentDpUserRequest('<event count="'
. $this->mEventCount++ . '" time="' . time() . '">' . $data
* Called when certain events occur, given with $name.
* @param object $name Name of event
* @param mixed $args One or more arguments, depends on event
if (TRUE === $this->isRegistered) {
$result = dp_db_query('SELECT userAge FROM Users WHERE '
$new_age = $age + (time() - $this->creationTime);
. ' WHERE userUsernameLower='
} elseif ($this->avatarCustom) {
* Tries to perform the action given by the user object
* Handles input area input mode and history. Uses DpLiving::performAction()
* for the real stuff. See DpLiving::performAction() for more information.
* @param string $action the action given by the user object
* @return boolean TRUE for success, FALSE for unsuccessful action
* @see DpLiving::performAction()
$action = $orig_action = trim($action);
if (!isset ($this->_GET['menuaction']) && 'say' === $this->inputMode
$action = $orig_action = dp_substr($action, 1);
if ('' !== $action && isset ($this->_GET['cmdline'])
* Shows this user a window with help information
* @param string $verb the action, "help"
* @param string $noun empty string
. ('say' === $this->inputMode ? 'help.html' : 'commands.html'));
$this->tell("<window><div id=\"helptext\">" . $tmp
. "<br clear=\"all\" /></div></window>");
* Shows this user source code of environment or of another object
* @param string $verb the action, "source"
* @param string $noun what to show source of, could be empty
* @return boolean TRUE for action completed, FALSE otherwise
if (FALSE === ($what = $this->isPresent($noun))
/* Without the \n and to   conversion, highlight_file gave
$this->tell("<window styleclass=\"dpwindow_src\">\n"
. $what->location, TRUE) . "\n</window>"));
* Shows this living a list of links in its environment or in another object
* @param string $verb the action, "links"
* @param string $noun what to take, could be empty
* @return boolean TRUE for action completed, FALSE otherwise
if (FALSE === ($what = $this->isPresent($noun))
|| 0 === count($links = $what->getExits())) {
$what->title) . '</b><br /><br />';
foreach ($links as $linktitle => $linkdata) {
$linkcommand = explode(' ', $linktitle);
. "?location={$linkdata[0]}\">$linkcommand</a><br />";
$this->tell('<window>' . $tell . '</window>');
* Shows this user a list of users on the site
* @param string $verb the action, "who"
* @param string $noun empty string
if (0 === count($users)) {
$this->tell('<window><b>' . dp_text('No one is on this site.')
$tell = '<b>' . dp_text('People currently on this site:')
$tell .= '<table cellpadding="0" cellspacing="0" border="0" style="'
foreach ($users as &$user) {
$env = $user->getEnvironment();
$env = FALSE === $env ? '-' : '<a href="' . $loc . '">'
$status = !isset ($user->status) || FALSE === $user->status ? ''
: ' (' . $user->status . ')';
$tell .= '<tr><td>' . $user->title . $status
. '</td><td style="padding-left: 10px">' . $env . '</td></tr>';
$this->tell("<window>$tell</window>");
* Shows this user a window with avatar settings
* @param string $verb the action, "avatar"
* @param string $noun empty string
* @return boolean TRUE for action completed, FALSE otherwise
* @see setAvatar, setBrowseAvatarCustom, uploadAvatarCustom,
. 'ajaxfileupload.js"> </script>');
function set_browse_avatar_custom()
data: "location="+encodeURIComponent(\''
. '\')+"&rand="+Math.round(Math.random()*9999)
+ "&call_object="+encodeURIComponent("' . $this->getUniqueId() . '")
+ "&method=setBrowseAvatarCustom",
function upload_avatar_custom()
jQuery("#dpuploading").show();
. '\')+"&rand="+Math.round(Math.random()*9999)
+ "&call_object="+encodeURIComponent("' . $this->getUniqueId()
. '") + "&method=uploadAvatarCustom"
+ "&ie6="+(jQuery.browser.msie
&& 6 == parseInt(jQuery.browser.version) ? "yes" : "no"),
fileElementId: "dpuploadimg",
success: function(resp) { handle_response(resp); },
error: function (data, status, e) { jQuery("#dpuploading").hide(); }
function remove_avatar_custom()
data: "location="+encodeURIComponent(\''
. '\')+"&rand="+Math.round(Math.random()*9999)
+ "&call_object="+encodeURIComponent("' . $this->getUniqueId() . '")
+ "&method=removeAvatarCustom",
function set_avatar(avatar_nr)
data: "location="+encodeURIComponent(\''
. '\')+"&rand="+Math.round(Math.random()*9999)
+ "&call_object="+encodeURIComponent("' . $this->getUniqueId() . '")
+ "&avatar_nr="+avatar_nr,
$cur_avatar_nr = (int) $this->avatarNr;
'<table cellpadding="0" cellspacing="0" border="0"><tr>';
$this->avatarCustom ? 0 : 1;
for ($done = 0; $i <= $nr_of_avatars; $i++ ) {
$avatar_settings .= '<td align="center" valign="bottom" '
. 'style="text-align: center">'
. $this->_getAvatarSettingsHtml($i) . '</td>';
$avatar_settings .= '</tr>';
if ($i < $nr_of_avatars) {
$avatar_settings .= '<tr>';
$avatar_settings .= '</tr></table>';
: dp_text('Choose your avatar (kindly provided by <a href="http://www.messdudes.com/" target="_blank">Mess Dudes</a>):'))
<div style="width: 100%; height: 170px; overflow: auto; margin-top: 7px">'
: '<p style="margin-top: 15px; margin-bottom: 5px">'
. dp_text('Upload your own avatar:') . '</p>
<form id="dpupload" action="" method="POST" enctype="multipart/form-data"
style="display: block; margin: 0">
<div style="float: left; height: 28px"><input id="dpuploadimg" type="file"
name="dpuploadimg" class="dpupload_button"
onmousedown="return set_browse_avatar_custom()" /> <button
id="buttonUpload" onclick="return upload_avatar_custom()"
class="dpupload_button">' . dp_text('Upload') . '</button>'
. (!$this->avatarCustom ? '' : ' <button id="buttonUpload"
onclick="return remove_avatar_custom()"
class="dpupload_button">' . dp_text('Delete') . '</button>')
. 'loading.gif" style="float: left; position: relative; top: -5px;
left: 5px; display: none">
</form><div id="dpupload_msg" style="display: none; margin: 0"></div>')
* Gets the HTML for a single avatar in the avatar configuration window
* @param int $avatarNr default avatar number, 0 for custom avatar
* @return string HTML for the given avatar
private function _getAvatarSettingsHtml($avatarNr)
. $avatarNr . '.gif' : (!$this->isRegistered
return '<img src="' . $img_src . '" '
. 'border="0" class="dpimage" alt="' . $alt . '" title="' . $alt
. '" style="margin-bottom: 12px; margin-left: ' . $margin
. '; margin-right: ' . $margin . '" onClick="set_avatar('
* Switches to another avatar when clicking on one using actionAvatar()
* Sets the avatarNr property to the given stock avatar number, or to 0 in
* case a custom avatar is used. Updates database for registered users.
* @see actionAvatar, uploadAvatarCustom, removeAvatarCustom
if (!isset ($this->_GET['avatar_nr']) || 0 === dp_strlen($avatar_nr
= $this->_GET['avatar_nr'])) {
$this->tell(dp_text('Error receiving settings.<br />'));
$this->avatarNr = $avatar_nr;
. $avatar_nr . '.gif' : (!$this->isRegistered
// TODO: Should get real width/height for non GD users:
$this->titleImgWidth = NULL;
$this->titleImgHeight = NULL;
. 'user' . $avatar_nr . '_body.gif' : (!$this->isRegistered
. '" border="0" alt="" align="left" style="margin-right: 15px" />'
if ($this->isRegistered) {
. ' WHERE userUsernameLower='
'<changeDpElement id="' . $this->getUniqueId() . '">'
'<changeDpElement id="' . $this->getUniqueId() . '">'
* Sets this user as busy browing for a file
* Sets the browseAvatarCustom property to TRUE, or unsets it otherwise.
* Called from the JavaScript client when the user clicks on "Browse..." to
* look for a file to upload. This causes browsers to halt execution of
* scripts while the file dialog is visible. DpCurrentRequest uses this
* property to users are not thrown out while browsing for a file.
* @param boolean $browseAvatarCustom TRUE to start browsing, FALSE to end
* @see actionAvatar, uploadAvatarCustom
echo "setBrowseAvatarCustom($browseAvatarCustom) called\n";
if (TRUE !== $browseAvatarCustom) {
if (isset ($this->browseAvatarCustom)) {
unset ($this->browseAvatarCustom);
if (!isset ($this->browseAvatarCustom)) {
echo "browseAvatarCustom: $this->browseAvatarCustom\n";
* Attempts to upload a file to be used as our avatar image
* @see actionAvatar, setBrowseAvatarCustom, removeAvatarCustom
$prevAvatar = $this->avatarCustom;
// Check if there are files uploaded
if (!isset ($this->_FILES['dpuploadimg'])
|| !empty($this->_FILES['dpuploadimg']['error'])
|| empty($this->_FILES['dpuploadimg']['tmp_name'])) {
$msg = empty($this->_FILES['dpuploadimg']['error'])
? dp_text('Failed to upload image.')
: (empty($this->_FILES['dpuploadimg']['tmp_name'])
? dp_text('No image was given to upload.')
: $this->_FILES['dpuploadimg']['error']);
} elseif ($this->_FILES['dpuploadimg']['size']
$msg = sprintf(dp_text('The image was too large. The maximum file size is %d kilobytes.'),
$name = $this->_FILES['dpuploadimg']['name'];
if (FALSE !== $pos && $pos < dp_strlen($name) - 1) {
// Make a unique filename for the avatar
$new_path = (!$this->isRegistered
$msg = dp_text('Failed to upload image.');
$tmp_name = $this->_FILES['dpuploadimg']['tmp_name'];
//$msg = "<p style=\"margin-bottom: 10px\">File Name: {$name}, "
// . " File Size: " . @filesize($tmp_name) . '</p>';
. ' WHERE userUsernameLower='
if ($this->avatarCustom) {
$this->avatarCustom = $new_fn;
$this->titleImg = (!$this->isRegistered
$this->body = '<img src="' . (!$this->isRegistered
. '" border="0" alt="" align="left" '
. 'style="margin-right: 15px" />'
$msg = '<br clear="all" />' . $msg;
/* In uploadAvatarCustomMessages messagea are sent to the user in XML
* format. These are retreived in the target iframe the AJAX form posts
* to. Internet Explorer 6 can't handle XML documents, and a small delay
* is needed so the messages are retreived by dpclient-js.php using AJAX
* instead, where Internet Explorer 6 can handle the XML.
if (isset ($this->_GET['ie6']) && 'yes' === $this->_GET['ie6']) {
$this->setTimeout('_uploadAvatarCustomMessages', 1, $msg, $err);
$this->_uploadAvatarCustomMessages($msg, $err);
* Finishes uploading, removes loading indicator, sends messages
* @param mixed $msg message string, FALSE for no message (the default)
* @param boolean $err TRUE for upload error, else FALSE (the default)
* @see actionAvatar, setBrowseAvatarCustom, uploadAvatarCustom,
function _uploadAvatarCustomMessages($msg = FALSE, $err = FALSE)
$this->tell('<script>jQuery("#dpuploading").hide();</script>');
. $this->getUniqueId() . '">'
'graphical' => '<changeDpElement id="'
. $this->getUniqueId() . '">'
. '</changeDpElement>'), $this);
$this->tell('<div id="dpupload_msg">' . $msg . '</div>');
* Removes the custom avatar
* @see actionAvatar, uploadAvatarCustom
function removeAvatarCustom()
$avatar_nr = $this->avatarNr = 1;
$this->avatarCustom = FALSE;
$this->titleImgWidth = $this->titleImgHeight = NULL;
. $avatar_nr . '_body.gif" border="0" alt="" align="left" '
. 'style="margin-right: 15px" />' . dp_text('A user.') . '<br />';
if ($this->isRegistered) {
. ',userAvatarCustom = NULL'
. ' WHERE userUsernameLower='
'abstract' => '<changeDpElement id="' . $this->getUniqueId() . '">'
'graphical' => '<changeDpElement id="'
. $this->getUniqueId() . '">'
* Shows this user a window with settings
* @param string $verb the action, "settings"
* @param string $noun empty string
* @return boolean TRUE for action completed, FALSE otherwise
function send_settings(avatar_nr)
. '&rand="+Math.round(Math.random()*9999)
+ "&call_object="+encodeURIComponent("' . $this->getUniqueId() . '")
+ "&display_mode="+(_gel("display_mode1").checked
? _gel("display_mode1").value : _gel("display_mode2").value)
+ "&people_entering="+(_gel("people_entering").checked ? "1" : "0")
+ "&people_leaving="+(_gel("people_leaving").checked ? "1" : "0")
+ "&bots_entering="+(_gel("bots_entering").checked ? "1" : "0"),
. dp_text('People and items on the page are displayed in:') . '<br />
<input type="radio" id="display_mode1" name="display_mode" value="graphical"' . ($this->displayMode == 'graphical' ? ' checked="checked"' : '') . ' onClick="send_settings()" style="cursor: pointer" />' . dp_text('Graphical mode') . '<br />
<input type="radio" id="display_mode2" name="display_mode" value="abstract"' . ($this->displayMode == 'abstract' ? ' checked="checked"' : '') . ' onClick="send_settings()" style="cursor: pointer" />' . dp_text('Abstract mode') . '<br /><br />'
. dp_text('Alert me of the following events:') . '<br />
<input type="checkbox" id="people_entering" name="people_entering" value="1"' . (isset ($this->mAlertEvents['people_entering']) ? ' checked="checked"' : '') . ' onClick="send_settings()" style="cursor: pointer" />' . dp_text('People entering this site') . '<br />
<input type="checkbox" id="people_leaving" name="people_leaving" value="1"' . (isset ($this->mAlertEvents['people_leaving']) ? ' checked="checked"' : '') . ' onClick="send_settings()" style="cursor: pointer" />' . dp_text('People leaving this site') . '<br />
<input type="checkbox" id="bots_entering" name="bots_entering" value="1"' . (isset ($this->mAlertEvents['bots_entering']) ? ' checked="checked"' : '') . ' onClick="send_settings()" style="cursor: pointer" />' . dp_text('Search engines indexing pages') . '<br />
* Applies settings from the settings menu obtained with actionSettings()
* Called from the Javascript that goes with the menu that pops up after the
* settings action has been performed. Applies avatar and dispay mode
* settings, based on the DpUser::_GET variable in this user.
if (!isset ($this->_GET['display_mode'])
= $this->_GET['display_mode'])) {
$this->tell(dp_text('Error receiving settings.<br />'));
$this->displayMode = $display_mode;
if (isset ($this->_GET['people_entering']) && $this->_GET['people_entering'] == '1') {
if (isset ($this->_GET['people_leaving']) && $this->_GET['people_leaving'] == '1') {
if (isset ($this->_GET['bots_entering']) && $this->_GET['bots_entering'] == '1') {
if ($this->isRegistered) {
. 'userDisplayMode=' . dp_db_quote($display_mode, 'text')
. ',userEventPeopleEntering='
. ',userEventPeopleLeaving='
. ',userEventBotsEntering='
. ' WHERE userUsernameLower='
* Shows this administrator various PHP/server information about a user
* @param string $verb the action, "svars"
* @param string $noun who to show info of, could be empty
* @return boolean TRUE for action completed, FALSE otherwise
if (FALSE === ($ob = $this->isPresent($noun))) {
if (FALSE === ($ob = $env->isPresent($noun))) {
dp_text('Target %s not found.<br />'), $noun));
. '</b><br /><pre>' . print_r($ob->_SERVER, TRUE) . '</pre>'
* @param string $verb the action, "destroy"
* @param string $noun the object to destroy, for example "rose"
* @return boolean TRUE for action completed, FALSE otherwise
($noun && !($dest_ob = $env->isPresent($noun)))) {
$this->setActionFailure(dp_text('Destroy what?<br />'));
$dest_ob->removeDpObject();
* Shows a list of all objects in this DutchPIPE universe in a window
* @param string $verb the action, "oblist"
* @param string $noun empty string
* @return boolean TRUE for action completed, FALSE otherwise
* @see DpUniverse::gteObjectList()
. 'oblist.css"></stylesheet>');
$this->tell('<window styleclass="dpwindow_oblist" delay="100">'
. '<div class="dpoblist_div">'
. '</div><a href="javascript:send_action2server(\'oblist\')">Reload'
$this->tell('<script type="text/javascript" ' .
$this->tell("<script>\nsetTimeout('sorttable.init()', 200);\n"
* @param string $verb the action, "goto"
* @param string $noun the location, for example "/page/about.php"
* @return boolean TRUE for action completed, FALSE otherwise
$this->setActionFailure(dp_text('Goto where?<br />'));
$this->tell("<location>$noun</location>");
* Makes this administrator force another user to perform an action
* @param string $verb the action, "force"
* @param string $noun who and what to force
* @return boolean TRUE for action completed, FALSE otherwise
|| FALSE === ($pos = dp_strpos($noun, ' '))) {
dp_text('Syntax: force <i>who what</i>.<br />'));
if (FALSE !== ($pos2 = dp_strpos($noun, '"'))) {
if (FALSE === ($who_ob = $this->isPresent($who))) {
$who_ob = $env->isPresent($who);
dp_text('Target %s not found.<br />'), $who));
dp_text('You give %s the old "Jedi mind-trick" stink eye.<br />'),
dp_text('%s gives %s the old "Jedi mind-trick" stink eye.<br />'),
dp_text('%s gives you the old "Jedi mind-trick" stink eye.<br />'),
$who_ob->performAction($what);
* Completes the move action performed by clicking on an object
* @param string $verb the action, "move"
* @return string a string such as "beer "
return (FALSE === dp_strpos($title, ' ') ? $title : '"' . $title . '"')
* Makes this administrator move an object to another environment
* @param string $verb the action, "move"
* @param string $noun what and where to move
* @return boolean TRUE for action completed, FALSE otherwise
|| FALSE === ($pos = dp_strpos($noun, ' '))) {
dp_text('Syntax: move <i>what where</i>.<br />'));
if (FALSE !== ($pos2 = dp_strpos($noun, '"'))) {
if (FALSE === ($what_ob = $this->isPresent($what))) {
$what_ob = $env->isPresent($what);
if (FALSE === $what_ob) {
if (FALSE === $what_ob) {
dp_text('Object to move %s not found.<br />'), $what));
$pos = !isset ($pos2) ? $pos + 1 : $pos2 + 2;
dp_text('Syntax: move <i>what where</i>.<br />'));
if (FALSE === $where_ob) {
dp_text("Can't move object %s to this location: you have no environment.<br />"),
elseif ('me' === $where) {
elseif (FALSE === ($where_ob = $this->isPresent($where))) {
$where_ob = $env->isPresent($where);
if (FALSE === $where_ob) {
if (FALSE === $where_ob) {
dp_text('Target %s not found.<br />'), $where));
if ($this === $what_ob && $this === $where_ob) {
dp_text('You cannot move yourself into yourself.<br />'));
dp_text('You give %s the old "Jedi mind-trick" stink eye.<br />'),
dp_text('%s gives %s the old "Jedi mind-trick" stink eye.<br />'),
dp_text('%s gives you the old "Jedi mind-trick" stink eye.<br />'),
$what_ob->moveDpObject($where_ob);
* Resets the environment.
$this->tell('Resetted.<br />');
* Go to the login page, logout if logon on.
$this->tell('<location>/page/login.php'
. ($this->isRegistered ? '&act=logout' : '')
* Moves to or sets personal home location
* @param string $verb the action, "myhome"
* @param string $noun empty to go home, "set" to set home
* @return boolean TRUE for action completed, FALSE otherwise
userHomeLocation,userHomeSublocation
$this->tell(dp_text('You have no home location set. Set your home location first.<br />'));
$this->tell('<location>' . $row[0] . (is_null($row[1]) ? ''
: '&sublocation=' . $row[1]) . '</location>');
if (!$env || !dp_strlen($loc = $env->location)) {
$subloc = $env->sublocation;
: dp_db_quote($subloc, 'text')) . ' WHERE userUsernameLower='
$this->tell(dp_text('Your home location has been set to the current page.<br />'));
$this->actionFailure = dp_text('Syntax: myhome [set]<br />');
* Sets the input field mode
* Without an argument, switches between the two modes "cmd" and "say".
* Otherwise switches to the given mode (if it is valid). The input field
* stays visible between page changes with mode "pin".
* @param string $verb the action, "mode"
* @param string $noun empty or a mode
* @return boolean TRUE for action completed, FALSE otherwise
$this->inputMode = 'cmd' !== $this->inputMode ? 'cmd' : 'say';
$this->inputMode = 'cmd';
$this->inputMode = 'say';
$this->actionFailure = dp_text('Invalid action mode (valid modes are: say and cmd).<br />');
$this->inputPersistent = $ip;
if ($this->isRegistered) {
. ' WHERE userUsernameLower='
if ($this->isRegistered) {
. ' WHERE userUsernameLower='
$this->tell('cmd' === $this->inputMode
? dp_text('The input field is now in command mode. Enter <tt>help</tt> for more information.<br />')
: dp_text('The input field is now in page chat mode. Enter <tt>/help</tt> for more information.<br />'));
return ('cmd' !== $this->inputMode ? '' : '<img src="'
. 'height="7" border="0" alt="" title="" />#'
* Makes this user object tell something to another user object
* @param string $verb the action, "tell"
* @param string $noun who and what to tell, could be empty
* @return boolean TRUE for action completed, FALSE otherwise
if (FALSE === ($pos = dp_strpos($noun, ' '))) {
setTimeout("bind_input(); _gel(\'dptell\').focus();", 50);
$this->tell('<window styleclass="dpwindow_tell">
<b>' . sprintf(dp_text('Private message to %s:'), $noun) . '</b><br /><br />
<form onSubmit="send_action2server(\''
. ' \' + jQuery(\'#dptell\').val()); close_dpwindow(); '
<input id="dptell" type="text" value="" size="50" maxlength="255"
class="dpcomm" /> <input type="submit" value=" > " /></form>
* Makes this user shout something to everyone on the site
* @param string $verb the action, "shout"
* @param string $noun what to shout, could be empty
* @return boolean TRUE for action completed, FALSE otherwise
setTimeout("bind_input(); _gel(\'dpshout\').focus();", 50);
$this->tell('<window styleclass="dpwindow_shout">
<b>' . dp_text('Message to everybody on this site:') . '</b><br /><br />
<form onSubmit="send_action2server(\''
. ' \' + jQuery(\'#dpshout\').val()); close_dpwindow(); '
<input id="dpshout" type="text" value="" size="50" maxlength="255"
class="dpcomm" /> <input type="submit" value=" > " /></form>
* Makes this user communicate a custom message to its environment
* @param string $verb the action, "emote"
* @param string $noun string to "emote"
* @return boolean TRUE for action completed, FALSE otherwise
setTimeout("bind_input(); _gel(\'dpemote\').focus();", 50);
$this->tell('<window styleclass="dpwindow_emote">
<b>' . dp_text('Emotion to everybody on this page:') . '</b><br /><br />'
. $this->title . ' <form onSubmit="send_action2server(\''
. ' \' + jQuery(\'#dpemote\').val()); close_dpwindow(); '
<input id="dpemote" type="text" value="" size="50" maxlength="255"
class="dpemote" /> <input type="submit" value=" > " /></form>
|