Location: PHPKode > projects > Toutateam Groupware > toutateam-v1.56/outsync/remoteaccess.php
<?php
/*
 * CREATE TABLE `outsync_cross_ref` (
`ID` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`type` VARCHAR( 10 ) NOT NULL ,
`data_local_ID` INT( 11 ) NOT NULL ,
`data_foreign_ID` VARCHAR( 80 ) NOT NULL ,
`user_ID` INT( 11 ) NOT NULL
) ENGINE = MYISAM ;
 */
// Includes required for XML RPC

$path_pre="../";
define("avoid_auth",1);
require_once($path_pre."lib/lib.inc.php");

include_once 'xmlrpc.inc.php';
include_once 'xmlrpcs.inc.php';
//include_once 'database.php';
//include_once 'config.inc.php';
include_once 'outsync.class.php';

$TheTablesFromType=array(	"calendar"=>"termine",
							"notes"=>"notes",
							"tasks"=>"todo",
							"contacts"=>"contacts",
							"cleancalendar"=>"termine",
							"cleannotes"=>"notes",
							"cleantasks"=>"todo",
							"cleancontacts"=>"contacts");

/*
$path_pre="../";
include_once $path_pre."lib/lib.inc.php";
*/
$user_ID=-1; // Keep the $user_ID Var for compatibility with Toutateam lib functions
if(!isset($pw_crypt)) $pw_crypt="1";

error_reporting(E_NONE);
//$database = new database( $server, $database_user,$database_password,$database_name,$database_prefix );

if(!isset($debug)) $debug=0;
if(!isset($logevents)) $logevents=0;
$logevents=1;
if($logevents==1)
{
	//$database->setQuery("DELETE FROM #__logevent;");
	//$database->query();
}
if($debug==1)
{
	if(isset($fonctiondebug)) echo "Debug de la fonction : ".$fonctiondebug."<br>\n";
	echo $fonctiondebug($catname,$userlevel);
    end;
}
// Beginning code
/*
function check_role($module,$theUserId) {
  global $database;
  $result = $database->setQuery("select roles.ID, $module as module from roles, users where users.role = roles.ID and users.ID = ".$theUserId.";") ;
  $row = $database->loadObjectList();
  // is there a role for this user?
  if (count($row) > 0) {
    // return the numeric value of the status: 0 = no access, 1 = read, 2 = write
    return $row[0]->module;
  }
  // otherwise give him the full rights
  // Modif YB du 26/11/2003 - Ne pas donner de droits si les droits ne sont pas définis !!!
//  	else { return "2"; }  // Original
    else { return "0"; }  // Final
  // Fin Modif YB du 26/11/2003 - Ne pas donner de droits si les droits ne sont pas définis !!!
}    
//*/

function check_rights($theModule,$theUserId)
{
	global $calendar,$notes,$todo,$adressen;
	switch($theModule)
	{
		case "cleancalendar":
			return ($calendar and check_role("calendar",$theUserId) > 1);
		case "cleancontacts":
			return ($adressen and check_role("contacts",$theUserId) > 1);
		case "cleantasks":
			return ($todo and check_role("todo",$theUserId) > 1);
		case "cleannotes":
			return ($notes and check_role("notes",$theUserId) > 1);
		case "calendar":
			return ($calendar and check_role("calendar",$theUserId) > 0);
		case "contacts":
			return ($adressen and check_role("contacts",$theUserId) > 0);
		case "tasks":
			return ($todo and check_role("todo",$theUserId) > 0);
		case "notes":
			return ($notes and check_role("notes",$theUserId) > 0);
	}
	return false;
}

function html_translate($theText)
{
	$theText=str_replace("&euro;","€",$theText);
	$transtable=array();
	$trans=get_html_translation_table(HTML_ENTITIES);
	foreach($trans as $key=>$value) $transtable[$value]=$key;
	
	return stripslashes(strtr($theText,$transtable));
}

function Text2URL($theText)
{
	$myURL=$theText;
	//*
	$myURL = preg_replace("/[àáâãäå]/g",'a',$myURL);
	$myURL = preg_replace("/[ç]/g",'c',$myURL);
	$myURL = preg_replace("/[òóôõöø]/g",'o',$myURL);
	$myURL = preg_replace("/[èéêë]/g",'e',$myURL);
	$myURL = preg_replace("/[ìíîï]/g",'i',$myURL);
	$myURL = preg_replace("/[ùúûüÿ]/g",'u',$myURL);
	$myURL = preg_replace("/[ñ]/g",'n',$myURL);
	$myURL = preg_replace("/[^a-z0-9_\s-]/g",'',$myURL);
	$myURL = preg_replace("/[\s]+/g",' ',$myURL);
	$myURL = preg_replace("/[ ]/g",'-',$myURL);
	//*/
	return $myURL;
}
function logevent($theEvent,$theComplement="")
{
	global $database,$logevents,$logfile,$myLogFH;
	//if(!isset($logfile)) $logfile="logfile.log";
	//if(!$myLogFH) $myLogFH=fopen();
	if($logevents!=1) return false;
	$database->setQuery("INSERT INTO rssf_logevent (DateEvent,TitreEvent,ComplementInfo) VALUES (NOW(),'".str_replace("'","\'",$theEvent)."','".str_replace("'","\'",$theComplement)."');");
	$database->query();
	return true;
}

// crypt string
function encrypt($password, $saltstring,$theCryptType="") {
	global $crypttype;
	$myCryptType=$crypttype;
	if($theCryptType=="md5" || $theCryptType=="crypt")
		$myCryptType=$theCryptType;
	switch($myCryptType)
	{
		case "md5":
			$enc_pw="{md5}".md5($password);
			break;
		case "crypt":
		default:
		  	$salt = substr($saltstring, 0, 2);
		  	$enc_pw = crypt($password, $salt);
			break;
	}
  	return $enc_pw;
}
/*
function encrypt($password, $saltstring) {
    global $pw_crypt;
    if($pw_crypt!="1") return $password;
  $salt = substr($saltstring, 0, 2);
  $enc_pw = crypt($password, $salt);
  return $enc_pw;
}
*/
// Modif YB du 15/09/2004 - Adding a few functions to make it easier to check user rank
/*
function isChief($user_access)
{
	//echo "Is chief $user_access ?<br>\n"; 
	$chief = strpos($user_access,"c");
	if($chief!==FALSE) { return true; }
	return false;
}

function isAdmin($user_access)
{
	//echo "Is admin $user_access ?<br>\n"; 
	$admin = strpos($user_access,"a");
	if($admin!==FALSE) { return true; }
	return false;
}
*/


function getUserId($theUser,$thePass,&$theUserId,&$theUserGroup,&$theAccess)
{
        global $database,$user_ID,$pw_crypt;
        if($pw_crypt=="1")
        	$myEncPw=encrypt($thePass,$thePass);
        else
        	$myEncPw=$thePass;
        $database->setQuery("SELECT * FROM users WHERE loginname='".$theUser."' AND pw='".$myEncPw."';");
        $myListUsers=$database->loadObjectList();
        if(count($myListUsers)<=0)
        {
            return false;
        }
        else
        {
            $theUserId=$myListUsers[0]->ID;
            $theUserGroup=$myListUsers[0]->gruppe;
            $theAccess=$myListUsers[0]->acc;
            $user_ID=$theUserId;
            return true;
        }
}

