diff --git a/htdocs/admin/webcalendar.php b/htdocs/admin/webcalendar.php
index 2f2dbb112f9eba4aa9c9fafff7222fa09d64055a..71ec5d87d5e0e2169258b6b892ffa830cbc15549 100644
--- a/htdocs/admin/webcalendar.php
+++ b/htdocs/admin/webcalendar.php
@@ -125,7 +125,7 @@ elseif ($actiontest)
 		// parametre host/user/pass identique.
         //$webcal->localdb->close();
     }
-    elseif ($webcal->connected == 1 && $webcal->database_selected != 1)
+    elseif ($webcal->localdb->connected == 1 && $webcal->localdb->database_selected != 1)
     {
         $mesg ="<div class=\"error\">".$langs->trans("WebCalTestKo1",$_POST["phpwebcalendar_host"],$_POST["phpwebcalendar_dbname"]);
         $mesg.="<br>".$webcal->localdb->error();
@@ -302,6 +302,15 @@ clearstatcache();
 if ($mesg) print "<br>$mesg<br>";
 print "<br>";
 
+// Show message
+$message='';
+$urlvcal='<a href="'.DOL_URL_ROOT.'/webcal/webcalexport.php?format=vcal" target="_blank">'.$dolibarr_main_url_root.DOL_URL_ROOT.'/webcal/webcalexport.php?format=vcal'.'</a>';
+$message.=$langs->trans("WebCalUrlForVCalExport",'vcal',$urlvcal);
+$message.='<br>';
+$urlical='<a href="'.DOL_URL_ROOT.'/webcal/webcalexport.php?format=ical" target="_blank">'.$dolibarr_main_url_root.DOL_URL_ROOT.'/webcal/webcalexport.php?format=ical'.'</a>';
+$message.=$langs->trans("WebCalUrlForVCalExport",'ical',$urlical);
+print info_admin($message);
+
 $db->close();
 
 llxFooter('$Date$ - $Revision$');
diff --git a/htdocs/conf/conf.class.php b/htdocs/conf/conf.class.php
index dc5f9538df5c4b435aed37cac3be569f7e9c4803..deda6233da21b4363144be172ced6baf21983f4d 100644
--- a/htdocs/conf/conf.class.php
+++ b/htdocs/conf/conf.class.php
@@ -283,6 +283,7 @@ class Conf
 		$this->webcal->db->user=defined('PHPWEBCALENDAR_USER')?PHPWEBCALENDAR_USER:'';
 		$this->webcal->db->pass=defined('PHPWEBCALENDAR_PASS')?PHPWEBCALENDAR_PASS:'';
 		$this->webcal->db->name=defined('PHPWEBCALENDAR_DBNAME')?PHPWEBCALENDAR_DBNAME:'';
+		$this->webcal->dir_temp=DOL_DATA_ROOT.'/webcal/temp';
 		// Module phenix
 		$this->phenix->enabled=defined('MAIN_MODULE_PHENIX')?MAIN_MODULE_PHENIX:0;
 		$this->phenix->db->type=defined('PHPPHENIX_TYPE')?PHPPHENIX_TYPE:'__dolibarr_main_db_type__';
diff --git a/htdocs/document.php b/htdocs/document.php
index f54d07b9895eb818835b0cc99afe7d668b473a75..ebb7a73b844aebade1e5c0458562585dad3d9491 100644
--- a/htdocs/document.php
+++ b/htdocs/document.php
@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2004-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
- * Copyright (C) 2004-2007 Laurent Destailleur  <eldy@users.sourceforge.net>
+ * Copyright (C) 2004-2008 Laurent Destailleur  <eldy@users.sourceforge.net>
  * Copyright (C) 2005      Simon Tosser         <simon@kornog-computing.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,8 +29,29 @@
 */
 
 if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1');
+if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
+if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
 
-require_once("./main.inc.php");
+$original_file = urldecode($_GET["file"]);
+$modulepart = urldecode($_GET["modulepart"]);
+$type = isset($_GET["type"]) ? urldecode($_GET["type"]) : '';
+
+// Define if we need master or master+main
+$needmasteronly=false;
+if ($modulepart == 'webcal') $needmasteronly=true;
+
+// Load master or main
+if ($needmasteronly)
+{
+	// Pour companylogo, on charge juste environnement sans logon qui charge le user
+	require("./master.inc.php");
+}
+else
+{
+	// Pour autre que companylogo, on charge environnement + info issus de logon comme le user
+	require("./main.inc.php");
+	// master.inc.php is included in main.inc.php
+}
 
 
 // C'est un wrapper, donc header vierge
@@ -52,6 +73,8 @@ if (eregi('\.xls$',$original_file))  	{ $type='application/x-msexcel'; $attachme
 if (eregi('\.jpg$',$original_file)) 	{ $type='image/jpeg'; $attachment = true; }
 if (eregi('\.png$',$original_file)) 	{ $type='image/jpeg'; $attachment = true; }
 if (eregi('\.tiff$',$original_file)) 	{ $type='image/tiff'; $attachment = true; }
+if (eregi('\.vcs$',$original_file))  	{ $type='text/calendar'; $attachment = true; }
+if (eregi('\.ics$',$original_file))  	{ $type='text/calendar'; $attachment = true; }
 
 // Suppression de la chaine de caract�re ../ dans $original_file
 $original_file = str_replace("../","/", "$original_file");
@@ -323,7 +346,12 @@ if ($modulepart)
 		$sqlprotectagainstexternals = '';
     }
 
-
+    // Wrapping pour les factures
+    if ($modulepart == 'webcal')
+    {
+        $accessallowed=1;
+        $original_file=$conf->webcal->dir_temp.'/'.$original_file;
+    }
 }
 
 // Basic protection (against external users only)
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index b61a97e4d375ca70c7b7eb219c54b516d8051aa0..c3dce260779c50b672e292163eaf85650b2cbd4c 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -534,6 +534,8 @@ WebCalAddEventOnStatusPropal=Add calendar event on commercial proposals status c
 WebCalAddEventOnStatusContract=Add calendar event on contracts status change
 WebCalAddEventOnStatusBill=Add calendar event on bills status change
 WebCalAddEventOnStatusMember=Add calendar event on members status change
