function plan_get_last_login($planowner)
{
    $planowner_pl = $_SERVER['PLAN_LOCATION_ARRAY'][$planowner];
    if (!$planowner_pl && !$_SERVER['PLAN_LOCATION_FAILED_ARRAY'][$planowner]) {
        $planowner = plan_get_real_location($planowner);
    } else {
        $planowner = $planowner_pl;
    }
    if (plan_is_local($planowner)) {
        $lastlogin = user_get_last_action($planowner);
    } else {
        list($user, $node) = explode('@', $planowner);
        if (!$node) {
            $node = 'planwatch.org';
        }
        $_SERVER['STOPWATCH']["lastlogin.rpc_begin"] = array_sum(explode(' ', microtime()));
        $f = new xmlrpcmsg('planworld.user.getLastLogin');
        $f->addParam(new xmlrpcval("{$user}", "string"));
        $nodeinfo = planworld_node_getinfo($node);
        $c = new xmlrpc_client($nodeinfo['directory'], $nodeinfo['server'], $nodeinfo['port']);
        $c->setDebug(0);
        //if (user_is_administrator()) $c->setDebug(1);
        $r = $c->send($f);
        if (!$r) {
            $lastlogin = "******";
        } elseif (!$r->faultCode()) {
            $lastlogin = xmlrpc_decode($r->value());
        }
        $_SERVER['STOPWATCH']["lastlogin.rpc_end"] = array_sum(explode(' ', microtime()));
    }
    return $lastlogin;
}
function planworld_online($m)
{
    global $xmlrpcerruser;
    $err = "";
    $onlineusers = array();
    exec("ls -d {$_SERVER['PWUSERS_DIR']}/*", $userlist);
    $threshhold = time() - 18600;
    foreach ($userlist as $user) {
        $user = ltrim(rtrim(basename($user)));
        $last = user_get_last_action($user);
        if ($last > $threshhold) {
            $onlineusers[] = new xmlrpcval($user, 'string');
        }
    }
    // if we generated an error, create an error return response
    if ($err) {
        return new xmlrpcresp(0, $xmlrpcerruser, $err);
    } else {
        // otherwise, we create the right response
        // with the state name
        return new xmlrpcresp(new xmlrpcval($onlineusers, 'array'));
    }
}