function getErrorMessage($theMsg)
{
        $struct = array('ttsummresult' => new xmlrpcval($theMsg, 'string'));
        return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
}
function getQueryFromType($theType,$theUserId,$theUserGroup,$theIdFilter,$offsetdebut="",$offsetfin="1")
{
	global $TheTablesFromType;
	$mySQLSelect=" c.*,o.data_local_ID as ttid,o.data_foreign_ID as ouid ";
	$mySQLLeftJoin=" as c LEFT JOIN outsync_cross_ref as o ON (o.data_local_ID=c.ID  AND o.user_ID=".$theUserId." AND o.type='".$theType."') ";
	$mySQLAndCond="";
    if($theType=="calendar")
    {
    	
        if($theIdFilter=="")
        {
	        $myRequete  = "select ".$mySQLSelect.",DATE_ADD(curdate(), INTERVAL ".$offsetdebut." month) as intervalbegin,DATE_ADD(curdate(), INTERVAL ".$offsetfin." month) as intervalend from ".$TheTablesFromType[$theType]." ".$mySQLLeftJoin." where c.an = ".$theUserId." AND ( (c.div1='-1' AND (c.div2 IS NULL OR c.div2='' OR  c.div2='recur')) OR (c.div2='groupe') ) ".$mySQLAndCond." ";
        	$myRequete .= "AND (";
        	$myRequete .= " 		( (c.div1='-1' OR c.div1 IS NULL OR c.div1='')  AND c.datum>=DATE_ADD(curdate(), INTERVAL ".$offsetdebut." month) AND c.datum<=DATE_ADD(curdate(), INTERVAL ".$offsetfin." month) ) ";
        	$myRequete .= "		OR 	(c.div1='-1' AND c.div2='recur')";
			$myRequete .= " )";
        }

		if($theIdFilter!="")
		{
	        $myRequete  = "select ".$mySQLSelect." from ".$TheTablesFromType[$theType]." ".$mySQLLeftJoin." where c.an = ".$theUserId." AND ( (c.div1='-1' AND (c.div2 IS NULL OR c.div2='' OR  c.div2='recur')) OR (c.div2='groupe') ) ".$mySQLAndCond." ";
			$myRequete .= $theIdFilter."";
		}
		$myRequete.=" GROUP BY c.ID";
    }
	Tools::Trace(__FUNCTION__."@".__LINE__."==> Requete From Type : ".Tools::Display($myRequete));
    if($theType=="contacts")
    {
        $myRequete  = "select ".$mySQLSelect." from ".$TheTablesFromType[$theType]." ".$mySQLLeftJoin." where (c.acc='a' OR (c.gruppe = ".$theUserGroup." and  (c.acc='g' OR c.acc='' OR c.acc=' ') ) OR c.von=".$theUserId.") ".$theIdFilter." AND (div2<>'d' OR div2 IS NULL) ".$mySQLAndCond.";";
    }

    if($theType=="tasks")
    {
		if (intval($offsetfin)>=1 )
		{
			$myRequete  = "select ".$mySQLSelect." from ".$TheTablesFromType[$theType]." ".$mySQLLeftJoin." where c.div1='-1' AND c.ext = ".$theUserId." ".$theIdFilter." AND (div2<>'d' OR div2 IS NULL)  ".$mySQLAndCond." ORDER BY deadline DESC;";
		}
        if(intval($offsetfin)<=0)
		{
			$myRequete  = "select ".$mySQLSelect." from ".$TheTablesFromType[$theType]." ".$mySQLLeftJoin." where c.div1='-1' AND c.ext = ".$theUserId." ".$theIdFilter." AND (c.deadline>=CURDATE() OR c.deadline='') ".$mySQLAndCond." ORDER BY c.deadline DESC;";
		}
    }  
    
    if($theType=="notes")
    {
        $myRequete  = "select ".$mySQLSelect." from ".$TheTablesFromType[$theType]." ".$mySQLLeftJoin." where (c.von = ".$theUserId." OR c.ext=".$theUserGroup.") ".$theIdFilter." ".$mySQLAndCond.";";
    }
	return $myRequete;
}
function GetLatestSummary($params) {
	global $database;
	global $logevents;
	global $TheTablesFromType;
	$debug=false;
	// Parse our parameters.
	$auteurval=$params->getParam(0);
	$auteur=$auteurval->scalarval();
	$passeval=$params->getParam(1);
	$passe=$passeval->scalarval();
	$keyval=$params->getParam(2);
	$key=$keyval->scalarval();
	$typeval = $params->getParam(3);
	$type = $typeval->scalarval();
	$offsetdebutval = $params->getParam(4);
	$offsetdebut = $offsetdebutval->scalarval();
	$offsetfinval=$params->getParam(5);
	$offsetfin=$offsetfinval->scalarval();

    //$myResume=$auteur.",".$passe.",".$type.",".$offsetdebut.",".$offsetfin;
    logevent("GetLatestSummary","$auteur,$passe,$key,$type,$offsetdebut,$offsetfin");
    Tools::Trace(__FUNCTION__."@".__LINE__." ".date("Y-m-d H:i:s")." => Début");
    if($debug) Tools::Trace(__FUNCTION__."@".__LINE__.": $auteur,$passe,$key,$type,$offsetdebut,$offsetfin");
    $myUserId=-1;$myUserGroup=-1;$myUserAccess="";
    getUserId($auteur,$passe,$myUserId,$myUserGroup,$myUserAccess);

	$myUserRights=check_rights($type,$myUserId);
    if($debug) Tools::Trace(__FUNCTION__."@".__LINE__.": $myUserId,$myUserRights");
	    
    if($myUserId<0) return getErrorMessage("Aucun utilisateur valide avec les identifiants proposés");
	if(!check_rights($type,$myUserId)) return getErrorMessage("Le module demandé (".$type.") n'est pas disponible pour $myUserId !");
    
    if(intval($offsetdebut)>0) $offsetdebut=0;
    else  $offsetdebut=intval($offsetdebut);
    if(intval($offsetfin)<0) $offsetfin=1;
    else $offsetfin=intval($offsetfin);


    $mRes=array();
    $mRes[]= new xmlrpcval("ident", 'string');
    $mRes[]= new xmlrpcval("lastsync", 'string');
    $mRes[]= new xmlrpcval("access", 'string');
    $mRes[]= new xmlrpcval("ttid", 'string');
    $mRes[]= new xmlrpcval("ouid", 'string');
    $mRes[]= new xmlrpcval("ouident", 'string');
	// Specific fields - Inserting titles
	switch($type)
	{
		case "notes":
    		$mRes[]= new xmlrpcval("subject", 'string');
    		$mRes[]= new xmlrpcval("body", 'string');
			break;
	}
    $myResult[] = new xmlrpcval($mRes, 'array');


    $myClsOutsyncCrossRef=new outsync_crossref($database);
    //$myClsOutsyncCrossRef->cleanOrphans();
    $mySingleRecords=$myClsOutsyncCrossRef->getSingleRecords($myUserId,$type,$TheTablesFromType[$type]);
    if($mySingleRecords!==false)
    	foreach($mySingleRecords as $myCurSingle)
    	{
	        $mRes=array();
	        $mRes[]= new xmlrpcval("", 'string');
	        $mRes[]= new xmlrpcval("", 'string');
	        $mRes[]= new xmlrpcval("", 'string');
	        $mRes[]= new xmlrpcval($myCurSingle->ttid, 'string');
	        $mRes[]= new xmlrpcval($myCurSingle->ouid, 'string');
	        $mRes[]= new xmlrpcval($myCurSingle->ouid, 'string');
			
			// Specific fields - Inserting data
			switch($type)
			{
				case "notes":
					$mRes[]= new xmlrpcval("" , 'string');
					$mRes[]= new xmlrpcval("", 'string');
					break;
			}
			
	        $myResult[] = new xmlrpcval($mRes, 'array');
    		
    	}




	
	$myRequete=getQueryFromType($type,$myUserId,$myUserGroup,"",$offsetdebut,$offsetfin);
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Requête : ".$database->getQuery()."\n Erreur : ".mysql_errno($database->_resource) . ": " . mysql_error($database->_resource). "\n");
    $database->setQuery($myRequete);
    $myListeResult=$database->loadObjectList();
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Requête brut : ".$myRequete."\nRequête db : ".$database->getQuery()."\n Erreur : ".mysql_errno($database->_resource) . ": " . mysql_error($database->_resource). "\n");
    logevent(__FUNCTION__,__LINE__." Requête : ".$myRequete);

    
    if(count($myListeResult)<=0)
    {
    	logevent(__FUNCTION__,__LINE__." Retour sans données");
    	if($mySingleRecords===false)
    		return getErrorMessage("L'utilisateur n'a encore aucun enregistrement dans le type indiqué (".$myRequete.")");
    }
    else
    {
	
		$myClsOutSyncCrossRef=new outsync_crossref($database);
	    foreach($myListeResult as $myCurRes)
	    {
	        $myAccess="w";
	        if($type=="contacts") if(($myCurRes->von!=$myUserId && !isAdmin($myUserAccess) && !isChief($myUserAccess)) || $myCurRes->gruppe!=$myUserGroup) $myAccess="r";
	        if($type=="calendar")
	        {
	        	Tools::Trace(__FUNCTION__."@".__LINE__."==>Test evt ".$myCurRes->ID." : ".$myCurRes->event." type ".$myCurRes->div2." => ".(($myClsOutSyncCrossRef->checkRecurAppointmentInterval($myCurRes))?"ok":"non")."<br>\n");
		
	        	if(!$myClsOutSyncCrossRef->checkRecurAppointmentInterval($myCurRes))
	        		continue;
	        }

	        $mRes=array();
			if($debug) Tools::Trace(__FUNCTION__."@".__LINE__."==>Xref de ID ".$myCurRes->ID."=".$myCurRes->ttid."/".$myCurRes->ouid);
			if($myCurRes->ID>0 && is_null($myCurRes->ttid))
			{
				$myClsOutSyncCrossRef->storeRef($myUserId,$type,$myCurRes->ID,"");
				$myCurRes->ttid=$myClsOutSyncCrossRef->data_local_ID;
				$myCurRes->ouid=$myClsOutSyncCrossRef->data_foreign_ID;
			}
	
	
	        $mRes[]= new xmlrpcval($myCurRes->ID, 'string');
	        $mRes[]= new xmlrpcval($myCurRes->sync_DerniereMAJ, 'string');
	        $mRes[]= new xmlrpcval($myAccess, 'string');
	        $mRes[]= new xmlrpcval($myCurRes->ttid, 'string');
	        $mRes[]= new xmlrpcval($myCurRes->ouid, 'string');
	        $mRes[]= new xmlrpcval($myCurRes->ouid, 'string');
			
			// Specific fields - Inserting data
			switch($type)
			{
				case "notes":
					$mRes[]= new xmlrpcval($myCurRes->name , 'string');
					$mRes[]= new xmlrpcval($myCurRes->name . "\r\n".$myCurRes->remark, 'string');
					break;
			}
			
	        $myResult[] = new xmlrpcval($mRes, 'array');
	    }
    }
    Tools::Trace(__FUNCTION__."@".__LINE__." => Retour des données résumées : ".print_r($myListeResult,true));
    //Tools::Trace(__FUNCTION__."@".__LINE__." => Tableau de retour converti : ".print_r($myResult,true));
	logevent(__FUNCTION__,__LINE__." Retour avec données (".count($myListeResult)." enregistrements)");
// Build our response.
	$struct = array('ttsummresult' => new xmlrpcval($myResult, 'array'));
	return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
}

