#!/usr/bin/env python
# -*- coding: utf-8 -*-

import stat, os, time, threading, datetime
from logging import getLogger
from db import conn_scope, session_scope, row2dict, MailAlert, MailSet, Session
from config import config
from smtplib import SMTP_SSL, SMTP
from email.header import Header
from email.mime.text import MIMEText
from jinja2 import Environment, PackageLoader, FileSystemLoader

def sendmail(server, user, passwd, sender, receiver, title, context, charset='utf-8', debug=False):
    smtp = SMTP(server)
    if debug:
        smtp.set_debuglevel(1)
    smtp.login(user, passwd)
    msg = MIMEText(context, _charset=charset)
    msg["Subject"] = Header(title, charset)
    msg["from"] = sender
    msg["to"] = receiver
    smtp.sendmail(sender, receiver, msg.as_string())
    #smtp.close()
    smtp.quit()

def get_statistics(hour):
    data = {'ALL': 0,
            'SQLI': 0,
            'XSS': 0,
            'GENERIC': 0,
            'PROTOCOL': 0,
            'TROJANS': 0,
            'LEAKAGE': 0,
            'OVERFLOW': 0,
            'ACCESSCTRL': 0,
            'OTHER': 0, 
            'CC': 0, 
            'DDOS': 0,
            'OUTBOUND': 0,
            'INTERVAL': hour,
            }
    t = datetime.datetime.now() - datetime.timedelta(hours=hour)
    getLogger('main').info('alertor get_statistics begin.')
    with conn_scope(**config['db']) as (conn, cursor):
        # cursor.execute("SELECT MAX(number) FROM logs.t_weboutlogs where dt > '%s';" % (t.strftime('%Y-%m-%d %H:%M:%S'), ) )
        cursor.execute("SELECT count(number) FROM logs.t_weboutlogs where dt > '%s';" % (t.strftime('%Y-%m-%d %H:%M:%S'), ) )
        (data['OUTBOUND'], ) = cursor.fetchone()
        # cursor.execute("SELECT MAX(id) FROM logs.t_ddoslogs where logtime > %s;" % (int(time.mktime(t.timetuple())), ) )
        cursor.execute("SELECT count(id) FROM logs.t_ddoslogs where logtime > %s;" % (int(time.mktime(t.timetuple())), ) )
        (data['DDOS'], ) = cursor.fetchone()
        if data['OUTBOUND']==None:
           data['OUTBOUND']=0
        if data['DDOS']==None:
           data['DDOS']=0
        data['ALL'] = data['OUTBOUND'] + data['DDOS']
        cursor.execute("SELECT `name`,`desc` FROM waf.t_rulecat WHERE 1 ORDER BY id ASC")
        for name, desc in cursor.fetchall():
            sqlstr = "SELECT count(id) FROM logs.t_alertlogs WHERE LogDateTime > '%s' AND RuleID IN \
                 (SELECT realid FROM waf.t_rules WHERE type='%s')" % (t.strftime('%Y-%m-%d %H:%M:%S'), name)
            cursor.execute(sqlstr)
            (data[name.upper()], ) = cursor.fetchone()
            data['ALL'] = data['ALL'] + data[name.upper()]
            #print("name: %s === desc: %s" % (name, desc))
        cursor.execute("SELECT * FROM waf.t_sitestatus WHERE time > '%s';" % (int(time.mktime(t.timetuple())), ) )
        url_status=[]
        results=cursor.fetchall()
        cursor.execute("SELECT count(*) FROM waf.t_sitestatus WHERE time > '%s';" % (int(time.mktime(t.timetuple())), ) )
        count=cursor.fetchall()[0][0]
        for result in results:
             if result[4]==0:
                site_status={}
                site_status['url']=result[1]
                site_status['desc']=result[5]
                url_status.append(site_status)
        url_status.append({'count':int(count)})     
        data['url']=url_status        
    getLogger('main').info('alertor get_statistics end.')
    return data,url_status

    

