예제 #1
0
 public function __call($method, $args)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     if (!in_array($method, array('get', 'visit', 'draw'))) {
         debug_dump_backtrace(sprintf('Incorrect use of method loading [%s]', $method), 1);
     }
     $methods = array();
     $fnct = array_shift($args);
     $object = $args[0];
     $class = get_class($object);
     $call = "{$method}{$fnct}{$class}";
     array_push($methods, $call);
     while ($class && !method_exists($this, $call)) {
         if (defined('DEBUGTMP') && DEBUGTMP) {
             printf('<font size=-2><i>Class (%s): Method doesnt exist (%s,%s)</i></font><br />', $class, get_class($this), $call);
         }
         $class = get_parent_class($class);
         $call = "{$method}{$fnct}{$class}";
         array_push($methods, $call);
     }
     if (defined('DEBUGTMP') && DEBUGTMP) {
         printf('<font size=-2><i>Calling Methods: %s</i></font><br />', implode('|', $methods));
     }
     if (defined('DEBUGTMP') && DEBUGTMP && method_exists($this, $call)) {
         printf('<font size=-2>Method Exists: %s::%s (%s)</font><br />', get_class($this), $call, $args);
     }
     if (method_exists($this, $call)) {
         $call .= '(';
         for ($i = 0; $i < count($args); $i++) {
             if ($i == 0) {
                 $call .= sprintf('$args[%s]', $i);
             } else {
                 $call .= sprintf(',$args[%s]', $i);
             }
         }
         $call .= ');';
         if (defined('DEBUGTMP') && DEBUGTMP) {
             printf('<font size=-2><b>Invoking Method: $this->%s</b></font><br />', $call);
         }
         eval('$r = $this->' . $call);
         if (isset($r)) {
             return $r;
         } else {
             return;
         }
     } elseif (DEBUG_ENABLED) {
         debug_log('Doesnt exist param (%s,%s)', 1, 0, __FILE__, __LINE__, __METHOD__, $method, $fnct);
     }
     printf('<font size=-2><i>NO Methods: %s</i></font><br />', implode('|', $methods));
 }
예제 #2
0
 protected function getNoteRequiredAttribute($attribute)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     if (DEBUGTMP) {
         printf('<font size=-2>%s</font><br />', __METHOD__);
     }
     $required_by = '';
     $sattr_required = '';
     # Is this attribute required by an objectClass ?
     $sattr = $this->getServer()->getSchemaAttribute($attribute->getName());
     if ($sattr) {
         $sattr_required = $sattr->getRequiredByObjectClasses();
     }
     if ($sattr_required) {
         $oc = $this->template->getAttribute('objectclass');
         if ($oc) {
             foreach ($oc->getValues() as $objectclass) {
                 # If this objectclass is in our required list
                 if (in_array_ignore_case($objectclass, $sattr_required)) {
                     $required_by .= sprintf('%s ', $objectclass);
                     continue;
                 }
                 # If not, see if it is in our parent.
                 $sattr = $this->getServer()->getSchemaObjectClass($objectclass);
                 if (array_intersect($sattr->getParents(), $sattr_required)) {
                     $required_by .= sprintf('%s ', $objectclass);
                 }
             }
         } else {
             debug_dump_backtrace('How can there be no objectclasses?', 1);
         }
     }
     if ($required_by) {
         return sprintf('<acronym title="%s %s">%s</acronym>', _('Required attribute for objectClass(es)'), $required_by, _('required'));
     } else {
         return '';
     }
 }
예제 #3
0
 /**
  * Does this attribute need supporting JS
  */
 public function needJS($type = null)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 5, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     if (is_null($type)) {
         foreach (array('focus', 'blur', 'validate') as $type) {
             if ($this->needJS($type)) {
                 return true;
             }
         }
         return false;
     } elseif ($type == 'focus') {
         # We dont have any focus javascript routines.
         return false;
     } elseif ($type == 'blur') {
         if ($this->onchange || $this->isRequired()) {
             return true;
         } else {
             return false;
         }
     } elseif ($type == 'validate') {
         if ($this->isRequired()) {
             return true;
         } else {
             return false;
         }
     } else {
         debug_dump_backtrace(sprintf('Unknown JS request %s', $type), 1);
     }
 }