function GetRecords($params) {
	global $database;
	global $logevents;

	// Parse our parameters.
	$auteurval=$params->getParam(0);
	$auteur=$auteurval->scalarval();
	$passeval=$params->getParam(1);
	$passe=$passeval->scalarval();
	$keyval=$params->getParam(2);
	$key=$keyval->scalarval();
	$typeval = $params->getParam(3);
	$type = $typeval->scalarval();
	$recordsarray = $params->getParam(4);
	
	$myArrayListeRecords=array();
    //$myResume=$auteur.",".$passe.",".$type.",".$offsetdebut.",".$offsetfin;
    $myUserId=-1;$myUserGroup=-1;$myUserAccess="";
    getUserId($auteur,$passe,$myUserId,$myUserGroup,$myUserAccess);
    if($myUserId<0) return getErrorMessage("Aucun utilisateur valide avec les identifiants proposés");
	if(!check_rights($type,$myUserId))   return getErrorMessage("Le module demandé (".$type.") n'est pas disponible pour $myUserId !");
	
	//$myArrayListeRecords[]=new xmlrpcval(serialize($recordsarray),'string');
	$myListExtractRecords=array();
	for($i=0;$i<$recordsarray->arraysize();$i++)
	{
		$xmlrpcVal=$recordsarray->arraymem($i);
		$myListExtractRecords[]=$xmlrpcVal->scalarval();
	}
	
	logevent("GetRecords",serialize($myListExtractRecords));
	
	if(sizeof($myListExtractRecords)==1) $myStrFilter=" AND c.ID=".$myListExtractRecords[0]." ";
	elseif(sizeof($myListExtractRecords)==0) return getErrorMessage("Aucun résultat trouvé");
	else $myStrFilter=" AND c.ID IN (".implode(",",$myListExtractRecords).") ";

	$myClsOutSyncCrossRef=new outsync_crossref($database);
	Tools::Trace(__FUNCTION__."@".__LINE__." ".date("Y-m-d H:i:s")." => liste id à renvoyer : ".print_r($myListExtractRecords,true));
	foreach($myListExtractRecords as $myCurId)
	{
		$myClsOutSyncCrossRef->searchRef($myUserId,$type,$myCurId);
		Tools::Trace(__FUNCTION__."@".__LINE__."=> ID trouvée pour $myUserId,$type,$myCurId : ".$myClsOutSyncCrossRef->ID);
		if($myClsOutSyncCrossRef->data_local_ID!=$myCurId)
		{
			Tools::Trace(__FUNCTION__."@".__LINE__."=> Pb sur l'ID, la XRef n'existe pas on la crée");
			$myClsOutSyncCrossRef->storeRef($myUserId,$type,$myCurId,$myCurId);
		}
		else
			Tools::Trace(__FUNCTION__."@".__LINE__."=> ID ok, la xref existe, on ne la crée pas");
		
	}

	$myRequete=getQueryFromType($type,$myUserId,$myUserGroup,$myStrFilter);
	$database->setQuery($myRequete);
	$myLstRecords=$database->loadObjectList();
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Liste des enregistrements : ".print_r($myLstRecords,true));
	logevent(__FUNCTION__,__LINE__." Requête : ".$myRequete);
	//return getErrorMessage("Nombre de résultats pour ".$database->getQuery()." : ".sizeof($myLstRecords));
	$myArrayListeRecords=getRecordsFromType($type,$myLstRecords);
// Build our response.
	if(count($myLstRecords)==0)
	{
		/*
		$myResult=array();
			$mRes=array();
				$mRes[]= new xmlrpcval("size", 'string');
				$mRes[]= new xmlrpcval("query", 'string');
				$myResult[] = new xmlrpcval($mRes, 'array');
			$mRes=array();
				$mRes[]= new xmlrpcval(sizeof($myLstRecords), 'string');
				$mRes[]= new xmlrpcval($myRequete, 'string');
				$myResult[] = new xmlrpcval($mRes, 'array');
		*/
		return getErrorMessage("Aucun enregistrement pour la requête $myRequete");
	}
	else
	{
		$myResult=$myArrayListeRecords;
	}
	//$myArrayListeRecords[]=new xmlrpcval($xmlrpcVal->scalarval(),'string');
	$struct = array('ttrecresult' => new xmlrpcval($myResult, 'array'));
	return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
}

function sendRecords($params) {
	global $database;
	global $logevents;
	Tools::Trace(__FUNCTION__."@".__LINE__."=> sendRecords : démarrage");
	logevent("sendRecords", "Début");
	// Parse our parameters.
	$auteurval=$params->getParam(0);
	$auteur=$auteurval->scalarval();
	$passeval=$params->getParam(1);
	$passe=$passeval->scalarval();
	$keyval=$params->getParam(2);
	$key=$keyval->scalarval();
	$typeval = $params->getParam(3);
	$type = $typeval->scalarval();
	
	Tools::Trace(__FUNCTION__."@".__LINE__."=> valeurs parsées");
	logevent(__FUNCTION__,  __LINE__." Type:".$type);
	$nbheadersval = $params->getParam(4);
	$nbheaders = $nbheadersval->scalarval();
	$nbrecordsval = $params->getParam(5);
	$nbrecords = $nbrecordsval->scalarval();

	$recordsarray = $params->getParam(6);
	$myArrayListeRecords=array();
	$myUserId=-1;$myUserGroup=-1;$myUserAccess="";
    getUserId($auteur,$passe,$myUserId,$myUserGroup,$myUserAccess);
    if($myUserId<0) return getErrorMessage("Aucun utilisateur valide avec les identifiants proposés");
	if(!check_rights($type,$myUserId))  
	{
		logevent(__FUNCTION__,  __LINE__." L'utilisateur n'a pas les droits d'accès pour ".$type);
		return getErrorMessage("Le module demandé (".$type.") n'est pas disponible pour $myUserId !");
	}
	
	Tools::Trace(__FUNCTION__."@".__LINE__."=> préparation des données");
	$myResult=array();
	$mRes=array();
	$myHeaders=array();
	for($i=0;$i<=$nbheaders;$i++)
	{
		$xmlrpcVal=$recordsarray->arraymem($i);
		$mRes[]= new xmlrpcval($xmlrpcVal->scalarval(), 'string');
	}
	$myResult[] = new xmlrpcval($mRes, 'array');

	for($j=1;$j<=$nbrecords;$j++)
	{
		$mRes=array();
		for($i=0;$i<=$nbheaders;$i++)
		{
			$myIndex=$j*($nbheaders+1)+$i;
			$xmlrpcVal=$recordsarray->arraymem($myIndex);
			$mRes[]= new xmlrpcval($xmlrpcVal->scalarval(), 'string');
		}
		$myResult[] = new xmlrpcval($mRes, 'array');
	}
	$myReturnMessage="Aucun enregistrement n'a été mis à jour sur le site";

	Tools::Trace(__FUNCTION__."@".__LINE__."=> Récupération des enregistrements");
	logevent(__FUNCTION__,  __LINE__."Récupération des enregistrements");
	// On a des enregistrements dans des tables linéaires, il faut les remettres à plat
	$myHeaders=array();
	$myData=array();
	for($i=0;$i<=$nbheaders;$i++)
	{
		$xmlrpcVal=$recordsarray->arraymem($i);
		$myHeaders[$i]= $xmlrpcVal->scalarval();
	}

	for($j=1;$j<=$nbrecords;$j++)
	{
		$mRes=array();
		for($i=0;$i<=$nbheaders;$i++)
		{
			$myIndex=$j*($nbheaders+1)+$i;
			$xmlrpcVal=$recordsarray->arraymem($myIndex);
			$myData[$j-1][$myHeaders[$i]]= $xmlrpcVal->scalarval();
		}
	}
	Tools::Trace(__FUNCTION__."@".__LINE__."=> headers:".$nbheaders." , records:".$nbrecords);
	$myReturn=0;
	logevent(__FUNCTION__,  __LINE__." Mise à jour");
	Tools::Trace(__FUNCTION__."@".__LINE__."=> MAJ des enregistrements");
	$myReturnIDList=array();
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Data : ".print_r($myData,true));
	$myReturn=UpdateLocalBaseWithDistantData($type,$myData,$nbrecords,$myUserId,$myUserGroup,$myUserAccess,$myReturnIDList);
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Mise à jour de ".$myReturn." enregistrements");
	if($myReturn!="") $myReturnMessage="Mise à jour de ".$myReturn." enregistrements";
	else  $myReturnMessage="Aucun enregistrement n'a été mis à jour sur le site (code retour : $myReturnIDList)";
	logevent(__FUNCTION__,  __LINE__." Message de retour : ".$myReturnMessage);
///* On garde ce bloc sous la main au cas où il faille construire une réponse	sous forme de tableau
	$myResult=array();
	$mRes=array();
	if(sizeof($myReturnIDList)>0)
	{
		$mRes[]= new xmlrpcval("ident", 'string');
		$mRes[]= new xmlrpcval("ouident", 'string');
		$myResult[] = new xmlrpcval($mRes, 'array');
		
		foreach($myReturnIDList as $myValue)
		{
			$mRes=array();
			$mRes[]= new xmlrpcval($myValue["ident"], 'string');
			$mRes[]= new xmlrpcval($myValue["ouident"], 'string');
			$myResult[] = new xmlrpcval($mRes, 'array');
		}
		$struct = array('ttrecresult' => new xmlrpcval($myResult, 'array'));
		return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
	}
//*/
	return getErrorMessage($myReturnMessage);
}


