# -*- coding: utf-8 -*-
"""
w2lapp.core.py: some core functions used throughout web2ldap

web2ldap - a web-based LDAP Client,
see http://www.web2ldap.de for details

(c) by Michael Stroeder <michael@stroeder.com>

This module is distributed under the terms of the
GPL (GNU GENERAL PUBLIC LICENSE) Version 2
(see http://www.gnu.org/copyleft/gpl.html)
"""

import sys,os,time,traceback,ldap,ldif,w2lapp.cnf,w2lapp

from types import StringType,UnicodeType,ListType

def str2unicode(s,charset):
  if type(s) is StringType:
    try:
      return unicode(s,charset)
    except UnicodeError:
      return unicode(s,'iso-8859-1')
  else:
    return s


def guessClientAddr(env=None):
  """
  Guesses the host name or IP address of the HTTP client by looking
  at various HTTP headers mapped to CGI-BIN environment.

  env
        dictionary containing environment vars (default os.env)
  """
  env = env or os.environ
  return env.get('FORWARDED_FOR',
         env.get('HTTP_X_FORWARDED_FOR',
         env.get('REMOTE_HOST',
         env.get('REMOTE_ADDR',None))))


class ErrorExit:
  """Base class for web2ldap application exceptions"""

  def __init__(self,Msg):
    assert type(Msg)==UnicodeType, TypeError("Type of argument 'Msg' must be UnicodeType: %s" % repr(Msg))
    self.Msg = Msg


LOG_SEPARATOR = '-'*60

def log_exception(errf,ls,env):
  """
  Write an exception with environment vars, LDAP connection data
  and Python traceback to errf file object.
  """
  # Get exception instance and traceback info
  exc_obj,exc_value,exc_traceback = sys.exc_info()
  # Signals are raised again to trigger handling in main process
  logentry = [
    LOG_SEPARATOR,
    'Unhandled error at %s' % (
      time.strftime(
        '%Y-%m-%dT%H:%M:%SZ',time.gmtime(time.time())
      ),
    ),
    'web2ldap version: %s' % w2lapp.__version__,
    'LDAPSession instance: %s' % repr(ls),
  ]
  # Log all known rootDSE attributes
  if not ls is None:
    logentry.append(ldif.CreateLDIF('',ls.rootDSE.data))
  # Log all environment vars
  env_vars = env.keys();env_vars.sort()
  for v in env_vars:
    logentry.append('%s: "%s"' % (v,env[v]))
  logentry.append(''.join(traceback.format_exception(exc_obj,exc_value,exc_traceback,20)))
  # Write the log entry to errf file object
  errf.write(os.linesep.join(logentry))
  # Avoid memory leaks
  exc_obj=None;exc_value=None;exc_traceback=None
  del exc_obj;del exc_value;del exc_traceback


########################################################################
# Initialize some constants
########################################################################

# Raise UnicodeError instead of output of UnicodeWarning
from exceptions import UnicodeWarning
from warnings import filterwarnings
filterwarnings(action="error", category=UnicodeWarning)

# Switch off processing .ldaprc or ldap.conf
os.environ['LDAPNOINIT']='1'

ldap._trace_level=w2lapp.cnf.misc.ldap_trace_level
ldap.set_option(ldap.OPT_DEBUG_LEVEL,w2lapp.cnf.misc.ldap_opt_debug_level)
ldap.set_option(ldap.OPT_RESTART,0)
ldap.set_option(ldap.OPT_DEREF,0)
ldap.set_option(ldap.OPT_REFERRALS,0)

startUpTime = time.time()

# Set up configuration for restricting access to the preconfigured LDAP URI list
ldap_uri_list_check_dict = w2lapp.cnf.PopulateCheckDict(w2lapp.cnf.hosts.ldap_uri_list)