class Alertor(threading.Thread):
    ''' 报警器 '''
    
    event = threading.Event()

    def __init__(self, ):
        super(Alertor, self).__init__(name = self.__class__.__name__)
    
    def start(self):
        getLogger('main').debug(self.__class__.__name__+ ' starting...')
        super(Alertor, self).start()
        getLogger('main').info(self.__class__.__name__+ ' started.')

    def stop(self):
        getLogger('main').debug(self.__class__.__name__+ ' Exiting...')
        self.event.set()
        self.join()
        getLogger('main').info(self.__class__.__name__+ ' Exited.')

    def proc(self, mailset, mailalert):
        (data,url_status) = get_statistics(mailalert['interval'])
        #getLogger('main').info(str(data))
        if data['ALL'] >0:
            data['DATE'] = time.strftime('%Y-%m-%d %X',time.localtime(time.time()))
            title = '蓝盾Web防火墙报警 ' + time.strftime('%Y-%m-%d', time.localtime(time.time()))
            msg = Environment(loader=FileSystemLoader('data/template/')).get_template('statistics').render(data=data)
            getLogger('main').info(msg)
            #user = mailset.username
            user = mailset['sender'].split("@")[0]
            if int(mailalert['phone_status']) == 1:
                os.system('echo "%s" | /usr/local/bluedon/gnokii/bin/gnokii --config /usr/local/bluedon/gnokii/config --sendsms %s' % (msg.encode('utf-8'), mailset['receiver_phone'].encode('utf-8')))
            if int(mailalert['status']) == 1:
                sendmail(mailset['smtpserver'], user, mailset['password'], mailset['sender'], mailset['receiver'], title, msg)
            
    def run(self):
        '''
        读报警日志的总数，与上次的记录的总数相减。数字大于0就发送邮件报警。
        '''
        interval = 1
        while 1:
            try:
                for _ in range(60*60):
                    time.sleep(1)
                    interval = interval + 1
                    if self.event.isSet():
                        return
                with session_scope() as session:
                    mailalert = row2dict(session.query(MailAlert).first())
                    if not mailalert:
                        continue
                    if mailalert['interval'] <= 0:
                        continue;
                    if int(mailalert['status']) != 1 and int(mailalert['phone_status']) != 1:
                        continue
                    if interval >= 60 * 60 * int(mailalert['interval']):
                       interval = 0
                       mailset = row2dict(session.query(MailSet).first())
                       if not mailset: 
                          continue
                       self.proc(mailset, mailalert)
            except Exception, e:
                getLogger('main').exception(e)
                
if __name__ == '__main__':
    #test_get_statistics()
    #echo '你好' | ./bin/gnokii --config config --sendsms 13929530587
    #exit(0)
    '''
    session = Session()
    mailalert = session.query(MailAlert).one()
    #self.interval = 60 * 60 * int(mailalert.interval)
    if 1:
        mailset = session.query(MailSet).one()
        user = mailset.sender.split("@")[0]
	#user = mailset.username
        interval = 0
        data = {'SENDOR': mailset.username, 'INTERVAL': mailalert.interval}
       
	title = "蓝盾Web防火墙报警" 
	msg = "test"
	sendmail(mailset.smtpserver, user, mailset.password, mailset.sender, mailset.receiver, title, msg)
	exit(0)
        get_statistics(data)
        if data['ALL'] > 0:
            data['DATE'] = time.strftime('%Y-%m-%d %X',time.localtime(time.time()))
            title = '蓝盾Web防火墙报警 ' + time.strftime('%Y-%m-%d', time.localtime(time.time()))
            msg = Environment(loader=FileSystemLoader('data/template/')).get_template('statistics').render(data=data)
            getLogger('main').info(msg)
            sendmail(mailset.smtpserver, user, mailset.password, mailset.sender, mailset.receiver, title, msg)
    exit(0)
    '''
    context = '''<p>入侵分类数据统计:</p>
         <p style="text-indent:2em;">入侵总数: $count</p>
         <p style="text-indent:2em;">SQL注入: $num1</p>
         <p style="text-indent:2em;">XSS跨站脚本: $num2</p>
         <p style="text-indent:2em;">通用攻击: $num3</p>
         <p style="text-indent:2em;">HTTP协议保护: $num4</p>
         <p style="text-indent:2em;">特洛伊木马: $num5</p>
         <p style="text-indent:2em;">信息泄漏: $num6</p>
         <p style="text-indent:2em;">其它攻击: $num7</p>
         <p style="text-indent:2em;">发送日期: $date</p>'''
    sendmail('smtp.163.com', 'testfor51', 'testforwy', 'testfor51@163.com', 'testfor51@163.com', 'title', context)
    #sendmail2()