function cleanForeignCrossRef($params) {
	global $database;
	global $logevents;
	logevent("sendRecords", "Début");
	// Parse our parameters.
	$auteurval=$params->getParam(0);
	$auteur=$auteurval->scalarval();
	$passeval=$params->getParam(1);
	$passe=$passeval->scalarval();
	$keyval=$params->getParam(2);
	$key=$keyval->scalarval();
	$typeval = $params->getParam(3);
	$type = $typeval->scalarval();
	
	logevent(__FUNCTION__,  __LINE__." Type:".$type);
	
	$nbheadersval = $params->getParam(4);
	$nbheaders = $nbheadersval->scalarval();
	$nbrecordsval = $params->getParam(5);
	$nbrecords = $nbrecordsval->scalarval();

	$recordsarray = $params->getParam(6);
	$myArrayListeRecords=array();
	$myUserId=-1;$myUserGroup=-1;$myUserAccess="";
    getUserId($auteur,$passe,$myUserId,$myUserGroup,$myUserAccess);
    if($myUserId<0) return getErrorMessage("Aucun utilisateur valide avec les identifiants proposés");
	if(!check_rights($type,$myUserId))  
	{
		logevent(__FUNCTION__,  __LINE__." L'utilisateur n'a pas les droits d'accès pour ".$type);
		return getErrorMessage("Le module demandé (".$type.") n'est pas disponible pour $myUserId !");
	}
	$myResult=array();
	$mRes=array();
	$myHeaders=array();
	for($i=0;$i<=$nbheaders;$i++)
	{
		$xmlrpcVal=$recordsarray->arraymem($i);
		$mRes[]= new xmlrpcval($xmlrpcVal->scalarval(), 'string');
	}
	$myHeaders[] = new xmlrpcval($mRes, 'array');
	$myClsOutsyncCrossRef=new outsync_crossref($database);
	$myReturn=0; //"";
	for($j=1;$j<=$nbrecords;$j++)
	{
		$mRes=array();
		for($i=0;$i<=$nbheaders;$i++)
		{
			$myIndex=$j*($nbheaders+1)+$i;
			$xmlrpcVal=$recordsarray->arraymem($myIndex);
			$myToCleanId= $xmlrpcVal->scalarval();
			Tools::Trace(__FUNCTION__."@".__LINE__."==> Préparation effacement clef crossref : $myUserId,$type,$myToCleanId,foreign");
			if($myClsOutsyncCrossRef->deleteRefForUser($myUserId,$type,$myToCleanId,"foreign")===false)
				$myReturn++; //.="($myUserId,$type,".print_r($myToCleanId,true).")";
			logevent(__FUNCTION__,  __LINE__." Nettoyage ref croisée $myUserId,$type,".print_r($myToCleanId,true));
		}
	}
	$myReturnMessage="Nettoyage effectué, ".$myReturn." erreur(s)";
	logevent(__FUNCTION__,  __LINE__." Message de retour : ".$myReturnMessage);
	return getErrorMessage($myReturnMessage);
}


function updateForeignCrossRef($params) {
	global $database;
	global $logevents;
	logevent("sendRecords", "Début");
	// Parse our parameters.
	$auteurval=$params->getParam(0);
	$auteur=$auteurval->scalarval();
	$passeval=$params->getParam(1);
	$passe=$passeval->scalarval();
	$keyval=$params->getParam(2);
	$key=$keyval->scalarval();
	$typeval = $params->getParam(3);
	$type = $typeval->scalarval();
	
	logevent(__FUNCTION__,  __LINE__." Type:".$type);
	
	$nbheadersval = $params->getParam(4);
	$nbheaders = $nbheadersval->scalarval();
	$nbrecordsval = $params->getParam(5);
	$nbrecords = $nbrecordsval->scalarval();

	$recordsarray = $params->getParam(6);
	$myArrayListeRecords=array();
	$myUserId=-1;$myUserGroup=-1;$myUserAccess="";
    getUserId($auteur,$passe,$myUserId,$myUserGroup,$myUserAccess);
    if($myUserId<0) return getErrorMessage("Aucun utilisateur valide avec les identifiants proposés");
	if(!check_rights($type,$myUserId))  
	{
		logevent(__FUNCTION__,  __LINE__." L'utilisateur n'a pas les droits d'accès pour ".$type);
		return getErrorMessage("Le module demandé (".$type.") n'est pas disponible pour $myUserId !");
	}
	$myResult=array();
	$mRes=array();
	$myHeaders=array();
	for($i=0;$i<=$nbheaders;$i++)
	{
		$xmlrpcVal=$recordsarray->arraymem($i);
		$myHeaders[]=$xmlrpcVal->scalarval();
		//$mRes[]= new xmlrpcval($xmlrpcVal->scalarval(), 'string');
	}
	if($myHeaders[0]!="ident" || $myHeaders[1]!="ouident")
	{
		$myReturnMessage="Erreur dans les entêtes !! Mauvais entêtes.";
	}
	else
	{
		//$myHeaders[] = new xmlrpcval($mRes, 'array');
		$myClsOutsyncCrossRef=new outsync_crossref($database);
		$myReturn=0; //"";
		for($j=1;$j<=$nbrecords;$j++)
		{
			$mRes=array();
			$myObj=new stdClass();
			for($i=0;$i<=$nbheaders;$i++)
			{
				$myIndex=$j*($nbheaders+1)+$i;
				$xmlrpcVal=$recordsarray->arraymem($myIndex);
				$myCurData= $xmlrpcVal->scalarval();
				$myHeaderName=$myHeaders[$i];
				$myObj->$myHeaderName=$myCurData;
			}
			
			if($myClsOutsyncCrossRef->searchRef($myUserId,$type,$myObj->ident)!==false)
			{
				$myClsOutsyncCrossRef->storeRef($myUserId,$type,$myObj->ident,$myObj->ouident);
			}
			else
			{
				$myReturn++; //.="($myUserId,$type,".print_r($myToCleanId,true).")";
			}
			logevent(__FUNCTION__,  __LINE__." MAJ ref croisée $myUserId,$type,".$myObj->ident);
		}
		$myReturnMessage="MAJ effectué, ".$myReturn." référence(s) non trouvée(s)";
	}
	logevent(__FUNCTION__,  __LINE__." Message de retour : ".$myReturnMessage);
	return getErrorMessage($myReturnMessage);
}