+WebCalUrlForVCalExport=An export link to <b>%s</b> format is available at following link: %s
+WebCalCheckWebcalSetup=May be, Webcal module setup is not correctly done.
 ##### Invoices #####
 BillsSetup=Invoices module setup
 BillsDate=Invoices date
diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang
index bf6a4d7cb7618dac84fc4be49e5f89d0fcbc97f7..1b9add175afac663f01ea705ad1b6002e5ed1b6d 100644
--- a/htdocs/langs/fr_FR/admin.lang
+++ b/htdocs/langs/fr_FR/admin.lang
@@ -533,6 +533,8 @@ WebCalAddEventOnStatusPropal=Ajouter 
 WebCalAddEventOnStatusContract=Ajouter �v�nement dans calendrier sur changement de statut des contrats
 WebCalAddEventOnStatusBill=Ajouter �v�nement dans calendrier sur changement de statut des factures
 WebCalAddEventOnStatusMember=Ajouter �v�nement dans calendrier sur changement de statut des adh�rents
+WebCalUrlForVCalExport=Un lien d'export du calendrier au format <b>%s</b> sera disponible � l'url: %s
+WebCalCheckWebcalSetup=La configuration du module Webcal est peut-�tre incorrecte.
 ##### Invoices #####
 BillsSetup=Configuration du module Factures
 BillsDate=Date des factures
diff --git a/htdocs/lib/databases/mssql.lib.php b/htdocs/lib/databases/mssql.lib.php
index 4bbb77e43a55efe03455036723092557003f0595..c1904444cb48de9570a62021a54be0d475d81ea3 100644
--- a/htdocs/lib/databases/mssql.lib.php
+++ b/htdocs/lib/databases/mssql.lib.php
@@ -52,6 +52,8 @@ class DoliDb
   var $database_selected; 
   //! Nom base s�lectionn�e
   var $database_name;			
+  //! Nom user base
+  var $database_user;		
   //! 1 si une transaction est en cours, 0 sinon
   var $transaction_opened;	
   //! Derniere requete ex�cut�e
