#!/usr/bin/env python
#
# @package      hubzero-forge
# @file         gensvnapache.py
# @author       Nicholas J. Kisseberth <nkissebe@purdue.edu>
# @copyright    Copyright (c) 2010-2015 HUBzero Foundation, LLC.
# @license      http://opensource.org/licenses/MIT MIT
#
# Copyright (c) 2010-2015 HUBzero Foundation, LLC.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# HUBzero is a registered trademark of HUBzero Foundation, LLC.
#

# Really quick and dirty port of the perl script of similar name
# but querying project data from MySQL instead of LDAP.
# This should get cleaned up an rewritten to use
# the hubzero python library (which isn't ready
# at the time of this writing).
#

import os
import ConfigParser
import re
import MySQLdb
import string
import sys
import subprocess

#
# Detect whether we are running Apache 2.2 or not so we set proper configuration
# directives later on. We assume 2.2 until proven otherwise. We also assume
# standard Debian or Redhat server locations. If running a custom installation
# this will likely fall back to assuming 2.2.
#
# @TODO: Add commandline or environment variable overrides to the autodetection
#

apache_2_2 = True
apache_bin = False

if os.path.exists('/usr/sbin/apache2'):
     apache_bin = '/usr/sbin/apache2'

if os.path.exists('/usr/sbin/httpd'):
     apache_bin = '/usr/sbin/httpd'