예제 #4
0
 /**
  * Modify objects
  */
 public function modify($dn, $attrs, $method = null)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 17, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     # Check our unique attributes.
     if (!$this->checkUniqueAttrs($dn, $attrs)) {
         return false;
     }
     $result = false;
     $summary = array();
     $current_attrs = $this->getDNAttrValues($dn, $method, LDAP_DEREF_NEVER, array('*'));
     # Go through our attributes and call our hooks for each attribute changing its value
     foreach ($attrs as $attr => $values) {
         # For new attributes
         if (count($values) && !isset($current_attrs[$attr])) {
             if (!run_hook('pre_attr_add', array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attr' => $attr, 'newvalue' => $values))) {
                 unset($attrs[$attr]);
                 system_message(array('title' => _('Attribute not added'), 'body' => sprintf('%s (<b>%s</b>)', _('Hook pre_attr_add prevented attribute from being added'), $attr), 'type' => 'warn'));
             } else {
                 $summary['add'][$attr]['new'] = $values;
             }
             # For modify attributes
         } elseif (count($values)) {
             if (!run_hook('pre_attr_modify', array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attr' => $attr, 'oldvalue' => $current_attrs[$attr], 'newvalue' => $values))) {
                 unset($attrs[$attr]);
                 system_message(array('title' => _('Attribute not modified'), 'body' => sprintf('%s (<b>%s</b>)', _('Hook pre_attr_modify prevented attribute from being modified'), $attr), 'type' => 'warn'));
             } else {
                 $summary['modify'][$attr]['new'] = $values;
                 $summary['modify'][$attr]['old'] = $current_attrs[$attr];
             }
             # For delete attributes
         } else {
             if (!run_hook('pre_attr_delete', array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attr' => $attr, 'oldvalue' => $current_attrs[$attr]))) {
                 unset($attrs[$attr]);
                 system_message(array('title' => _('Attribute not deleted'), 'body' => sprintf('%s (<b>%s</b>)', _('Hook pre_attr_delete prevented attribute from being deleted'), $attr), 'type' => 'warn'));
             } else {
                 $summary['delete'][$attr]['old'] = $current_attrs[$attr];
             }
         }
     }
     if (!count($attrs)) {
         return false;
     }
     if (run_hook('pre_entry_modify', array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attrs' => $attrs))) {
         $result = @ldap_modify($this->connect($method), $dn, $attrs);
         if ($result) {
             run_hook('post_entry_modify', array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attrs' => $attrs));
             foreach (array('add', 'modify', 'delete') as $mode) {
                 if (isset($summary[$mode])) {
                     foreach ($summary[$mode] as $attr => $values) {
                         switch ($mode) {
                             case 'add':
                                 run_hook(sprintf('post_attr_%s', $mode), array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attr' => $attr, 'newvalue' => $values['new']));
                                 break;
                             case 'modify':
                                 run_hook(sprintf('post_attr_%s', $mode), array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attr' => $attr, 'oldvalue' => $values['old'], 'newvalue' => $values['new']));
                                 break;
                             case 'delete':
                                 run_hook(sprintf('post_attr_%s', $mode), array('server_id' => $this->index, 'method' => $method, 'dn' => $dn, 'attr' => $attr, 'oldvalue' => $values['old']));
                                 break;
                             default:
                                 debug_dump_backtrace(sprintf('Unkown mode %s', $mode), 1);
                         }
                     }
                 }
             }
         } else {
             system_message(array('title' => _('Could not perform ldap_modify operation.'), 'body' => ldap_error_msg($this->getErrorMessage($method), $this->getErrorNum($method)), 'type' => 'error'));
         }
     }
     return $result;
 }
예제 #5
0
 /**
  * Return the number of children an entry has. Optionally autoread the child entry.
  *
  * @param dn DN of the entry
  * @param boolean LDAP Size Limit
  */
 protected function readChildrenNumber($dn, $nolimit = false)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 33, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     $dnlower = $this->indexDN($dn);
     if (!isset($this->entries[$dnlower])) {
         debug_dump_backtrace('Reading children on an entry that isnt set?', true);
     }
     # Read the entry if we havent got it yet.
     if (!$this->entries[$dnlower]->isLeaf() && !$this->entries[$dnlower]->getChildren()) {
         $this->readChildren($dn, $nolimit);
     }
     return count($this->entries[$dnlower]->getChildren());
 }
예제 #6
0
 /**
  * Return an object Instance of a configured database.
  *
  * @param int Index
  * @return object Datastore instance object.
  */
 public function Instance($index = null)
 {
     if (defined('DEBUG_ENABLED') && DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 17, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     # If no index defined, then pick the lowest one.
     if (is_null($index)) {
         $index = min($this->GetServerList())->getIndex();
     }
     if (!isset($this->objects[$index])) {
         debug_dump_backtrace(sprintf('Error: Datastore instance [%s] doesnt exist?', htmlspecialchars($index)), 1);
     }
     if (defined('DEBUG_ENABLED') && DEBUG_ENABLED) {
         debug_log('Returning instance of database (%s)', 3, 0, __FILE__, __LINE__, __METHOD__, $index);
     }
     return $this->objects[$index];
 }
예제 #7
0
 /**
  * Given a DN string and a path like syntax, this returns the parent container portion of the string.
  *
  * @param string The DN whose container string to return.
  * @param string Either '/', '.' or something like '../../<rdn>'
  * @return string The container
  */
 public function getContainerPath($dn, $path = '..')
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 17, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     $top = $this->getContainerTop($dn);
     if ($path[0] == '/') {
         $dn = $top;
         $path = substr($path, 1);
     } elseif ($path == '.') {
         return $dn;
     }
     $parenttree = explode('/', $path);
     foreach ($parenttree as $key => $value) {
         if ($value == '..') {
             if ($this->getContainer($dn)) {
                 $dn = $this->getContainer($dn);
             }
             if ($dn == $top) {
                 break;
             }
         } elseif ($value) {
             $dn = sprintf('%s,%s', $value, $dn);
         } else {
             break;
         }
     }
     if (!$dn) {
         debug_dump(array(__METHOD__, 'dn' => $dn, 'path' => $path));
         debug_dump_backtrace('Container is empty?', 1);
     }
     return $dn;
 }
예제 #8
0
 /**
  * Build the attributes array for the entry when the change type is modify
  */
 private function getModifyDetails($lines)
 {
     if (!count($lines)) {
         return $this->error(_('Missing attributes for'), $lines);
     }
     # While the array is not empty
     while (count($lines)) {
         $processline = false;
         $deleteattr = false;
         # Get the current line with the action
         $currentLine = array_shift($lines);
         $attrvalue = $this->getAttrValue($currentLine);
         $action_attribute = $attrvalue[0];
         $action_attribute_value = $attrvalue[1];
         if (!in_array($action_attribute, array('add', 'delete', 'replace'))) {
             return $this->error(_('Missing modify command add, delete or replace'), array_merge(array($currentLine), $lines));
         }
         $processline = true;
         switch ($action_attribute) {
             case 'add':
                 break;
             case 'delete':
                 $attribute = $this->template->getAttribute($action_attribute_value);
                 if (is_null($attribute)) {
                     return $this->error(sprintf('%s %s', _('Attempting to delete a non existant attribute'), $action_attribute_value), array_merge(array($currentLine), $lines));
                 }
                 $deleteattr = true;
                 break;
             case 'replace':
                 $attribute = $this->template->getAttribute($action_attribute_value);
                 if (is_null($attribute)) {
                     return $this->error(sprintf('%s %s', _('Attempting to replace a non existant attribute'), $action_attribute_value), array_merge(array($currentLine), $lines));
                 }
                 break;
             default:
                 debug_dump_backtrace(sprintf('Unknown action %s', $action_attribute), 1);
         }
         # Fetch the attribute for the following line
         $currentLine = array_shift($lines);
         while ($processline && trim($currentLine) && trim($currentLine) != '-') {
             $processline = false;
             # If there is a valid line
             if (preg_match('/:/', $currentLine)) {
                 $attrvalue = $this->getAttrValue($currentLine);
                 $attr = $attrvalue[0];
                 $attribute_value_part = $attrvalue[1];
                 # Check that it correspond to the one specified before
                 if ($attr == $action_attribute_value) {
                     # Get the value part of the attribute
                     $attribute_value = $this->getAttributeValue($attribute_value_part);
                     $attribute = $this->template->getAttribute($attr);
                     # This should be a add/replace operation
                     switch ($action_attribute) {
                         case 'add':
                             if (is_null($attribute)) {
                                 $attribute = $this->template->addAttribute($attr, array('values' => array($attribute_value_part)));
                             } else {
                                 $attribute->addValue($attribute_value_part, -1);
                             }
                             $attribute->justModified();
                             break;
                         case 'delete':
                             $deleteattr = false;
                             if (($key = array_search($attribute_value_part, $attribute->getValues())) !== false) {
                                 $attribute->delValue($key);
                             } else {
                                 return $this->error(sprintf('%s %s', _('Delete value doesnt exist in DN'), $attribute_value_part), array_merge(array($currentLine), $lines));
                             }
                             break;
                         case 'replace':
                             if ($attribute->hasBeenModified()) {
                                 $attribute->addValue($attribute_value_part, -1);
                             } else {
                                 $attribute->setValue(array($attribute_value_part));
                             }
                             break;
                         default:
                             debug_dump_backtrace(sprintf('Unexpected operation %s', $action_attribute));
                     }
                 } else {
                     return $this->error(sprintf('%s %s', _('The attribute to modify doesnt match the one specified by'), $action_attribute), array_merge(array($currentLine), $lines));
                 }
             } else {
                 return $this->error(sprintf('%s %s', _('Attribute not valid'), $currentLine), array_merge(array($currentLine), $lines));
             }
             $currentLine = array_shift($lines);
             if (trim($currentLine)) {
                 $processline = true;
             }
         }
         if ($action_attribute == 'delete' && $deleteattr) {
             $attribute->setValue(array());
         }
     }
     return $this->template;
 }
예제 #9
0
/**
 * The only function which should be called by a user
 *
 * @see common.php
 * @see APP_SESSION_ID
 * @return boolean Returns true if the session was started the first time
 */
function app_session_start()
{
    $sysmsg = null;
    # If we have a sysmsg before our session has started, then preserve it.
    if (isset($_SESSION['sysmsg'])) {
        $sysmsg = $_SESSION['sysmsg'];
    }
    /* If session.auto_start is on in the server's PHP configuration (php.ini), then
     * we will have problems loading our schema cache since the session will have started
     * prior to loading the SchemaItem (and descedants) class. Destroy the auto-started
     * session to prevent this problem.
     */
    if (ini_get('session.auto_start') && !array_key_exists(app_session_id_init, $_SESSION)) {
        @session_destroy();
    }
    # Do we already have a session?
    if (@session_id()) {
        return;
    }
    @session_name(APP_SESSION_ID);
    @session_start();
    # Do we have a valid session?
    $is_initialized = is_array($_SESSION) && array_key_exists(app_session_id_init, $_SESSION);
    if (!$is_initialized) {
        if (app_session_id_paranoid) {
            ini_set('session.use_trans_sid', 0);
            @session_destroy();
            @session_id(app_session_get_id());
            @session_start();
            ini_set('session.use_trans_sid', 1);
        }
        $_SESSION[app_session_id_init]['name'] = app_name();
        $_SESSION[app_session_id_init]['version'] = app_version();
        $_SESSION[app_session_id_init]['config'] = filemtime(CONFDIR . 'config.php');
    }
    @header('Cache-control: private');
    // IE 6 Fix
    if (app_session_id_paranoid && !app_session_verify_id()) {
        error('Session inconsistent or session timeout', 'error', 'index.php');
    }
    # Check we have the correct version of the SESSION cache
    if (isset($_SESSION['cache']) || isset($_SESSION[app_session_id_init])) {
        if (!is_array($_SESSION[app_session_id_init])) {
            $_SESSION[app_session_id_init] = array();
        }
        if (!isset($_SESSION[app_session_id_init]['version']) || !isset($_SESSION[app_session_id_init]['config']) || !isset($_SESSION[app_session_id_init]['name']) || $_SESSION[app_session_id_init]['name'] !== app_name() || $_SESSION[app_session_id_init]['version'] !== app_version() || $_SESSION[app_session_id_init]['config'] != filemtime(CONFDIR . 'config.php')) {
            $_SESSION[app_session_id_init]['name'] = app_name();
            $_SESSION[app_session_id_init]['version'] = app_version();
            $_SESSION[app_session_id_init]['config'] = filemtime(CONFDIR . 'config.php');
            unset($_SESSION['cache']);
            unset($_SESSION[APPCONFIG]);
            # Our configuration information has changed, so we'll redirect to index.php to get it reloaded again.
            system_message(array('title' => _('Configuration cache stale.'), 'body' => _('Your configuration has been automatically refreshed.'), 'type' => 'info', 'special' => true));
            $config_file = CONFDIR . 'config.php';
            $config = check_config($config_file);
            if (!$config) {
                debug_dump_backtrace('config is empty?', 1);
            }
        } else {
            # Sanity check, specially when upgrading from a previous release.
            if (isset($_SESSION['cache'])) {
                foreach (array_keys($_SESSION['cache']) as $id) {
                    if (isset($_SESSION['cache'][$id]['tree']['null']) && !is_object($_SESSION['cache'][$id]['tree']['null'])) {
                        unset($_SESSION['cache'][$id]);
                    }
                }
            }
        }
    }
    # If we came via index.php, then set our $config.
    if (!isset($_SESSION[APPCONFIG]) && isset($config)) {
        $_SESSION[APPCONFIG] = $config;
    }
    # Restore our sysmsg's if there were any.
    if ($sysmsg) {
        if (!isset($_SESSION['sysmsg']) || !is_array($_SESSION['sysmsg'])) {
            $_SESSION['sysmsg'] = array();
        }
        $_SESSION['sysmsg'] = array_merge($_SESSION['sysmsg'], $sysmsg);
    }
}
예제 #10
0
/**
 * Record a system message.
 * This function can be used as an alternative to generate a system message, if page hasnt yet been defined.
 */
function system_message($msg, $redirect = null)
{
    if (!is_array($msg)) {
        return null;
    }
    if (!isset($msg['title']) && !isset($msg['body'])) {
        return null;
    }
    if (!isset($msg['type'])) {
        $msg['type'] = 'info';
    }
    if (!isset($_SESSION['sysmsg']) || !is_array($_SESSION['sysmsg'])) {
        $_SESSION['sysmsg'] = array();
    }
    # Try and detect if we are in a redirect loop
    if (get_request('redirect', 'GET') && $msg['type'] != 'debug') {
        foreach ($_SESSION['sysmsg'] as $detail) {
            if ($msg == $detail && !isset($detail['special'])) {
                debug_dump(array('Incoming MSG' => $msg, 'existing' => $_SESSION['sysmsg']));
                debug_dump_backtrace('Redirect Loop Detected', true);
            }
        }
    }
    array_push($_SESSION['sysmsg'], $msg);
    if ($redirect) {
        if (preg_match('/\\?/', $redirect)) {
            $redirect .= '&';
        } else {
            $redirect .= '?';
        }
        $redirect .= 'redirect=true';
        # Check if we were an ajax request, and only render the ajax message
        if (get_request('meth', 'REQUEST') == 'ajax') {
            $redirect .= '&meth=ajax';
        }
        header("Location: {$redirect}");
        die;
    }
}
예제 #11
0
 /**
  * Add another attribute to this template
  *
  * @return int Attribute ID
  */
 public function addAttribute($name, $value, $source = null)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 5, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     if (!is_array($value)) {
         debug_dump_backtrace('Value should be an array()', 1);
     }
     $server = $this->getServer();
     # Initialise the Attribute Factory.
     $attribute_factory = new AttributeFactory();
     # If there isnt a schema item for this attribute
     $attribute = $attribute_factory->newAttribute($name, $value, $server->getIndex(), $source);
     $attrid = $this->getAttrID($attribute->getName());
     if (is_null($attrid)) {
         array_push($this->attributes, $attribute);
     } else {
         debug_dump_backtrace(sprintf('There was a request to add an attribute (%s), but it was already defined? (%s)', $attrid, __METHOD__), true);
     }
     if ($this->getID() == 'none') {
         usort($this->attributes, 'sortAttrs');
     }
     return $attribute;
 }
예제 #12
0
 /**
  * Add another attribute to this template
  *
  * @return int Attribute ID
  */
 public function addAttribute($name, $value, $source = null)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 5, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     if (!is_array($value)) {
         debug_dump_backtrace('Value should be an array()', 1);
     }
     $server = $this->getServer();
     # Initialise the Attribute Factory.
     $attribute_factory = new AttributeFactory();
     if (preg_match('/;/', $name)) {
         system_message(array('title' => 'phpLDAPadmin doesnt support RFC3866.', 'body' => sprintf('%s {%s} (%s)', 'PLA might not do what you expect...', $name, is_array($value) ? serialize($value) : $value), 'type' => 'warn'));
     }
     # If there isnt a schema item for this attribute
     $attribute = $attribute_factory->newAttribute($name, $value, $server->getIndex(), $source);
     $attrid = $this->getAttrID($attribute->getName());
     if (is_null($attrid)) {
         array_push($this->attributes, $attribute);
     }
     return $attribute;
 }
예제 #13
0
 /**
  * This function will setup our template object (read LDAP for current values, read $_REQUEST for new values, etc)
  * so that it can be rendered.
  */
 private function visitStart()
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 129, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     if (DEBUGTMP) {
         printf('<font size=-2>%s</font><br />', __METHOD__);
     }
     # If we have a DN, then we are an editing template
     if ($this->dn) {
         $this->template->setDN($this->dn);
     } elseif ($this->container || get_request('create_base')) {
         $this->template->setContainer($this->container);
     } else {
         debug_dump_backtrace('Dont know what type of template we are - no DN or CONTAINER?', 1);
     }
     # Header
     $this->drawHeader();
 }
예제 #14
0
 /**
  * Copy a DN
  */
 public function copy($template, $rdn, $asnew = false)
 {
     if (DEBUG_ENABLED && (($fargs = func_get_args()) || ($fargs = 'NOARGS'))) {
         debug_log('Entered (%%)', 5, 0, __FILE__, __LINE__, __METHOD__, $fargs);
     }
     $rdnarray = rdn_explode($rdn);
     $counter = 1;
     foreach ($template->getAttributes(true) as $sattribute) {
         $attribute = $this->addAttribute($sattribute->getName(false), array('values' => $sattribute->getValues()));
         # Set our new RDN, and its values
         if (is_null($attribute)) {
             debug_dump_backtrace('Attribute is null, it probably doesnt exist in the destination server?');
         } else {
             # Mark our internal attributes.
             if ($sattribute->isInternal()) {
                 $attribute->setInternal();
             }
             $modified = false;
             foreach ($rdnarray as $index => $rdnattr) {
                 list($attr, $value) = explode('=', $rdnattr);
                 if (strtolower($attr) == $attribute->getName()) {
                     # If this is already marked as an RDN, then this multivalue RDN was updated on a previous loop
                     if (!$modified) {
                         $attribute->setValue(array($value));
                         $attribute->setRDN($counter++);
                         $modified = true;
                     } else {
                         $attribute->addValue($value);
                     }
                     # This attribute has been taken care of, we'll drop it from our list.
                     unset($rdnarray[$index]);
                 }
             }
         }
         // @todo If this is a Jpeg Attribute, we need to mark it read only, since it cant be deleted like text attributes can
         if (strcasecmp(get_class($attribute), 'jpegAttribute') == 0) {
             $attribute->setReadOnly();
         }
     }
     # If we have any RDN values left over, there werent in the original entry and need to be added.
     foreach ($rdnarray as $rdnattr) {
         list($attr, $value) = explode('=', $rdnattr);
         $attribute = $this->addAttribute($attr, array('values' => array($value)));
         if (is_null($attribute)) {
             debug_dump_backtrace('Attribute is null, it probably doesnt exist in the destination server?');
         } else {
             $attribute->setRDN($counter++);
         }
     }
     # If we are copying into a new entry, we need to discard all the "old values"
     if ($asnew) {
         foreach ($this->getAttributes(true) as $sattribute) {
             $sattribute->setOldValue(array());
         }
     }
 }