@@ -110,6 +112,8 @@ class DoliDb
   function DoliDb($type='mssql', $host, $user, $pass, $name='', $newlink=0)
   {
     global $conf,$langs;
+
+	$this->database_user=$user;
     $this->transaction_opened=0;
         
     if (! function_exists("mssql_connect"))
diff --git a/htdocs/lib/databases/mysql.lib.php b/htdocs/lib/databases/mysql.lib.php
index 88b4400e57374728f159740d18f73ee605600f54..f7df54f9597cd4a917efe554297aaee893f1769a 100644
--- a/htdocs/lib/databases/mysql.lib.php
+++ b/htdocs/lib/databases/mysql.lib.php
@@ -132,7 +132,7 @@ class DoliDb
 		if (isset($conf->db->dolibarr_main_db_collation) && $conf->db->dolibarr_main_db_collation) {
 			$this->forcecollate=$conf->db->dolibarr_main_db_collation;
 		}
-		$this->db_user=$conf->db->user;
+		$this->database_user=$user;
 
 		$this->transaction_opened=0;
 		
diff --git a/htdocs/lib/databases/mysqli.lib.php b/htdocs/lib/databases/mysqli.lib.php
index 286627663fe6531d86c0140df0700f613814dec8..10065585d6d6b183a65abece69f0875bc65ea8cb 100644
--- a/htdocs/lib/databases/mysqli.lib.php
+++ b/htdocs/lib/databases/mysqli.lib.php
@@ -131,7 +131,7 @@ class DoliDb
   		if (isset($conf->db->dolibarr_main_db_collation) && $conf->db->dolibarr_main_db_collation) {
 	    	$this->forcecollate=$conf->db->dolibarr_main_db_collation;
   		}
-	    $this->db_user=$conf->db->user;
+	    $this->database_user=$user;
 
         $this->transaction_opened=0;
 
diff --git a/htdocs/lib/databases/pgsql.lib.php b/htdocs/lib/databases/pgsql.lib.php
index cc9caa5e6e727e6ba77b709d3320c815caa09fce..a582cced11c6a919211e45a0ea59ab29e3b42ed2 100644
--- a/htdocs/lib/databases/pgsql.lib.php
+++ b/htdocs/lib/databases/pgsql.lib.php
@@ -84,7 +84,7 @@ class DoliDb
 		*/
 		$this->forcecharset=$conf->character_set_client;
 	    $this->forcecollate=$conf->db->dolibarr_main_db_collation;
-	    $this->db_user=$conf->db->user;
+	    $this->database_user=$user;
 
         $this->transaction_opened=0;
 
diff --git a/htdocs/lib/functions.inc.php b/htdocs/lib/functions.inc.php
index e3493a568cd7ac4cd09704382abcc57811ec3345..5fdd096e32db46ddfb373cda677b4fd4b9dc0513 100644
--- a/htdocs/lib/functions.inc.php
+++ b/htdocs/lib/functions.inc.php
@@ -546,12 +546,13 @@ function dolibarr_print_date($time,$format='')
     // Si format non d�fini, on prend $conf->format_date_text_short sinon %Y-%m-%d %H:%M:%S
     if (! $format) $format=(isset($conf->format_date_text_short) ? $conf->format_date_text_short : '%Y-%m-%d %H:%M:%S');
 
-    if ($format == 'day')         $format=$conf->format_date_short;
-    if ($format == 'hour')        $format=$conf->format_hour_short;
-    if ($format == 'daytext')     $format=$conf->format_date_text_short;
-    if ($format == 'dayhour')     $format=$conf->format_date_hour_short;
-    if ($format == 'dayhourtext') $format=$conf->format_date_hour_text_short;
-    if ($format == 'dayhourldap') $format='%Y%m%d%H%M%SZ';
+    if ($format == 'day')          $format=$conf->format_date_short;
+    if ($format == 'hour')         $format=$conf->format_hour_short;
+    if ($format == 'daytext')      $format=$conf->format_date_text_short;
+    if ($format == 'dayhour')      $format=$conf->format_date_hour_short;
+    if ($format == 'dayhourtext')  $format=$conf->format_date_hour_text_short;
+    if ($format == 'dayhourldap')  $format='%Y%m%d%H%M%SZ';
+    if ($format == 'dayhourxcard') $format='%Y%m%dT%H%M%SZ';
 
     // Si date non definie, on renvoie ''
     if ($time == '') return '';		// $time=0 permis car signifie 01/01/1970 00:00:00
@@ -2653,20 +2654,22 @@ function clean_url($url,$http=1)
    \param   string      StringHtml
    \return  string	    CleanString
 */
-function clean_html($StringHtml)
+function clean_html($StringHtml,$removelinefeed=1)
 {
-  $pattern = "<[^>]+>";
-  $temp = dol_entity_decode($StringHtml);
-  $temp = ereg_replace($pattern,"",$temp);
-  // Supprime aussi les retours
-  $temp=str_replace("\n"," ",$temp);
-  // et les espaces doubles
-  while(STRPOS($temp,"  "))
-  {
-  	$temp = STR_REPLACE("  "," ",$temp);
-  }
-  $CleanString = $temp;
-  return $CleanString;
+	$pattern = "<[^>]+>";
+	$temp = dol_entity_decode($StringHtml);
+	$temp = ereg_replace($pattern,"",$temp);
+
+	// Supprime aussi les retours
+	if ($removelinefeed) $temp=str_replace("\n"," ",$temp);
+
+	// et les espaces doubles
+	while(STRPOS($temp,"  "))
+	{
+		$temp = STR_REPLACE("  "," ",$temp);
+	}
+	$CleanString = $temp;
+	return $CleanString;
 }
 
 /**
diff --git a/htdocs/lib/xcal.lib.php b/htdocs/lib/xcal.lib.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b850a3dc4b86949ccacc8c3e8cb3bf9271e37b4
--- /dev/null
+++ b/htdocs/lib/xcal.lib.php
@@ -0,0 +1,238 @@
+<?php
+/* Copyright (C) 2008 Laurent Destailleur  <eldy@users.sourceforge.net>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+ 
+ 
+/**
+   \file       htdocs/lib/xcal.lib.php
+   \brief      Function to manage calendar files (vcal/ical/...)
+   \version    $Revision$
+*/
+
+/**
+	\brief		Build a file from an array of events
+	\param		format				'vcal' or 'ical'
+	\param		events_array		Array of events ('eid','startdate','duration','enddate','title','summary','category','email','url','desc','author')
+	\param		outputfile			Output file
+	\param		filter				Filter
+	\return		int					<0 if ko, Nb of events in file if ok
+*/
+function build_calfile($format='vcal',$events_array,$outputfile,$filter='')
+{
+	dolibarr_syslog("xcal.lib.php::build_cal_file Build cal file ".$outputfile." to format ".$format);
+
+	if (empty($outputfile)) return -1;
+	
+	$calfileh=fopen($outputfile,'w');
+	if ($calfileh)
+	{
+		$now=mktime();
+		
+		// Print header
+		fwrite($calfileh,"BEGIN:VCALENDAR\n");
+		fwrite($calfileh,"VERSION:2.0\n");
+		fwrite($calfileh,"METHOD:PUBLISH\n");
+		fwrite($calfileh,"PRODID:-//DOLIBARR ".DOL_VERSION."//EN\n");
+		/*
+		X-WR-CALNAME:Agenda du Libre
+		X-WR-TIMEZONE:Europe/Paris
+		CALSCALE:GREGORIAN
+		X-WR-CALDESC:L'Agenda des �v�nements autour du Libre
+		*/
+		
+		foreach ($events_array as $date => $event)
+		{
+			$eventqualified=true;
+			if ($filter)
+			{
+				// \TODO Add a filter
+
+				$eventqualified=false;
+			}
+			
+			if ($eventqualified)
+			{
+				# slurp out the fields to make it more convenient
+				$uid 		= dolibarr_print_date($now,'dayhourxcard').'-'.$event['uid']."-export@".$_SERVER["SERVER_NAME"];
+				$startdate	= $event['startdate'];
+				$duration	= $event['duration'];
+				$enddate	= $event['enddate'];
+				$summary	= $event['summary'];
+				$category	= $event['category'];
+				$location	= $event['location'];
+				$email 		= $event['email'];
+				$url		= $event['url'];
+				$description=eregi_replace('<br[ \/]?>',"\n",$event['desc']);
+ 				$description=clean_html($description,0);	// Remove html tags
+
+				// Uncomment for tests
+				//$summary="Resume";
+				//$description="Description";
+				//$description="MemberValidatedInDolibarr gd gdf gd gdff\nNom: tgdf g dfgdf gfd r ter\nType: gdfgfdf dfg fd gfd gd gdf gdf gfd gdfg dfg ddf\nAuteur: AD01fg dgdgdfg df gdf gd";
+
+				// Format
+				$summary=format_cal($format,$summary);
+				$description=format_cal($format,$description);
+				
+				$encoding='';
+				if ($format == 'vcal') $encoding='ENCODING=QUOTED-PRINTABLE:';
+				
+				# Output the vCard/iCal VEVENT object
+				fwrite($calfileh,"BEGIN:VEVENT\n");
+				fwrite($calfileh,"UID:".$uid."\n");
+				if ($email <> "")
+				{
+					fwrite($calfileh,"ORGANIZER:MAILTO:".$email."\n");
+					fwrite($calfileh,"CONTACT:MAILTO:".$email."\n");
+				}
+				if ($url <> "") {  fwrite($calfileh,"URL:".$url."\n"); };
+				
+				fwrite($calfileh,"SUMMARY:".$encoding.$summary."\n");
+				fwrite($calfileh,"DESCRIPTION:".$encoding.$description."\n");
+				fwrite($calfileh,"CATEGORIES:".$category."\n");
+				fwrite($calfileh,"LOCATION:".$location."\n");
+				fwrite($calfileh,"TRANSP:OPAQUE\n");
+				fwrite($calfileh,"CLASS:CONFIDENTIAL\n");
+				fwrite($calfileh,"DTSTAMP:".dolibarr_print_date($now,'dayhourxcard')."\n");
+
+				// Dates
+				$startdatef = dolibarr_print_date($startdate,'dayhourxcard');
+				fwrite($calfileh,"DTSTART:".$startdatef."\n");
+
+				if (empty($enddate)) $enddate=$startdate+$duration;
+				$enddatef = dolibarr_print_date($enddate,'dayhourxcard');
+				fwrite($calfileh,"DTEND:".$enddatef."\n");
+
+				// Put other info in comment
+				/*
+				$comment=array();
+				$comment ['eid']			= $eid;
+				$comment ['url']			= $linktoevent;
+				$comment ['date']			= dolibarr_mktime($evttime,"Ymd");
+				$comment ['duration']		= $duration;
+				$comment ['startdate']		= $startdate;
+				$comment ['enddate']		= $enddate;
+				fwrite($calfileh,"COMMENT:" . serialize ($comment) . "\n");
+				*/
+				
+				fwrite($calfileh,"END:VEVENT\n");
+			}
+		}
+
+		// Footer
+		fwrite($calfileh,"END:VCALENDAR\n");
+		
+		fclose($calfileh);
+	}
+	else
+	{
+		dolibarr_syslog("xcal.lib.php::build_cal_file Failed to open file ".$outputfile." for writing");
+		return -2;
+	}
+}
+
+
+function format_cal($format,$string)
+{
+	$newstring=$string;
+	
+	if ($format == 'vcal')
+	{
+		$newstring=QPEncode($newstring);
+	}
+	if ($format == 'ical')
+	{
+		// Replace new lines chars by '\n'
+		$newstring=eregi_replace("\r\n","\n",$newstring);
+		$newstring=eregi_replace("\n\r","\n",$newstring);
+		$newstring=eregi_replace("\n",'\n',$newstring);
+		// Must not exceed 75 char. Cut with "\r\n"+Space
+		$newstring=CalEncode($newstring);
+	}
+	
+	return $newstring;
+}
+
+/**
+	\brief		Cut string after 75 chars. Add CRLF+Space.
+	\param		string		String to convert
+	\return		string 		String converted
+*/
+function CalEncode($line)
+{
+	$out = '';
+
+	$newpara = '';
+
+	for ($j = 0; $j <= strlen($line) - 1; $j++)
+	{
+		$char = substr ( $line, $j, 1 );
+
+		if ( ( strlen ( $newpara ) + strlen ( $char ) ) >= 75 )
+		{
+			$out .= $newpara . "\r\n ";	// CRLF + Space for cal
+			$newpara = '';
+		}
+		$newpara .= $char;
+	}
+	$out .= $newpara;
+
+	return trim($out);
+}
+
+
+function QPEncode($str,$forcal=0)
+{
+	$lines = preg_split("/\r\n/", $str);
+	$out = '';
+
+	foreach ($lines as $line)
+	{
+		$newpara = '';
+
+		for ($j = 0; $j <= strlen($line) - 1; $j++)
+		{
+			$char = substr ( $line, $j, 1 );
+			$ascii = ord ( $char );
+
+			if ( $ascii < 32 || $ascii == 61 || $ascii > 126 )
+			$char = '=' . strtoupper ( sprintf("%02X", $ascii ) );
+
+			if ( ( strlen ( $newpara ) + strlen ( $char ) ) >= 76 )
+			{
+				$out .= $newpara . '=' . "\r\n";	// CRLF
+				if ($forcal) $out .= " ";		// + Space for cal
+				$newpara = '';
+			}
+			$newpara .= $char;
+		}
+		$out .= $newpara;
+	}
+	return trim ( $out );
+}
+
+function QPDecode( $str )
+{
+	$out = preg_replace('/=\r?\n/', '', $str);
+	$out = preg_replace('/=([A-F0-9]{2})/e', chr( hexdec ('\\1' ) ), $out);
+
+	return trim($out);
+} 
+
+?>
\ No newline at end of file
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index 9dd63ca6240bf797bb895e9f26822f1e90dd5447..02867bd455a4426c92156e5a4f68d51c08a56fb1 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -74,9 +74,9 @@ foreach ($_POST as $key => $val)
 require_once("master.inc.php");
 
 // Chargement des includes complementaire de presentation
-if ($conf->use_ajax) require_once(DOL_DOCUMENT_ROOT.'/lib/ajax.lib.php');
 if (! defined('NOREQUIREMENU')) require_once(DOL_DOCUMENT_ROOT ."/menu.class.php");
 if (! defined('NOREQUIREHTML')) require_once(DOL_DOCUMENT_ROOT ."/html.form.class.php");
+if (! defined('NOREQUIREAJAX') && $conf->use_ajax) require_once(DOL_DOCUMENT_ROOT.'/lib/ajax.lib.php');
 
 // Init session
 $sessionname="DOLSESSID_".$dolibarr_main_db_name;
diff --git a/htdocs/viewimage.php b/htdocs/viewimage.php
index 77d28427c16e305a64237625d5d6519af234ff36..330a5107082257bf9075e0c45a17e855df3b60cd 100644
--- a/htdocs/viewimage.php
+++ b/htdocs/viewimage.php
@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2004-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
- * Copyright (C) 2005-2007 Laurent Destailleur  <eldy@users.sourceforge.net>
+ * Copyright (C) 2005-2008 Laurent Destailleur  <eldy@users.sourceforge.net>
  *
  * 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
@@ -28,32 +28,40 @@
 */
 
 if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1');
-
-
-// C'est un wrapper, donc header vierge
-function llxHeader() { }
-
+if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
+if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
 
 $original_file = urldecode($_GET["file"]);
 $modulepart = urldecode($_GET["modulepart"]);
 $type = isset($_GET["type"]) ? urldecode($_GET["type"]) : '';
 
-// Protection, on interdit les .. dans les chemins
-$original_file = eregi_replace('\.\.','',$original_file);
+// Define if we need master or master+main
+$needmasteronly=false;
+if ($modulepart == 'companylogo') $needmasteronly=true;
 
-
-if ($modulepart == 'companylogo')
+// Load master or main
+if ($needmasteronly)
 {
 	// Pour companylogo, on charge juste environnement sans logon qui charge le user
-	require_once("master.inc.php");
+	require("./master.inc.php");
 }
 else
 {
 	// Pour autre que companylogo, on charge environnement + info issus de logon comme le user
-	require_once("main.inc.php");
+	require("./main.inc.php");
+	// master.inc.php is included in main.inc.php
 }
 
 
+// C'est un wrapper, donc header vierge
+function llxHeader() { }
+
+
+
+// Protection, on interdit les .. dans les chemins
+$original_file = eregi_replace('\.\.','',$original_file);
+
+
 
 $accessallowed=0;
 if ($modulepart)
diff --git a/htdocs/webcal/webcal.class.php b/htdocs/webcal/webcal.class.php
index 322cbc30b76d012cd54b4612c4f428e02f3fa3fc..d62c5fa85579dc9415316535be951cbbf0f580d8 100644
--- a/htdocs/webcal/webcal.class.php
+++ b/htdocs/webcal/webcal.class.php
@@ -74,7 +74,7 @@ class Webcal {
             \return     int         1 en cas de succ�s, -1,-2,-3 en cas d'erreur, -4 si login webcal non d�fini
     */
     function add($user)
-{
+	{
         global $langs;
         
         dolibarr_syslog("Webcal::add user=".$user->id);
@@ -173,6 +173,110 @@ class Webcal {
             return -1;
         }
     }
-   
+
+	
+    /**
+    		\brief      Export fichier cal depuis base webcalendar
+			\param		format			'ical' or 'vcal'
+			\param		cachedelay		Do not rebuild file if date older than cachedelay seconds	
+			\param		filename		Force filename
+			\param		filter			Array of filters
+    		\return     int     		<0 if error, nb of events in new file if ok
+    */
+	function build_calfile($format,$cachedelay,$filename,$filters)
+	{
+		global $conf,$langs;
+		
+		require_once (DOL_DOCUMENT_ROOT ."/lib/xcal.lib.php");
+
+		dolibarr_syslog("webcal::build_calfile Build cal file format=".$format.", cachedelay=".$cachedelay.", filename=".$filename.", filters size=".sizeof($filters), LOG_DEBUG);
+
+		// Check parameters
+		if (empty($format)) return -1;
+
+		// Clean parameters
+		if (! $filename)
+		{
+			$extension='vcs';
+			if ($format == 'ical') $extension='ics';
+			$filename=$format.'.'.$extension;
+		}
+		
+		create_exdir($conf->webcal->dir_temp);
+		$outputfile=$conf->webcal->dir_temp.'/'.$filename;
+		$result=0;
+		
+		$buildfile=true;
+		if ($cachedelay)
+		{
+			// \TODO Check cache
+		}
+		
+		if ($buildfile)
+		{
+			// Build event array
+			$eventarray=array();
+			
+			$sql = "SELECT cal_id, cal_create_by, ";
+			$sql.= " cal_date, cal_time, cal_mod_date,";
+			$sql.= " cal_mod_time, cal_duration, cal_priority, cal_type, cal_access, cal_name, cal_description";
+			$sql.= " FROM webcal_entry";
+			$sql.= " order by cal_date";
+
+			dolibarr_syslog("Webcal::build_vcal select events sql=".$sql);
+			$resql=$this->localdb->query($sql);
+			if ($resql)
+			{
+				while ($obj=$this->localdb->fetch_object($resql))
+				{
+					$qualified=true;
+					
+					// 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author'
+					$event=array();
+					$event['uid']=$obj->cal_id;
+					$date=$obj->cal_date;
+					$time=$obj->cal_time;
+					if (eregi('^([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])$',$date,$reg))
+					{
+						$year=$reg[1];
+						$month=$reg[2];
+						$day=$reg[3];
+						if (! empty($filters['year'])  && $year != $filters['year'])  $qualified=false;
+						if (! empty($filters['month']) && $year != $filters['month']) $qualified=false;
+						if (! empty($filters['day'])   && $year != $filters['day'])   $qualified=false;
+					}
+					if (eregi('^([0-9]?[0-9])([0-9][0-9])([0-9][0-9])$',$time,$reg))
+					{
+						$hour=sprintf("%02d",$reg[1]);
+						$min=sprintf("%02d",$reg[2]);
+						$sec=sprintf("%02d",$reg[3]);
+					}
+					$datestart=dolibarr_mktime($hour,$min,$sec,$month,$day,$year);
+					$event['startdate']=$datestart;
+					$event['duration']=$obj->cal_duration;
+					$event['enddate']='';
+					$event['summary']=$obj->cal_name;
+					$event['desc']=$obj->cal_description;
+					$event['author']=$obj->cal_create_by;
+					
+					if ($qualified)
+					{
+						$eventarray[$datestart]=$event;
+					}
+				}
+			}
+			else
+			{
+				dolibarr_syslog("webcal::build_calfile ".$this->localdb->lasterror());
+				return -1;
+			}
+			
+			// Write file
+			$result=build_calfile($format,$eventarray,$outputfile);
+		}
+		
+		return $result;
+	}
+  
 }
 ?>
diff --git a/htdocs/webcal/webcal.php b/htdocs/webcal/webcal.php
index 717638691995df8801fd3547ecb2bb62bd3aa85e..7d8b26fe7f9ed42ad8c549c71b87d1c8c5e75e19 100644
--- a/htdocs/webcal/webcal.php
+++ b/htdocs/webcal/webcal.php
@@ -18,7 +18,7 @@
  * $Id$
  */
 
-/**	    \file       htdocs/wecal/webcal.php
+/**	    \file       htdocs/webcal/webcal.php
         \ingroup    webcalendar
 		\brief      Page g�n�rant 2 frames, une pour le menu Dolibarr, l'autre pour l'affichage du calendrier
 		\author	    Laurent Destailleur
diff --git a/htdocs/webcal/webcalexport.php b/htdocs/webcal/webcalexport.php
new file mode 100644
index 0000000000000000000000000000000000000000..5977736efe14f9328212997bbfe366068e35ec72
--- /dev/null
+++ b/htdocs/webcal/webcalexport.php
@@ -0,0 +1,105 @@
+<?php
+/* Copyright (C) 2008 Laurent Destailleur <eldy@users.sourceforge.net>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+/**	    \file       htdocs/webcal/webcalexport.php
+        \ingroup    webcalendar
+		\brief      Page export webcalendar
+		\version    $Revision$
+*/
+
+require("../master.inc.php");
+require_once(DOL_DOCUMENT_ROOT.'/webcal/webcal.class.php');
+
+
+// C'est un wrapper, donc header vierge
+function llxHeader() { print '<html><title>Export cal</title><body>'; }
+function llxFooter() { print '</body></html>'; }
+
+
+// Check config
+if (empty($conf->global->PHPWEBCALENDAR_URL))
+{
+	$user->getrights();
+
+	llxHeader();
+	print '<div class="error">Module Webcalendar was not configured properly.</div>';
+	llxFooter('$Date$ - $Revision$');
+	exit;
+}
+
+// Connect to database
+$webcal=new WebCal();
+if (! $webcal->localdb->connected || ! $webcal->localdb->database_selected)
+{
+	llxHeader();
+	if ($webcal->localdb->connected == 1 && $webcal->localdb->database_selected != 1)
+    {
+        print '<div class="error">'.$langs->trans("WebCalTestKo1",$conf->webcal->db->host,$conf->webcal->db->name);
+        print '<br>'.$webcal->localdb->error();
+		print '<br>'.$langs->trans("WebCalCheckWebcalSetup");
+        print "</div>";
+        //$webcal->localdb->close();    Ne pas fermer car la conn de webcal est la meme que dolibarr si parametre host/user/pass identique
+    }
+    else
+    {
+        print "<div class=\"error\">".$langs->trans("WebCalTestKo2",$conf->webcal->db->host,$conf->webcal->db->user);
+        print "<br>".$webcal->localdb->error();
+		print '<br>'.$langs->trans("WebCalCheckWebcalSetup");
+        print "</div>";
+    }
+	llxFooter('$Date$ - $Revision$');
+	exit;
+}
+
+
+$mainmenu=isset($_GET["mainmenu"])?$_GET["mainmenu"]:"";
+$leftmenu=isset($_GET["leftmenu"])?$_GET["leftmenu"]:"";
+
+// Define format, filename and filter
+$format='vcal';
+$filename='';
+if (! empty($_GET["format"])) $format=$_GET["format"];
+if ($format == 'vcal') $filename='webcalendar.vcs';
+if ($format == 'ical') $filename='webcalendar.ics';
+if (! $filename)
+{
+	$langs->load("main");
+	$langs->load("errors");
+	llxHeader();
+    print '<div class="error">'.$langs->trans("ErrorWrongValueForParameterX",'format').'</div>';
+	llxFooter('$Date$ - $Revision$');
+	exit;
+}
+$filters=array();
+if (! empty($_GET["year"])) $filters['year']=$_GET["year"];
+
+// Build file
+$result=$webcal->build_calfile($format,0,$filename,$filters);
+if ($result >= 0)
+{
+	header("Location: ".DOL_URL_ROOT.'/document.php?modulepart=webcal&file='.urlencode($filename));
+	exit;
+}
+
+llxHeader();
+print '<div class="error">'.$webcal->error.'</div>';
+llxFooter('$Date$ - $Revision$');
+
+?>