function UpdateLocalBaseWithDistantData($theType,$theData,$theNbRecords,$theUserId,$theGroupId,$theUserAccess,&$theReturnIDList)
{
	global $database,$TheTablesFromType,$path_pre;
	$myResult="";
	$myReturnIndex=0;
	$curaction="";
	Tools::Trace(__FUNCTION__."@".__LINE__."=> démarrage");
	Tools::Trace(__FUNCTION__."@".__LINE__."=> type=".$theType);
	logevent("UpdateLocalBaseWithDistantData-".$theType,serialize($theData));
	if(intval($theUserId)<=0) return $myResult;
	for($i=0;$i<$theNbRecords;$i++)
	{
		$myObjectExists=false;
		$myFlagInitFailed=false;
		$myClsCrossReference=new outsync_crossref($database);
		$myTable=$TheTablesFromType[$theType];
		switch($theType)
		{
			case "cleancalendar":
				$curaction="clean";
				if(isset($theData[$i]["ident"]))
				{
					require_once($path_pre."calendar/calendar_class.php");
					$myClsCalendar=new calendarmanager();
					$myClsCalendar->del($theData[$i]["ident"]);
					$myClsCrossReference->searchRef($theUserId,"calendar",$theData[$i]["ident"]);
					//$database->setQuery("DELETE FROM ".$myTable." WHERE ID=".trim($theData[$i]["ident"]).";");
					//if($database->query()!==false)
					Tools::Trace(__FUNCTION__."@".__LINE__."==>Effacement crossref : ".$theUserId.",".$theType.",".$theData[$i]["ident"]);
					$myClsCrossReference->deleteRefForUser($theUserId,"calendar",$theData[$i]["ident"]);
					$myObject=new stdClass();
					$myObject->ID=trim($theData[$i]["ident"]);
				}
				break;
			case "cleancontacts":
				$curaction="clean";
				if(isset($theData[$i]["ident"]))
				{
					$myClsCrossReference->searchRef($theUserId,"contacts",$theData[$i]["ident"]);
					$database->setQuery("DELETE FROM ".$myTable." WHERE ID=".trim($theData[$i]["ident"]).";");
					if($database->query()!==false)
					{
						Tools::Trace(__FUNCTION__."@".__LINE__."==>Effacement crossref : ".$theUserId.",".$theType.",".$theData[$i]["ident"]);
						$myClsCrossReference->deleteRefForUser($theUserId,"contacts",$theData[$i]["ident"]);
					}
					$myObject=new stdClass();
					$myObject->ID=trim($theData[$i]["ident"]);
				}
				break;
			case "cleannotes":
				$curaction="clean";
				if(isset($theData[$i]["ident"]))
				{
					$myClsCrossReference->searchRef($theUserId,"notes",$theData[$i]["ident"]);
					$database->setQuery("DELETE FROM ".$myTable." WHERE ID=".trim($theData[$i]["ident"]).";");
					if($database->query()!==false)
					{
						Tools::Trace(__FUNCTION__."@".__LINE__."==>Effacement crossref : ".$theUserId.",".$theType.",".$theData[$i]["ident"]);
						$myClsCrossReference->deleteRefForUser($theUserId,"notes",$theData[$i]["ident"]);
					}
					$myObject=new stdClass();
					$myObject->ID=trim($theData[$i]["ident"]);
				}
				break;
			case "cleantasks":
				$curaction="clean";
				if(isset($theData[$i]["ident"]))
				{
					$myClsCrossReference->searchRef($theUserId,"tasks",$theData[$i]["ident"]);
					$database->setQuery("DELETE FROM ".$myTable." WHERE ID=".trim($theData[$i]["ident"]).";");
					if($database->query()!==false)
					{
						Tools::Trace(__FUNCTION__."@".__LINE__."==>Effacement crossref : ".$theUserId.",".$theType.",".$theData[$i]["ident"]);
						$myClsCrossReference->deleteRefForUser($theUserId,"tasks",$theData[$i]["ident"]);
					}
					$myObject=new stdClass();
					$myObject->ID=trim($theData[$i]["ident"]);
				}
				break;
			case "calendar":
				// If object exists, we just open it then update it
				$myObject=new stdClass();
				$myFlagInitFailed=true;
				if(isset($theData[$i]["ident"]))
				{
					if(intval($theData[$i]["ident"])>0)
					{
						$myReturnSearch=$myClsCrossReference->searchRef($theUserId,$theType,$theData[$i]["ident"]);
						if($myReturnSearch!==false)
						{
							$myObject=$database->getObjectFromTable($myTable,trim($theData[$i]["ident"]),"ID");
							if($myObject->ID>0)
								$myFlagInitFailed=false;
						}
					}
				}
				// If not ... let's init the values that were not transfered by foreign host
				$myObjectExists=true;
				if($myObject===false || $myFlagInitFailed)
				{
					$myObjectExists=false;
					if(isset($myObject->ID)) unset($myObject->ID);
					$myObject->von=$theUserId;
					$myObject->an=$theUserId;
					$myObject->projekt="0";
					$myObject->erstellt=date("YmdHis");
					$myObject->contact="0";
					$myObject->div1=-1;
					$myObject->div2=""; // Set default type for appointments to sync'ed to private
					$myObject->remind="0";
					$myObject->visi="0";
				}

				$myRecurPattern=new stdClass();
				if(isset($theData[$i]["recur"])) $myRecurPattern->recur=$theData[$i]["recur"];
				if(isset($theData[$i]["endday"])) $myRecurPattern->endday=$theData[$i]["endday"];
				if(isset($theData[$i]["interval"])) $myRecurPattern->interval=$theData[$i]["interval"];
				if(isset($theData[$i]["daysofweek"])) $myRecurPattern->daysofweek=$theData[$i]["daysofweek"];
				if(isset($theData[$i]["instance"])) $myRecurPattern->instance=$theData[$i]["instance"];
				if(isset($theData[$i]["dayofmonth"])) $myRecurPattern->dayofmonth=$theData[$i]["dayofmonth"];
				if(isset($theData[$i]["monthofyear"])) $myRecurPattern->monthofyear=$theData[$i]["monthofyear"];
				Tools::Trace(__FUNCTION__."@".__LINE__."=> Informations de récurence : ".print_r($myRecurPattern,true));
				$myOptions=setCalendarRecurPattern($myRecurPattern,$myObject->options1);
				$myObject->options1=$myOptions;
				Tools::Trace(__FUNCTION__."@".__LINE__."=> Options du rendez-vous : ".$myObject->options1);
				
				if(isset($theData[$i]["subject"])) $myObject->event=html_translate($theData[$i]["subject"]);
				if(isset($theData[$i]["body"])) $myObject->note2=html_translate($theData[$i]["body"]);
				if(isset($theData[$i]["begin"]))
				{
					$myObject->datum=date("Y-m-d",strtotime($theData[$i]["begin"]));
					if(strstr($theData[$i]["begin"],":")===FALSE) $myObject->anfang="----";
					else $myObject->anfang=date("Hi",strtotime($theData[$i]["begin"]));
				}
				if(strstr($theData[$i]["end"],":")===FALSE) $myObject->ende="----";
				else $myObject->ende=date("Hi",strtotime($theData[$i]["end"]));
				
				if(isset($theData[$i]["visi"])) $myObject->visi=$theData[$i]["visi"];
				if(isset($theData[$i]["place"])) $myObject->note=html_translate($theData[$i]["place"]);
				if(isset($theData[$i]["lastsync"]))	$myObject->sync_DerniereMAJ=$theData[$i]["lastsync"];
				else $myObject->sync_DerniereMAJ=date("Y/m/d H:i:s");
				break;
			case "contacts":
				// header
				// If object exists, we just open it then update it
				$myFlagInitFailed=true;
				if(isset($theData[$i]["ident"]))
				{
					if(intval($theData[$i]["ident"])>0)
					{
						$myReturnSearch=$myClsCrossReference->searchRef($theUserId,$theType,$theData[$i]["ident"]);
						if($myReturnSearch!==false)
						{
							$myObject=$database->getObjectFromTable($myTable,trim($theData[$i]["ident"]),"ID");
							if($myObject->ID>0)
								$myFlagInitFailed=false;
						}						
					}
					
				}
				// If not ... let's init the values that were not transfered by foreign host
				$myObjectExists=true;
				if($myObject===false || $myFlagInitFailed)
				{
					$myObjectExists=false;
					if(isset($myObject->ID)) unset($myObject->ID);
					$myObject->von=$theUserId;
					if(isset($theData[$i]["private"]) && $theData[$i]["private"]=="1") 
						$myObject->acc="u";
					$myObject->acc="g";
					$myObject->gruppe=$theGroupId;
					$myObject->parent="0";
					$myObject->sync1=1;
				}
				if(isset($theData[$i]["title"])) $myObject->anrede=html_translate($theData[$i]["title"]);
				if(isset($theData[$i]["firstname"])) $myObject->vorname=html_translate($theData[$i]["firstname"]);
				if(isset($theData[$i]["lastname"])) $myObject->nachname=html_translate($theData[$i]["lastname"]);
				if(isset($theData[$i]["company"])) $myObject->firma=html_translate($theData[$i]["company"]);
				if(isset($theData[$i]["email"])) $myObject->email=html_translate($theData[$i]["email"]);
				if(isset($theData[$i]["url"])) $myObject->url=html_translate($theData[$i]["url"]);
				if(isset($theData[$i]["phone"])) $myObject->tel1=html_translate($theData[$i]["phone"]);
				if(isset($theData[$i]["mobile"])) $myObject->mobil=html_translate($theData[$i]["mobile"]);
				if(isset($theData[$i]["fax"])) $myObject->fax=html_translate($theData[$i]["fax"]);
				if(isset($theData[$i]["address"])) $myObject->strasse=html_translate($theData[$i]["address"]);
				if(isset($theData[$i]["city"])) $myObject->stadt=html_translate($theData[$i]["city"]);
				if(isset($theData[$i]["postcode"])) $myObject->plz=html_translate($theData[$i]["postcode"]);
				if(isset($theData[$i]["country"])) $myObject->land=html_translate($theData[$i]["country"]);
				if(isset($theData[$i]["comment"])) $myObject->bemerkung=html_translate($theData[$i]["comment"]);
				if(isset($theData[$i]["lastsync"])) $myObject->sync_DerniereMAJ=$theData[$i]["lastsync"];

				// data
				break;
			case "notes":
				// If object exists, we just open it then update it
				$myFlagInitFailed=true;
				if(isset($theData[$i]["ident"]))
				{
					if(intval($theData[$i]["ident"])>0)
					{
						$myReturnSearch=$myClsCrossReference->searchRef($theUserId,$theType,$theData[$i]["ident"]);
						if($myReturnSearch!==false)
						{
							$myObject=$database->getObjectFromTable($myTable,trim($theData[$i]["ident"]),"ID");
							if($myObject->ID>0)
								$myFlagInitFailed=false;
						}
					}
					
				}
				// If not ... let's init the values that were not transfered by foreign host
				$myObjectExists=true;
				if($myObject===false || $myFlagInitFailed)
				{
					$myObjectExists=false;
					if(isset($myObject->ID)) unset($myObject->ID);
					$myObject->von=$theUserId;
					$myObject->ext=0;
					$myObject->contact="0";
					$myObject->div1=date("YmdHis");
					$myObject->projekt="0";
					$myObject->sync1=1;
				}
				$myObject->div2=date("YmdHis");
				if(isset($theData[$i]["subject"])) $myObject->name=html_translate($theData[$i]["subject"]);
				if(isset($theData[$i]["body"]))
				{
					$myObject->remark=html_translate(substr_replace($theData[$i]["body"],"",0,strlen($theData[$i]["subject"])));
				}
				if(isset($theData[$i]["lastsync"])) $myObject->sync_DerniereMAJ=$theData[$i]["lastsync"];

				break;
			case "tasks":
				// If object exists, we just open it then update it
				/*
				*/
				Tools::Trace(__FUNCTION__."@".__LINE__."=> démarrage tasks");
				$myFlagInitFailed=true;
				if(isset($theData[$i]["ident"]))
				{
					if(intval($theData[$i]["ident"])>0)
					{
						$myReturnSearch=$myClsCrossReference->searchRef($theUserId,$theType,$theData[$i]["ident"]);
						if($myReturnSearch!==false)
						{
							$myObject=$database->getObjectFromTable($myTable,trim($theData[$i]["ident"]),"ID");
							if($myObject->ID>0)
								$myFlagInitFailed=false;
						}
					}
				}
				Tools::Trace(__FUNCTION__."@".__LINE__."=> tasks courante ID=".$theData[$i]["ident"]);
				// If not ... let's init the values that were not transfered by foreign host
				$myObjectExists=true;
				if($myObject===false || $myFlagInitFailed)
				{
					$myObjectExists=false;
					if(isset($myObject->ID)) unset($myObject->ID);
					$myObject->von=$theUserId;
					$myObject->ext=$theUserId;
					$myObject->div1="-1";
					$myObject->div2="unique";
					$myObject->sync1=1;
					$myObject->status="2";
					$myObject->progress="0";
					$myObject->project="0";
					$myObject->contact="0";
					$myObject->datum=date("YmdHis");
				}
				if($myObject->datum=="") $myObject->datum=date("YmdHis");
				if(isset($theData[$i]["task"])) $myObject->remark=html_translate($theData[$i]["task"]);
				//if(isset($theData[$i]["begin"])) $myObject->datum=date("YmdHis",strtotime($theData[$i]["begin"]));
				if(isset($theData[$i]["end"])) $myObject->deadline=date("Y-m-d",strtotime($theData[$i]["end"]));
				if(isset($theData[$i]["priority"])) $myObject->priority=$theData[$i]["priority"]*5; // Outlook met une importance entre 0 et 2 pour la priorité des tâches
				if(isset($theData[$i]["note"])) $myObject->note=html_translate($theData[$i]["note"]);
				if(isset($theData[$i]["lastsync"])) $myObject->sync_DerniereMAJ=date("Y/m/d H:i:s",strtotime($theData[$i]["lastsync"]));
				Tools::Trace(__FUNCTION__."@".__LINE__."=> tasks courante nom=".$myObject->remark);
				break;
		}
		if($theType=="calendar")
		{
			$myCalReturnId=saveOrUpdateAppointment($theUserId,$myObject);
			$myResult.=$i.":".$myCalReturnId."/".$theData[$i]["ouident"];
			if($myCalReturnId>0 && $theData[$i]["ouident"] !="")
				$myClsCrossReference->storeRef($theUserId,$theType,$myObject->ID,$theData[$i]["ouident"]);
		}
		else
		{
			if(isset($myObject) && $myTable!="" && $curaction!="clean")
			{
				if(!$myObjectExists)
				{
					if(isset($myObject) && $myTable!="") $database->insertObject($myTable,$myObject,"ID");
					$myResult.="i " /* .$database->getQuery() */;
				}
				else
				{
					if(isset($myObject) && $myTable!="") $database->updateObject($myTable,$myObject,"ID");
					$myResult.="u";
				}
				Tools::Trace(__FUNCTION__."@".__LINE__."=> tasks courante enregistrement objet ID:".$myObject->ID);
				$myClsCrossReference->storeRef($theUserId,$theType,$myObject->ID,$theData[$i]["ouident"]);
			}
		}
		
		if(isset($myObject->ID)) $theReturnIDList[$myReturnIndex]["ident"]=$myObject->ID;
		if(isset($myObject->ID)) $theReturnIDList[$myReturnIndex]["ouident"]=$theData[$i]["ouident"];
		$myResult.=$i.":".$theReturnIDList[$myReturnIndex]["ident"]."/".$theData[$i]["lastsync"].";";
		$myReturnIndex++;
		$myTable="";
		unset($myObject);
	}
	logevent("UpdateLocalBaseWithDistantData-".$theType."-store",$myResult);
	return $myResult;
}

