function fromArray($arr)
 {
     $this->name = $arr['name'];
     $this->attribs = $arr['attribs'];
     $this->text = $arr['text'];
     $this->html = $arr['html'];
     $this->subtags = array();
     foreach ($arr['tags'] as $subtag) {
         $newobj = new CXMLTag();
         $newobj->fromArray($subtag);
         $this->subtags[] = $newobj;
     }
 }
function xmpp_presence($stanza, $sock, $ircsock)
{
    global $xmppparams, $ircdata;
    $obj = new CXMLTag();
    $obj->fromArray($stanza);
    $toparts = xmpp_parse_jid($obj->attribs['to']);
    $fromparts = xmpp_parse_jid($obj->attribs['from']);
    // Join only valid IRC channel
    if (!irc_valid_channel(from_utf($toparts['user']))) {
        debugmsg("Invalid channel name\n");
        return false;
    }
    // Ignore invalid jid
    if (!$toparts['user'] || !$toparts['resource'] || !$fromparts['user'] || !$fromparts['resource']) {
        $answer = $obj->createError("modify", "jid-malformed", true);
        debugmsg("No nickname or room name\n");
        xmpp_write($sock, $answer->toString());
        return false;
    }
    $channel = from_utf($toparts['user']);
    // Normalize case if channel exists
    if ($norm_ch = $ircdata->channel_exists($channel)) {
        $channel = $norm_ch;
    } else {
        $ircdata->add_channel($channel);
    }
    $nick = $ircdata->jid_exists(from_utf($obj->attribs['from']));
    $newnick = from_utf($toparts['resource']);
    $forcenick = '';
    //    dump_ircdata("ircdata.dump", FILE_APPEND, "Do");
    if (!$nick) {
        debugmsg("New user, trying to join IRC\n");
        if (isset($obj->attribs['type'])) {
            return false;
        }
        // First enter of JID
        $nick = from_utf($toparts['resource']);
        if (!irc_valid_nick($nick)) {
            $answer = $obj->createError("cancel", "not-acceptable", true);
            debugmsg("Invalid nick\n");
            xmpp_write($sock, $answer->toString());
            return false;
        }
        if ($ircdata->nick_exists($nick)) {
            $answer = $obj->createError("cancel", "conflict", true);
            debugmsg("Nick already exists\n");
            xmpp_write($sock, $answer->toString());
            return false;
        }
        $ircdata->add_nick($nick, '', '', '', from_utf($obj->attribs['from']));
        // Send new nick to IRC server
        irc_nick($ircsock, $nick);
    } else {
        if (isset($obj->attribs['type'])) {
            if ($obj->attribs['type'] == 'unavailable') {
                debugmsg("Part room\n");
                if ($ircdata->is_on($nick, $channel)) {
                    if ($statustag = $obj->firstSubtag('status')) {
                        $status = from_utf($statustag->text);
                    } else {
                        $status = '';
                    }
                    xmpp_write($sock, xmpp_part(to_utf($nick), $toparts['user']));
                    irc_part($ircsock, $nick, $channel);
                    $ircdata->part_channel($nick, $channel, $status);
                    if (!$ircdata->get_on_channels($nick)) {
                        irc_quit($ircsock, $nick, $status);
                        $ircdata->remove_nick($nick);
                    }
                } else {
                    return false;
                }
                return true;
            }
        }
        // JID already exists
        // Fix for status changes
        if ($nick == $newnick) {
            //return false;
            debugmsg("JID already exists\n");
        }
        if (strcasecmp(from_utf($toparts['resource']), $nick) != 0) {
            $forcenick = $nick;
        }
    }
    // Is channel pressent
    if ($nick != $newnick && $ircdata->is_on($nick, $channel)) {
        // debugmsg("   ---   Test: user on channel", 1);
        if (!irc_valid_nick($newnick)) {
            $answer = $obj->createError('cancel', 'not-acceptable', true);
            debugmsg("Invalid nick\n");
            xmpp_write($sock, $answer->toString());
            return false;
        }
        // Change nick
        $can_change = $ircdata->can_change_nick($nick, $newnick);
        if ($can_change === true) {
            debugmsg("Changing nick\n");
            irc_change_nick($ircsock, $nick, $newnick);
            xmpp_write($sock, xmpp_change_nick(to_utf($nick), to_utf($newnick)));
            $ircdata->change_nick($nick, $newnick);
            //	    dump_ircdata("ircdata2.dump", FILE_APPEND, "Posle");
            return true;
        } else {
            $errtag = $obj->createError('cancel', $can_change['error'], true);
            debugmsg("Nick can't change\n");
            xmpp_write($sock, $errtag->toString());
            return false;
        }
        return false;
    } else {
        // debugmsg("   ---   Test: can user join?", 1);
        if ($forcenick) {
            $nick = $forcenick;
        }
        $password = '';
        if ($xtag = $obj->validSubtag('x', 'xmlns', FEAT_MUC)) {
            if ($passtag = $xtag->firstSubtag('password')) {
                $password = $passtag->text;
            }
        }
        $join = $ircdata->can_join($nick, $channel, from_utf($password));
        // var_dump($join);
        if ($join === true) {
            $ircdata->join_channel($nick, $channel);
            // Give op to first user in channel
            if (count($ircdata->channels[$channel]['nicks']) == 1) {
                $ircdata->set_chumode($channel, $nick, 'o', true);
                irc_join($ircsock, $nick, $channel, '@');
            } else {
                irc_join($ircsock, $nick, $channel);
            }
            // Send channel members to new user
            xmpp_write($sock, xmpp_presence_to_new(to_utf($nick), $toparts['user']));
            // Send new user to channel members
            xmpp_write($sock, xmpp_presence_to_all(to_utf($nick), $toparts['user'], $forcenick ? to_utf($nick) : ''));
            // Send subject to new user
            xmpp_write($sock, xmpp_message_to_one(to_utf($ircdata->channels[$channel]['topic_by']), to_utf($nick), 'subject', to_utf(text_from_irc($ircdata->channels[$channel]['topic'])), $toparts['user']));
            return true;
        } else {
            // Send error messages
            $errtag = false;
            switch ($join['error']) {
                case 'invite':
                    $errtag = $obj->createError('auth', 'registration-required', true);
                    break;
                case 'password':
                    $errtag = $obj->createError('auth', 'not-authorized', true);
                    break;
                case 'limit':
                    $errtag = $obj->createError('wait', 'service-unavailable', true);
                    break;
                case 'ban':
                    $errtag = $obj->createError('auth', 'forbidden', true);
                    break;
            }
            if ($errtag) {
                xmpp_write($sock, $errtag->toString());
            }
        }
    }
    return false;
}