<?php if (!defined('PmWiki')) exit();
/*
 * Phonebook - AD integrated Profiles for PmWiki
 * (c) 2007 Tjeerd van der Laan <tjeerd (at) suezkade (dot) nl>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

$RecipeInfo['Phonebook']['Version'] = '$Rev: 0.2 $';

// Paths
SDV($Phonebook_GroupName, 'Profiles'); 
SDV($Phonebook_LdapServer,'ldap://dc.internal.services');
SDV($Phonebook_LdapUser,'DOMAIN\username');
SDV($Phonebook_LdapPass,'password');
SDV($Phonebook_BaseDn,'dc=internal,dc=services');
SDV($Phonebook_Filter,'(&(objectClass=user)(objectClass=person)(telephonenumber=*)(|(homeMDB=*)(msExchHomeServerName=*))(!(objectClass=computer))(!(description=Disabled*)))');
SDV($Phonebook_Title,'cn'); 
SDV($Phonebook_Fields, Array('cn','sn','givenname','description','title','initials','department','mail','telephonenumber','physicaldeliveryofficename','samaccountname','mobile'));
SDV($Phonebook_Interval,3600); // cleanup pages every hour
SDV($Phonebook_Keep, Array('GroupHeader','GroupAttributes','HomePage','RecentChanges','Zoeken'));

#################################################################################
class ProfilePageStore extends PageStore {

    function ProfilePageStore() {
	$this->dirfmt=$d; 
	$this->iswrite=$w; 
	$this->timestamp = "wiki.d/.phonebook.timestamp";
	//$this->PageStore();
	//$this->PageStore("$Phonebook_GroupName/\$FullName",1);
    }
    function pagefile($pagename) {
	$return = "wiki.d/$pagename";
	return $return;
    }
    function ls($pats=NULL) {
	if ($this->cleanup()) $this->sync();
	return parent::ls($pats);
    }
    function sync() {
	global $Phonebook_GroupName, $Phonebook_Fields, $Now, $Version;
	global $Phonebook_LdapServer, $Phonebook_LdapUser, $Phonebook_LdapPass;
	global $Phonebook_BaseDn, $Phonebook_Filter;
	global $GroupPattern, $NamePattern;
	global $Phonebook_Title, $Phonebook_Keep;
	StopWatch("Phonebook::sync begin");
	$pagelist = Array();
	$connect = ldap_connect($Phonebook_LdapServer) or Abort(ldap_error($connect));
	ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3) or Abort(ldap_error($connect));
	ldap_set_option($connect, LDAP_OPT_REFERRALS, 0) or Abort(ldap_error($connect));
	$bind = ldap_bind($connect, $Phonebook_LdapUser, $Phonebook_LdapPass) or Abort(ldap_error($connect));
	$search = ldap_search($connect, $Phonebook_BaseDn, $Phonebook_Filter) or Abort(ldap_error($connect));
	$info = ldap_get_entries($connect, $search) or Abort(ldap_error($connect));
	for ($i=0; $i<$info["count"]; $i++) {
	    $meta = Array();
	    foreach ($Phonebook_Fields as $field) {
		$meta[$field] = $info[$i][$field][0];
	    }
	    $pagename = $Phonebook_GroupName.'.'.ucfirst($meta['samaccountname']);
	    if (!$this->exists($pagename)) {
		$page['name'] = $pagename;
		$page['title'] = $meta[$Phonebook_Title];
		$page['phonebook'] = implode(",",$meta);
		$page['author'] = "system";
		$page['ctime'] = $Now;
		$page['text'] = "\n\n";
		$this->write($pagename,$page);
	    } else {
		$page = $this->read($pagename);
		$page['title'] = $meta[$Phonebook_Title];
		$page['phonebook'] = implode(",",$meta);
		$this->write($pagename,$page);
	    }
	    $pagelist[] = $pagename;
	}
        $filelist = parent::ls("$Phonebook_GroupName.*");
	$rm = array_diff($filelist,$pagelist);
	$omit = implode('|',$Phonebook_Keep);
	foreach($rm as $pagename) {
	    if (!preg_match("/$Phonebook_GroupName.($omit)/i",$pagename)) {
			$this->delete($pagename);
	    }
	}
	StopWatch("Phonebook::sync end");
	return $out;
    }
    // The write() function is a copy of the inherited class, only converts more character
    // Something dor the PIT
    function write($pagename,$page) {
	global $Now, $Version;
	$page['name'] = $pagename;
	$page['time'] = $Now;
	$page['host'] = $_SERVER['REMOTE_ADDR'];
	$page['agent'] = @$_SERVER['HTTP_USER_AGENT'];
	$page['rev'] = @$page['rev']+1;
	unset($page['version']); unset($page['newline']);
	uksort($page, 'CmpPageAttr');
	$s = false;
	$pagefile = $this->pagefile($pagename);
	$dir = dirname($pagefile); mkdirp($dir);
	if (!file_exists("$dir/.htaccess") && $fp = @fopen("$dir/.htaccess", "w")) {
	    fwrite($fp, "Order Deny,Allow\nDeny from all\n"); fclose($fp);
	}
	if ($pagefile && ($fp=fopen("$pagefile,new","w"))) {
	    $r0 = array('%',"\n",'<','ü','é');
	    $r1 = array('%25','%0a','%3c','%fc','%e9');
	    $x = "version=$Version ordered=1 urlencoded=1\n";
	    $s = true && fputs($fp, $x); $sz = strlen($x);
	    foreach($page as $k=>$v) {
    		if ($k > '' && $k{0} != '=') {
	    	    $x = str_replace($r0, $r1, "$k=$v") . "\n";
		    $s = $s && fputs($fp, $x); $sz += strlen($x);
		}
	    }
	    $s = fclose($fp) && $s;
	    $s = $s && (filesize("$pagefile,new") > $sz * 0.95);
	    if (file_exists($pagefile)) $s = $s && unlink($pagefile);
	    $s = $s && rename("$pagefile,new", $pagefile);
	}
	$s && fixperms($pagefile);
	if (!$s) Abort("Cannot write page to $pagename ($pagefile)...changes not saved");
	PCache($pagename, $page);
    }
										         
    function cleanup() {
	global $Phonebook_Interval;
	if( !file_exists( $this->timestamp ) ) {
	    touch($this->timestamp);
	    $return = TRUE;
	} else {
	    if (time()-filemtime($this->timestamp)>$Phonebook_Interval) {
		touch($this->timestamp);
		$return = TRUE;
	    } else {
		$return = FALSE;
	    }
	}
        return $return;
    }
}

#################################################################################
$WikiLibDirs[] = new ProfilePageStore($Phonebook_GroupName,1);


function ldap($field) {
    global $Phonebook_Fields, $pagename, $PCache, $Cursor;
    $p = (is_null($Cursor)?$pagename:$Cursor['=']);
    $value = $PCache[$p]['phonebook'];
    $meta = explode(",",$value);
    $return=$meta[array_search($field,$Phonebook_Fields)];
    return $return;
}

foreach ($Phonebook_Fields as $field) {
    $FmtPV["\$ldap_$field"] = "ldap('$field')";
}