/**
* reduce_ip_delegation($oldmipb,$newmipb,$childauDN,$auDN)  
* Einen an eine untergeordnete AU delegierten IP Bereich verkleinern. Diese Funktion wird rekursiv fuer
* alle weiter-delegierten Teilbereiche abgearbeitet. FreeIPBlocks der AU und Child-AU, sowie MaxIPBlocks
* der Child-AU werden angepasst.
*
* @param string oldmipb delegierter maximaler IP Bereich, der verkleinert werden soll
* @param string newmipb delegierter maximaler IP Bereich nach der Verkleinerung
* @param string childauDN Distinguished Name des untergeordneten (Child) LDAP AU-Objektes
* @param string auDN Distinguished Name des LDAP AU-Objektes
*
* @return boolean 1 bei Erfolg bzw. 0 bei Misserfolg
*
* @author Tarik Gasmi
*/
function reduce_ip_delegation($oldmipb, $newmipb, $childauDN, $auDN)
{
    global $ds, $suffix, $ldapError;
    # Durch Reduzierung zu loeschende IP Ranges (Array)
    $delip = split_iprange($newmipb, $oldmipb);
    #print_r($delip);printf("<br><br>");
    # Finde unter allen Child-AUs diejenigen, die von Reduzierung betroffene Child-Child-AUs haben
    # Diese sind werden rekursiv abgearbeitet
    $cchild_array = get_childau($childauDN, array("dn", "maxipblock"));
    $cchild_todo = array();
    foreach ($delip as $delipitem) {
        foreach ($cchild_array as $item) {
            if (count($item['maxipblock']) > 1) {
                foreach ($item['maxipblock'] as $item2) {
                    if (intersect_ipranges($delipitem, $item2) != false) {
                        $cchild_todo[] = array('coldmipb' => $item2, 'cnewmipb' => intersect_ipranges($newmipb, $item2), 'ccauDN' => $item['dn'], 'childauDN' => $childauDN);
                    }
                }
            } elseif (count($item['maxipblock']) == 1) {
                if (intersect_ipranges($delipitem, $item['maxipblock']) != false) {
                    $cchild_todo[] = array('coldmipb' => $item['maxipblock'], 'cnewmipb' => intersect_ipranges($newmipb, $item['maxipblock']), 'ccauDN' => $item['dn'], 'childauDN' => $childauDN);
                }
            }
        }
    }
    #print_r($cchild_todo);printf("<br><br>");
    ######################
    # Rekursionsaufruf (für jede Child-AU, die betroffene Child-Child-AU hat)
    foreach ($cchild_todo as $item) {
        if ($item['cnewmipb'] == false) {
            delete_ip_delegation($item['coldmipb'], $item['ccauDN'], $item['childauDN']);
        } else {
            reduce_ip_delegation($item['coldmipb'], $item['cnewmipb'], $item['ccauDN'], $item['childauDN']);
        }
    }
    ######################
    # Ab hier: alles was bei jedem Fkt.Aufruf zu machen ist (auf Ebene AU und Child-AU)
    # in CAU Check ob RechnerIPs oder DhcpIPs betroffen:
    # - falls ja: nochmals Abfrage (Hammermethode: diese auch loeschen) ob diese zu loeschen sind
    #   -> ja, betreffende IPs loeschen
    #   -> nein, Abbruch.
    # - falls nein: fuer jedes FIPB in CAU intersect(FIPB,newmipb)-> Schnittmengen bilden die neuen FIPB
    $del_objects = objects_to_adjust($newmipb, $delip, $childauDN, $cchild_array);
    # print_r($del_objects);printf("<br><br>");
    if (count($del_objects['hostips']) != 0) {
        printf("<br>Host IP Addresses that will be deleted: <br>");
        foreach ($del_objects['hostips'] as $item) {
            printf("HostDN: %s &nbsp;&nbsp; IP Address: %s <br>", $item['dn'], $item['ip']);
        }
    }
    if (count($del_objects['dhcpranges']) != 0) {
        printf("<br>Subnet IP Ranges that will be adjusted: <br>");
        foreach ($del_objects['dhcpranges'] as $item) {
            printf("DhcpObjectDN: %s &nbsp;&nbsp; New IP Range: %s <br>", $item['dn'], $item['newrange']);
        }
    }
    # momentan wird einfach geloescht:
    if (count($del_objects['hostips']) != 0) {
        foreach ($del_objects['hostips'] as $item) {
            delete_ip_host($item['dn'], $item['auDN']);
        }
    }
    if (count($del_objects['dhcpranges']) != 0) {
        foreach ($del_objects['dhcpranges'] as $item) {
            if (count($item['newrange']) >= 1) {
                modify_ip_dhcprange($item['newrange'], $item['dn'], $item['auDN']);
            } else {
                delete_ip_dhcprange($item['dn'], $item['auDN']);
            }
        }
    }
    # in Child-AU: oldmipb -> newmipb
    $mipb_array = get_maxipblocks_au($childauDN);
    # print_r($mipb_array);printf("<br><br>");
    foreach ($delip as $delipitem) {
        for ($i = 0; $i < count($mipb_array); $i++) {
            if (intersect_ipranges($delipitem, $mipb_array[$i]) != 0) {
                $ipranges = intersect_ipranges($newmipb, $mipb_array[$i]);
                array_splice($mipb_array, $i, 1, $ipranges);
            }
        }
    }
    # print_r($mipb_array);printf("<br><br>");
    for ($i = 0; $i < count($mipb_array); $i++) {
        if ($mipb_array[$i] == false) {
            array_splice($mipb_array, $i, 1);
        }
    }
    #print_r($mipb_array);printf("<br><br>");
    if (count($mipb_array) == 0) {
        $entry['MaxIPBlock'] = array();
        #print_r($entry);printf("<br><br>");
        $results = ldap_mod_del($ds, $childauDN, $entry);
    } else {
        foreach ($mipb_array as $item) {
            $entry['MaxIPBlock'][] = $item;
        }
        #print_r($entry);printf("<br><br>");
        $results = ldap_mod_replace($ds, $childauDN, $entry);
    }
    if ($results) {
        echo "<br>MIPBs in Child-AU erfolgreich aktualisiert!<br>";
        # in Child-AU: FIPBs anpassen
        $fipb_array = get_freeipblocks_au($childauDN);
        #print_r($fipb_array);printf("<br><br>");
        foreach ($delip as $delipitem) {
            for ($i = 0; $i < count($fipb_array); $i++) {
                if (intersect_ipranges($delipitem, $fipb_array[$i]) != 0) {
                    $ipranges = intersect_ipranges($newmipb, $fipb_array[$i]);
                    array_splice($fipb_array, $i, 1, $ipranges);
                }
            }
        }
        # print_r($fipb_array);printf("<br><br>");
        for ($i = 0; $i < count($fipb_array); $i++) {
            if ($fipb_array[$i] == false) {
                array_splice($fipb_array, $i, 1);
            }
        }
        #print_r($fipb_array);printf("<br><br>");
        if (count($fipb_array) == 0) {
            $entry1['FreeIPBlock'] = array();
            #print_r($entry1);printf("<br><br>");
            $results = ldap_mod_del($ds, $childauDN, $entry1);
        } else {
            foreach ($fipb_array as $item) {
                $entry1['FreeIPBlock'][] = $item;
            }
            #print_r($entry1);printf("<br><br>");
            $results = ldap_mod_replace($ds, $childauDN, $entry1);
        }
        if ($results) {
            echo "FIPBs in Child-AU erfolgreich aktualisiert!<br>";
            # in AU: Geloeschte IP Bereiche als neue FIPBs aufnehmen
            foreach ($delip as $item) {
                $entry2['FreeIPBlock'][] = $item;
            }
            #print_r($entry2);printf("<br><br>");
            $results = ldap_mod_add($ds, $auDN, $entry2);
            if ($results) {
                echo "FIPBs in AU erfolgreich aktualisiert!<br>";
                # IP Bloecke aufraeumen in Child-AU und AU (Merging)
                merge_ipranges($auDN);
                merge_ipranges($childauDN);
                return 1;
            } else {
                echo "Fehler beim aktualisieren der FIPBs in AU!<br>";
                return 0;
            }
        } else {
            echo "Fehler beim aktualisieren der FIPBs in Child-AU!<br>";
            return 0;
        }
    } else {
        echo "<br>Fehler beim aktualisieren der MIPBs in Child-AU!<br>";
        return 0;
    }
}
function modify_subnet_dn($subnetDN, $newsubnetDN)
{
    global $ds, $suffix, $auDN, $ldapError;
    # check IP-Net-Syntax ...
    # Subnet CNs (IP) in internes Range ".._.." Format bringen
    $newcn = ldap_explode_dn($newsubnetDN, 1);
    $newcnarray = array($newcn[0], $newcn[0]);
    $newsubnetip = implode("_", $newcnarray);
    $oldcn = ldap_explode_dn($subnetDN, 1);
    $oldcnarray = array($oldcn[0], $oldcn[0]);
    $oldsubnetip = implode("_", $oldcnarray);
    # IP checken und FIBS anpassen
    $fipb_array = get_freeipblocks_au($auDN);
    for ($i = 0; $i < count($fipb_array); $i++) {
        if (split_iprange($newsubnetip, $fipb_array[$i]) != 0) {
            $ipranges = split_iprange($newsubnetip, $fipb_array[$i]);
            array_splice($fipb_array, $i, 1, $ipranges);
            break;
        }
    }
    if ($i < count($fipb_array)) {
        # zunächst alte DHCP Ranges löschen
        delete_ip_dhcprange($subnetDN, $auDN);
        # Move Subtree
        if (move_subtree($subnetDN, $newsubnetDN)) {
            adjust_dhcpsubnet_dn($newsubnetDN, $subnetDN);
            printf("<br>Subnet Name (IP) erfolgreich von %s zu %s ge&auml;ndert!<br>", $oldcn[0], $newcn[0]);
            # neue Subnetz-IP aus FIPBs entfernen
            foreach ($fipb_array as $item) {
                $entry['FreeIPBlock'][] = $item;
            }
            # alte Subnetz-IP in FIPBs integrieren
            $entry['FreeIPBlock'][] = $oldsubnetip;
            $results = ldap_mod_replace($ds, $auDN, $entry);
            if ($results) {
                merge_ipranges($auDN);
                update_dhcpmtime($auDN);
                echo "<br>FIPBs erfolgreich angepasst!<br>";
                return 1;
            } else {
                echo "<br>Fehler beim Anpassen der FIPBs!<br>";
            }
        } else {
            echo "<br>Fehler beim &auml;ndern des Subnet Namens (IP)!<br>";
        }
    } else {
        printf("<br>Neues Subnet %s nicht im verfuegbaren IP Bereich!<br>", $newcn[0]);
        return 0;
    }
}
function delete_childau($childDN, $childou, $delmodus)
{
    global $ds, $suffix, $auDN, $domDN, $assocdom, $ldapError;
    if ($delmodus == "integrate") {
        # Associated DNS Domain integrieren
        $childdc = get_domain_data($childDN, array("dn", "associatedname"));
        print_r($childdc);
        echo "<br>";
        # wenn einzige AU dann einfach in Parentdomain aufnehmen und betroffene Einträge löschen
        if (count($childdc[0]['associatedname']) == 1) {
            echo "einzige AU<br>";
            # dc Childs verschieben
            $dcchilds = get_dc_childs($childdc[0]['dn'], array("dn", "dc"));
            # print_r($dcchilds); echo "<br>";
            if (count($dcchilds) != 0) {
                foreach ($dcchilds as $dcc) {
                    # print_r($dcc['dn']); echo " >> "; print_r("dc=".$dcc['dc'].",".$domDN); echo "<br>";
                    if (move_subtree($dcc['dn'], "dc=" . $dcc['dc'] . "," . $domDN)) {
                        $newdom = $dcc['dc'] . "." . $assocdom;
                        #print_r($newdom); echo "<br><br>";
                        dive_into_dctree_adapt("dc=" . $dcc['dc'] . "," . $domDN, $newdom);
                    }
                }
            }
            # alten dc-Knoten löschen
            dive_into_tree_del($childdc[0]['dn'], "");
        }
        # wenn noch andere AUs in der Domain, dann nur betroffene Einträge entfernen
        if (count($childdc[0]['associatedname']) > 1) {
            echo "mehrere AUs<br>";
            # ChildAU-Rollen unterhalb dc-Knoten löschen (nur diese)(oder übernehmen: MA zu HA, HA zu HA)
            $roles = get_roles($childDN);
            #print_r($roles); echo "<br>";
            # was ist wenn rollen nur noch ein member haben ... fehler
            if (count($roles['MainAdmin']) != 0) {
                $mainadmins = $roles['MainAdmin'];
                for ($i = 0; $i < count($mainadmins); $i++) {
                    $entryRoleMain['member'][$i] = $mainadmins[$i];
                }
                #print_r($entryRoleHost); echo "<br>";
                $resultMA = ldap_mod_del($ds, "cn=MainAdmin,cn=roles," . $childdc[0]['dn'], $entryRoleMain);
            }
            if (count($roles['HostAdmin']) != 0) {
                $hostadmins = $roles['HostAdmin'];
                for ($i = 0; $i < count($hostadmins); $i++) {
                    $entryRoleHost['member'][$i] = $hostadmins[$i];
                }
                #print_r($entryRoleHost); echo "<br>";
                $resultHA = ldap_mod_del($ds, "cn=HostAdmin,cn=roles," . $childdc[0]['dn'], $entryRoleHost);
            }
            if (count($roles['ZoneAdmin']) != 0) {
                $zoneadmins = $roles['ZoneAdmin'];
                for ($i = 0; $i < count($zoneadmins); $i++) {
                    $entryRoleZone['member'][$i] = $zoneadmins[$i];
                }
                $resultZA = ldap_mod_del($ds, "cn=ZoneAdmin,cn=roles," . $childdc[0]['dn'], $entryRoleZone);
            }
            $entrydel['associatedname'] = $childDN;
            # print_r($entrydel); echo "<br>";
            ldap_mod_del($ds, $childdc[0]['dn'], $entrydel);
            $zentries = get_zone_entries_assocname($childdc[0]['dn'], array("dn"), $childDN);
            # print_r($zentries); echo "<br>";
            foreach ($zentries as $ze) {
                # print_r($ze['dn']); echo "<br>";
                ldap_delete($ds, $ze['dn']);
            }
        }
        # Rechner (mit IP) + dranhängende MCs, PXEs verschieben
        $hosts = get_hosts($childDN, array("dn", "hostname"));
        if (count($hosts) != 0) {
            foreach ($hosts as $host) {
                # print_r($host['dn']); echo "<br>";
                # print_r($host['hostname']);  echo "<br>";
                # print_r("hostname=".$host['hostname']."-int-".$childou.",cn=computers,".$auDN); echo "<br><br>";
                if (move_subtree($host['dn'], "hostname=" . $host['hostname'] . "-ex-" . $childou . ",cn=computers," . $auDN)) {
                    $newhostDN = "hostname=" . $host['hostname'] . "-ex-" . $childou . ",cn=computers," . $auDN;
                    $dhcp = get_node_data($newhostDN, array("dhcphlpcont"));
                    # print_r($dhcp); echo "<br>";
                    if ($dhcp['dhcphlpcont'] != "") {
                        $entrydel['dhcphlpcont'] = array();
                        $entrydel['objectclass'] = "dhcpHost";
                        # print_r($dhcphlpcont);
                        ldap_mod_del($ds, $newhostDN, $entrydel);
                    }
                }
            }
        }
        # DHCP Objekte IP Ranges löschen
        $subnets = get_subnets($childDN, array("dn"));
        # print_r($subnets); echo "<br>";
        if (count($subnets) != 0) {
            foreach ($subnets as $subnet) {
                # print_r($subnet['dn']); echo "<br>";
                delete_ip_dhcprange($subnet['dn'], $childDN);
            }
        }
        # DHCP Pools auch noch
        # Freie IP Bereiche zurücknehmen
        $fipb_array = get_freeipblocks_au($childDN);
        # print_r($fipb_array); echo "<br>";
        # print_r(count($fipb_array)); echo "<br>";
        if (count($fipb_array) == 1 && $fipb_array[0] != "") {
            $entry_ipblock['freeipblock'] = $fipb_array[0];
            # print_r($entry_ipblock); echo "<br>";
            ldap_mod_add($ds, $auDN, $entry_ipblock);
        }
        if (count($fipb_array) > 1) {
            foreach ($fipb_array as $fipb) {
                $entry_ipblock['FreeIPBlock'][] = $fipb;
                # print_r($entry_ipblock); echo "<br>";
                ldap_mod_add($ds, $auDN, $entry_ipblock);
            }
        }
        merge_ipranges($auDN);
        # Verschieben der Childs an neue Stelle
        $child_childs = get_childau($childDN, array("dn", "ou"));
        # print_r($child_childs); echo "<br>";
        if (count($child_childs) != 0) {
            foreach ($child_childs as $cc) {
                $child_childDN = $cc['dn'];
                $newccDN = "ou=" . $cc['ou'] . "," . $auDN;
                # print_r($child_childDN); echo " >> ";
                # print_r($newccDN); echo "<br>";
                if (move_subtree($child_childDN, $newccDN)) {
                    adjust_dn_entries($child_childDN, $newccDN);
                }
            }
        }
        # Löschen des AU Knotens
        dive_into_tree_del($childDN, "");
        $mesg = "<br>Erfolgreich gel&ouml;scht mit Integration<br>";
        return $mesg;
    }
    if ($delmodus == "complete") {
        # IP Bereiche zurück
        # DNS Teilbaum Objekte löschen
        # alles rekursive löschen
        /*if (dive_into_tree_del($dcDN,"")){
        			$delentry ['objectclass'] = "domainrelatedobject";
        			$delentry ['associateddomain'] = $domsuffix;
        			#print_r($delentry); echo "<br>";
        			$delresult = ldap_mod_del($ds,$childDN,$delentry);
        		   if ($delresult){
        				$mesg = "Domain komplett gel&ouml;scht<br>";
        			}else{$mesg = "Fehler! ldap_mod_del<br>";}
        		}else{$mesg = "Fehler! dive_into_tree_del<br>";}
        		*/
        $mesg = "Komplettes l&ouml;schen mometan noch nicht unterst&uuml;tzt.<br>\n\t\t\t\t\tNur eine Ebene mit Integration ...<br>";
        return $mesg;
    }
}
                    printf("Neue dynamische IP Range %s - %s erfolgreich in Subnetz %s0 eingetragen!<br>", $addrange1[$i], $addrange2[$i], $net);
                } else {
                    echo "<br>Fehler beim eintragen des dynamischen DHCP Pools!<br>";
                }
            } else {
                printf("Neue Range %s - %s nicht in Subnetz %s0", $addrange1[$i], $addrange2[$i], $net);
            }
        } else {
            printf("falsche IP Syntax der neuen Range %s - %s<br>", $addrange1[$i], $addrange2[$i]);
        }
    }
}
#########################################################################################
# In Pools bereits angelegte Ranges verarbeiten (löschen, verkleinern, vergrößern)
# vorzunehmende Änderungen in Arrays ($mod_dhcpranges, $new_fibs) speichern
$fipbs = get_freeipblocks_au($auDN);
$new_fipbs['freeipblock'] = $fipbs;
$mod_dhcpranges = array();
for ($i = 0; $i < count($rangepooldn); $i++) {
    $range = implode('_', array($range1[$i], $range2[$i]));
    $oldrange = implode('_', array($oldrange1[$i], $oldrange2[$i]));
    if ($oldrange1[$i] != "" && $oldrange2[$i] != "" && $range1[$i] == "" && $range2[$i] == "") {
        # Range löschen
        $mod_dhcpranges[$rangepooldn[$i]] = $poolranges[$rangepooldn[$i]];
        $range_key = array_search($oldrange, $mod_dhcpranges[$rangepooldn[$i]]);
        #print_r($range_key); echo "<br>";
        array_splice(&$mod_dhcpranges[$rangepooldn[$i]], $range_key, 1);
        array_splice(&$poolranges[$rangepooldn[$i]], $range_key, 1);
        $new_fipbs['freeipblock'][] = $oldrange;
        # Subnet-AU auf DHCP-Modify setzen
        $au_to_update[] = $subnetau[$i];
echo "\n<html>\n<head>\n\t<title>AU Management</title>\n\t<link rel='stylesheet' href='../styles.css' type='text/css'>\n</head>\n<body>\n<table border='0' cellpadding='30' cellspacing='0'> \n<tr><td>\n<form action='move_hosts.php' method='post'>";
if (!$automove) {
    $seconds = 2;
    $mesg .= "Sie haben keine Ziel-AU gew&auml;hlt!<br>";
}
if (!$hostsmove) {
    $seconds = 2;
    $mesg .= "Sie haben keine Clients zum verschieben gew&auml;hlt!<br>";
} elseif ($automove && $hostsmove) {
    $exp_automove = explode("_", $automove);
    $target_audn = $exp_automove[0];
    $target_zone = $exp_automove[1];
    $target_ou = ldap_explode_dn($target_audn, 1);
    #echo "$target_audn<br>";
    #echo "$target_zone<br>";
    $target_fipbs = get_freeipblocks_au($target_audn);
    $ip_select = array();
    foreach ($target_fipbs as $fipb) {
        $fipbexp = explode('_', $fipb);
        if ($fipbexp[0] == $fipbexp[1]) {
            $ip_select[] = $fipbexp[0];
        } else {
            $ip = ip2long($fipbexp[0]);
            $ipmax = ip2long($fipbexp[1]);
            while ($ip <= $ipmax) {
                $ip_select[] = long2ip($ip);
                $ip++;
            }
        }
    }
    natsort($ip_select);
<?php

# Max und Free IP Blocks
$mipb_array = get_maxipblocks_au($auDN);
$fipb_array = get_freeipblocks_au($auDN);
#print_r($mipb_array); echo "<br>";
natsort($mipb_array);
natsort($fipb_array);
#print_r($mipb_array); echo "<br>";
#print_r(count($mipb_array)); echo "<br>";
#print_r(count($fipb_array)); echo "<br>";
$ipblocks = "";
# print_r($mipb_array);
if ($mipb_array[0] != "") {
    if (count($mipb_array) > 1) {
        $ipblocks .= "<table border='1' cellpadding='2' cellspacing='0' width='100%' style='border-width: 0 0 0 0;'>\n\t\t\t\t\t\t\t<tr><td colspan='3' style='border-color: black; border-style: solid; border-width: 0 0 3 0;'>\n\t\t\t\t\t\t\t<b>Zugewiesene IP Bereiche:</b></td></tr>";
        foreach ($mipb_array as $mipb) {
            $exp = explode('_', $mipb);
            $ipblocks .= "<tr><td width='45%' class='tab_d'>{$exp['0']}&nbsp;</td>";
            if ($exp[0] != $exp[1]) {
                $ipblocks .= "<td class='tab_d'> - </td>\n\t\t\t\t\t\t\t<td width='45%' class='tab_d'>{$exp['1']}&nbsp;</td>";
            } else {
                $ipblocks .= "<td class='tab_d' colspan='2'>&nbsp;</td>";
            }
            $ipblocks .= "</tr>";
        }
    } elseif (count($mipb_array) == 1) {
        $ipblocks .= "<table border='1' cellpadding='2' cellspacing='0' width='100%' style='border-width: 0 0 0 0;'>\n\t\t\t\t\t\t\t<tr><td colspan='3' style='border-color: black; border-style: solid; border-width: 0 0 3 0;'>\n\t\t\t\t\t\t\t<b>Zugewiesener IP Bereich:</b></td></tr>";
        $exp = explode('_', $mipb_array[0]);
        $ipblocks .= "<tr><td width='45%' class='tab_d'>{$exp['0']}&nbsp;</td>";
        if ($exp[0] != $exp[1]) {