#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2005-2006 Insecure.Com LLC.
# Copyright (C) 2007-2008 Adriano Monteiro Marques
#
# Authors: Adriano Monteiro Marques <adriano@umitproject.org>
#          Cleber Rodrigues <cleber.gnu@gmail.com>
#          Frederico Silva Ribeiro <ribeiro.fsilva@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

import os
import sys
import signal

# used by exception hook
import cgitb
import tempfile

from umitCore.I18N import _
from umitCore.Version import VERSION
#########################

UMIT_DEVELOPMENT = os.environ.get("UMIT_DEVELOPMENT", False)

class UmitExceptionHook(object):
    def __call__(self, etype, emsg, etb):
        import warnings
        warnings.filterwarnings("error", module = "gtk")
        try:
            import gtk
            from umitGUI.BugReport import CrashReport
            from higwidgets.higdialogs import HIGAlertDialog
        except Warning, e:
            print e.message
            sys.exit(-1)
        warnings.resetwarnings()

        # Getting dependencies versions
        import higwidgets
        import umitCore
        import umitGUI

        gtk_version = "%s.%s.%s" % gtk.gtk_version
        pygtk_version = "%s.%s.%s" % gtk.ver
        higwidgets_version = getattr(higwidgets, "__version__", "< 0.9.5")
        python_version = sys.version
        nmap_version = os.popen2("nmap -V")[1].read().strip("\n")
        osuname = " ".join(os.uname())
        umit_version = VERSION
        umitCore_version = getattr(umitCore, "__version__", "< 0.9.5")
        umitGUI_version = getattr(umitGUI, "__version__", "< 0.9.5")

        versions = _("""
Versions:
---
GTK: %s
PyGTK: %s
HIGWidgets: %s
Python: %s
Nmap: %s
Operating System: %s
Umit: %s
UmitCore: %s
UmitGUI: %s
---""") % (gtk_version,
           pygtk_version,
           higwidgets_version,
           python_version,
           nmap_version,
           osuname,
           umit_version,
           umitCore_version,
           umitGUI_version)

        if etype == ImportError:
            d = HIGAlertDialog(type=gtk.MESSAGE_ERROR,
                message_format=_("Import error"),
                secondary_text=_("\nA required module was not "
                    "found.\n\nError: %s" % emsg))
            d.run()
            d.destroy()
            return
        crash_text = cgitb.text((etype, emsg, etb))
        crash_text_dialog = "\n%s\n%s\n" % (versions, crash_text)
        crash_text= "{{{\n%s\n%s\n}}}" % (versions, crash_text)
        
        #Dialog info
        extrainfo_dialog = "%-17s %s\n%-17s %s\n%-17s %s\n%-17s %s\n" % (
            "sys.platform", sys.platform, "os.name", os.name, 
            "Gtk version", '.'.join(map(str, gtk.gtk_version)), 
            "Umit version", VERSION)
        crashmsg_dialog = "Crash Report\n%s\n%s\nDescription\n%s\n%s" % \
                        ('=' * 10, extrainfo_dialog, '-' * 20,\
                         crash_text_dialog)
        
        extrainfo = "%-17s %s\n[[BR]]%-17s %s\n[[BR]]%-17s %s\n[[BR]]%-17s %s[[BR]]\n" % (
            "sys.platform", sys.platform, "os.name", os.name, 
            "Gtk version", '.'.join(map(str, gtk.gtk_version)), 
            "Umit version", VERSION)
        crashmsg = "Crash Report\n[[BR]]%s[[BR]]\n[[BR]]%s\nDescription\n%s\n%s" % ('=' * 10, 
            extrainfo, '-' * 20, crash_text)

        try:
            try:
                cwin = CrashReport("Umit Crash - '%s'" % emsg, crashmsg,
                                   description_dialog=crashmsg_dialog)
                cwin.show_all()
                while True: 
                    # keeping running while bug report is not sent successfully,
                    # or until the user closes the window.
                    result = cwin.run()
                    if result in (gtk.RESPONSE_CANCEL,
                        gtk.RESPONSE_DELETE_EVENT,
                        gtk.RESPONSE_NONE):

                        cwin.destroy()
                        break
            except:
                tempfd, tempname = tempfile.mkstemp()
                os.write(tempfd, crashmsg_dialog)
                d = HIGAlertDialog(type=gtk.MESSAGE_ERROR,
                    message_format=_("Bug not reported"),
                    secondary_text=_("A critical error occourried during "
                        "Umit execution, \nand it was not properly reported " 
                        "to our bug tracker. The crash description was saved to: "
                        "%s, so you can still report it on our bug "
                        "tracker.") % tempname)
                os.close(tempfd)
                d.run()
                d.destroy()
        finally:
            gtk.main_quit()


if not UMIT_DEVELOPMENT:
    
    from tempfile import mktemp
    # Generating temporary files names
    stdout_output = mktemp()
    stderr_output = mktemp()

    old_stdout = sys.stdout
    old_stderr = sys.stderr

    _stdout = open(stdout_output, "w")
    _stderr = open(stderr_output, "w")

    sys.stdout = _stdout
    sys.stderr = _stderr

    
    sys.excepthook = UmitExceptionHook()

def main(args):
    # Setting the umit home directory
    from umitCore.Paths import Path
    Path.set_umit_conf(os.path.split(args[0])[0])
    #################################

    from umitGUI.App import App

    umit_app = App()

    if os.name == "posix":
        signal.signal(signal.SIGHUP, umit_app.safe_shutdown)
    signal.signal(signal.SIGTERM, umit_app.safe_shutdown)
    signal.signal(signal.SIGINT, umit_app.safe_shutdown)

    try:
        umit_app.run()
    except KeyboardInterrupt:
        sys.exit(signal.SIGINT)

if __name__ == "__main__":
    main(sys.argv)