function saveOrUpdateAppointment($theUserId, &$theApp)
{
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Début sauvegarde ...");
	global $path_pre,$TheClsUser,$database,$projekte;
	$TheClsUser->load($theUserId);
	$myObject=$theApp;
	require_once($path_pre."calendar/calendar_class.php");
	require_once($path_pre."calendar/appointment.class.php");
	$myClsCalendar=new appointment($database,$path_pre,"");
	$myObjOptions=unserialize($myObject->options1);

	$myClsCalendar->user_access=$TheClsUser->acc;	
	$myClsCalendar->user_email=$TheClsUser->email;		
	$myClsCalendar->user_group=$TheClsUser->gruppe;
	$myClsCalendar->user_ID=$theUserId;

	$myClsCalendar->make="create";		
	if($myObject->ID>0)
	{
		$myClsCalendar->make="update";		
		$myClsCalendar->ressource=$myClsCalendar->getRessourcesArrayFromAppointmentID($myObject->ID);				
	}
	$myClsCalendar->event_ID=$myObject->ID;
	$myClsCalendar->open_group_appointment=$myObjOptions->open_group_appointment;
	$myClsCalendar->colorrdv=$myObjOptions->colorrdv;
	$myClsCalendar->an_form	=	$myObject->an;
	unset($myClsCalendar->projectid);
	$myClsCalendar->project=	$myObject->projekt;
	Tools::Trace(__FUNCTION__."@".__LINE__." ".date("Y-m-d H:i:s")." => Projects activés : ".$projekte." ...");
	if($projekte>0)
	{
		Tools::Trace(__FUNCTION__."@".__LINE__." ".date("Y-m-d H:i:s")." => Inclusion classe projets ...");
		require_once($path_pre."projects/projects_class.php");
		$myCurProj=new projectmanager();
		Tools::Trace(__FUNCTION__."@".__LINE__." ".date("Y-m-d H:i:s")." => Création projet ...");
		
		$myCurProj->user_ID=$myClsCalendar->user_ID;
		$myCurProj->user_kurz=$TheClsUser->kurz;
		$myCurProj->user_group=$myClsCalendar->user_group;
		$myCurProj->path_pre=$path_pre;
		
		$myPrjLoadResult=$myCurProj->load($myClsCalendar->project);
		//Tools::Trace(__FUNCTION__."@".__LINE__." ".date("Y-m-d H:i:s")." => Chargement projet : ".$myPrjLoadResult."...");
		//Tools::Trace(__FUNCTION__."@".__LINE__." ".date("Y-m-d H:i:s")." => Objet Projet : ".Tools::Display($myCurProj)."...");
		$myClsCalendar->projectid=$myCurProj->dataobj->ID;
		$myClsCalendar->subproject="";
		if($myCurProj->dataobj->parent>0)
		{
			$myClsCalendar->projectid=$myCurProj->dataobj->parent;
			$myClsCalendar->subproject=$myCurProj->dataobj->name;
		}
		
	}
	//$myObject->erstellt
	$myClsCalendar->contact	=	$myObject->contact;
	//	=	$myObject->div1
	//	=	$myObject->div2
	//	=	$myObject->remind
	$myClsCalendar->visi	=	$myObject->visi;
	$myClsCalendar->event	=	addslashes($myObject->event);
	$myClsCalendar->remark	=	addslashes($myObject->note2);
	list($myClsCalendar->year, $myClsCalendar->month, $myClsCalendar->day) = sscanf($myObject->datum,"%4s-%2s-%2s");
	
	$myClsCalendar->anfang	=	addslashes($myObject->anfang);
	$myClsCalendar->ende	=	addslashes($myObject->ende);
	$myClsCalendar->note	=	addslashes($myObject->note);
	//(auto)	=	$myObject->sync_DerniereMAJ
	$myClsCalendar->chkDeleteAllOcc=0;
	if($myObjOptions->serie!="")
		$myClsCalendar->chkDeleteAllOcc=1;
		
	$myClsCalendar->serie=$myObjOptions->serie;
	$myClsCalendar->txtDaily	=	$myObjOptions->txtDaily;
	$myClsCalendar->radDaily	=	$myObjOptions->radDaily;
	$myClsCalendar->txtWeekly	=	$myObjOptions->txtWeekly;
	$myClsCalendar->txtWeeklyDay	=	$myObjOptions->txtWeeklyDay;
	$myClsCalendar->radMonthly	=	$myObjOptions->radMonthly;
	$myClsCalendar->txtMonthlyEachDay	=	$myObjOptions->txtMonthlyEachDay;
	$myClsCalendar->txtMonthlyEachMonth	=	$myObjOptions->txtMonthlyEachMonth;
	$myClsCalendar->cmbMonthlyOnMonth	=	$myObjOptions->cmbMonthlyOnMonth;
	$myClsCalendar->cmbMonthlyOnDay	=	$myObjOptions->cmbMonthlyOnDay;
	$myClsCalendar->cmbMonthlyOnWeek	=	$myObjOptions->cmbMonthlyOnWeek;
	$myClsCalendar->radYearly	=	$myObjOptions->radYearly;
	$myClsCalendar->txtYearlyEachDay	=	$myObjOptions->txtYearlyEachDay;
	$myClsCalendar->txtYearlyEachMonth	=	$myObjOptions->txtYearlyEachMonth;
	$myClsCalendar->cmbYearlyOnDay	=	$myObjOptions->cmbYearlyOnDay;
	$myClsCalendar->cmbYearlyOnMonth	=	$myObjOptions->cmbYearlyOnMonth;
	$myClsCalendar->cmbYearlyOnWeek	=	$myObjOptions->cmbYearlyOnWeek;
	$myClsCalendar->endyear	=	$myObjOptions->endyear;
	if(!isset($myObjOptions->endyear) || $myObjOptions->endyear=="")
		$myClsCalendar->endyear=date("Y");
	$myClsCalendar->endday	=	$myObjOptions->endday;
	if(!isset($myObjOptions->endday) || $myObjOptions->endday=="")
		$myClsCalendar->endday=date("d");
	$myClsCalendar->endmonth	=	$myObjOptions->endmonth;
	if(!isset($myObjOptions->endmonth) || $myObjOptions->endmonth=="")
		$myClsCalendar->endmonth=date("m");
	if($myObjOptions->endmonth=="" && $myObjOptions->endday=="" && $myObjOptions->endyear=="")
	{
		$myClsDate=new clsDateManipulation();
		$myClsDate->dateAdd($myClsCalendar->endday,$myClsCalendar->endmonth,$myClsCalendar->endyear,2,"month");
	}
	$myClsCalendar->pers	=	null ;
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Avant sauvegarde ...");
	$theApp->ID=-1;
	Tools::Trace(__FUNCTION__."@".__LINE__."=> Objet : ".Tools::Display($myClsCalendar));
	$myClsCalendar->CreateAppointment();
	$theApp->ID=$myClsCalendar->reference_ID;
	Tools::Trace(__FUNCTION__."@".__LINE__."=> RDV sauvegardé : ".$theApp->ID." ...");
	return $theApp->ID;
}

$myDaysArray=array("sun"=>1,"mon"=>2,"tue"=>4,"wed"=>8,"thu"=>16,"fri"=>32,"sat"=>64);
$myDayNbArray=array("first"=>1,"second"=>2,"third"=>3,"fourth"=>4,"fifth"=>5);
$myMonthsArray=array("jan"=>1,"feb"=>2,"mar"=>3,"apr"=>4,"may"=>5,"jun"=>6,"jul"=>7,"aug"=>8,"sep"=>9,"oct"=>10,"nov"=>11,"dev"=>12);

