# -*- coding: utf-8 -*-

import protocol
import core
from mmptypes import *
import xmpp
import i18n
import traceback
import spool
import utils
import sys
import time
import base64
import urllib2
import locale
import random
import socket
import logging
import mrim
import forms
import async
import pool
import config
import bisect

conf = mrim.conf

class MMPConnection(core.Client):

	def __init__(self, user, password, xmpp_conn, jid, priority, show, ver, iq_register):
		self.iq_register = iq_register
		self.user = user
		self.password = password
		self.xmpp_conn = xmpp_conn
		self.jid = xmpp.JID(xmpp.JID(jid).getStripped())
		self.starttime = time.time()
		self.init_status = utils.show2status(show)
		self.roster_action = {}
		self.ids = []
		self.resources = {}
		self.prios = []
		self.addResource(xmpp.JID(jid).getResource(), priority, show, ver)
		self.current_status = self.init_status
		self.authed_users = []
		self.Roster = spool.Profile(self.jid)
		core.Client.__init__(self,self.user,self.password,xmpp_conn.logger,
			                 agent=conf.agent,status=self.init_status,proxy=conf.http_proxy)
		pool.add(self.jid, self)

	#def __del__(self):
	#	print "deleting glue.MMPConnection @", self

	def send_stanza(self, stanza, jid=None):
		typ = stanza.getType()
		if typ in ['subscribe','subscribed','unsubscribe','unsubscribed']:
			stanza.setTo(self.jid)
			self.xmpp_conn.send(stanza)
		elif jid:
			if stanza.name == 'message' and not jid.getResource():
				jid = self.getMaxJid()
			stanza.setTo(jid)
			self.xmpp_conn.send(stanza)
		else:
			for resource in self.getResources():
				To = xmpp.JID(self.jid)
				To.setResource(resource)
				stanza.setTo(To)
				self.xmpp_conn.send(stanza)

	def broadcast_offline(self, jid=None):
		offline = xmpp.Presence(frm=conf.name,typ='unavailable')
		self.send_stanza(offline, jid)
		if not self._got_roster:
			return
		for e_mail in self.contact_list.getEmails():
			mrim_status = self.contact_list.getUserStatus(e_mail)
			typ, s = utils.status2show(mrim_status)
			if not typ:
				user_offline = xmpp.Presence(frm=utils.mail2jid(e_mail),typ='unavailable')
				self.send_stanza(user_offline, jid)

	def broadcast_online(self, jid=None):
		if not self._got_roster:
			return
		for e_mail in self.contact_list.getEmails():
			mrim_status = self.contact_list.getUserStatus(e_mail)
			typ, s = utils.status2show(mrim_status)
			if not typ:
				p = xmpp.Presence(frm=utils.mail2jid(e_mail))
				utils.add_caps_c(p)
				if s:
					p.setShow(s)
				self.send_stanza(p, jid)

	def handle_expt(self):

		self.failure_exit("Connection has been closed abnormally")

	def handle_error(self):

		t, err, tb = sys.exc_info()
		if t == socket.error:
			reason = utils.socket_error(err)
		else:
			reason = "Unhandled exception"
			traceback.print_exc()
		self.failure_exit(reason)

	def exit(self, notify=True):
		if notify:
			self.broadcast_offline()
		pool.rm(self.jid)
		self.mmp_connection_close()

	def failure_exit(self,errtxt):
		if self.iq_register:
			rej = xmpp.ERR_INTERNAL_SERVER_ERROR
			rej_txt = i18n.CONNECTION_ERROR
			self.xmpp_conn.send_error(self.iq_register,rej,rej_txt)
		else:
			self.broadcast_offline()
		try:
			pool.rm(self.jid)
			self.close()
		except:
			pass
		self.log(logging.INFO, "Connection error (%s): %s" % (self.mrim_host, errtxt))
		timeout = random.choice(xrange(1,10))
		if self.state != 'session_established' and not self.iq_register:
			timeout = conf.reconnect_timeout
			error = xmpp.Presence(to=self.jid, frm=conf.name)
			error_txt = i18n.REMOTE_SERVER_ERROR
			self.xmpp_conn.send_error(error,xmpp.ERR_INTERNAL_SERVER_ERROR,error_txt,reply=0)
		if not self.iq_register:
			self.xmpp_conn.reconnect_user(self.jid, self.user, timeout)

	def start(self, server, port):
		self.mrim_host = server
		self.mrim_port = port
		self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
		self.log(logging.INFO, "Connecting to %s:%s" % (self.mrim_host,self.mrim_port))
		self.state = 'wait_for_connect'
		self.async_connect((self.mrim_host,self.mrim_port))
		self.connect_timer = self.set_timer(30, "timeout")

	def mmp_handler_server_authorized(self):
		if self.iq_register:
			ok_iq = self.iq_register.buildReply(typ='result')
			ok_iq.setPayload([],add=0)
			self.xmpp_conn.send(ok_iq)
			account = spool.Profile(self.jid)
			account.setUsername(self.user)
			account.setPassword(self.password)
			self.exit(notify=False)
		subscribe = xmpp.Presence(frm=conf.name,typ='subscribe')
		online = xmpp.Presence(frm=conf.name)
		utils.add_caps_s(online)
		if self.current_status != self.init_status:
			self.mmp_change_status(self.current_status)
		typ,show = utils.status2show(self.current_status)
		if show:
			online.setShow(show)
		self.send_stanza(subscribe)
		self.send_stanza(online)
		self.starttime = time.time()

	def mmp_handler_server_not_authorized(self, reason):
		if self.iq_register:
			err = xmpp.ERR_NOT_ACCEPTABLE
			txt = i18n.WRONG_USER_OR_PASSWORD
			self.xmpp_conn.send_error(self.iq_register,err,txt)
			self.exit()
		else:
			reject = xmpp.Message(to=self.jid, frm=conf.name)
			reject.setSubject(i18n.AUTH_ERROR)
			reject.setBody(' ')
			if reason == 'Invalid login':
				rej_txt = i18n.WRONG_USER_OR_PASSWORD
			else:
				rej_txt = '%s: %s' % (i18n.SERVER_REPLIED, reason)
			err = xmpp.ERR_NOT_AUTHORIZED
			self.xmpp_conn.send_error(reject,err,rej_txt,reply=0)
			self.exit()

	def mmp_handler_got_user_status(self, e_mail, mrim_status):
		jid_from = utils.mail2jid(e_mail)
		typ, s = utils.status2show(mrim_status)
		p = xmpp.Presence(frm=jid_from)
		if typ:
			p.setType(typ)
		elif s:
			p.setShow(s)
		if not typ:
			utils.add_caps_c(p)
		self.send_stanza(p)

	def mmp_handler_got_contact_list2(self):

		for e_mail in self.contact_list.getEmails():
			if self.contact_list.isValidUser(e_mail):
				nickname = self.contact_list.getUserNick(e_mail)
				if not nickname:
					nickname = e_mail
				jid_from = utils.mail2jid(e_mail)
				subscribe = xmpp.Presence(frm=jid_from,typ='subscribe')
				subscribe.addChild(name='nick',payload=[nickname],namespace=xmpp.NS_NICK)
				self.authed_users.append(e_mail)
				self.send_stanza(subscribe)
				mrim_status = self.contact_list.getUserStatus(e_mail)
				typ, s = utils.status2show(mrim_status)
				p = xmpp.Presence(frm=jid_from)
				if typ:
					p.setType(typ)
				elif s:
					p.setShow(s)
				if not typ:
					utils.add_caps_c(p)
				self.send_stanza(p)

	def mmp_handler_got_message(self, mess, offtime):
		mail = utils.win2str(mess.getFrom())
		body = mess.getBodyPayload()
		jid_from = utils.mail2jid(mail)
		msg = xmpp.Message(frm=jid_from)
		msg.setBody(body)
		if mess.hasFlag(MESSAGE_FLAG_SYSTEM):
			msg.setSubject(i18n.SYSTEM_NOFIFY)
			msg.setFrom(conf.name)
		elif mess.hasFlag(MESSAGE_FLAG_SMS_STATUS):
			msg.setSubject(i18n.SMS_DELIVERY_STATUS + mail)
			msg.setFrom(conf.name)
		else:
			msg.setType('chat')
			if not offtime:
				xevent = xmpp.simplexml.Node('x', attrs={'xmlns':'jabber:x:event'})
				xevent.setTag('composing')
				active = xmpp.Node('active', attrs={'xmlns':xmpp.NS_CHATSTATES})
				msg.addChild(node=xevent)
				msg.addChild(node=active)
			else:
				old_stamp = time.strftime('%Y%m%dT%H:%M:%S', offtime)
				old_delay = xmpp.Node('x',
					attrs={'xmlns':xmpp.NS_DELAY, 'from':conf.name, 'stamp':old_stamp})
				new_stamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', offtime)
				new_delay = xmpp.Node('delay',
					attrs={'xmlns':xmpp.NS_NEW_DELAY, 'from':conf.name, 'stamp':new_stamp})
				msg.addChild(node=old_delay)
				msg.addChild(node=new_delay)
		self.send_stanza(msg, self.jid)

	def mmp_handler_got_sms(self, number, users, text, offtime):
		jids = [utils.mail2jid(u) for u in users]
		msg = xmpp.Message(frm=conf.name)
		msg.setSubject(i18n.INCOMING_SMS + number)
		msg.setBody(text)
		if offtime:
			stamp = time.strftime('%Y%m%dT%H:%M:%S', offtime)
			delay = xmpp.Node('x', attrs={'xmlns':xmpp.NS_DELAY, 'from':conf.name})
			delay.setAttr('stamp', stamp)
			msg.addChild(node=delay)
		if not jids:
			jid_from = conf.name
		else:
			jid_from = jids[0]
		msg.setFrom(jid_from)
		self.send_stanza(msg, self.jid)

	def mmp_handler_got_subscribe(self, e_mail, name, txt, offtime):
		
		subscribe = xmpp.Presence(frm=utils.mail2jid(e_mail),typ='subscribe')
		if not name:
			name = e_mail
		subscribe.addChild(name='nick',payload=[name],namespace=xmpp.NS_NICK)
		if offtime:
			stamp = time.strftime('%Y%m%dT%H:%M:%S', offtime)
			delay = xmpp.Node('x', attrs={'xmlns':xmpp.NS_DELAY, 'from':conf.name})
			delay.setAttr('stamp', stamp)
			subscribe.addChild(node=delay)
		self.send_stanza(subscribe)

	def mmp_handler_got_subscribed(self, e_mail):
		subscribed = xmpp.Presence(frm=utils.mail2jid(e_mail),typ='subscribed')
		self.send_stanza(subscribed)

	def mmp_send_subscribed(self, to):
		"Roster-sync workaround"
		p = protocol.MMPPacket(typ=MRIM_CS_AUTHORIZE,dict={'user':to})
		try:
			self.authed_users.pop(self.authed_users.index(to))
		except (ValueError,IndexError):
			self._send_packet(p)

	def mmp_handler_dual_login(self):
		reject = xmpp.Message(to=self.jid, frm=conf.name)
		reject.setBody(' ')
		reject.setSubject(i18n.CONNECTION_ERROR)
		err = xmpp.ERR_CONFLICT
		err_txt = i18n.DUAL_LOGIN
		self.xmpp_conn.send_error(reject,err,err_txt,reply=0)
		self.exit()

	def mmp_handler_composing_start(self, e_mail):
		xevent = xmpp.Node('x', attrs={'xmlns':'jabber:x:event'})
		xevent.setTag('composing')
		xevent.setTag('id')
		c = xmpp.Node('composing', attrs={'xmlns':xmpp.NS_CHATSTATES})
		composing = xmpp.Message(frm=utils.mail2jid(e_mail))
		composing.addChild(node=xevent)
		composing.addChild(node=c)
		self.send_stanza(composing, self.jid)

	def mmp_handler_composing_stop(self, e_mail):
		xevent = xmpp.simplexml.Node('x', attrs={'xmlns':'jabber:x:event'})
		xevent.setTag('id')
		paused = xmpp.Node('paused', attrs={'xmlns':xmpp.NS_CHATSTATES})
		composing = xmpp.Message(frm=utils.mail2jid(e_mail))
		composing.addChild(node=xevent)
		composing.addChild(node=paused)
		self.send_stanza(composing, self.jid)

	def mmp_handler_got_mbox_status(self, url, total, unread):
		if not unread or spool.Options(self.jid).getMboxStatus()!='1':
			return
		body = "ÐÐµÐ¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ‹Ñ… Ð¿Ð¸ÑÐµÐ¼: %s\nÐ’ÑÐµÐ³Ð¾ Ð¿Ð¸ÑÐµÐ¼: %s" % (unread, total)
		subject = "Ð£ Ð²Ð°Ñ ÐµÑÑ‚ÑŒ Ð½ÐµÐ¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ‹Ðµ Ð¿Ð¸ÑÑŒÐ¼Ð°"
		xoob = xmpp.simplexml.Node('x', attrs={'xmlns':'jabber:x:oob'})
		xoob.setTagData('url', url)
		xoob.setTagData('desc', 'ÐŸÑ€Ð¾ÑÐ¼Ð¾Ñ‚Ñ€ÐµÑ‚ÑŒ')
		msg = xmpp.Message(frm=conf.name,typ='headline')
		msg.setSubject(subject)
		msg.setBody(body)
		msg.addChild(node=xoob)
		self.send_stanza(msg, self.jid)

	def mmp_handler_got_new_mail(self, url, number, sender, subject, unix_time):
		if spool.Options(self.jid).getNewMail()!='1':
			return
		ltime = time.strftime('%c', time.localtime(unix_time))
		xmpp_subject = "Ð’Ð°Ð¼ Ð¿Ñ€Ð¸ÑˆÐ»Ð¾ Ð½Ð¾Ð²Ð¾Ðµ Ð¿Ð¾Ñ‡Ñ‚Ð¾Ð²Ð¾Ðµ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ"
		body = "ÐžÑ‚Ð¿Ñ€Ð°Ð²Ð¸Ñ‚ÐµÐ»ÑŒ: %s\n" % sender
		body += "Ð¢ÐµÐ¼Ð°: %s\n" % subject
		body += 6*"-"+"\n"
		body += "Ð’ÑÐµÐ³Ð¾ Ð½ÐµÐ¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ‹Ñ… Ð¿Ð¸ÑÐµÐ¼: %s" % number
		xoob = xmpp.simplexml.Node('x', attrs={'xmlns':'jabber:x:oob'})
		xoob.setTagData('url', url)
		xoob.setTagData('desc', 'ÐŸÑ€Ð¾ÑÐ¼Ð¾Ñ‚Ñ€ÐµÑ‚ÑŒ')
		msg = xmpp.Message(frm=conf.name,typ='headline')
		msg.setSubject(xmpp_subject)
		msg.setBody(body)
		msg.addChild(node=xoob)
		self.send_stanza(msg, self.jid)

	def mmp_handler_got_contact_list(self, mail, clist, offtime):
		body = ''
		for address,nick in clist:
			body += "%s (%s)\n" % (address, nick)
		jid_from = utils.mail2jid(mail)
		msg = xmpp.Message(frm=jid_from)
		msg.setBody(body)
		msg.setSubject('Ð¡Ð¿Ð¸ÑÐ¾Ðº ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð¾Ð²')
		if offtime:
			stamp = time.strftime('%Y%m%dT%H:%M:%S', offtime)
			delay = xmpp.Node('x', attrs={'xmlns':xmpp.NS_DELAY, 'from':conf.name})
			delay.setAttr('stamp', stamp)
			msg.addChild(node=delay)
		self.send_stanza(msg, self.jid)

	def add_contact(self, mail):
		if utils.is_valid_email(mail):
			self.mmp_add_contact_with_search(mail, ackf=self.add_contact_result,
				acka={'mail':mail})
		else:
			reject = xmpp.Message(frm=utils.mail2jid(mail),to=self.jid)
			reject.setSubject('ÐžÑˆÐ¸Ð±ÐºÐ° Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ')
			reject.setBody(' ')
			err = xmpp.ERR_ITEM_NOT_FOUND
			error_reason = 'Ð”Ð¾Ð±Ð°Ð²Ð»ÑÐµÐ¼Ð¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ ÑÑƒÑ‰ÐµÑÑ‚Ð²ÑƒÐµÑ‚ Ð² ÑÐ¸ÑÑ‚ÐµÐ¼Ðµ'
			self.xmpp_conn.send_error(reject,err,error_reason,reply=0)

	def del_contact(self, mail):
		if utils.is_valid_email(mail):
			self.mmp_del_contact(mail, ackf=self.del_contact_result, acka={'mail':mail})

	def add_contact_result(self, status, mail):
		if status == CONTACT_OPER_SUCCESS:
			#self.mmp_send_subscribe(mail)
			return
		reject = xmpp.Message(frm=utils.mail2jid(mail),to=self.jid)
		if status == CONTACT_OPER_ERROR:
			error_reason = 'ÐŸÐµÑ€ÐµÐ´Ð°Ð½Ð½Ñ‹Ðµ Ð´Ð°Ð½Ð½Ñ‹Ðµ Ð±Ñ‹Ð»Ð¸ Ð½ÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ñ‹'
		elif status == CONTACT_OPER_INTERR:
			error_reason = 'ÐŸÑ€Ð¸ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐµ Ð·Ð°Ð¿Ñ€Ð¾ÑÐ° Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°'
		elif status == CONTACT_OPER_NO_SUCH_USER:
			error_reason = 'Ð”Ð¾Ð±Ð°Ð²Ð»ÑÐµÐ¼Ð¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ ÑÑƒÑ‰ÐµÑÑ‚Ð²ÑƒÐµÑ‚ Ð² ÑÐ¸ÑÑ‚ÐµÐ¼Ðµ'
		elif status == CONTACT_OPER_INVALID_INFO:
			error_reason = 'ÐÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ðµ Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ'
		elif status == CONTACT_OPER_USER_EXISTS:
			#error_reason = 'ÐŸÐ¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒ ÑƒÐ¶Ðµ ÐµÑÑ‚ÑŒ Ð² ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚-Ð»Ð¸ÑÑ‚Ðµ'
			return
		elif status == CONTACT_OPER_GROUP_LIMIT:
			error_reason = 'ÐŸÑ€ÐµÐ²Ñ‹ÑˆÐµÐ½Ð¾ Ð¼Ð°ÐºÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð¾ Ð´Ð¾Ð¿ÑƒÑÑ‚Ð¸Ð¼Ð¾Ðµ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑÑ‚Ð²Ð¾ Ð³Ñ€ÑƒÐ¿Ð¿ (20)'
		else:
			error_reason = 'ÐÐµÐ¸Ð·Ð²ÐµÑÑ‚Ð½Ñ‹Ð¹ ÐºÐ¾Ð´ Ð¾ÑˆÐ¸Ð±ÐºÐ¸ (%s)' % status
		reject.setSubject('ÐžÑˆÐ¸Ð±ÐºÐ° Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ')
		reject.setBody(' ')
		err = xmpp.ERR_ITEM_NOT_FOUND
		self.xmpp_conn.send_error(reject,err,error_reason,reply=0)

	def del_contact_result(self, status, mail):
		pass

	def got_vcard(self, anketa, mail, msg):
		anketa_entries = anketa.getVCards()
		status = anketa.getStatus()
		jid_to = msg.getFrom()
		if len(anketa_entries) == 1:
			self.mmp_send_avatar_request(mail, ackf=self.got_full_vcard,
				acka={'vcard':anketa_entries[0], 'msg':msg, 'mail':mail})
		else:
			if status == MRIM_ANKETA_INFO_STATUS_NOUSER:
				err = xmpp.ERR_ITEM_NOT_FOUND
				err_txt = 'ÐÐµÑ‚ Ñ‚Ð°ÐºÐ¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ'
			elif status == MRIM_ANKETA_INFO_STATUS_DBERR:
				err = xmpp.ERR_INTERNAL_SERVER_ERROR
				err_txt = 'ÐžÑˆÐ¸Ð±ÐºÐ° Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ð´Ð°Ð½Ð½Ñ‹Ñ…'
			elif status == MRIM_ANKETA_INFO_STATUS_RATELIMERR:
				err = xmpp.ERR_REMOTE_SERVER_TIMEOUT
				err_txt = 'Ð¡Ð»Ð¸ÑˆÐºÐ¾Ð¼ Ð¼Ð½Ð¾Ð³Ð¾ Ð·Ð°Ð¿Ñ€Ð¾ÑÐ¾Ð², Ð¿Ð¾Ð¸ÑÐº Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾ Ð·Ð°Ð¿Ñ€ÐµÑ‰ÐµÐ½'
			else:
				err = xmpp.ERR_INTERNAL_SERVER_ERROR
				err_txt = 'ÐÐµÐ¸Ð·Ð²ÐµÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°'
			self.xmpp_conn.send_error(msg,err,err_txt)

	def got_full_vcard(self, avatara, typ, album, vcard, msg, mail):
		jid_from = msg.getTo()
		jid_to = msg.getFrom()
		iq = xmpp.Iq(frm=jid_from,typ='result')
		iq.setAttr('id', msg.getAttr('id'))
		card = self.anketa2vcard(vcard, avatara, typ, album)
		iq.setPayload([card])
		self.send_stanza(iq, jid_to)

	def got_status(self, anketa, mail):
		anketa_entries = anketa.getVCards()
		jid_from = utils.mail2jid(mail)
		status = anketa.getStatus()
		if len(anketa_entries) == 1:
			mrim_status = int(anketa_entries[0]['mrim_status'])
			if mail in self.contact_list.getEmails():
				self.contact_list.setUserStatus(mail,mrim_status)
			self.mmp_handler_got_user_status(mail, status)

	def send_message(self, mail_to, body, mess):
		if utils.is_valid_email(mail_to):
			self.mmp_send_message(mail_to,body,ackf=self.got_message_status,acka={'msg':mess})
		else:
			err_txt = 'ÐÐµÑ‚ Ñ‚Ð°ÐºÐ¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ'
			self.xmpp_conn.send_error(mess,xmpp.ERR_ITEM_NOT_FOUND,err_txt)

	def got_message_status(self,status,msg):

		_id = msg.getAttr('id')
		if status != MESSAGE_DELIVERED:
			if status == MESSAGE_REJECTED_NOUSER:
				error_name = xmpp.ERR_ITEM_NOT_FOUND
				error_text = 'ÐÐµÑ‚ Ñ‚Ð°ÐºÐ¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ'
			elif status == MESSAGE_REJECTED_LIMIT_EXCEEDED:
				error_name = xmpp.ERR_NOT_ALLOWED
				error_text = 'ÐŸÐ¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½ Ð¾Ñ‚ ÑÐµÑ‚Ð¸, Ð¸ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ Ð½Ðµ Ð¿Ð¾Ð¼ÐµÑ‰Ð°ÐµÑ‚ÑÑ Ð² ÐµÐ³Ð¾ Ð¿Ð¾Ñ‡Ñ‚Ð¾Ð²Ñ‹Ð¹ ÑÑ‰Ð¸Ðº'
			elif status == MESSAGE_REJECTED_TOO_LARGE:
				error_name = xmpp.ERR_NOT_ACCEPTABLE
				error_text = 'Ð Ð°Ð·Ð¼ÐµÑ€ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€ÐµÐ²Ñ‹ÑˆÐ°ÐµÑ‚ Ð¼Ð°ÐºÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð¾ Ð´Ð¾Ð¿ÑƒÑÑ‚Ð¸Ð¼Ñ‹Ð¹'
			elif status == MESSAGE_REJECTED_DENY_OFFMSG:
				error_name = xmpp.ERR_NOT_ALLOWED
				error_text = 'ÐŸÐ¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½ Ð¾Ñ‚ ÑÐµÑ‚Ð¸, Ð° Ð½Ð°ÑÑ‚Ñ€Ð¾Ð¹ÐºÐ¸ ÐµÐ³Ð¾ Ð¿Ð¾Ñ‡Ñ‚Ð¾Ð²Ð¾Ð³Ð¾ ÑÑ‰Ð¸ÐºÐ° Ð½Ðµ Ð´Ð¾Ð¿ÑƒÑÐºÐ°ÑŽÑ‚ Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ðµ Ð¾Ñ„Ñ„Ð»Ð°Ð¹Ð½Ð¾Ð²Ñ‹Ñ… ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ð¹'
			else:
				error_name = xmpp.ERR_INTERNAL_SERVER_ERROR
				error_text = 'ÐŸÑ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°'
			self.xmpp_conn.send_error(msg,error_name,error_text)
		elif _id:
			x = msg.getTag('x')
			request = msg.getTag('request')
			if x or request:
				repl_msg = xmpp.Message(frm=msg.getTo())
				repl_msg.setAttr('id', _id)
				need_reply = False
				if x and (x.getNamespace()=='jabber:x:event') \
			       and (not x.getTag('id')) and x.getTag('delivered'):
					id_x = xmpp.Node('x',attrs={'xmlns':'jabber:x:event'})
					id_x.setTag('delivered')
					id_x.setTagData('id',_id)
					repl_msg.addChild(node=id_x)
					need_reply = True
				if request and (request.getNamespace()==xmpp.NS_RECEIPTS):
					id_request = xmpp.Node('received', attrs={'xmlns':xmpp.NS_RECEIPTS})
					repl_msg.addChild(node=id_request)
					need_reply = True
				if need_reply:
					self.send_stanza(repl_msg,msg.getFrom())

	def get_vcard(self, mail, mess):
		if utils.is_valid_email(mail):
			user,domain = mail.split('@')
			d = {
				MRIM_CS_WP_REQUEST_PARAM_USER:user,
				MRIM_CS_WP_REQUEST_PARAM_DOMAIN:domain
			}
			self.mmp_send_wp_request(d, ackf=self.got_vcard, acka={'mail':mail, 'msg':mess})
		else:
			err = xmpp.ERR_ITEM_NOT_FOUND
			err_txt = 'ÐÐµÑ‚ Ñ‚Ð°ÐºÐ¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ'
			self.xmpp_conn.send_error(mess,err,err_txt)

	def anketa2vcard(self, anketa, avatara, ava_typ, album):
		attributes = {'xmlns':"vcard-temp"}
		e_mail = xmpp.Node('EMAIL')
		tel = xmpp.Node('TEL')
		adr = xmpp.Node('ADR')
		N = xmpp.Node('N')
		vcard = xmpp.Node('vCard', attrs=attributes)
		vcard.setTagData('FN', anketa['FirstName'] + ' ' + anketa['LastName'])
		N.setTagData('FAMILY', anketa['LastName'])
		N.setTagData('GIVEN', anketa['FirstName'])
		vcard.addChild(node=N)
		if anketa['Nickname'].strip():
			vcard.setTagData('NICKNAME', anketa['Nickname'])
		else:
			vcard.setTagData('NICKNAME', anketa['Username'])
		try:
			vcard.setTagData('BDAY',anketa['Birthday'])
		except:
			pass
		e_mail.setTagData('INTERNET', '')
		e_mail.setTagData('USERID', anketa['Username']+'@'+anketa['Domain'])
		tel.setTagData('HOME', '')
		tel.setTagData('VOICE', '')
		tel.setTagData('NUMBER', anketa['Phone'])
		vcard.setPayload([tel,e_mail],add=1)
		desc = ''
		if anketa['Sex'] == '1':
			desc = 'ÐŸÐ¾Ð»: ÐœÑƒÐ¶ÑÐºÐ¾Ð¹\n'
		elif anketa['Sex'] == '2':
			desc = 'ÐŸÐ¾Ð»: Ð–ÐµÐ½ÑÐºÐ¸Ð¹\n'
		if ZODIAC.has_key(anketa['Zodiac']):
			desc += 'Ð—Ð½Ð°Ðº Ð·Ð¾Ð´Ð¸Ð°ÐºÐ°: %s\n' % ZODIAC[anketa['Zodiac']]
		location = anketa['Location']
		if location:
			coords = location.strip().split(',')
			if len(coords) == 1:
				country = coords[0].strip()
				adr.setTagData('CTRY', country)
			elif len(coords) == 2:
				country = coords[0].strip()
				city = coords[1].strip()
				adr.setTagData('CTRY', country)
				adr.setTagData('LOCALITY', city)
			elif len(coords) > 2:
				country = coords[0].strip()
				region = ','.join(coords[1:-1]).strip()
				city = coords[-1].strip()
				adr.setTagData('CTRY', country)
				adr.setTagData('REGION', region)
				adr.setTagData('LOCALITY', city)
			vcard.setPayload([adr],add=1)
		if avatara and (ava_typ in ['image/gif','image/jpeg','image/png']):
			photo = xmpp.Node('PHOTO')
			avahex = base64.encodestring(avatara)
			photo.setTagData('TYPE', ava_typ)
			photo.setTagData('BINVAL', '\n'+avahex)
			vcard.setPayload([photo],add=1)
			desc += 'Ð¤Ð¾Ñ‚Ð¾Ð°Ð»ÑŒÐ±Ð¾Ð¼: %s\n' % album.__str__()
		vcard.setTagData('DESC', desc)
		return vcard

	def search(self, vals, mess):
		err = xmpp.ERR_NOT_ACCEPTABLE
		err_txt = 'ÐŸÐµÑ€ÐµÐ´Ð°Ð½Ñ‹ Ð½ÐµÐ²ÐµÑ€Ð½Ñ‹Ðµ Ð´Ð°Ð½Ð½Ñ‹Ðµ Ð´Ð»Ñ Ð¿Ð¾Ð¸ÑÐºÐ°'
		if not vals:
			self.xmpp_conn.send_error(mess,err,err_txt)
			return
		else:
			self.mmp_send_wp_request(vals, self.got_search_result, {'mess':mess})

	def got_search_result(self, anketa, mess):
		status = anketa.getStatus()
		if status not in [MRIM_ANKETA_INFO_STATUS_OK, MRIM_ANKETA_INFO_STATUS_NOUSER]:
			if status == MRIM_ANKETA_INFO_STATUS_DBERR:
				error_name = xmpp.ERR_ITEM_NOT_FOUND
				error_text = 'ÐžÑˆÐ¸Ð±ÐºÐ° Ð¿Ð¾Ð¸ÑÐºÐ° Ð² Ð±Ð°Ð·Ðµ Ð´Ð°Ð½Ð½Ñ‹Ñ…'
			elif status == MRIM_ANKETA_INFO_STATUS_RATELIMERR:
				error_name = xmpp.ERR_REMOTE_SERVER_TIMEOUT
				error_text = 'Ð¡Ð»Ð¸ÑˆÐºÐ¾Ð¼ Ð¼Ð½Ð¾Ð³Ð¾ Ð·Ð°Ð¿Ñ€Ð¾ÑÐ¾Ð². ÐŸÐ¾Ð¸ÑÐº Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾ Ð¿Ñ€Ð¸Ð¾ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½'
			else:
				error_name = xmpp.ERR_ITEM_NOT_FOUND
				error_text = 'ÐÐµÐ¸Ð·Ð²ÐµÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°'
			self.xmpp_conn.send_error(mess,error_name,error_text)
			return
		xdf = forms.anketa2search(anketa.getVCards())
		iq_form = xmpp.Iq(frm=conf.name,typ='result')
		iq_form.setAttr('id', mess.getAttr('id'))
		iq_form.setQueryNS(xmpp.NS_SEARCH)
		iq_form.setQueryPayload([xdf])
		self.send_stanza(iq_form, mess.getFrom())

	def set_sms_phones(self, mail, numbers):
		self.mmp_modify_sms(mail, numbers)

	def uptime(self):
		return utils.uptime(time.time() - self.starttime)

	def getResources(self):
		return self.resources.keys()

	def delResource(self, resource):
		if self.resources.has_key(resource):
			del self.resources[resource]
			for r in self.prios:
				if r[1] == resource:
					self.prios.remove(r)

	def updatePriority(self, resource, priority, show):
		if self.resources.has_key(resource):
			try:
				prio = int(priority)
				for r in self.prios:
					if r[1] == resource:
						self.prios.remove(r)
						bisect.insort(self.prios, (prio, resource, show))
			except TypeError, ValueError:
				pass

	def getMaxPriority(self):
		return self.prios[-1][0]

	def getMaxResource(self):
		return self.prios[-1][1]

	def getMaxShow(self):
		return self.prios[-1][2]

	def getMaxJid(self):
		jid = xmpp.JID(self.jid)
		jid.setResource(self.getMaxResource())
		return jid

	def haveResource(self, resource):
		return self.resources.has_key(resource)

	def getResourceCaps(self, resource):
		if self.resources.has_key(resource):
			return self.resources[resource]
		else:
			return ""

	def addResource(self, resource, priority, show, ver=("","")):
		if not self.resources.has_key(resource):
			self.resources[resource] = ver
			try:
				prio = int(priority)
			except TypeError, ValueError:
				prio = 0
			bisect.insort(self.prios, (prio, resource, show))
			to = xmpp.JID(self.jid)
			to.setResource(resource)
			self.xmpp_conn.request_caps(ver, to)