#!/usr/bin/env python
 
# -*- coding: utf-8 -*-
 
 
 
"""Methods for reporting bugs."""
 
 
 
import subprocess, sys, os
 
 
 
__all__ = ['ReportFailure', 'BugReport', 'getReporters']
 
 
 
#
 
 
 
class ReportFailure(Exception):
 
    """Generic exception for failures in bug reporting."""
 
    def __init__(self, value):        
 
        self.value = value
 
 
 
# Collect information about a bug.
 
 
 
class BugReport(object):
 
    def __init__(self, title, description, files):
 
        self.title = title
 
        self.description = description
 
        self.files = files
 
 
 
# Reporter interfaces.
 
 
 
import os
 
 
 
import email, mimetypes, smtplib
 
from email import encoders
 
from email.message import Message
 
from email.mime.base import MIMEBase
 
from email.mime.multipart import MIMEMultipart
 
from email.mime.text import MIMEText
 
 
 
#===------------------------------------------------------------------------===#
 
# ReporterParameter
 
#===------------------------------------------------------------------------===#
 
 
 
class ReporterParameter(object):
 
  def __init__(self, n):
 
    self.name = n
 
  def getName(self):
 
    return self.name
 
  def getValue(self,r,bugtype,getConfigOption):
 
     return getConfigOption(r.getName(),self.getName())
 
  def saveConfigValue(self):
 
    return True
 
 
 
class TextParameter (ReporterParameter):
 
  def getHTML(self,r,bugtype,getConfigOption):
 
    return """\
 
<tr>
 
<td class="form_clabel">%s:</td>
 
<td class="form_value"><input type="text" name="%s_%s" value="%s"></td>
 
</tr>"""%(self.getName(),r.getName(),self.getName(),self.getValue(r,bugtype,getConfigOption))
 
 
 
class SelectionParameter (ReporterParameter):
 
  def __init__(self, n, values):
 
    ReporterParameter.__init__(self,n)
 
    self.values = values
 
    
 
  def getHTML(self,r,bugtype,getConfigOption):
 
    default = self.getValue(r,bugtype,getConfigOption)
 
    return """\
 
<tr>
 
<td class="form_clabel">%s:</td><td class="form_value"><select name="%s_%s">
 
%s
 
</select></td>"""%(self.getName(),r.getName(),self.getName(),'\n'.join(["""\
 
<option value="%s"%s>%s</option>"""%(o[0],
 
                                     o[0] == default and ' selected="selected"' or '',
 
                                     o[1]) for o in self.values]))
 
 
 
#===------------------------------------------------------------------------===#
 
# Reporters
 
#===------------------------------------------------------------------------===#
 
 
 
class EmailReporter(object):
 
    def getName(self):
 
        return 'Email'
 
 
 
    def getParameters(self):
 
        return [TextParameter(x) for x in ['To', 'From', 'SMTP Server', 'SMTP Port']]
 
 
 
    # Lifted from python email module examples.
 
    def attachFile(self, outer, path):
 
        # Guess the content type based on the file's extension.  Encoding
 
        # will be ignored, although we should check for simple things like
 
        # gzip'd or compressed files.
 
        ctype, encoding = mimetypes.guess_type(path)
 
        if ctype is None or encoding is not None:
 
            # No guess could be made, or the file is encoded (compressed), so
 
            # use a generic bag-of-bits type.
 
            ctype = 'application/octet-stream'
 
        maintype, subtype = ctype.split('/', 1)
 
        if maintype == 'text':
 
            fp = open(path)
 
            # Note: we should handle calculating the charset
 
            msg = MIMEText(fp.read(), _subtype=subtype)
 
            fp.close()
 
        else:
 
            fp = open(path, 'rb')
 
            msg = MIMEBase(maintype, subtype)
 
            msg.set_payload(fp.read())
 
            fp.close()
 
            # Encode the payload using Base64
 
            encoders.encode_base64(msg)
 
        # Set the filename parameter
 
        msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(path))
 
        outer.attach(msg)
 
 
 
    def fileReport(self, report, parameters):
 
        mainMsg = """\
 
BUG REPORT
 
---
 
Title: %s
 
Description: %s
 
"""%(report.title, report.description)
 
 
 
        if not parameters.get('To'):
 
            raise ReportFailure('No "To" address specified.')
 
        if not parameters.get('From'):
 
            raise ReportFailure('No "From" address specified.')
 
 
 
        msg = MIMEMultipart()
 
        msg['Subject'] = 'BUG REPORT: %s'%(report.title)
 
        # FIXME: Get config parameters
 
        msg['To'] = parameters.get('To')
 
        msg['From'] = parameters.get('From')
 
        msg.preamble = mainMsg
 
 
 
        msg.attach(MIMEText(mainMsg, _subtype='text/plain'))
 
        for file in report.files:
 
            self.attachFile(msg, file)
 
 
 
        try:
 
            s = smtplib.SMTP(host=parameters.get('SMTP Server'),
 
                             port=parameters.get('SMTP Port'))
 
            s.sendmail(msg['From'], msg['To'], msg.as_string())
 
            s.close()
 
        except:
 
            raise ReportFailure('Unable to send message via SMTP.')
 
 
 
        return "Message sent!"
 
 
 
class BugzillaReporter(object):
 
    def getName(self):
 
        return 'Bugzilla'
 
    
 
    def getParameters(self):
 
        return [TextParameter(x) for x in ['URL','Product']]
 
 
 
    def fileReport(self, report, parameters):
 
        raise NotImplementedError
 
 
 
 
 
class RadarClassificationParameter(SelectionParameter):
 
  def __init__(self):
 
    SelectionParameter.__init__(self,"Classification",
 
            [['1', 'Security'], ['2', 'Crash/Hang/Data Loss'],
 
             ['3', 'Performance'], ['4', 'UI/Usability'], 
 
             ['6', 'Serious Bug'], ['7', 'Other']])
 
 
 
  def saveConfigValue(self):
 
    return False
 
    
 
  def getValue(self,r,bugtype,getConfigOption):
 
    if bugtype.find("leak") != -1:
 
      return '3'
 
    elif bugtype.find("dereference") != -1:
 
      return '2'
 
    elif bugtype.find("missing ivar release") != -1:
 
      return '3'
 
    else:
 
      return '7'
 
 
 
###
 
 
 
def getReporters():
 
    reporters = []
 
    reporters.append(EmailReporter())
 
    return reporters