foreach($myDaysArray as $key=>$value) $myInvDaysArray[$value]=$key;
foreach($myDayNbArray as $key=>$value) $myInvDayNbArray[$value]=$key;
foreach($myMonthsArray as $key=>$value) $myInvMonthsArray[$value]=$key;


function setCalendarRecurPattern($theRecur,$theOriginalOption)
{
	global $myInvDaysArray,$myInvDayNbArray,$myInvMonthsArray;
	$myopen_group_appointment=0;
	$mycolorrdv="";
	if($theOriginalOption!="")
	{
		$myOrigOption=unserialize($theOriginalOption);
		if(isset($myOrigOption->open_group_appointment))
			$myopen_group_appointment=$myOrigOption->open_group_appointment;
		else
			$myopen_group_appointment=0;
		if(isset($myOrigOption->colorrdv))
			$mycolorrdv=$myOrigOption->colorrdv;
		else
			$mycolorrdv="";
	}
	$myRecurPattern=$theRecur;
	$myTxtOptions="O:8:\"stdClass\":22:{s:5:\"serie\";N;s:8:\"radDaily\";N;s:8:\"txtDaily\";N;s:9:\"txtWeekly\";N;s:12:\"txtWeeklyDay\";N;s:10:\"radMonthly\";N;s:17:\"txtMonthlyEachDay\";N;s:19:\"txtMonthlyEachMonth\";N;s:15:\"cmbMonthlyOnDay\";N;s:16:\"cmbMonthlyOnWeek\";N;s:17:\"cmbMonthlyOnMonth\";N;s:9:\"radYearly\";N;s:16:\"txtYearlyEachDay\";N;s:18:\"txtYearlyEachMonth\";N;s:14:\"cmbYearlyOnDay\";N;s:15:\"cmbYearlyOnWeek\";N;s:16:\"cmbYearlyOnMonth\";N;s:6:\"endday\";N;s:8:\"endmonth\";N;s:7:\"endyear\";N;s:15:\"backgroundcolor\";N;s:22:\"open_group_appointment\";N;}";
	$myObjOptions=unserialize($myTxtOptions);
	
	$myObjOptions->colorrdv=$mycolorrdv;
	$myObjOptions->open_group_appointment=$myopen_group_appointment;
	
	list($myObjOptions->endyear,$myObjOptions->endmonth,$myObjOptions->endday)=explode("-",$myRecurPattern->endday);
	$myLastYear=date("Y")+1;
	if($myObjOptions->endyear>$myLastYear) $myObjOptions->endyear="".$myLastYear;
	
	if(strlen($myObjOptions->endmonth)==1) $myObjOptions->endmonth="0".$myObjOptions->endmonth;
	if(strlen($myObjOptions->endday)==1) $myObjOptions->endday="0".$myObjOptions->endday;
	switch($myRecurPattern->recur)
	{
		case "none":
			$myObjOptions->serie=null;
			break;
		case "0":
			$myObjOptions->serie="tag";
			if($myRecurPattern->daysofweek==127 || $myRecurPattern->daysofweek==0)
			{
				$myObjOptions->radDaily="every";
				$myObjOptions->txtDaily=$myRecurPattern->interval;
			}
			elseif($myRecurPattern->daysofweek==62)
			{
				$myObjOptions->radDaily="opendays";
			}
			else
			{
				$myObjOptions->serie="woche";
				$myObjOptions->txtWeekly="1";
				$myObjOptions->txtWeeklyDay=array();
				foreach($myInvDaysArray as $key=>$value)
				{
					if($myRecurPattern->daysofweek & $key)
							$myObjOptions->txtWeeklyDay[]=$value;
				}
			}
			break;
		case "1":
			$myObjOptions->serie="woche";
			$myObjOptions->txtWeekly=$myRecurPattern->interval;
			$myObjOptions->txtWeeklyDay=array();
			foreach($myInvDaysArray as $key=>$value)
			{
				if($myRecurPattern->daysofweek & $key)
						$myObjOptions->txtWeeklyDay[]=$value;
			}
			break;
		case "2":
			$myObjOptions->radMonthly="each";
			$myObjOptions->txtMonthlyEachDay=$myRecurPattern->dayofmonth;
			$myObjOptions->txtMonthlyEachDay=$myRecurPattern->dayofmonth;
			$myObjOptions->txtMonthlyEachMonth=$myRecurPattern->interval;
			$myObjOptions->serie="monat";
			break;
		case "3":
			$myObjOptions->serie="monat";
			$myObjOptions->radMonthly="on";
			$myObjOptions->cmbMonthlyOnMonth=$myRecurPattern->interval;
			$myObjOptions->cmbMonthlyOnDay=$myInvDayNbArray[$myRecurPattern->instance];
			if(!in_array($myRecurPattern->daysofweek,$myInvDaysArray))
			{
				foreach($myInvDaysArray as $key=>$value)
				{
					if($myRecurPattern->daysofweek & $key) // Incompatible with outlook, we have to filter a day
						$myObjOptions->cmbMonthlyOnWeek=$value;
				}
			}
			break;
		case "5":
			$myObjOptions->serie="jahr";
			$myObjOptions->radYearly="each";
			$myObjOptions->txtYearlyEachDay=$myRecurPattern->dayofmonth;
			$myObjOptions->txtYearlyEachMonth=$myInvMonthsArray[$myRecurPattern->monthofyear];
		case "6":
			$myObjOptions->serie="jahr";
			$myObjOptions->radYearly="on";
			$myObjOptions->cmbYearlyOnDay=$myInvDayNbArray[$myRecurPattern->instance];
			$myObjOptions->cmbYearlyOnMonth=$myInvMonthsArray[$myRecurPattern->monthofyear];
			if(!in_array($myRecurPattern->daysofweek,$myInvDaysArray))
			{
				foreach($myInvDaysArray as $key=>$value)
				{
					if($myRecurPattern->daysofweek & $key) // Incompatible with outlook, we have to filter a day
						$myObjOptions->cmbYearlyOnWeek=$value;
				}
			}
			break;
	}
	
	$myTxtOptions=serialize($myObjOptions);
	return $myTxtOptions;
}

function getCalendarRecurPattern($theOptions,$endhour)
{
	global $myDaysArray,$myDayNbArray,$myMonthsArray;
	
	$myRecurPattern=new stdClass();

	$myRecurPattern->recur="";
	$myRecurPattern->interval="";
	$myRecurPattern->daysofweek="";
	$myRecurPattern->dayofmonth="";
	$myRecurPattern->monthofyear="";
	$myRecurPattern->instance="";
	$myRecurPattern->endday="";


	$myOptions=unserialize($theOptions);
	if($endhour=="--:--")
		$endhour="23:59";
	$myRecurPattern->endday=$myOptions->endyear."-".(($myOptions->endmonth<10)?"0":"").$myOptions->endmonth."-".(($myOptions->endday<10)?"0":"").$myOptions->endday." ".$endhour;
	
	switch($myOptions->serie)
	{
		case "tag":
			$myRecurPattern->recur="0";
			switch($myOptions->radDaily)
			{
				case "every":
					$myRecurPattern->interval=$myOptions->txtDaily;
					$myRecurPattern->daysofweek=1+2+4+8+16+32+64;
					break;
				case "opendays":
					$myRecurPattern->interval="1";
					$myRecurPattern->daysofweek=2+4+8+16+32; // Week begins sunday !!
					break;
			}
			break;
		case "woche":
			$myRecurPattern->recur="1";
			$myRecurPattern->interval=$myOptions->txtWeekly;
			$myRecurPattern->daysofweek=0;
			foreach($myOptions->txtWeeklyDay as $myCurDay)
				if(isset($myDaysArray[$myCurDay]))
					$myRecurPattern->daysofweek+=$myDaysArray[$myCurDay];
			break;
		case "monat":
			switch($myOptions->radMonthly)
			{
				case "each":
					$myRecurPattern->recur="2";
					$myRecurPattern->dayofmonth=$myOptions->txtMonthlyEachDay;
					$myRecurPattern->interval=$myOptions->txtMonthlyEachMonth;
					break;
				case "on":
					$myRecurPattern->recur="3";
					$myRecurPattern->interval=$myOptions->cmbMonthlyOnMonth;
					$myRecurPattern->instance=$myDayNbArray[$myOptions->cmbMonthlyOnDay];
					$myRecurPattern->daysofweek=$myDaysArray[$myOptions->cmbMonthlyOnWeek];
					break;
			}
			break;
		case "jahr":
			switch($myOptions->radYearly)
			{
				case "each":
					$myRecurPattern->recur="5";
					$myRecurPattern->dayofmonth=$myOptions->txtYearlyEachDay;
					$myRecurPattern->monthofyear=$myMonthsArray[$myOptions->txtYearlyEachMonth];
					break;
				case "on":
					$myRecurPattern->recur="6";
					$myRecurPattern->instance=$myDayNbArray[$myOptions->cmbYearlyOnDay];
					$myRecurPattern->daysofweek=$myDaysArray[$myOptions->cmbYearlyOnWeek];
					$myRecurPattern->monthofyear=$myMonthsArray[$myOptions->cmbYearlyOnMonth];
					break;
			}
			break;
		default:
			$myRecurPattern->recur="none";
			return $myRecurPattern;
			break;
	}
	return $myRecurPattern;
}