if apache_bin:
  proc = subprocess.Popen([apache_bin, "-v"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  out, err = proc.communicate()

  needle = r'(?m)^.*Apache/(\d+)\.(\d+)\.(\d+).*$'

  m = re.match(needle, out)

  if m and m.group(1) >= 2 and m.group(2) > 2:
    apache_2_2 = False

db = False
dbcursor = False

data = {}
data['joomla'] = {}
data['hubzero'] = {}
config = ConfigParser.RawConfigParser()
config.read('/etc/hubzero.conf')
section = config.get('DEFAULT','site')
docroot = config.get(section, 'DocumentRoot')

file_read = open(docroot + '/configuration.php',"r")
contents = file_read.read()
file_read.close()
for m in re.finditer("\s*(?:var|public)\s+\$(\w+)\s*=\s*\'*(.*?)\'*\s*\;\s*", contents):
  data['joomla'][m.group(1)] = m.group(2).strip(" \'\"\t")

file_read = open(docroot + '/hubconfiguration.php',"r")
contents = file_read.read()
file_read.close()
for m in re.finditer("\s*(?:var|public)\s+\$(\w+)\s*=\s*\'*(.*?)\'*\s*\;\s*", contents):
  data['hubzero'][m.group(1)] = string.replace(m.group(2).strip(" \'\"\t"),"\\'","'")

mysql_host = data['joomla']['host']
mysql_user = data['joomla']['user']
mysql_password = data['joomla']['password']
mysql_db = data['joomla']['db']
ldapbase = data['hubzero']['hubLDAPBaseDN']
ldaphost = data['hubzero']['hubLDAPMasterHost']
ldapbinduser = data['hubzero']['hubLDAPSearchUserDN']
ldapbindpass = data['hubzero']['hubLDAPSearchUserPW']
ldapgroupobjectclass = 'posixGroup'
try:
  ldapgroupobjectclass = data['hubzero']['hubLDAPGroupObjectClass']
except:
  pass

if (ldapgroupobjectclass != 'posixGroup'):
  ldapgroupobjectclass = 'hubGroup'

try:
  db = MySQLdb.connect(host=mysql_host, user=mysql_user, passwd=mysql_password, db=mysql_db)
except:
  pass

if len(sys.argv) != 5 and len(sys.argv) != 6:
    print "Usage: " + sys.argv[0] + " svn_root_path svn_url_path hub_path [type]"
    sys.exit(1)

svnroot = sys.argv[1]
svnurl = sys.argv[2]
hubdir = sys.argv[3]
svnauthz = False

if len(sys.argv) == 5:
  type = sys.argv[4]
else:
  type = None

if (not os.path.isdir(svnroot)):
  print "Error:  '" + svnroot + "' is not a valid directory."
  sys.exit(2)

if (not os.path.isdir(hubdir)):
  print "Error: '" + hubdir + "' is not a valid directory."
  sys.exit(3)

if not db:
  print "Error: Unable to connect to HUBzero database."
  sys.exit(4)

cursor = db.cursor()

if not cursor:
  print "Error: Unable to obtain HUBzero database cursor."
  sys.exit(5)

dirlist = os.listdir(svnroot)

print "#"
print "# Apache configuration for SVN repositories";
print "#";
print "# This file is generated automatically from MySQL.";
print "#      !!!  DO NOT MODIFY THIS FILE  !!!";
print "#";
print "";

for dir in dirlist:
    if (not os.path.isdir(svnroot + '/' + dir)):
	continue

    sourcepublic = False
    id = dir
    if (type != 'tool'):
      gid = []
      gid.append(id)
      gid.append('apps')
      name=id
    else:
      gid = set([])
      cursor.execute("SELECT title,codeaccess,tg.cn FROM jos_tool_version AS tv, jos_tool_groups AS tg WHERE tg.toolid=tv.toolid AND tv.toolname='" + id + "' AND state='3' AND (tg.role=1 or tg.role=2)")
      rows = cursor.fetchall()
      if len(rows) == 0:
        continue
      name = id
      for name,sourcepublic,gidref in rows:
        if (sourcepublic == '@OPEN'):
          sourcepublic = True
        else:
          sourcepublic = False
        gid.add(gidref)
      #if (len(gid) == 0):
      #	  print name + " has no groups"

    if (os.path.isfile(svnroot + "/" + id + "/conf/svnauthz.conf")):
      svnauthz = True
    else:
      svnauthz = False

    url = string.replace(svnurl, "@PROJECT@", id)

    print "<Location " + url + ">"
    print "\tRemoveEncoding .tgz"
    print "\tRemoveEncoding .gz"
    print "\tRemoveEncoding .Z"
    print "\tDAV svn"
    print "\tSVNPath " + svnroot + "/" + id
    print "\tAuthType Basic"
    print "\tAuthBasicProvider ldap"
    print "\tAuthName \"" + name.replace('"',r'\"') + " Subversion Repository\""
    if apache_2_2:
      print "\tAuthzLDAPAuthoritative on"
    if (ldapbinduser != ""):
      print "\tAuthLDAPBindDN \"" + ldapbinduser + "\""
      print "\tAuthLDAPBindPassword \"" + ldapbindpass + "\""
    if (ldapgroupobjectclass == 'hubGroup'):
      print "\tAuthLDAPGroupAttributeIsDN on"
      print "\tAuthLDAPGroupAttribute owner"
      print "\tAuthLDAPGroupAttribute member"
    else:
      print "\tAuthLDAPGroupAttributeIsDN off"
      print "\tAuthLDAPGroupAttribute memberUid"

    print "\tAuthLDAPURL " + ldaphost + "/ou=users," + ldapbase 

    if svnauthz:
      print "\tAuthzSVNAccessFile " + svnroot + "/" + id + "/conf/svnauthz.conf"
      print "\tRequire valid-user"
      if sourcepublic:
        print "\tSatisfy Any"
    else:
      if sourcepublic:
        print "\t<LimitExcept GET PROPFIND OPTIONS REPORT>"
      for group in gid:
        if sourcepublic:
          print "\t",
        if (ldapgroupobjectclass == 'hubGroup'):
          print "\tRequire ldap-group gid=" + group  + ",ou=groups," + ldapbase
        else:
          print "\tRequire ldap-group cn=" + group  + ",ou=groups," + ldapbase
      if sourcepublic:
        print "\t</LimitExcept>"

    print "</Location>"
    print ""
 
