phpldapadmin/lib/export_functions.php
2009-06-30 21:52:55 +10:00

716 lines
19 KiB
PHP
Executable File

<?php
// $Header: /cvsroot/phpldapadmin/phpldapadmin/lib/export_functions.php,v 1.36.2.2 2008/12/12 12:20:23 wurley Exp $
/**
* Fuctions and classes for exporting ldap entries to others formats
* (LDIF,DSML,..)
* An example is provided at the bottom of this file if you want implement yours. *
* @package phpLDAPadmin
* @author The phpLDAPadmin development team
* @see export.php and export_form.php
*/
/**
*/
# registry for the exporters
$exporters = array();
$exporters[] = array(
'output_type'=>'ldif',
'desc' => 'LDIF',
'extension' => 'ldif'
);
$exporters[] = array(
'output_type'=>'dsml',
'desc' => 'DSML V.1',
'extension' => 'xml'
);
$exporters[] = array(
'output_type'=>'vcard',
'desc' => 'VCARD 2.1',
'extension' => 'vcf'
);
$exporters[] = array(
'output_type'=>'csv',
'desc' => _('CSV (Spreadsheet)'),
'extension' => 'csv'
);
/**
* This class encapsulate informations about the ldap server
* from which the export is done.
* The following info are provided within this class:
*
* $ldapserver: the object of the server.
* $base_dn: if the source of the export is the ldap server,
* it indicates the base dn of the search.
* $query_filter: if the source of the export is the ldap server,
* it indicates the query filter for the search.
* $scope: if the source of the export is the ldap server,
* it indicates the scope of the search.
*
* @package phpLDAPadmin
*/
class LdapExportInfo {
public $ldapserver;
public $base_dn;
public $query_filter;
public $scope;
/**
* Create a new LdapExportInfo object
*
* @param int $server_id the server id
* @param String $base_dn the base_dn for the search in a ldap server
* @param String $query_filter the query filter for the search
* @param String $scope the scope of the search in a ldap server
*/
function LdapExportInfo($server_id,$base_dn=null,$query_filter=null,$scope=null) {
$this->ldapserver = $_SESSION[APPCONFIG]->ldapservers->Instance($server_id);
$this->ldapserver->base_dn = $base_dn;
$this->ldapserver->query_filter = $query_filter;
$this->ldapserver->scope = $scope;
}
}
/**
* This class represents the base class of all exporters
* It can be subclassed directly if your intend is to write
* a source exporter(ie. it will act only as a decoree
* which will be wrapped by an another exporter.)
* If you consider writting an exporter for filtering data
* or directly display entries, please consider subclass
* the PlaExporter
*
* @see PlaExporter
* @package phpLDAPadmin
*/
class PlaAbstractExporter {
/**
* Return the number of entries
* @return int the number of entries to be exported
*/
function pla_num_entries() {}
/**
* Return the results
* @return array if there is some more entries to be processed
*/
function pla_results() {}
/**
* Return a PlaLdapInfo Object
* @return LdapInfo Object with info from the ldap serveur
*/
function pla_get_ldap_info() {}
} # end PlaAbstractExporter
/**
* PlaExporter acts a wrapper around another exporter.
* In other words, it will act as a decorator for another decorator
*
* @package phpLDAPadmin
*/
class PlaExporter extends PlaAbstractExporter {
# Default CRLN
public $br = "\n";
# The wrapped $exporter
public $exporter;
public $compress = false;
/**
* Constructor
* @param source $source the decoree for this exporter
*/
function PlaExporter($source) {
$this->exporter = $source;
}
/**
* Return the number of entries
* @return int the number of entries to be exported
*/
function pla_num_entries() {
return $this->exporter->pla_num_entries();
}
/**
* Return the results
* @return array if there is some more entries to be processed
*/
function pla_results() {
return $this->exporter->pla_results();
}
/**
* Return a PlaLdapInfo Object
* @return LdapInfo Object with info from the ldap serveur
*/
function pla_get_ldap_info() {
return $this->exporter->pla_get_ldap_info();
}
/**
* Helper method to check if the attribute value should be base 64 encoded.
* @param String $str the string to check.
* @return bool true if the string is safe ascii, false otherwise.
*/
function is_safe_ascii($str) {
for ($i=0;$i<strlen($str);$i++)
if (ord($str{$i}) < 32 || ord($str{$i}) > 127)
return false;
return true;
}
/**
* Abstract method use to export data.
* Must be implemented in a sub-class if you write an exporter
* which export data.
* Leave it empty if you write a sub-class which do only some filtering.
*/
function export() {}
/**
* Set the carriage return /linefeed for the export
* @param String $br the CRLF to be set
*/
function setOutputFormat($br){
$this->br = $br;
}
/**
* Display the header for the export
*/
function displayExportInfoHeader($type,$ldapserver) {
$output = '';
$output .= sprintf("version: 1%s%s",$this->br,$this->br);
$output .= sprintf('# '.$type."%s",$ldapserver->base_dn,$this->br);
$output .= sprintf('# '._('Generated by phpLDAPadmin ( http://phpldapadmin.sourceforge.net/ ) on %s')."%s",date('F j, Y g:i a'),$this->br);
$output .= sprintf("# %s: %s (%s)%s",_('Server'),$ldapserver->name,$ldapserver->host,$this->br);
$output .= sprintf("# %s: %s%s",_('Search Scope'),$ldapserver->scope,$this->br);
$output .= sprintf("# %s: %s%s",_('Search Filter'),$ldapserver->query_filter,$this->br);
$output .= sprintf("# %s: %s%s",_('Total Entries'),$this->pla_num_entries(),$this->br);
$output .= $this->br;
return $output;
}
function compress($boolean) {
$this->compress = $boolean;
}
function isCompressed() {
return $this->compress;
}
} # end PlaExporter
/**
* Export data from a ldap server
* @extends PlaAbstractExporter
* @package phpLDAPadmin
*/
class PlaLdapExporter extends PlaAbstractExporter {
public $scope;
public $base_dn;
public $server_id;
public $queryFilter;
public $attributes;
public $ldap_info;
public $results;
public $num_entries;
/**
* Create a PlaLdapExporter object.
* @param int $server_id the server id
* @param String $queryFilter the queryFilter for the export
* @param String $base_dn the base_dn for the data to export
* @param String $scope the scope for export
*/
function PlaLdapExporter($server_id,$queryFilter,$base_dn,$scope,$attributes) {
$this->scope = $scope;
$this->base_dn = $base_dn;
$this->server_id = $server_id;
$this->queryFilter = $queryFilter;
$this->attributes = $attributes;
# infos for the server
$this->ldap_info = new LdapExportInfo($server_id,$base_dn,$queryFilter,$scope);
# get the data to be exported
$this->results = $this->ldap_info->ldapserver->search(null,$this->base_dn,$this->queryFilter,$this->attributes,
$this->scope,true,$_SESSION[APPCONFIG]->GetValue('deref','export'));
# if no result, there is a something wrong
if (! $this->results && $this->ldap_info->ldapserver->errno())
system_message(array(
'title'=>_('Encountered an error while performing search.'),
'body'=>ldap_error_msg($this->ldap_info->ldapserver->error(),$this->ldap_info->ldapserver->errno()),
'type'=>'error'));
usort($this->results,'pla_compare_dns');
$this->num_entries = count($this->results);
} # End constructor
/**
* Return the results
* @return array if there is some more entries to be processed
*/
function pla_results() {
return $this->results;
}
/**
* Return a PlaLdapInfo Object
* @return LdapInfo Object with info from the ldap serveur
*/
function pla_get_ldap_info() {
return $this->ldap_info->ldapserver;
}
/**
* Return the number of entries
* @return int the number of entries to be exported
*/
function pla_num_entries() {
return $this->num_entries;
}
} # End PlaLdapExporter
/**
* Export entries to ldif format
* @extends PlaExporter
* @package phpLDAPadmin
*/
class PlaLdifExporter extends PlaExporter {
# variable to keep the count of the entries
public $counter = 0;
# the maximum length of the ldif line
public $MAX_LDIF_LINE_LENGTH = 76;
/**
* Create a PlaLdifExporter object
* @param PlaAbstractExporter $exporter the source exporter
*/
function PlaLdifExporter($exporter) {
$this->exporter = $exporter;
}
/**
* Export entries to ldif format
*/
function export() {
$ldapserver = $this->pla_get_ldap_info();
$output = $this->displayExportInfoHeader(_('LDIF Export for: %s'),$ldapserver);
# Sift through the entries.
foreach ($this->pla_results() as $dn => $dndetails) {
$this->counter++;
if (isset($dndetails['dn'])) {
$dn = $dndetails['dn'];
unset($dndetails['dn']);
}
$title_string = sprintf('# %s %s: %s%s',_('Entry'),$this->counter,$dn,$this->br);
if (strlen($title_string) > $this->MAX_LDIF_LINE_LENGTH-3)
$title_string = substr($title_string,0,$this->MAX_LDIF_LINE_LENGTH-3).'...'.$this->br;
# display dn
if ($this->is_safe_ascii($dn))
$output .= $this->multi_lines_display(sprintf('dn: %s',$dn));
else
$output .= $this->multi_lines_display(sprintf('dn:: %s',base64_encode($dn)));
# display the attributes
foreach ($dndetails as $key => $attr) {
if (! is_array($attr))
$attr = array($attr);
foreach ($attr as $value) {
if (! $this->is_safe_ascii($value) || $ldapserver->isAttrBinary($key)) {
$output .= $this->multi_lines_display(sprintf('%s:: %s',$key,base64_encode($value)));
} else {
$output .= $this->multi_lines_display(sprintf('%s: %s',$key,$value));
}
}
} # end foreach
$output .= $this->br;
}
if ($this->compress)
echo gzencode($output);
else
echo $output;
}
/**
* Helper method to wrap ldif lines
* @param String $str the line to be wrapped if needed.
*/
function multi_lines_display($str) {
$length_string = strlen($str);
$max_length = $this->MAX_LDIF_LINE_LENGTH;
$output = '';
while ($length_string > $max_length) {
$output .= substr($str,0,$max_length).$this->br.' ';
$str = substr($str,$max_length,$length_string);
$length_string = strlen($str);
/* need to do minus one to align on the right
* the first line with the possible following lines
* as these will have an extra space. */
$max_length = $this->MAX_LDIF_LINE_LENGTH-1;
}
$output .= $str.$this->br;
return $output;
}
}
/**
* Export entries to DSML v.1
* @extends PlaExporter
* @package phpLDAPadmin
*/
class PlaDsmlExporter extends PlaExporter {
public $counter = 0;
/**
* Create a PlaDsmlExporter object
* @param PlaAbstractExporter $exporter the decoree exporter
*/
function PlaDsmlExporter($exporter) {
$this->exporter = $exporter;
}
/**
* Export the entries to DSML
*/
function export() {
$ldapserver = $this->pla_get_ldap_info();
# not very elegant, but do the job for the moment as we have just 4 level
$directory_entries_indent = ' ';
$entry_indent= ' ';
$attr_indent = ' ';
$attr_value_indent = ' ';
# print declaration
$output = '<?xml version="1.0"?>'.$this->br;
# print root element
$output .= '<dsml>'.$this->br;
# print info related to this export
$output .= '<!--'.$this->br;
$output .= $this->displayExportInfoHeader(_('DSLM Export for: %s'),$ldapserver);
$output .= '-->'.$this->br;
$output .= $this->br;
$output .= $directory_entries_indent.'<directory-entries>'.$this->br;
# Sift through the entries.
foreach ($this->pla_results() as $dn => $dndetails) {
$this->counter++;
unset($dndetails['dn']);
# display dn
$output .= sprintf($entry_indent.'<entry dn="%s">'."%s",htmlspecialchars($dn),$this->br);
# echo the objectclass attributes first
if (isset($dndetails['objectClass'])) {
$output .= $attr_indent.'<objectClass>'.$this->br;
foreach ($dndetails['objectClass'] as $ocValue) {
$output .= sprintf($attr_value_indent.'<oc-value>%s</oc-value>'."%s",$ocValue,$this->br);
}
$output .= $attr_indent.'</objectClass>'.$this->br;
unset($dndetails['objectClass']);
}
$binary_mode = 0;
# display the attributes
foreach ($dndetails as $key => $attr) {
if (! is_array($attr))
$attr = array($attr);
$output .= sprintf($attr_indent.'<attr name="%s">'."%s",$key,$this->br);
# if the attribute is binary, set the flag $binary_mode to true
$binary_mode = $ldapserver->isAttrBinary($key) ? 1 : 0;
foreach ($attr as $value) {
$output .= sprintf($attr_value_indent.'<value>%s</value>'."%s",
($binary_mode ? base64_encode($value) : htmlspecialchars($value)),$this->br);
}
$output .= $attr_indent.'</attr>'.$this->br;
} # end foreach
$output .= $entry_indent.'</entry>'.$this->br;
}
$output .= $directory_entries_indent.'</directory-entries>'.$this->br;
$output .= '</dsml>'.$this->br;
if ($this->compress)
echo gzencode($output);
else
echo $output;
}
}
/**
* @package phpLDAPadmin
*/
class PlaVcardExporter extends PlaExporter {
# mappping one to one attribute
public $vcardMapping = array('cn' => 'FN',
'title' => 'TITLE',
'homePhone' => 'TEL;HOME',
'mobile' => 'TEL;CELL',
'mail' => 'EMAIL;Internet',
'labeledURI' =>'URL',
'o' => 'ORG',
'audio' => 'SOUND',
'facsmileTelephoneNumber' =>'TEL;WORK;HOME;VOICE;FAX',
'jpegPhoto' => 'PHOTO;ENCODING=BASE64',
'businessCategory' => 'ROLE',
'description' => 'NOTE'
);
public $deliveryAddress = array('postOfficeBox',
'street',
'l',
'st',
'postalCode',
'c');
function PlaVcardExporter($exporter){
$this->exporter = $exporter;
}
/**
* When doing an exporter, the method export need to be overriden.
* A basic implementation is provided here. Customize to your need
**/
function export() {
$output = '';
# Sift through the entries.
foreach ($this->pla_results() as $id => $dndetails) {
# check the attributes needed for the delivery address field
$addr = 'ADR:';
foreach ($this->deliveryAddress as $attr_name) {
if (isset($dndetails[$attr_name])) {
$addr .= $dndetails[$attr_name];
unset($dndetails[$attr_name]);
}
$addr .= ';';
}
$output .= 'BEGIN:VCARD'.$this->br;
# loop for the attributes
foreach ($dndetails as $key => $attr) {
if (! is_array($attr))
$attr = array($attr);
/* if an attribute of the ldap entry exist
* in the mapping array for vcard */
if (isset($this->vcardMapping[$key])) {
/* case of organisation. Need to append the
* possible ou attribute*/
if (strcasecmp($key ,'o') == 0) {
$output .= sprintf('%s:%s',$this->vcardMapping[$key],$attr[0]);
if (isset($entry['ou']))
foreach ($entry['ou'] as $ou_value) {
$output .= sprintf(';%s',$ou_value);
}
# the attribute is binary. (to do : need to fold the line)
} elseif (strcasecmp($key,'audio') == 0 || strcasecmp($key,'jpegPhoto') == 0) {
$output .= $this->vcardMapping[$key].':'.$this->br;
$output .= ' '.base64_encode($attr[0]);
} else {
$output .= $this->vcardMapping[$key].':'.$attr[0];
}
$output .= $this->br;
}
}
$output .= sprintf('UID:%s'."%s",isset($dndetails['entryUUID']) ? $dndetails['entryUUID'] : $dndetails['dn'],$this->br);
$output .= 'VERSION:2.1'.$this->br;
$output .= $addr.$this->br;
$output .= 'END:VCARD'.$this->br;
} # end while
if ($this->compress)
echo gzencode($output);
else
echo $output;
}
}
/**
* Export to cvs format
*
* @author Glen Ogilvie
* @package phpLDAPadmin
*/
class PlaCSVExporter extends PlaExporter {
function PlaCSVExporter($exporter) {
$this->exporter = $exporter;
}
/**
* When doing an exporter, the method export need to be overriden.
* A basic implementation is provided here. Customize to your need
**/
public $separator = ',';
public $qualifier = '"';
public $multivalue_separator = ' | ';
public $escapeCode = '"';
function export() {
$entries = array();
$headers = array();
$ldap_info = $this->pla_get_ldap_info();
$output = '';
/* go thru and find all the attribute names first. This is needed, because, otherwise we have
* no idea as to which search attributes were actually populated with data */
foreach ($this->pla_results() as $dn => $dndetails) {
foreach (array_keys($dndetails) as $key) {
if (!in_array($key,$headers))
array_push($headers,$key);
}
array_push($entries,$dndetails);
}
$num_headers = count($headers);
# print out the headers
for ($i = 0; $i < $num_headers; $i++) {
$output .= $this->qualifier.$headers[$i].$this->qualifier;
if ($i < $num_headers-1)
$output .= $this->separator;
}
array_shift($headers);
$num_headers--;
$output .= $this->br;
# loop on every entry
foreach ($entries as $index => $entry) {
$dn = $entry['dn'];
unset($entry['dn']);
$output .= $this->qualifier.$this->LdapEscape($dn).$this->qualifier.$this->separator;
# print the attributes
for ($j=0; $j < $num_headers; $j++) {
$attr_name = $headers[$j];
$output .= $this->qualifier;
if (key_exists($attr_name,$entry)) {
$binary_attribute = $ldap_info->isAttrBinary($attr_name) ? 1 : 0;
if (! is_array($entry[$attr_name]))
$attr_values = array($entry[$attr_name]);
else
$attr_values = $entry[$attr_name];
$num_attr_values = count($attr_values);
for ($i=0; $i<$num_attr_values; $i++) {
if ($binary_attribute)
$output .= base64_encode($attr_values[$i]);
else
$output .= $this->LdapEscape($attr_values[$i]);
if ($i < $num_attr_values - 1)
$output .= $this->multivalue_separator;
}
} # end if key
$output .= $this->qualifier;
if ($j < $num_headers - 1)
$output .= $this->separator;
}
$output .= $this->br;
}
if ($this->compress)
echo gzencode($output);
else
echo $output;
} #end export
/* function to escape data, where the qualifier happens to also
* be in the data. */
function LdapEscape ($var) {
return str_replace($this->qualifier,$this->escapeCode.$this->qualifier,$var);
}
}
/**
* @package phpLDAPadmin
*/
class MyCustomExporter extends PlaExporter {
function MyCustomExporter($exporter) {
$this->exporter = $exporter;
}
/**
* When doing an exporter, the method export need to be overriden.
* A basic implementation is provided here. Customize to your need
**/
function export() {
/* With the method pla->get_ldap_info,
* you have access to some values related
* to you ldap server */
$ldap_info = $this->pla_get_ldap_info();
/* Just a simple loop. For each entry
* do your custom export
* see PlaLdifExporter or PlaDsmlExporter as an example */
foreach ($this->pla_results() as $dn => $dndetails) {
unset($dndetails['dn']);
# loop for the attributes
foreach ($dndetails as $key => $attr) {
if (! is_array($attr))
$attr = array($attr);
foreach ($attr as $value) {
/* simple example
echo "Attribute Name:".$attr;
echo " - value:".$value;
echo $this->br;
*/
}
}
} # end while
}
}
?>