function getRecordsFromType($theType,$theRecords)
{
	global $database;
	$myResult=array();
	switch($theType)
	{
		case "calendar":
			$mRes=array();
			$mRes[]= new xmlrpcval("ident", 'string');
			$mRes[]= new xmlrpcval("subject", 'string');
			$mRes[]= new xmlrpcval("body", 'string');
			$mRes[]= new xmlrpcval("begin", 'string');
			$mRes[]= new xmlrpcval("end", 'string');
			$mRes[]= new xmlrpcval("place", 'string');

			$mRes[]= new xmlrpcval("allday", 'string');
			
			$mRes[]= new xmlrpcval("recur", 'string');
			$mRes[]= new xmlrpcval("interval", 'string');
			$mRes[]= new xmlrpcval("daysofweek", 'string');
			$mRes[]= new xmlrpcval("dayofmonth", 'string');
			$mRes[]= new xmlrpcval("monthofyear", 'string');
			$mRes[]= new xmlrpcval("instance", 'string');
			$mRes[]= new xmlrpcval("endday", 'string');
			
			$mRes[]= new xmlrpcval("lastsync", 'string');
			$mRes[]= new xmlrpcval("options1", 'string');

			$myResult[] = new xmlrpcval($mRes, 'array');
			
			$myClsOutSyncCrossRef=new outsync_crossref($database);
			
			foreach($theRecords as $theCurRec)
			{
				$mRes=array();
				$myFullDay="0";
				if($theCurRec->anfang=="----" && $theCurRec->ende=="----")
					$myFullDay="1";
				$myBeginDate= $theCurRec->datum . " " . substr($theCurRec->anfang,0,2) . ":" . substr($theCurRec->anfang,2,2);
				$myEndDate= $theCurRec->datum . " " . substr($theCurRec->ende,0,2) . ":" . substr($theCurRec->ende,2,2);
				$mRes[]= new xmlrpcval($theCurRec->ID, 'string');
				$mRes[]= new xmlrpcval($theCurRec->event, 'string');
				$mRes[]= new xmlrpcval($theCurRec->note2, 'string');
				$mRes[]= new xmlrpcval($myBeginDate, 'string');
				$mRes[]= new xmlrpcval($myEndDate, 'string');
				$mRes[]= new xmlrpcval($theCurRec->note, 'string');
				
				$mRes[]= new xmlrpcval($myFullDay, 'string');
				$myRecurPattern=getCalendarRecurPattern($theCurRec->options1,substr($theCurRec->ende,0,2) . ":" . substr($theCurRec->ende,2,2));

				$mRes[]= new xmlrpcval($myRecurPattern->recur, 'string');
				$mRes[]= new xmlrpcval($myRecurPattern->interval, 'string');
				$mRes[]= new xmlrpcval($myRecurPattern->daysofweek, 'string');
				$mRes[]= new xmlrpcval($myRecurPattern->dayofmonth, 'string');
				$mRes[]= new xmlrpcval($myRecurPattern->monthofyear, 'string');
				$mRes[]= new xmlrpcval($myRecurPattern->instance, 'string');
				$mRes[]= new xmlrpcval($myRecurPattern->endday, 'string');
				
				$mRes[]= new xmlrpcval($theCurRec->sync_DerniereMAJ, 'string');
				$mRes[]= new xmlrpcval($theCurRec->options1, 'string');

				$myResult[] = new xmlrpcval($mRes, 'array');
			}
			break;
		case "contacts":
			// header
			$mRes=array();
			$mRes[]= new xmlrpcval("ident", 'string');
			$mRes[]= new xmlrpcval("title", 'string');
			$mRes[]= new xmlrpcval("firstname", 'string');
			$mRes[]= new xmlrpcval("lastname", 'string');
			$mRes[]= new xmlrpcval("company", 'string');
			$mRes[]= new xmlrpcval("email", 'string');
			$mRes[]= new xmlrpcval("url", 'string');
			$mRes[]= new xmlrpcval("phone", 'string');
			$mRes[]= new xmlrpcval("mobile", 'string');
			$mRes[]= new xmlrpcval("fax", 'string');
			$mRes[]= new xmlrpcval("address", 'string');
			$mRes[]= new xmlrpcval("city", 'string');
			$mRes[]= new xmlrpcval("postcode", 'string');
			$mRes[]= new xmlrpcval("country", 'string');
			$mRes[]= new xmlrpcval("comment", 'string');
			$mRes[]= new xmlrpcval("lastsync", 'string');
			$myResult[] = new xmlrpcval($mRes, 'array');
			foreach($theRecords as $theCurRec)
			{
				$mRes=array();
				$mRes[]= new xmlrpcval($theCurRec->ID, 'string');
				$mRes[]= new xmlrpcval($theCurRec->anrede, 'string');
				$mRes[]= new xmlrpcval($theCurRec->vorname, 'string');
				$mRes[]= new xmlrpcval($theCurRec->nachname, 'string');
				$mRes[]= new xmlrpcval($theCurRec->firma, 'string');
				$mRes[]= new xmlrpcval($theCurRec->email, 'string');
				$mRes[]= new xmlrpcval($theCurRec->url, 'string');
				$mRes[]= new xmlrpcval($theCurRec->tel1, 'string');
				$mRes[]= new xmlrpcval($theCurRec->mobil, 'string');
				$mRes[]= new xmlrpcval($theCurRec->fax, 'string');
				$mRes[]= new xmlrpcval($theCurRec->strasse, 'string');
				$mRes[]= new xmlrpcval($theCurRec->stadt, 'string');
				$mRes[]= new xmlrpcval($theCurRec->plz, 'string');
				$mRes[]= new xmlrpcval($theCurRec->land, 'string');
				$mRes[]= new xmlrpcval($theCurRec->bemerkung, 'string');
				$mRes[]= new xmlrpcval($theCurRec->sync_DerniereMAJ, 'string');
				$myResult[] = new xmlrpcval($mRes, 'array');
			}
			// data
			break;
		case "notes":	
			$mRes=array();
			$mRes[]= new xmlrpcval("ident", 'string');
			$mRes[]= new xmlrpcval("subject", 'string');
			$mRes[]= new xmlrpcval("body", 'string');
			$mRes[]= new xmlrpcval("lastsync", 'string');
			$myResult[] = new xmlrpcval($mRes, 'array');
			foreach($theRecords as $theCurRec)
			{
				$mRes=array();
				$mRes[]= new xmlrpcval($theCurRec->ID, 'string');
				$mRes[]= new xmlrpcval($theCurRec->name, 'string');
			 // Specific for Outlook ! Outlook recreates the subject of a note from the first line of its body
				$mRes[]= new xmlrpcval($theCurRec->name . "\n\r".$theCurRec->remark, 'string');
				$mRes[]= new xmlrpcval($theCurRec->sync_DerniereMAJ, 'string');
				$myResult[] = new xmlrpcval($mRes, 'array');
			}
			break;
		case "tasks":
			$mRes=array();
			$mRes[]= new xmlrpcval("ident", 'string');
			$mRes[]= new xmlrpcval("task", 'string');
			$mRes[]= new xmlrpcval("begin", 'string');
			$mRes[]= new xmlrpcval("end", 'string');
			$mRes[]= new xmlrpcval("priority", 'string');
			$mRes[]= new xmlrpcval("note", 'string');
			$mRes[]= new xmlrpcval("lastsync", 'string');
			$myResult[] = new xmlrpcval($mRes, 'array');
			foreach($theRecords as $theCurRec)
			{
				$mRes=array();
				$mRes[]= new xmlrpcval($theCurRec->ID, 'string');
				$mRes[]= new xmlrpcval($theCurRec->remark, 'string');
				$mRes[]= new xmlrpcval($theCurRec->datum, 'string');
				$mRes[]= new xmlrpcval($theCurRec->deadline, 'string');
				$mRes[]= new xmlrpcval(intval(intval($theCurRec->priority)/5), 'string'); // Transformation vers le modèle Outlook
				$mRes[]= new xmlrpcval($theCurRec->note, 'string');
				$mRes[]= new xmlrpcval($theCurRec->sync_DerniereMAJ, 'string');
				$myResult[] = new xmlrpcval($mRes, 'array');
			}
			break;
	}
	logevent("getRecordsFromType-".$theType,serialize($myResult));
	return $myResult;
}

// Declare our signature and provide some documentation.
// (The PHP server supports remote introspection. Nifty!)
$GetLatestSummary_sig = array(array('struct', 'string','string', 'string', 'string', 'string', 'string'));
$GetLatestSummary_doc = 'Get latest data from base, based on the type passed, the user rights and the date offset (usefull for calendar only)';

$GetRecords_sig = array(array('struct', 'string', 'string', 'string', 'string', 'array'));
$GetRecords_doc = 'Get specific records of data from database';

$sendRecords_sig = array(array('struct', 'string', 'string', 'string', 'string','int','int', 'array'));
$sendRecords_doc = 'Save specified records of data to database';

$cleanForeignCrossRef_sig = array(array('struct', 'string', 'string', 'string', 'string','int','int', 'array'));
$cleanForeignCrossRef_doc = 'Clean records from cross ref table';

$updateForeignCrossRef_sig = array(array('struct', 'string', 'string', 'string', 'string','int','int', 'array'));
$updateForeignCrossRef_doc = 'Update records id and entryid in cross ref table after they are added or modified in outlook';

new xmlrpc_server(array(
		'toutateam.GetLatestSummary' =>array('function' => 'GetLatestSummary','signature' => $GetLatestSummary_sig,'docstring' => $GetLatestSummary_doc),
		'toutateam.GetRecords' =>array('function' => 'GetRecords','signature' => $GetRecords_sig,'docstring' => $GetRecords_doc),
		'toutateam.sendRecords' =>array('function' => 'sendRecords','signature' => $sendRecords_sig,'docstring' => $sendRecords_doc),
		'toutateam.cleanForeignCrossRef' =>array('function' => 'cleanForeignCrossRef','signature' => $cleanForeignCrossRef_sig,'docstring' => $cleanForeignCrossRef_doc),
		'toutateam.updateForeignCrossRef' =>array('function' => 'updateForeignCrossRef','signature' => $updateForeignCrossRef_sig,'docstring' => $updateForeignCrossRef_doc)
		));
?>
Return current item: Toutateam Groupware