+
+
+
+
+
+
+
+
+ ';
+ echo $html_string;
+?>
diff --git a/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_components.php b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_components.php
new file mode 100644
index 00000000..3e6e7fcd
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_components.php
@@ -0,0 +1,628 @@
+construct();
+ }
+
+ function construct() {
+ // Initialize the components array
+ if(empty($this->components)) {
+ $this->components = array();
+ foreach($this->valid_components as $name) {
+ $this->components[$name] = array();
+ }
+ }
+ }
+
+ function get_name() {
+ return $this->name;
+ }
+
+ function add_property($name, $value = NULL, $parameters = NULL) {
+
+ // Uppercase first of all
+ $name = strtoupper($name);
+ // Are we trying to add a valid property?
+ $xname = false;
+ if(!isset($this->valid_properties[$name])) {
+ // If not, is it an x-name as per RFC 2445?
+ if(!rfc2445_is_xname($name)) {
+ return false;
+ }
+ // Since this is an xname, all components are supposed to allow this property
+ $xname = true;
+ }
+
+ // Create a property object of the correct class
+ if($xname) {
+ $property = new iCalendar_property_x;
+ $property->set_name($name);
+ }
+ else {
+ $classname = 'iCalendar_property_'.strtolower(str_replace('-', '_', $name));
+ $property = new $classname;
+ }
+ // If $value is NULL, then this property must define a default value.
+ if($value === NULL) {
+ $value = $property->default_value();
+ if($value === NULL) {
+ return false;
+ }
+ }
+
+ // Set this property's parent component to ourselves, because some
+ // properties behave differently according to what component they apply to.
+ $property->set_parent_component($this->name);
+
+ // Set parameters before value; this helps with some properties which
+ // accept a VALUE parameter, and thus change their default value type.
+
+ // The parameters must be valid according to property specifications
+ if(!empty($parameters)) {
+ foreach($parameters as $paramname => $paramvalue) {
+ if(!$property->set_parameter($paramname, $paramvalue)) {
+ return false;
+ }
+ }
+
+ // Some parameters interact among themselves (e.g. ENCODING and VALUE)
+ // so make sure that after the dust settles, these invariants hold true
+ if(!$property->invariant_holds()) {
+ return false;
+ }
+ }
+
+ // $value MUST be valid according to the property data type
+ if(!$property->set_value($value)) {
+ return false;
+ }
+
+ // If this property is restricted to only once, blindly overwrite value
+ if(!$xname && $this->valid_properties[$name] & RFC2445_ONCE) {
+ $this->properties[$name] = array($property);
+ }
+
+ // Otherwise add it to the instance array for this property
+ else {
+ $this->properties[$name][] = $property;
+ }
+
+ // Finally: after all these, does the component invariant hold?
+ if(!$this->invariant_holds()) {
+ // If not, completely undo the property addition
+ array_pop($this->properties[$name]);
+ if(empty($this->properties[$name])) {
+ unset($this->properties[$name]);
+ }
+ return false;
+ }
+
+ return true;
+
+ }
+
+ function add_component($component) {
+
+ // With the detailed interface, you can add only components with this function
+ if(!is_object($component) || !is_subclass_of($component, 'iCalendar_component')) {
+ return false;
+ }
+
+ $name = $component->get_name();
+
+ // Only valid components as specified by this component are allowed
+ if(!in_array($name, $this->valid_components)) {
+ return false;
+ }
+
+ // Add it
+ $this->components[$name][] = $component;
+
+ return true;
+ }
+
+ function get_property_list($name) {
+ }
+
+ function invariant_holds() {
+ return true;
+ }
+
+ function is_valid() {
+ // If we have any child components, check that they are all valid
+ if(!empty($this->components)) {
+ foreach($this->components as $component => $instances) {
+ foreach($instances as $number => $instance) {
+ if(!$instance->is_valid()) {
+ return false;
+ }
+ }
+ }
+ }
+ // Finally, check the valid property list for any mandatory properties
+ // that have not been set and do not have a default value
+ foreach($this->valid_properties as $property => $propdata) {
+ if(($propdata & RFC2445_REQUIRED) && empty($this->properties[$property])) {
+ $classname = 'iCalendar_property_'.strtolower(str_replace('-', '_', $property));
+ $object = new $classname;
+ if($object->default_value() === NULL) {
+ return false;
+ }
+ unset($object);
+ }
+ }
+
+ return true;
+ }
+
+ function serialize() {
+ // Check for validity of the object
+ if(!$this->is_valid()) {
+ return false;
+ }
+
+ // Maybe the object is valid, but there are some required properties that
+ // have not been given explicit values. In that case, set them to defaults.
+ foreach($this->valid_properties as $property => $propdata) {
+ if(($propdata & RFC2445_REQUIRED) && empty($this->properties[$property])) {
+ $this->add_property($property);
+ }
+ }
+
+ // Start tag
+ $string = rfc2445_fold('BEGIN:'.$this->name) . RFC2445_CRLF;
+ // List of properties
+ if(!empty($this->properties)) {
+ foreach($this->properties as $name => $properties) {
+ foreach($properties as $property) {
+ $string .= $property->serialize();
+ }
+ }
+ }
+ // List of components
+ if(!empty($this->components)) {
+ foreach($this->components as $name => $components) {
+ foreach($components as $component) {
+ $string .= $component->serialize();
+ }
+ }
+ }
+
+ // End tag
+ $string .= rfc2445_fold('END:'.$this->name) . RFC2445_CRLF;
+
+ return $string;
+ }
+
+ function assign_values($activity) {
+ foreach($this->mapping_arr as $key=>$components){
+ if(!is_array($components['component']) && empty($components['function'])){
+ $this->add_property($key,$activity[$components['component']]);
+ } else if(is_array($components['component']) && empty($components['function'])){
+ $component = '';
+ foreach($components['component'] as $comp){
+ if(!empty($component)) $component .= ',';
+ $component .= $activity[$comp];
+ }
+ $this->add_property($key,$component);
+ } else if(!empty($components['function'])){
+ $this->$components['function']($activity);
+ }
+ }
+ return true;
+ }
+
+ function generateArray($ical_activity){
+ global $current_user;
+ $activity = array();
+ $activitytype = $ical_activity['TYPE'];
+ if($activitytype=='VEVENT'){
+ $modtype = 'Events';
+ } else {
+ $modtype = 'Calendar';
+ }
+ foreach($this->mapping_arr as $key=>$comp){
+ $type = $comp['type'];
+ $component = $comp['component'];
+ if(!is_array($component)){
+ if($type!='user'){
+ if(isset($this->field_mapping_arr[$component])){
+ if(getFieldVisibilityPermission($modtype,$current_user->id,$this->field_mapping_arr[$component])=='0')
+ $activity[$this->field_mapping_arr[$component]] = $ical_activity[$key];
+ else
+ $activity[$this->field_mapping_arr[$component]] = '';
+ } else {
+ if(getFieldVisibilityPermission($modtype,$current_user->id,$component)=='0')
+ $activity[$component] = $ical_activity[$key];
+ else
+ $activity[$component] = '';
+ }
+ }
+ } else {
+ $temp = $ical_activity[$key];
+ $count = 0;
+ if($type == 'string'){
+ $values = explode('\\,',$temp);
+ } else if($type == 'datetime'){
+ $values = $this->strtodatetime($temp);
+ }
+ foreach($component as $index){
+ if(!isset($activity[$index])){
+ if(isset($this->field_mapping_arr[$index])){
+ if(getFieldVisibilityPermission($modtype,$current_user->id,$this->field_mapping_arr[$index])=='0')
+ $activity[$this->field_mapping_arr[$index]] = $values[$count];
+ else
+ $activity[$this->field_mapping_arr[$index]] = '';
+ } else {
+ if(getFieldVisibilityPermission($modtype,$current_user->id,$index)=='0')
+ $activity[$index] = $values[$count];
+ else
+ $activity[$index] = '';
+ }
+ }
+ $count++;
+ }
+ unset($values);
+ }
+ }
+ if($activitytype=='VEVENT'){
+ $activity['activitytype'] = 'Meeting';
+ if(!empty($ical_activity['VALARM'])){
+ $temp = str_replace("PT",'',$ical_activity['VALARM']['TRIGGER']);
+ $duration_type = $temp[strlen($temp)-1];
+ $duration = intval($temp);
+ if($duration_type=='H'){
+ $reminder_time = $duration*60;
+ } else if($duration_type=='M'){
+ $reminder_time = $duration;
+ }
+ $activity['reminder_time'] = $reminder_time;
+ }
+ } else {
+ $activity['activitytype'] = 'Task';
+ }
+ return $activity;
+ }
+
+ function strtodatetime($date){
+ $date = preg_replace('/[A-Za-z_]*/', '', $date);
+ $year = substr($date,0,4);
+ $month = substr($date,4,2);
+ $day = substr($date,6,2);
+ $hours = substr($date,8,2);
+ $minutes = substr($date,10,2);
+ $seconds = substr($date,12,2);
+ $datetime[] = $year."-".$month."-".$day;
+ $datetime[] = $hours.":".$minutes.":".$seconds;
+ return $datetime;
+ }
+}
+
+class iCalendar extends iCalendar_component {
+ var $name = 'VCALENDAR';
+
+ function construct() {
+ $this->valid_properties = array(
+ 'CALSCALE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'METHOD' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'PRODID' => RFC2445_REQUIRED | RFC2445_ONCE,
+ 'VERSION' => RFC2445_REQUIRED | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+
+ $this->valid_components = array(
+ 'VEVENT', 'VTODO', 'VTIMEZONE'
+ // TODO: add support for the other component types
+ //, 'VJOURNAL', 'VFREEBUSY', 'VALARM'
+ );
+ parent::construct();
+ }
+
+}
+
+class iCalendar_event extends iCalendar_component {
+
+ var $name = 'VEVENT';
+ var $properties;
+ var $mapping_arr = array(
+ 'CLASS' => array('component'=>'visibility','type'=>'string'),
+ 'DESCRIPTION' => array('component'=>'description','type'=>'string'),
+ 'DTSTART' => array('component'=>array('date_start','time_start'),'function'=>'iCalendar_event_dtstart','type'=>'datetime'),
+ 'DTEND' => array('component'=>array('due_date','time_end'),'function'=>'iCalendar_event_dtend','type'=>'datetime'),
+ 'DTSTAMP' => array('component'=>array('date_start','time_start'),'function'=>'iCalendar_event_dtstamp','type'=>'datetime'),
+ 'LOCATION' => array('component'=>'location','type'=>'string'),
+ 'STATUS' => array('component'=>'eventstatus','type'=>'string'),
+ 'SUMMARY' => array('component'=>'subject','type'=>'string'),
+ 'PRIORITY' => array('component'=>'priority','type'=>'string'),
+ 'ATTENDEE' => array('component'=>'activityid','function'=>'iCalendar_event_attendee','type'=>'user'),
+ 'RESOURCES' => array('component'=>array('location','eventstatus'),'type'=>'string'),
+ );
+ var $field_mapping_arr = array(
+ 'priority'=>'taskpriority'
+ );
+
+ function construct() {
+
+ $this->valid_components = array('VALARM');
+
+ $this->valid_properties = array(
+ 'CLASS' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'CREATED' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DESCRIPTION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ // Standard ambiguous here: in 4.6.1 it says that DTSTAMP in optional,
+ // while in 4.8.7.2 it says it's REQUIRED. Go with REQUIRED.
+ 'DTSTAMP' => RFC2445_REQUIRED | RFC2445_ONCE,
+ // Standard ambiguous here: in 4.6.1 it says that DTSTART in optional,
+ // while in 4.8.2.4 it says it's REQUIRED. Go with REQUIRED.
+ 'DTSTART' => RFC2445_REQUIRED | RFC2445_ONCE,
+ 'GEO' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LAST-MODIFIED' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LOCATION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'ORGANIZER' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'PRIORITY' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'SEQUENCE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'STATUS' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'SUMMARY' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'TRANSP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ // Standard ambiguous here: in 4.6.1 it says that UID in optional,
+ // while in 4.8.4.7 it says it's REQUIRED. Go with REQUIRED.
+ 'UID' => RFC2445_REQUIRED | RFC2445_ONCE,
+ 'URL' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'RECURRENCE-ID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DTEND' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DURATION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'ATTACH' => RFC2445_OPTIONAL,
+ 'ATTENDEE' => RFC2445_OPTIONAL,
+ 'CATEGORIES' => RFC2445_OPTIONAL,
+ 'COMMENT' => RFC2445_OPTIONAL,
+ 'CONTACT' => RFC2445_OPTIONAL,
+ 'EXDATE' => RFC2445_OPTIONAL,
+ 'EXRULE' => RFC2445_OPTIONAL,
+ 'REQUEST-STATUS' => RFC2445_OPTIONAL,
+ 'RELATED-TO' => RFC2445_OPTIONAL,
+ 'RESOURCES' => RFC2445_OPTIONAL,
+ 'RDATE' => RFC2445_OPTIONAL,
+ 'RRULE' => RFC2445_OPTIONAL,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+
+ parent::construct();
+ }
+
+ function invariant_holds() {
+ // DTEND and DURATION must not appear together
+ if(isset($this->properties['DTEND']) && isset($this->properties['DURATION'])) {
+ return false;
+ }
+
+
+ if(isset($this->properties['DTEND']) && isset($this->properties['DTSTART'])) {
+ // DTEND must be later than DTSTART
+ // The standard is not clear on how to hande different value types though
+ // TODO: handle this correctly even if the value types are different
+ if($this->properties['DTEND'][0]->value <= $this->properties['DTSTART'][0]->value) {
+ return false;
+ }
+
+ // DTEND and DTSTART must have the same value type
+ if($this->properties['DTEND'][0]->val_type != $this->properties['DTSTART'][0]->val_type) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ function iCalendar_event_dtstamp($activity){
+ $components = gmdate('Ymd', strtotime($activity['date_start']." ".$activity['time_start']))."T".gmdate('His', strtotime($activity['date_start']." ".$activity['time_start']))."Z";
+ $this->add_property("DTSTAMP",$components);
+ return true;
+ }
+
+ function iCalendar_event_dtstart($activity){
+ $time = str_replace(':','',$activity['time_start']);
+ if(strlen($time)<6){
+ while((6-strlen($time)) > 0 ){
+ $time .= '0';
+ }
+ }
+ $components = str_replace('-', '', $activity['date_start']).'T'. $time . 'Z';
+ $this->add_property("DTSTART",$components);
+ return true;
+ }
+
+ function iCalendar_event_dtend($activity){
+ $time = str_replace(':','',$activity['time_end']);
+ if(strlen($time)<6){
+ while((6-strlen($time)) > 0 ){
+ $time .= '0';
+ }
+ }
+ $components = str_replace('-', '', $activity['due_date']).'T'. $time . 'Z';
+ $this->add_property("DTEND",$components);
+ return true;
+ }
+
+ function iCalendar_event_attendee($activity){
+ global $adb;
+ $users_res = $adb->pquery("SELECT inviteeid FROM vtiger_invitees WHERE activityid=?", array($activity['id']));
+ if($adb->num_rows($users_res)>0){
+ for($i=0;$i<$adb->num_rows($users_res);$i++){
+ $inviteeid = $adb->query_result($users_res,$i,'inviteeid');
+ $username = getUserFullName($inviteeid);
+ $user_email = getUserEmail($inviteeid);
+ $attendee = 'mailto:'.$user_email;
+ $this->add_property('ATTENDEE',$attendee);
+ }
+ }
+ return true;
+ }
+
+}
+
+class iCalendar_todo extends iCalendar_component {
+ var $name = 'VTODO';
+ var $properties;
+ var $mapping_arr = array(
+ 'DESCRIPTION' => array('component'=>'description','type'=>'string'),
+ 'DTSTAMP' => array('component'=>array('date_start','time_start'),'function'=>'iCalendar_event_dtstamp','type'=>'datetime'),
+ 'DTSTART' => array('component'=>array('date_start','time_start'),'function'=>'iCalendar_event_dtstart','type'=>'datetime'),
+ 'DUE' => array('component'=>array('due_date'),'function'=>'iCalendar_event_dtend','type'=>'datetime'),
+ 'STATUS' => array('component'=>'status','type'=>'string'),
+ 'SUMMARY' => array('component'=>'subject','type'=>'string'),
+ 'PRIORITY' => array('component'=>'priority','type'=>'string'),
+ 'RESOURCES' => array('component'=>array('status'),'type'=>'string'),
+ );
+ var $field_mapping_arr = array(
+ 'status'=>'taskstatus',
+ 'priority'=>'taskpriority'
+ );
+
+ function construct() {
+
+ $this->valid_components = array();
+ $this->valid_properties = array(
+ 'CLASS' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'COMPLETED' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'CREATED' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DESCRIPTION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DTSTAMP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DTSTART' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'GEO' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LAST-MODIFIED' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LOCATION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'ORGANIZER' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'PERCENT' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'PRIORITY' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'RECURID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'SEQUENCE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'STATUS' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'SUMMARY' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'UID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'URL' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DURATION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'ATTACH' => RFC2445_OPTIONAL,
+ 'ATTENDEE' => RFC2445_OPTIONAL,
+ 'CATEGORIES' => RFC2445_OPTIONAL,
+ 'COMMENT' => RFC2445_OPTIONAL,
+ 'CONTACT' => RFC2445_OPTIONAL,
+ 'EXDATE' => RFC2445_OPTIONAL,
+ 'EXRULE' => RFC2445_OPTIONAL,
+ 'RSTATUS' => RFC2445_OPTIONAL,
+ 'RELATED' => RFC2445_OPTIONAL,
+ 'RESOURCES' => RFC2445_OPTIONAL,
+ 'RDATE' => RFC2445_OPTIONAL,
+ 'RRULE' => RFC2445_OPTIONAL,
+ 'XPROP' => RFC2445_OPTIONAL
+ );
+
+ parent::construct();
+ // TODO:
+ // either 'due' or 'duration' may appear in a 'eventprop', but 'due'
+ // and 'duration' MUST NOT occur in the same 'eventprop'
+ }
+ function iCalendar_event_dtstamp($activity){
+ $components = gmdate('Ymd', strtotime($activity['date_start']." ".$activity['time_start']))."T".gmdate('His', strtotime($activity['date_start']." ".$activity['time_start']))."Z";
+ $this->add_property("DTSTAMP",$components);
+ return true;
+ }
+
+ function iCalendar_event_dtstart($activity){
+ $time = str_replace(':','',$activity['time_start']);
+ if(strlen($time)<6){
+ while((6-strlen($time)) > 0 ){
+ $time .= '0';
+ }
+ }
+ $components = str_replace('-', '', $activity['date_start']).'T'. $time . 'Z';
+ $this->add_property("DTSTART",$components);
+ return true;
+ }
+
+ function iCalendar_event_dtend($activity){
+ $components = str_replace('-', '', $activity['due_date']).'T000000Z';
+ $this->add_property("DUE",$components);
+ return true;
+ }
+}
+
+class iCalendar_journal extends iCalendar_component {
+ // TODO: implement
+}
+
+class iCalendar_freebusy extends iCalendar_component {
+ // TODO: implement
+}
+
+class iCalendar_alarm extends iCalendar_component {
+ var $name='VALARM';
+ var $properties;
+ var $mapping_arr = array(
+ 'TRIGGER' => array('component'=>'reminder_time', 'function'=>'iCalendar_event_trigger'),
+ );
+
+ function construct() {
+
+ $this->valid_components = array();
+ $this->valid_properties = array(
+ 'TRIGGER' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DESCRIPTION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'ACTION' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'X-WR-ALARMUID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+
+ parent::construct();
+ }
+
+ function iCalendar_event_trigger($activity){
+ $reminder_time = $activity['reminder_time'];
+ if($reminder_time>60){
+ $reminder_time = round($reminder_time/60);
+ $reminder = $reminder_time.'H';
+ }else {
+ $reminder = $reminder_time.'M';
+ }
+ $this->add_property('ACTION', 'DISPLAY');
+ $this->add_property('TRIGGER', 'PT'.$reminder);
+ $this->add_property('DESCRIPTION', 'Reminder');
+ return true;
+ }
+}
+
+class iCalendar_timezone extends iCalendar_component {
+ var $name = 'VTIMEZONE';
+ var $properties;
+
+ function construct() {
+ $this->valid_components = array();
+ $this->valid_properties = array(
+ 'TZID' => RFC2445_REQUIRED | RFC2445_ONCE,
+ 'LAST-MODIFIED' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'TZURL' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ // TODO: the next two are components of their own!
+ 'STANDARDC' => RFC2445_OPTIONAL,
+ 'DAYLIGHTC' => RFC2445_OPTIONAL,
+ 'TZOFFSETFROM' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'TZOFFSETTO' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'X-PROP' => RFC2445_OPTIONAL
+ );
+
+ parent::construct();
+ }
+
+}
+
+// REMINDER: DTEND must be later than DTSTART for all components which support both
+// REMINDER: DUE must be later than DTSTART for all components which support both
+
+?>
diff --git a/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_parameters.php b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_parameters.php
new file mode 100644
index 00000000..1b029c9c
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_parameters.php
@@ -0,0 +1,227 @@
+ array('PLAIN', 'RICHTEXT', 'ENRICHED', 'TAB-SEPARATED-VALUES', 'HTML', 'SGML',
+ 'VND.LATEX-Z', 'VND.FMI.FLEXSTOR'),
+ 'MULTIPART' => array('MIXED', 'ALTERNATIVE', 'DIGEST', 'PARALLEL', 'APPLEDOUBLE', 'HEADER-SET',
+ 'FORM-DATA', 'RELATED', 'REPORT', 'VOICE-MESSAGE', 'SIGNED', 'ENCRYPTED',
+ 'BYTERANGES'),
+ 'MESSAGE' => array('RFC822', 'PARTIAL', 'EXTERNAL-BODY', 'NEWS', 'HTTP'),
+ 'APPLICATION' => array('OCTET-STREAM', 'POSTSCRIPT', 'ODA', 'ATOMICMAIL', 'ANDREW-INSET', 'SLATE',
+ 'WITA', 'DEC-DX', 'DCA-RFT', 'ACTIVEMESSAGE', 'RTF', 'APPLEFILE',
+ 'MAC-BINHEX40', 'NEWS-MESSAGE-ID', 'NEWS-TRANSMISSION', 'WORDPERFECT5.1',
+ 'PDF', 'ZIP', 'MACWRITEII', 'MSWORD', 'REMOTE-PRINTING', 'MATHEMATICA',
+ 'CYBERCASH', 'COMMONGROUND', 'IGES', 'RISCOS', 'ESHOP', 'X400-BP', 'SGML',
+ 'CALS-1840', 'PGP-ENCRYPTED', 'PGP-SIGNATURE', 'PGP-KEYS', 'VND.FRAMEMAKER',
+ 'VND.MIF', 'VND.MS-EXCEL', 'VND.MS-POWERPOINT', 'VND.MS-PROJECT',
+ 'VND.MS-WORKS', 'VND.MS-TNEF', 'VND.SVD', 'VND.MUSIC-NIFF', 'VND.MS-ARTGALRY',
+ 'VND.TRUEDOC', 'VND.KOAN', 'VND.STREET-STREAM', 'VND.FDF',
+ 'SET-PAYMENT-INITIATION', 'SET-PAYMENT', 'SET-REGISTRATION-INITIATION',
+ 'SET-REGISTRATION', 'VND.SEEMAIL', 'VND.BUSINESSOBJECTS',
+ 'VND.MERIDIAN-SLINGSHOT', 'VND.XARA', 'SGML-OPEN-CATALOG', 'VND.RAPID',
+ 'VND.ENLIVEN', 'VND.JAPANNET-REGISTRATION-WAKEUP',
+ 'VND.JAPANNET-VERIFICATION-WAKEUP', 'VND.JAPANNET-PAYMENT-WAKEUP',
+ 'VND.JAPANNET-DIRECTORY-SERVICE', 'VND.INTERTRUST.DIGIBOX', 'VND.INTERTRUST.NNCP'),
+ 'IMAGE' => array('JPEG', 'GIF', 'IEF', 'G3FAX', 'TIFF', 'CGM', 'NAPLPS', 'VND.DWG', 'VND.SVF',
+ 'VND.DXF', 'PNG', 'VND.FPX', 'VND.NET-FPX'),
+ 'AUDIO' => array('BASIC', '32KADPCM', 'VND.QCELP'),
+ 'VIDEO' => array('MPEG', 'QUICKTIME', 'VND.VIVO', 'VND.MOTOROLA.VIDEO', 'VND.MOTOROLA.VIDEOP')
+ );
+ $value = strtoupper($value);
+ if(rfc2445_is_xname($value)) {
+ return true;
+ }
+ @list($type, $subtype) = explode('/', $value);
+ if(empty($type) || empty($subtype)) {
+ return false;
+ }
+ if(!isset($fmttypes[$type]) || !in_array($subtype, $fmttypes[$type])) {
+ return false;
+ }
+ return true;
+ break;
+
+ case 'LANGUAGE':
+ $value = strtoupper($value);
+ $parts = explode('-', $value);
+ foreach($parts as $part) {
+ if(empty($part)) {
+ return false;
+ }
+ if(strspn($part, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') != strlen($part)) {
+ return false;
+ }
+ }
+ return true;
+ break;
+
+ case 'PARTSTAT':
+ $value = strtoupper($value);
+ switch($parent_property->parent_component) {
+ case 'VEVENT':
+ return ($value == 'NEEDS-ACTION' || $value == 'ACCEPTED' || $value == 'DECLINED' || $value == 'TENTATIVE'
+ || $value == 'DELEGATED' || rfc2445_is_xname($value));
+ break;
+ case 'VTODO':
+ return ($value == 'NEEDS-ACTION' || $value == 'ACCEPTED' || $value == 'DECLINED' || $value == 'TENTATIVE'
+ || $value == 'DELEGATED' || $value == 'COMPLETED' || $value == 'IN-PROCESS' || rfc2445_is_xname($value));
+ break;
+ case 'VJOURNAL':
+ return ($value == 'NEEDS-ACTION' || $value == 'ACCEPTED' || $value == 'DECLINED' || rfc2445_is_xname($value));
+ break;
+ }
+ return false;
+ break;
+
+ case 'RANGE':
+ $value = strtoupper($value);
+ return ($value == 'THISANDPRIOR' || $value == 'THISANDFUTURE');
+ break;
+
+ case 'RELATED':
+ $value = strtoupper($value);
+ return ($value == 'START' || $value == 'END');
+ break;
+
+ case 'RELTYPE':
+ $value = strtoupper($value);
+ return ($value == 'PARENT' || $value == 'CHILD' || $value == 'SIBLING' || rfc2445_is_xname($value));
+ break;
+
+ case 'ROLE':
+ $value = strtoupper($value);
+ return ($value == 'CHAIR' || $value == 'REQ-PARTICIPANT' || $value == 'OPT-PARTICIPANT' || $value == 'NON-PARTICIPANT' || rfc2445_is_xname($value));
+ break;
+
+ case 'RSVP':
+ $value = strtoupper($value);
+ return ($value == 'TRUE' || $value == 'FALSE');
+ break;
+
+ case 'TZID':
+ if(empty($value)) {
+ return false;
+ }
+ return (strcspn($value, '";:,') == strlen($value));
+ break;
+
+ case 'VALUE':
+ $value = strtoupper($value);
+ return ($value == 'BINARY' || $value == 'BOOLEAN' || $value == 'CAL-ADDRESS' || $value == 'DATE' ||
+ $value == 'DATE-TIME' || $value == 'DURATION' || $value == 'FLOAT' || $value == 'INTEGER' ||
+ $value == 'PERIOD' || $value == 'RECUR' || $value == 'TEXT' || $value == 'TIME' ||
+ $value == 'URI' || $value == 'UTC-OFFSET' || rfc2445_is_xname($value));
+ break;
+ }
+ }
+
+ function do_value_formatting($parameter, $value) {
+ switch($parameter) {
+ // Parameters of type CAL-ADDRESS or URI MUST be double-quoted
+ case 'ALTREP':
+ case 'DIR':
+ case 'DELEGATED-FROM':
+ case 'DELEGATED-TO':
+ case 'MEMBER':
+ case 'SENT-BY':
+ return '"'.$value.'"';
+ break;
+
+ // Textual parameter types must be double quoted if they contain COLON, SEMICOLON
+ // or COMMA. Quoting always sounds easier and standards-conformant though.
+ case 'CN':
+ return '"'.$value.'"';
+ break;
+
+ // Parameters with enumerated legal values, just make them all caps
+ case 'CUTYPE':
+ case 'ENCODING':
+ case 'FBTYPE':
+ case 'FMTTYPE':
+ case 'LANGUAGE':
+ case 'PARTSTAT':
+ case 'RANGE':
+ case 'RELATED':
+ case 'RELTYPE':
+ case 'ROLE':
+ case 'RSVP':
+ case 'VALUE':
+ return strtoupper($value);
+ break;
+
+ // Parameters we shouldn't be messing with
+ case 'TZID':
+ return $value;
+ break;
+ }
+ }
+
+ function undo_value_formatting($parameter, $value) {
+ }
+
+}
+
+?>
diff --git a/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_properties.php b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_properties.php
new file mode 100644
index 00000000..2c373e0a
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_properties.php
@@ -0,0 +1,1367 @@
+construct();
+ }
+
+ function construct() {
+ $this->parameters = array();
+ }
+
+ // If some property needs extra care with its parameters, override this
+ // IMPORTANT: the parameter name MUST BE CAPITALIZED!
+ function is_valid_parameter($parameter, $value) {
+
+ if(is_array($value)) {
+ if(!iCalendar_parameter::multiple_values_allowed($parameter)) {
+ return false;
+ }
+ foreach($value as $item) {
+ if(!iCalendar_parameter::is_valid_value($this, $parameter, $item)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return iCalendar_parameter::is_valid_value($this, $parameter, $value);
+ }
+
+ function invariant_holds() {
+ return true;
+ }
+
+ // If some property is very picky about its values, it should do the work itself
+ // Only data type validation is done here
+ function is_valid_value($value) {
+ if(is_array($value)) {
+ if(!$this->val_multi) {
+ return false;
+ }
+ else {
+ foreach($value as $oneval) {
+ if(!rfc2445_is_valid_value($oneval, $this->val_type)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return rfc2445_is_valid_value($value, $this->val_type);
+ }
+
+ function default_value() {
+ return $this->val_default;
+ }
+
+ function set_parent_component($componentname) {
+ if(class_exists('iCalendar_'.strtolower(substr($componentname, 1)))) {
+ $this->parent_component = strtoupper($componentname);
+ return true;
+ }
+
+ return false;
+ }
+
+ function set_value($value) {
+ if($this->is_valid_value($value)) {
+ // This transparently formats any value type according to the iCalendar specs
+ if(is_array($value)) {
+ foreach($value as $key => $item) {
+ $value[$key] = rfc2445_do_value_formatting($item, $this->val_type);
+ }
+ $this->value = implode(',', $value);
+ }
+ else {
+ $this->value = rfc2445_do_value_formatting($value, $this->val_type);
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ function get_value() {
+ // First of all, assume that we have multiple values
+ $valarray = explode('\\,', $this->value);
+
+ // Undo transparent formatting
+ $replace_function = create_function('$a', 'return rfc2445_undo_value_formatting($a, '.$this->val_type.');');
+ $valarray = array_map($replace_function, $valarray);
+
+ // Now, if this property cannot have multiple values, don't return as an array
+ if(!$this->val_multi) {
+ return $valarray[0];
+ }
+
+ // Otherwise return an array even if it has one element, for uniformity
+ return $valarray;
+
+ }
+
+ function set_parameter($name, $value) {
+
+ // Uppercase
+ $name = strtoupper($name);
+
+ // Are we trying to add a valid parameter?
+ $xname = false;
+ if(!isset($this->valid_parameters[$name])) {
+ // If not, is it an x-name as per RFC 2445?
+ if(!rfc2445_is_xname($name)) {
+ return false;
+ }
+ // No more checks -- all components are supposed to allow x-name parameters
+ $xname = true;
+ }
+
+ if(!$this->is_valid_parameter($name, $value)) {
+ return false;
+ }
+
+ if(is_array($value)) {
+ foreach($value as $key => $element) {
+ $value[$key] = iCalendar_parameter::do_value_formatting($name, $element);
+ }
+ }
+ else {
+ $value = iCalendar_parameter::do_value_formatting($name, $value);
+ }
+
+ $this->parameters[$name] = $value;
+
+ // Special case: if we just changed the VALUE parameter, reflect this
+ // in the object's status so that it only accepts correct type values
+ if($name == 'VALUE') {
+ // TODO: what if this invalidates an already-set value?
+ $this->val_type = constant('RFC2445_TYPE_'.str_replace('-', '_', $value));
+ }
+
+ return true;
+
+ }
+
+ function get_parameter($name) {
+
+ // Uppercase
+ $name = strtoupper($name);
+
+ if(isset($this->parameters[$name])) {
+ // If there are any double quotes in the value, invisibly strip them
+ if(is_array($this->parameters[$name])) {
+ foreach($this->parameters[$name] as $key => $value) {
+ if(substr($value, 0, 1) == '"') {
+ $this->parameters[$name][$key] = substr($value, 1, strlen($value) - 2);
+ }
+ }
+ return $this->parameters[$name];
+ }
+
+ else {
+ if(substr($this->parameters[$name], 0, 1) == '"') {
+ return substr($this->parameters[$name], 1, strlen($this->parameters[$name]) - 2);
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ function serialize() {
+ $string = $this->name;
+
+ if(!empty($this->parameters)) {
+ foreach($this->parameters as $name => $value) {
+ $string .= ';'.$name.'=';
+ if(is_array($value)) {
+ $string .= implode(',', $value);
+ }
+ else {
+ $string .= $value;
+ }
+ }
+ }
+
+ $string .= ':'.$this->value;
+
+ return rfc2445_fold($string) . RFC2445_CRLF;
+ }
+}
+
+// 4.7 Calendar Properties
+// -----------------------
+
+class iCalendar_property_calscale extends iCalendar_property {
+
+ var $name = 'CALSCALE';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ // This is case-sensitive
+ return ($value === 'GREGORIAN');
+ }
+}
+
+class iCalendar_property_method extends iCalendar_property {
+
+ var $name = 'METHOD';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ // This is case-sensitive
+ // Methods from RFC 2446
+ $methods == array('PUBLISH', 'REQUEST', 'REPLY', 'ADD', 'CANCEL', 'REFRESH', 'COUNTER', 'DECLINECOUNTER');
+ return in_array($value, $methods);
+ }
+}
+
+class iCalendar_property_prodid extends iCalendar_property {
+
+ var $name = 'PRODID';
+ var $val_type = RFC2445_TYPE_TEXT;
+ var $val_default = NULL;
+
+ function construct() {
+ $this->val_default = '-//John Papaioannou/NONSGML Bennu '._BENNU_VERSION.'//EN';
+
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_version extends iCalendar_property {
+
+ var $name = 'VERSION';
+ var $val_type = RFC2445_TYPE_TEXT;
+ var $val_default = '2.0';
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ return($value === '2.0' || $value === 2.0);
+ }
+
+}
+
+// 4.8.1 Descriptive Component Properties
+// --------------------------------------
+
+class iCalendar_property_attach extends iCalendar_property {
+
+ var $name = 'ATTACH';
+ var $val_type = RFC2445_TYPE_URI;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'FMTTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'ENCODING' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function invariant_holds() {
+ if(isset($this->parameters['ENCODING']) && !isset($this->parameters['VALUE'])) {
+ return false;
+ }
+ if(isset($this->parameters['VALUE']) && !isset($this->parameters['ENCODING'])) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function is_valid_parameter($parameter, $value) {
+
+ $parameter = strtoupper($parameter);
+
+ if(!parent::is_valid_parameter($parameter, $value)) {
+ return false;
+ }
+
+ if($parameter === 'ENCODING' && strtoupper($value) != 'BASE64') {
+ return false;
+ }
+
+ if($parameter === 'VALUE' && strtoupper($value) != 'BINARY') {
+ return false;
+ }
+
+ return true;
+ }
+}
+
+class iCalendar_property_categories extends iCalendar_property {
+
+ var $name = 'CATEGORIES';
+ var $val_type = RFC2445_TYPE_TEXT;
+ var $val_multi = true;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_class extends iCalendar_property {
+
+ var $name = 'CLASS';
+ var $val_type = RFC2445_TYPE_TEXT;
+ var $val_default = 'PUBLIC';
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+ function is_valid_value($value) {
+ $value = strtoupper($value);
+ // If this is not an xname, it is case-sensitive
+ return ($value === 'PUBLIC' || $value === 'PRIVATE' || $value === 'CONFIDENTIAL' || rfc2445_is_xname(strtoupper($value)));
+ }
+}
+
+class iCalendar_property_comment extends iCalendar_property {
+
+ var $name = 'COMMENT';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_description extends iCalendar_property {
+
+ var $name = 'DESCRIPTION';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_geo extends iCalendar_property {
+
+ var $name = 'GEO';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ // This MUST be two floats separated by a semicolon
+ if(!is_string($value)) {
+ return false;
+ }
+
+ $floats = explode(';', $value);
+ if(count($floats) != 2) {
+ return false;
+ }
+
+ return rfc2445_is_valid_value($floats[0], RFC2445_TYPE_FLOAT) && rfc2445_is_valid_value($floats[1], RFC2445_TYPE_FLOAT);
+ }
+
+ function set_value($value) {
+ // Must override this, otherwise the semicolon separating
+ // the two floats would get auto-quoted, which is illegal
+ if($this->is_valid_value($value)) {
+ $this->value = $value;
+ return true;
+ }
+
+ return false;
+ }
+
+}
+
+class iCalendar_property_location extends iCalendar_property {
+
+ var $name = 'LOCATION';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_percent_complete extends iCalendar_property {
+
+ var $name = 'PERCENT-COMPLETE';
+ var $val_type = RFC2445_TYPE_INTEGER;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ // Only integers between 0 and 100 inclusive allowed
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ $value = intval($value);
+ return ($value >= 0 && $value <= 100);
+ }
+
+}
+
+class iCalendar_property_priority extends iCalendar_property {
+
+ var $name = 'PRIORITY';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ // Only integers between 0 and 9 inclusive allowed
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ return true;
+ //$value = intval($value);
+ //return ($value >= 0 && $value <= 9);
+ }
+}
+
+class iCalendar_property_resources extends iCalendar_property {
+
+ var $name = 'RESOURCES';
+ var $val_type = RFC2445_TYPE_TEXT;
+ var $val_multi = true;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_status extends iCalendar_property {
+
+ var $name = 'STATUS';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+/* function is_valid_value($value) {
+ // This is case-sensitive
+ switch ($this->parent_component) {
+ case 'VEVENT':
+ $allowed = array('TENTATIVE', 'CONFIRMED', 'CANCELLED');
+ break;
+ case 'VTODO':
+ $allowed = array('NEEDS-ACTION', 'COMPLETED', 'IN-PROCESS', 'CANCELLED');
+ break;
+ case 'VJOURNAL':
+ $allowed = array('DRAFT', 'FINAL', 'CANCELLED');
+ break;
+ }
+ return in_array($value, $allowed);
+
+ }
+*/
+}
+
+class iCalendar_property_summary extends iCalendar_property {
+
+ var $name = 'SUMMARY';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+// 4.8.2 Date and Time Component Properties
+// ----------------------------------------
+
+class iCalendar_property_completed extends iCalendar_property {
+
+ var $name = 'COMPLETED';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ // Time MUST be in UTC format
+ return(substr($value, -1) == 'Z');
+ }
+}
+
+class iCalendar_property_dtend extends iCalendar_property {
+
+ var $name = 'DTEND';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+
+ // If present in a FREEBUSY component, must be in UTC format
+ if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ function is_valid_parameter($parameter, $value) {
+
+ $parameter = strtoupper($parameter);
+
+ if(!parent::is_valid_parameter($parameter, $value)) {
+ return false;
+ }
+ if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) {
+ return false;
+ }
+
+ return true;
+ }
+}
+
+class iCalendar_property_due extends iCalendar_property {
+
+ var $name = 'DUE';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+
+ // If present in a FREEBUSY component, must be in UTC format
+ if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ function is_valid_parameter($parameter, $value) {
+
+ $parameter = strtoupper($parameter);
+
+ if(!parent::is_valid_parameter($parameter, $value)) {
+ return false;
+ }
+ if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) {
+ return false;
+ }
+
+ return true;
+ }
+}
+
+class iCalendar_property_dtstart extends iCalendar_property {
+
+ var $name = 'DTSTART';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ // TODO: unimplemented stuff when parent is a VTIMEZONE component
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ // If present in a FREEBUSY component, must be in UTC format
+ if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') {
+ return false;
+ }
+
+ return true;
+ }
+
+ function is_valid_parameter($parameter, $value) {
+ $parameter = strtoupper($parameter);
+
+ if(!parent::is_valid_parameter($parameter, $value)) {
+ return false;
+ }
+ if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) {
+ return false;
+ }
+
+ return true;
+ }
+}
+
+class iCalendar_property_duration extends iCalendar_property {
+
+ var $name = 'DURATION';
+ var $val_type = RFC2445_TYPE_DURATION;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+
+ // Value must be positive
+ return ($value{0} != '-');
+ }
+}
+
+class iCalendar_property_freebusy extends iCalendar_property {
+
+ var $name = 'FREEBUSY';
+ var $val_type = RFC2445_TYPE_PERIOD;
+ var $val_multi = true;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'FBTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+
+ $pos = strpos($value, '/'); // We know there's only one / in there
+ if($value{$pos - 1} != 'Z') {
+ // Start time MUST be in UTC
+ return false;
+ }
+ if($value{$pos + 1} != 'P' && $substr($value, -1) != 'Z') {
+ // If the second part is not a period, it MUST be in UTC
+ return false;
+ }
+
+ return true;
+ }
+
+ // TODO: these properties SHOULD be shorted in ascending order (by start time and end time as tiebreak)
+}
+
+class iCalendar_property_transp extends iCalendar_property {
+
+ var $name = 'TRANSP';
+ var $val_type = RFC2445_TYPE_TEXT;
+ var $val_default = 'OPAQUE';
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ return ($value === 'TRANSPARENT' || $value === 'OPAQUE');
+ }
+}
+
+// TODO: 4.8.3 timezone component properties
+
+
+// 4.8.4 Relationship Component Properties
+// ---------------------------------------
+
+class iCalendar_property_attendee extends iCalendar_property {
+
+ var $name = 'ATTENDEE';
+ var $val_type = RFC2445_TYPE_CAL_ADDRESS;
+
+ // TODO: MUST NOT be specified when the calendar object has METHOD=PUBLISH
+ // TODO: standard has lots of detail here, make triple sure that we eventually conform
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'CN' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'ROLE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'PARTSTAT' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'RSVP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'CUTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'MEMBER' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DELEGATED-TO' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DELEGATED-FROM' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'SENT-BY' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DIR' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function set_parent_component($componentname) {
+ if(!parent::set_parent_component($componentname)) {
+ return false;
+ }
+
+ if($this->parent_component == 'VFREEBUSY' || $this->parent_component == 'VALARM') {
+ // Most parameters become invalid in this case, the full allowed set is now:
+ $this->valid_parameters = array(
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ return false;
+ }
+
+}
+
+class iCalendar_property_contact extends iCalendar_property {
+
+ var $name = 'CONTACT';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_organizer extends iCalendar_property {
+
+ var $name = 'ORGANIZER';
+ var $val_type = RFC2445_TYPE_CAL_ADDRESS;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'CN' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'DIR' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'SENT-BY' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ // TODO:
+/*
+ Conformance: This property MUST be specified in an iCalendar object
+ that specifies a group scheduled calendar entity. This property MUST
+ be specified in an iCalendar object that specifies the publication of
+ a calendar user's busy time. This property MUST NOT be specified in
+ an iCalendar object that specifies only a time zone definition or
+ that defines calendar entities that are not group scheduled entities,
+ but are entities only on a single user's calendar.
+*/
+
+}
+
+class iCalendar_property_recurrence_id extends iCalendar_property {
+
+ // TODO: can only be specified when defining recurring components in the calendar
+/*
+ Conformance: This property can be specified in an iCalendar object
+ containing a recurring calendar component.
+
+ Description: The full range of calendar components specified by a
+ recurrence set is referenced by referring to just the "UID" property
+ value corresponding to the calendar component. The "RECURRENCE-ID"
+ property allows the reference to an individual instance within the
+ recurrence set.
+*/
+
+ var $name = 'RECURRENCE-ID';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'RANGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_parameter($parameter, $value) {
+
+ $parameter = strtoupper($parameter);
+
+ if(!parent::is_valid_parameter($parameter, $value)) {
+ return false;
+ }
+ if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
+
+class iCalendar_property_related_to extends iCalendar_property {
+
+ var $name = 'RELATED-TO';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ // TODO: the value of this property must reference another component's UID
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'RELTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_url extends iCalendar_property {
+
+ var $name = 'URL';
+ var $val_type = RFC2445_TYPE_URI;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_uid extends iCalendar_property {
+
+ var $name = 'UID';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+
+ // The exception to the rule: this is not a static value, so we
+ // generate it on-the-fly here. Guaranteed to be different for
+ // each instance of this property, too. Nice.
+ $this->val_default = rfc2445_guid();
+ }
+}
+
+// 4.8.5 Recurrence Component Properties
+// -------------------------------------
+
+class iCalendar_property_exdate extends iCalendar_property {
+
+ var $name = 'EXDATE';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+ var $val_multi = true;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_parameter($parameter, $value) {
+
+ $parameter = strtoupper($parameter);
+
+ if(!parent::is_valid_parameter($parameter, $value)) {
+ return false;
+ }
+ if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
+
+class iCalendar_property_exrule extends iCalendar_property {
+
+ var $name = 'EXRULE';
+ var $val_type = RFC2445_TYPE_RECUR;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_rdate extends iCalendar_property {
+
+ var $name = 'RDATE';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+ var $val_multi = true;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_parameter($parameter, $value) {
+
+ $parameter = strtoupper($parameter);
+
+ if(!parent::is_valid_parameter($parameter, $value)) {
+ return false;
+ }
+ if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME' || $value == 'PERIOD')) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
+
+class iCalendar_property_rrule extends iCalendar_property {
+
+ var $name = 'RRULE';
+ var $val_type = RFC2445_TYPE_RECUR;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+// TODO: 4.8.6 Alarm Component Properties
+
+// 4.8.7 Change Management Component Properties
+// --------------------------------------------
+
+class iCalendar_property_created extends iCalendar_property {
+
+ var $name = 'CREATED';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ // Time MUST be in UTC format
+ return(substr($value, -1) == 'Z');
+ }
+}
+
+class iCalendar_property_dtstamp extends iCalendar_property {
+
+ var $name = 'DTSTAMP';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ // Time MUST be in UTC format
+ return(substr($value, -1) == 'Z');
+ }
+}
+
+class iCalendar_property_last_modified extends iCalendar_property {
+ var $name = 'LAST-MODIFIED';
+ var $val_type = RFC2445_TYPE_DATE_TIME;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ // Time MUST be in UTC format
+ return(substr($value, -1) == 'Z');
+ }
+}
+
+class iCalendar_property_sequence extends iCalendar_property {
+
+ var $name = 'SEQUENCE';
+ var $val_type = RFC2445_TYPE_INTEGER;
+ var $val_default = 0;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!parent::is_valid_value($value)) {
+ return false;
+ }
+ $value = intval($value);
+ return ($value >= 0);
+ }
+}
+
+// 4.8.8 Miscellaneous Component Properties
+// ----------------------------------------
+
+class iCalendar_property_x extends iCalendar_property {
+
+ var $name = RFC2445_XNAME;
+ var $val_type = NULL;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function set_name($name) {
+
+ $name = strtoupper($name);
+
+ if(rfc2445_is_xname($name)) {
+ $this->name = $name;
+ return true;
+ }
+
+ return false;
+ }
+}
+
+class iCalendar_property_request_status extends iCalendar_property {
+
+ // IMPORTANT NOTE: This property value includes TEXT fields
+ // separated by semicolons. Unfortunately, auto-value-formatting
+ // cannot be used in this case. As an exception, the value passed
+ // to this property MUST be already escaped.
+
+ var $name = 'REQUEST-STATUS';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+
+ function is_valid_value($value) {
+ if(!is_string($value) || empty($value)) {
+ return false;
+ }
+
+ $len = strlen($value);
+ $parts = array();
+ $from = 0;
+ $escch = false;
+
+ for($i = 0; $i < $len; ++$i) {
+ if($value{$i} == ';' && !$escch) {
+ // Token completed
+ $parts[] = substr($value, $from, $i - $from);
+ $from = $i + 1;
+ continue;
+ }
+ $escch = ($value{$i} == '\\');
+ }
+ // Add one last token with the remaining text; if the value
+ // ended with a ';' it was illegal, so check that this token
+ // is not the empty string.
+ $parts[] = substr($value, $from);
+
+ $count = count($parts);
+
+ // May have 2 or 3 tokens (last one is optional)
+ if($count != 2 && $count != 3) {
+ return false;
+ }
+
+ // REMEMBER: if ANY part is empty, we have an illegal value
+
+ // First token must be hierarchical numeric status (3 levels max)
+ if(strlen($parts[0]) == 0) {
+ return false;
+ }
+
+ if($parts[0]{0} < '1' || $parts[0]{0} > '4') {
+ return false;
+ }
+
+ $len = strlen($parts[0]);
+
+ // Max 3 levels, and can't end with a period
+ if($len > 5 || $parts[0]{$len - 1} == '.') {
+ return false;
+ }
+
+ for($i = 1; $i < $len; ++$i) {
+ if(($i & 1) == 1 && $parts[0]{$i} != '.') {
+ // Even-indexed chars must be periods
+ return false;
+ }
+ else if(($i & 1) == 0 && ($parts[0]{$i} < '0' || $parts[0]{$i} > '9')) {
+ // Odd-indexed chars must be numbers
+ return false;
+ }
+ }
+
+ // Second and third tokens must be TEXT, and already escaped, so
+ // they are not allowed to have UNESCAPED semicolons, commas, slashes,
+ // or any newlines at all
+
+ for($i = 1; $i < $count; ++$i) {
+ if(strpos($parts[$i], "\n") !== false) {
+ return false;
+ }
+
+ $len = strlen($parts[$i]);
+ if($len == 0) {
+ // Cannot be empty
+ return false;
+ }
+
+ $parts[$i] .= '#'; // This guard token saves some conditionals in the loop
+
+ for($j = 0; $j < $len; ++$j) {
+ $thischar = $parts[$i]{$j};
+ $nextchar = $parts[$i]{$j + 1};
+ if($thischar == '\\') {
+ // Next char must now be one of ";,\nN"
+ if($nextchar != ';' && $nextchar != ',' && $nextchar != '\\' &&
+ $nextchar != 'n' && $nextchar != 'N') {
+ return false;
+ }
+
+ // OK, this escaped sequence is correct, bypass next char
+ ++$j;
+ continue;
+ }
+ if($thischar == ';' || $thischar == ',' || $thischar == '\\') {
+ // This wasn't escaped as it should
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ function set_value($value) {
+ // Must override this, otherwise the value would be quoted again
+ if($this->is_valid_value($value)) {
+ $this->value = $value;
+ return true;
+ }
+
+ return false;
+ }
+
+}
+
+class iCalendar_property_trigger extends iCalendar_property {
+
+ var $name = 'TRIGGER';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_action extends iCalendar_property {
+
+ var $name = 'ACTION';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ 'DISPLAY' => RFC2445_OPTIONAL | RFC2445_ONCE,
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_x_wr_alarmuid extends iCalendar_property {
+
+ var $name = 'X_WR_ALARMUID';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_tzoffsetto extends iCalendar_property {
+
+ var $name = 'TZOFFSETTO';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_daylightc extends iCalendar_property {
+
+ var $name = 'DAYLIGHTC';
+ var $val_type = RFC2445_TYPE_INTEGER;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_standardc extends iCalendar_property {
+
+ var $name = 'STANDARDC';
+ var $val_type = RFC2445_TYPE_INTEGER;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+
+class iCalendar_property_tzid extends iCalendar_property {
+
+ var $name = 'TZID';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_REQUIRED
+ );
+ }
+}
+
+#######################
+/*
+class iCalendar_property_class extends iCalendar_property {
+
+ var $name = 'CLASS';
+ var $val_type = RFC2445_TYPE_TEXT;
+
+ function construct() {
+ $this->valid_parameters = array(
+ RFC2445_XNAME => RFC2445_OPTIONAL
+ );
+ }
+}
+*/
+
+?>
diff --git a/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_rfc2445.php b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_rfc2445.php
new file mode 100644
index 00000000..a1625d71
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/iCal/iCalendar_rfc2445.php
@@ -0,0 +1,807 @@
+ RFC2445_FOLDED_LINE_LENGTH) {
+ $retval .= substr($string, 0, RFC2445_FOLDED_LINE_LENGTH - 1) . RFC2445_CRLF . ' ';
+ $string = substr($string, RFC2445_FOLDED_LINE_LENGTH - 1);
+ }
+
+ $retval .= $string;
+
+ return $retval;
+
+}
+
+function rfc2445_unfold($string) {
+ for($i = 0; $i < strlen(RFC2445_WSP); ++$i) {
+ $string = str_replace(RFC2445_CRLF.substr(RFC2445_WSP, $i, 1), '', $string);
+ }
+
+ return $string;
+}
+
+function rfc2445_is_xname($name) {
+
+ // If it's less than 3 chars, it cannot be legal
+ if(strlen($name) < 3) {
+ return false;
+ }
+
+ // If it contains an illegal char anywhere, reject it
+ if(strspn($name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-') != strlen($name)) {
+ return false;
+ }
+
+ // To be legal, it must still start with "X-"
+ return substr($name, 0, 2) === 'X-';
+}
+
+function rfc2445_is_valid_value($value, $type) {
+
+ // This branch should only be taken with xname values
+ if($type === NULL) {
+ return true;
+ }
+
+ switch($type) {
+ case RFC2445_TYPE_CAL_ADDRESS:
+ case RFC2445_TYPE_URI:
+ if(!is_string($value)) {
+ return false;
+ }
+ $valid_schemes = array('ftp', 'http', 'ldap', 'gopher', 'mailto', 'news', 'nntp', 'telnet', 'wais', 'file', 'prospero');
+
+ $pos = strpos($value, ':');
+ if(!$pos) {
+ return false;
+ }
+
+ $scheme = strtolower(substr($value, 0, $pos));
+ $remain = substr($value, $pos + 1);
+
+ if(!in_array($scheme, $valid_schemes)) {
+ return false;
+ }
+
+ if($scheme === 'mailto') {
+ $regexp = '/^[a-zA-Z0-9]+[_a-zA-Z0-9\-]*(\.[_a-z0-9\-]+)*@(([0-9a-zA-Z\-]+\.)+[a-zA-Z][0-9a-zA-Z\-]+|([0-9]{1,3}\.){3}[0-9]{1,3})$/';
+ }
+ else {
+ $regexp = '/^//(.+(:.*)?@)?(([0-9a-zA-Z\-]+\.)+[a-zA-Z][0-9a-zA-Z\-]+|([0-9]{1,3}\.){3}[0-9]{1,3})(:[0-9]{1,5})?(/.*)?$/';
+ }
+
+ return preg_match($regexp, $remain);
+ break;
+
+ case RFC2445_TYPE_BINARY:
+ if(!is_string($value)) {
+ return false;
+ }
+
+ $len = strlen($value);
+
+ if($len % 4 != 0) {
+ return false;
+ }
+
+ for($i = 0; $i < $len; ++$i) {
+ $ch = $value{$i};
+ if(!($ch >= 'a' && $ch <= 'z' || $ch >= 'A' && $ch <= 'Z' || $ch >= '0' && $ch <= '9' || $ch == '-' || $ch == '+')) {
+ if($ch == '=' && $len - $i <= 2) {
+ continue;
+ }
+ return false;
+ }
+ }
+ return true;
+ break;
+
+ case RFC2445_TYPE_BOOLEAN:
+ if(is_bool($value)) {
+ return true;
+ }
+ if(is_string($value)) {
+ $value = strtoupper($value);
+ return ($value == 'TRUE' || $value == 'FALSE');
+ }
+ return false;
+ break;
+
+ case RFC2445_TYPE_DATE:
+ if(is_int($value)) {
+ if($value < 0) {
+ return false;
+ }
+ $value = "$value";
+ }
+ else if(!is_string($value)) {
+ return false;
+ }
+
+ if(strlen($value) != 8) {
+ return false;
+ }
+
+ $y = intval(substr($value, 0, 4));
+ $m = intval(substr($value, 4, 2));
+ $d = intval(substr($value, 6, 2));
+
+ return checkdate($m, $d, $y);
+ break;
+
+ case RFC2445_TYPE_DATE_TIME:
+ if(!is_string($value) || strlen($value) < 15) {
+ return false;
+ }
+
+ return($value{8} == 'T' &&
+ rfc2445_is_valid_value(substr($value, 0, 8), RFC2445_TYPE_DATE) &&
+ rfc2445_is_valid_value(substr($value, 9), RFC2445_TYPE_TIME));
+ break;
+
+ case RFC2445_TYPE_DURATION:
+ if(!is_string($value)) {
+ return false;
+ }
+
+ $len = strlen($value);
+
+ if($len < 3) {
+ // Minimum conformant length: "P1W"
+ return false;
+ }
+
+ if($value{0} == '+' || $value{0} == '-') {
+ $value = substr($value, 1);
+ --$len; // Don't forget to update this!
+ }
+
+ if($value{0} != 'P') {
+ return false;
+ }
+
+ // OK, now break it up
+ $num = '';
+ $allowed = 'WDT';
+
+ for($i = 1; $i < $len; ++$i) {
+ $ch = $value{$i};
+ if($ch >= '0' && $ch <= '9') {
+ $num .= $ch;
+ continue;
+ }
+ if(strpos($allowed, $ch) === false) {
+ // Non-numeric character which shouldn't be here
+ return false;
+ }
+ if($num === '' && $ch != 'T') {
+ // Allowed non-numeric character, but no digits came before it
+ return false;
+ }
+
+ // OK, $ch now holds a character which tells us what $num is
+ switch($ch) {
+ case 'W':
+ // If duration in weeks is specified, this must end the string
+ return ($i == $len - 1);
+ break;
+
+ case 'D':
+ // Days specified, now if anything comes after it must be a 'T'
+ $allowed = 'T';
+ break;
+
+ case 'T':
+ // Starting to specify time, H M S are now valid delimiters
+ $allowed = 'HMS';
+ break;
+
+ case 'H':
+ $allowed = 'M';
+ break;
+
+ case 'M':
+ $allowed = 'S';
+ break;
+
+ case 'S':
+ return ($i == $len - 1);
+ break;
+ }
+
+ // If we 're going to continue, reset $num
+ $num = '';
+
+ }
+
+ // $num is kept for this reason: if we 're here, we ran out of chars
+ // therefore $num must be empty for the period to be legal
+ return ($num === '' && $ch != 'T');
+
+ break;
+
+ case RFC2445_TYPE_FLOAT:
+ if(is_float($value)) {
+ return true;
+ }
+ if(!is_string($value) || $value === '') {
+ return false;
+ }
+
+ $dot = false;
+ $int = false;
+ $len = strlen($value);
+ for($i = 0; $i < $len; ++$i) {
+ switch($value{$i}) {
+ case '-': case '+':
+ // A sign can only be seen at position 0 and cannot be the only char
+ if($i != 0 || $len == 1) {
+ return false;
+ }
+ break;
+ case '.':
+ // A second dot is an error
+ // Make sure we had at least one int before the dot
+ if($dot || !$int) {
+ return false;
+ }
+ $dot = true;
+ // Make also sure that the float doesn't end with a dot
+ if($i == $len - 1) {
+ return false;
+ }
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ $int = true;
+ break;
+ default:
+ // Any other char is a no-no
+ return false;
+ break;
+ }
+ }
+ return true;
+ break;
+
+ case RFC2445_TYPE_INTEGER:
+ if(is_int($value)) {
+ return true;
+ }
+ if(!is_string($value) || $value === '') {
+ return false;
+ }
+
+ if($value{0} == '+' || $value{0} == '-') {
+ if(strlen($value) == 1) {
+ return false;
+ }
+ $value = substr($value, 1);
+ }
+
+ if(strspn($value, '0123456789') != strlen($value)) {
+ return false;
+ }
+
+ return ($value >= -2147483648 && $value <= 2147483647);
+ break;
+
+ case RFC2445_TYPE_PERIOD:
+ if(!is_string($value) || empty($value)) {
+ return false;
+ }
+
+ $parts = explode('/', $value);
+ if(count($parts) != 2) {
+ return false;
+ }
+
+ if(!rfc2445_is_valid_value($parts[0], RFC2445_TYPE_DATE_TIME)) {
+ return false;
+ }
+
+ // Two legal cases for the second part:
+ if(rfc2445_is_valid_value($parts[1], RFC2445_TYPE_DATE_TIME)) {
+ // It has to be after the start time, so
+ return ($parts[1] > $parts[0]);
+ }
+ else if(rfc2445_is_valid_value($parts[1], RFC2445_TYPE_DURATION)) {
+ // The period MUST NOT be negative
+ return ($parts[1]{0} != '-');
+ }
+
+ // It seems to be illegal
+ return false;
+ break;
+
+ case RFC2445_TYPE_RECUR:
+ if(!is_string($value)) {
+ return false;
+ }
+
+ $parts = explode(';', strtoupper($value));
+
+ // First of all, we need at least a FREQ and a UNTIL or COUNT part, so...
+ if(count($parts) < 2) {
+ return false;
+ }
+
+ // Let's get that into a more easily comprehensible format
+ $vars = array();
+ foreach($parts as $part) {
+
+ $pieces = explode('=', $part);
+ // There must be exactly 2 pieces, e.g. FREQ=WEEKLY
+ if(count($pieces) != 2) {
+ return false;
+ }
+
+ // It's illegal for a variable to appear twice
+ if(isset($vars[$pieces[0]])) {
+ return false;
+ }
+
+ // Sounds good
+ $vars[$pieces[0]] = $pieces[1];
+ }
+
+ // OK... now to test everything else
+
+ // FREQ must be the first thing appearing
+ reset($vars);
+ if(key($vars) != 'FREQ') {
+ return false;
+ }
+
+ // It's illegal to have both UNTIL and COUNT appear
+ if(isset($vars['UNTIL']) && isset($vars['COUNT'])) {
+ return false;
+ }
+
+ // Special case: BYWEEKNO is only valid for FREQ=YEARLY
+ if(isset($vars['BYWEEKNO']) && $vars['FREQ'] != 'YEARLY') {
+ return false;
+ }
+
+ // Special case: BYSETPOS is only valid if another BY option is specified
+ if(isset($vars['BYSETPOS'])) {
+ $options = array('BYSECOND', 'BYMINUTE', 'BYHOUR', 'BYDAY', 'BYMONTHDAY', 'BYYEARDAY', 'BYWEEKNO', 'BYMONTH');
+ $defined = array_keys($vars);
+ $common = array_intersect($options, $defined);
+ if(empty($common)) {
+ return false;
+ }
+ }
+
+ // OK, now simply check if each element has a valid value,
+ // unsetting them on the way. If at the end the array still
+ // has some elements, they are illegal.
+
+ if($vars['FREQ'] != 'SECONDLY' && $vars['FREQ'] != 'MINUTELY' && $vars['FREQ'] != 'HOURLY' &&
+ $vars['FREQ'] != 'DAILY' && $vars['FREQ'] != 'WEEKLY' &&
+ $vars['FREQ'] != 'MONTHLY' && $vars['FREQ'] != 'YEARLY') {
+ return false;
+ }
+ unset($vars['FREQ']);
+
+ // Set this, we may need it later
+ $weekdays = explode(',', RFC2445_WEEKDAYS);
+
+ if(isset($vars['UNTIL'])) {
+ if(rfc2445_is_valid_value($vars['UNTIL'], RFC2445_TYPE_DATE_TIME)) {
+ // The time MUST be in UTC format
+ if(!(substr($vars['UNTIL'], -1) == 'Z')) {
+ return false;
+ }
+ }
+ else if(!rfc2445_is_valid_value($vars['UNTIL'], RFC2445_TYPE_DATE_TIME)) {
+ return false;
+ }
+ }
+ unset($vars['UNTIL']);
+
+
+ if(isset($vars['COUNT'])) {
+ if(empty($vars['COUNT'])) {
+ // This also catches the string '0', which makes no sense
+ return false;
+ }
+ if(strspn($vars['COUNT'], '0123456789') != strlen($vars['COUNT'])) {
+ return false;
+ }
+ }
+ unset($vars['COUNT']);
+
+
+ if(isset($vars['INTERVAL'])) {
+ if(empty($vars['INTERVAL'])) {
+ // This also catches the string '0', which makes no sense
+ return false;
+ }
+ if(strspn($vars['INTERVAL'], '0123456789') != strlen($vars['INTERVAL'])) {
+ return false;
+ }
+ }
+ unset($vars['INTERVAL']);
+
+
+ if(isset($vars['BYSECOND'])) {
+ if($vars['BYSECOND'] == '') {
+ return false;
+ }
+ // Comma also allowed
+ if(strspn($vars['BYSECOND'], '0123456789,') != strlen($vars['BYSECOND'])) {
+ return false;
+ }
+ $secs = explode(',', $vars['BYSECOND']);
+ foreach($secs as $sec) {
+ if($sec == '' || $sec < 0 || $sec > 59) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYSECOND']);
+
+
+ if(isset($vars['BYMINUTE'])) {
+ if($vars['BYMINUTE'] == '') {
+ return false;
+ }
+ // Comma also allowed
+ if(strspn($vars['BYMINUTE'], '0123456789,') != strlen($vars['BYMINUTE'])) {
+ return false;
+ }
+ $mins = explode(',', $vars['BYMINUTE']);
+ foreach($mins as $min) {
+ if($min == '' || $min < 0 || $min > 59) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYMINUTE']);
+
+
+ if(isset($vars['BYHOUR'])) {
+ if($vars['BYHOUR'] == '') {
+ return false;
+ }
+ // Comma also allowed
+ if(strspn($vars['BYHOUR'], '0123456789,') != strlen($vars['BYHOUR'])) {
+ return false;
+ }
+ $hours = explode(',', $vars['BYHOUR']);
+ foreach($hours as $hour) {
+ if($hour == '' || $hour < 0 || $hour > 23) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYHOUR']);
+
+
+ if(isset($vars['BYDAY'])) {
+ if(empty($vars['BYDAY'])) {
+ return false;
+ }
+
+ // First off, split up all values we may have
+ $days = explode(',', $vars['BYDAY']);
+
+ foreach($days as $day) {
+ $daypart = substr($day, -2);
+ if(!in_array($daypart, $weekdays)) {
+ return false;
+ }
+
+ if(strlen($day) > 2) {
+ $intpart = substr($day, 0, strlen($day) - 2);
+ if(!rfc2445_is_valid_value($intpart, RFC2445_TYPE_INTEGER)) {
+ return false;
+ }
+ if(intval($intpart) == 0) {
+ return false;
+ }
+ }
+ }
+ }
+ unset($vars['BYDAY']);
+
+
+ if(isset($vars['BYMONTHDAY'])) {
+ if(empty($vars['BYMONTHDAY'])) {
+ return false;
+ }
+ $mdays = explode(',', $vars['BYMONTHDAY']);
+ foreach($mdays as $mday) {
+ if(!rfc2445_is_valid_value($mday, RFC2445_TYPE_INTEGER)) {
+ return false;
+ }
+ $mday = abs(intval($mday));
+ if($mday == 0 || $mday > 31) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYMONTHDAY']);
+
+
+ if(isset($vars['BYYEARDAY'])) {
+ if(empty($vars['BYYEARDAY'])) {
+ return false;
+ }
+ $ydays = explode(',', $vars['BYYEARDAY']);
+ foreach($ydays as $yday) {
+ if(!rfc2445_is_valid_value($yday, RFC2445_TYPE_INTEGER)) {
+ return false;
+ }
+ $yday = abs(intval($yday));
+ if($yday == 0 || $yday > 366) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYYEARDAY']);
+
+
+ if(isset($vars['BYWEEKNO'])) {
+ if(empty($vars['BYWEEKNO'])) {
+ return false;
+ }
+ $weeknos = explode(',', $vars['BYWEEKNO']);
+ foreach($weeknos as $weekno) {
+ if(!rfc2445_is_valid_value($weekno, RFC2445_TYPE_INTEGER)) {
+ return false;
+ }
+ $weekno = abs(intval($weekno));
+ if($weekno == 0 || $weekno > 53) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYWEEKNO']);
+
+
+ if(isset($vars['BYMONTH'])) {
+ if(empty($vars['BYMONTH'])) {
+ return false;
+ }
+ // Comma also allowed
+ if(strspn($vars['BYMONTH'], '0123456789,') != strlen($vars['BYMONTH'])) {
+ return false;
+ }
+ $months = explode(',', $vars['BYMONTH']);
+ foreach($months as $month) {
+ if($month == '' || $month < 1 || $month > 12) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYMONTH']);
+
+
+ if(isset($vars['BYSETPOS'])) {
+ if(empty($vars['BYSETPOS'])) {
+ return false;
+ }
+ $sets = explode(',', $vars['BYSETPOS']);
+ foreach($sets as $set) {
+ if(!rfc2445_is_valid_value($set, RFC2445_TYPE_INTEGER)) {
+ return false;
+ }
+ $set = abs(intval($set));
+ if($set == 0 || $set > 366) {
+ return false;
+ }
+ }
+ }
+ unset($vars['BYSETPOS']);
+
+
+ if(isset($vars['WKST'])) {
+ if(!in_array($vars['WKST'], $weekdays)) {
+ return false;
+ }
+ }
+ unset($vars['WKST']);
+
+
+ // Any remaining vars must be x-names
+ if(empty($vars)) {
+ return true;
+ }
+
+ foreach($vars as $name => $var) {
+ if(!rfc2445_is_xname($name)) {
+ return false;
+ }
+ }
+
+ // At last, all is OK!
+ return true;
+
+ break;
+
+ case RFC2445_TYPE_TEXT:
+ return true;
+ break;
+
+ case RFC2445_TYPE_TIME:
+ if(is_int($value)) {
+ if($value < 0) {
+ return false;
+ }
+ $value = "$value";
+ }
+ else if(!is_string($value)) {
+ return false;
+ }
+
+ if(strlen($value) == 7) {
+ if(strtoupper(substr($value, -1)) != 'Z') {
+ return false;
+ }
+ $value = substr($value, 0, 6);
+ }
+ if(strlen($value) != 6) {
+ return false;
+ }
+
+ $h = intval(substr($value, 0, 2));
+ $m = intval(substr($value, 2, 2));
+ $s = intval(substr($value, 4, 2));
+
+ return ($h <= 23 && $m <= 59 && $s <= 60);
+ break;
+
+ case RFC2445_TYPE_UTC_OFFSET:
+ if(is_int($value)) {
+ if($value >= 0) {
+ $value = "+$value";
+ }
+ else {
+ $value = "$value";
+ }
+ }
+ else if(!is_string($value)) {
+ return false;
+ }
+
+ if(strlen($value) == 7) {
+ $s = intval(substr($value, 5, 2));
+ $value = substr($value, 0, 5);
+ }
+ if(strlen($value) != 5 || $value == "-0000") {
+ return false;
+ }
+
+ if($value{0} != '+' && $value{0} != '-') {
+ return false;
+ }
+
+ $h = intval(substr($value, 1, 2));
+ $m = intval(substr($value, 3, 2));
+
+ return ($h <= 23 && $m <= 59 && $s <= 59);
+ break;
+ }
+
+ // TODO: remove this assertion
+ trigger_error('bad code path', E_USER_WARNING);
+ var_dump($type);
+ return false;
+}
+
+function rfc2445_do_value_formatting($value, $type) {
+ // Note: this does not only do formatting; it also does conversion to string!
+ switch($type) {
+ case RFC2445_TYPE_CAL_ADDRESS:
+ case RFC2445_TYPE_URI:
+ // Enclose in double quotes
+ $value = '"'.$value.'"';
+ break;
+ case RFC2445_TYPE_TEXT:
+ // Escape entities
+ $value = strtr($value, array("\n" => '\\n', '\\' => '\\\\', ',' => '\\,', ';' => '\\;'));
+ break;
+ }
+ return $value;
+}
+
+function rfc2445_undo_value_formatting($value, $type) {
+ switch($type) {
+ case RFC2445_TYPE_CAL_ADDRESS:
+ case RFC2445_TYPE_URI:
+ // Trim beginning and end double quote
+ $value = substr($value, 1, strlen($value) - 2);
+ break;
+ case RFC2445_TYPE_TEXT:
+ // Unescape entities
+ $value = strtr($value, array('\\n' => "\n", '\\N' => "\n", '\\\\' => '\\', '\\,' => ',', '\\;' => ';'));
+ break;
+ }
+ return $value;
+}
+
+// This is cheating: GUIDs have nothing to do with RFC 2445
+
+function rfc2445_guid() {
+ // Implemented as per the Network Working Group draft on UUIDs and GUIDs
+
+ // These two octets get special treatment
+ $time_hi_and_version = sprintf('%02x', (1 << 6) + mt_rand(0, 15)); // 0100 plus 4 random bits
+ $clock_seq_hi_and_reserved = sprintf('%02x', (1 << 7) + mt_rand(0, 63)); // 10 plus 6 random bits
+
+ // Need another 14 random octects
+ $pool = '';
+ for($i = 0; $i < 7; ++$i) {
+ $pool .= sprintf('%04x', mt_rand(0, 65535));
+ }
+
+ // time_low = 4 octets
+ $random = substr($pool, 0, 8).'-';
+
+ // time_mid = 2 octets
+ $random .= substr($pool, 8, 4).'-';
+
+ // time_high_and_version = 2 octets
+ $random .= $time_hi_and_version.substr($pool, 12, 2).'-';
+
+ // clock_seq_high_and_reserved = 1 octet
+ $random .= $clock_seq_hi_and_reserved;
+
+ // clock_seq_low = 1 octet
+ $random .= substr($pool, 13, 2).'-';
+
+ // node = 6 octets
+ $random .= substr($pool, 14, 12);
+
+ return $random;
+}
+
+?>
diff --git a/oss/vtiger/trunk/modules/Calendar/iCal/ical-parser-class.php b/oss/vtiger/trunk/modules/Calendar/iCal/ical-parser-class.php
new file mode 100644
index 00000000..ed4d3c32
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/iCal/ical-parser-class.php
@@ -0,0 +1,91 @@
+folders = 'cache/import/';
+ }
+
+ function iCalReader($filename,$root_directory='') {
+ $iCaltoArray = $this->iCalDecoder($filename,$root_directory);
+ return $iCaltoArray;
+ }
+
+ function iCalDecoder($file,$root_directory) {
+ $ical = file_get_contents($root_directory.$this->folders.$file);
+ preg_match_all('/BEGIN:VEVENT.*?END:VEVENT/si', $ical, $eventresult, PREG_PATTERN_ORDER);
+ preg_match_all('/BEGIN:VTODO.*?END:VTODO/si', $ical, $todoresult, PREG_PATTERN_ORDER);
+ for ($i = 0; $i < count($eventresult[0]); $i++) {
+ $tmpbyline = explode("\r\n", $eventresult[0][$i]);
+ $begin = false;
+ $key=NULL;
+ foreach ($tmpbyline as $item) {
+ $tmpholderarray = explode(":",$item,2);
+
+ if (count($tmpholderarray) >1) {
+ if($tmpholderarray[0]=='BEGIN'){
+ if($begin==false){
+ $begin = true;
+ $majorarray['TYPE']=$tmpholderarray[1];
+ } else {
+ $majorarray[$tmpholderarray[1]]=array();
+ $key = $tmpholderarray[1];
+ }
+ } else if($tmpholderarray[0]=='END'){
+ if(!empty($key)){
+ $key = NULL;
+ }
+ } else {
+ if(!empty($key)){
+ $majorarray[$key][$tmpholderarray[0]] = $tmpholderarray[1];
+ } else {
+ $majorarray[$tmpholderarray[0]] = $tmpholderarray[1];
+ }
+ }
+ }
+
+ }
+ $icalarray[] = $majorarray;
+ unset($majorarray);
+ }
+
+ for ($i = 0; $i < count($todoresult[0]); $i++) {
+ $tmpbyline = explode("\r\n", $todoresult[0][$i]);
+ $begin = false;
+ $key=NULL;
+ foreach ($tmpbyline as $item) {
+ $tmpholderarray = explode(":",$item);
+
+ if (count($tmpholderarray) >1) {
+ if($tmpholderarray[0]=='BEGIN'){
+ if($begin==false){
+ $begin = true;
+ $majorarray['TYPE']=$tmpholderarray[1];
+ } else {
+ $majorarray[$tmpholderarray[1]]=array();
+ $key = $tmpholderarray[1];
+ }
+ } else if($tmpholderarray[0]=='END'){
+ if(!empty($key)){
+ $key = NULL;
+ }
+ } else {
+ if(!empty($key)){
+ $majorarray[$key][$tmpholderarray[0]] = $tmpholderarray[1];
+ } else {
+ $majorarray[$tmpholderarray[0]] = $tmpholderarray[1];
+ }
+ }
+ }
+
+ }
+ $icalarray[] = $majorarray;
+ unset($majorarray);
+ }
+ return $icalarray;
+ }
+}
+
+?>
diff --git a/oss/vtiger/trunk/modules/Calendar/iCalExport.php b/oss/vtiger/trunk/modules/Calendar/iCalExport.php
new file mode 100644
index 00000000..6886deb4
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/iCalExport.php
@@ -0,0 +1,113 @@
+id .
+ " and vtiger_activity.activitytype NOT IN ('Emails')";
+
+$calendar_results = $adb->query($ical_query);
+
+// Send the right content type and filename
+header ("Content-type: text/calendar");
+header('Content-Disposition: attachment; '."filename={$filename}.ics");
+
+$todo_fields = getColumnFields('Calendar');
+$event_fields = getColumnFields('Events');
+$event = $todo = array();
+$keys_to_replace = array(
+ 'events'=>array('taskpriority'),
+ 'todo'=>array('taskpriority','taskstatus')
+);
+$keyvals_to_replace = array(
+ 'events'=>array('taskpriority'=>'priority'),
+ 'todo'=>array('taskpriority'=>'priority','taskstatus'=>'status')
+);
+foreach($todo_fields as $key=>$val){
+ if(getFieldVisibilityPermission('Calendar',$current_user->id,$key)==0){
+ if(!in_array($key,$keys_to_replace['todo'])){
+ $todo[$key] = 'yes';
+ } else {
+ $todo[$keyvals_to_replace['todo'][$key]] = 'yes';
+ }
+ }
+}
+foreach($event_fields as $key=>$val){
+ if(getFieldVisibilityPermission('Events',$current_user->id,$key)==0){
+ if(!in_array($key,$keys_to_replace['events'])){
+ $event[$key] = 'yes';
+ } else {
+ $event[$keyvals_to_replace['events'][$key]] = 'yes';
+ }
+ }
+}
+
+$tz = new iCalendar_timezone;
+if(!empty($default_timezone)){
+ $tzid = split('/',$default_timezone);
+} else {
+ $default_timezone = date_default_timezone_get();
+ $tzid = split('/',$default_timezone);
+}
+
+if(!empty($tzid[1])){
+ $tz->add_property('TZID', $tzid[1]);
+} else {
+ $tz->add_property('TZID', $tzid[0]);
+}
+$tz->add_property('TZOFFSETTO', date('O'));
+if(date('I')==1){
+ $tz->add_property('DAYLIGHTC', date('I'));
+} else {
+ $tz->add_property('STANDARDC', date('I'));
+}
+
+$myical = new iCalendar;
+
+$myical->add_component($tz);
+
+while (!$calendar_results->EOF) {
+ $this_event = $calendar_results->fields;
+ $id = $this_event['activityid'];
+ $type = $this_event['activitytype'];
+ if($type!='Task'){
+ $temp = $event;
+ foreach($temp as $key=>$val){
+ $temp[$key] = $this_event[$key];
+ }
+ $temp['id'] = $id;
+ $ev = new iCalendar_event;
+ $ev->assign_values($temp);
+
+ $al = new iCalendar_alarm;
+ $al->assign_values($temp);
+ $ev->add_component($al);
+ } else {
+ $temp = $todo;
+ foreach($temp as $key=>$val){
+ $temp[$key] = $this_event[$key];
+ }
+ $ev = new iCalendar_todo;
+ $ev->assign_values($temp);
+ }
+
+ $myical->add_component($ev);
+ $calendar_results->MoveNext();
+}
+// Print the actual calendar
+echo $myical->serialize();
+
+?>
\ No newline at end of file
diff --git a/oss/vtiger/trunk/modules/Calendar/iCalImport.php b/oss/vtiger/trunk/modules/Calendar/iCalImport.php
new file mode 100644
index 00000000..01440132
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/iCalImport.php
@@ -0,0 +1,146 @@
+mark_deleted_by_user_id($current_user->id);
+ $file_details = $_FILES['ics_file'];
+ $binFile = 'vtiger_import'.date('YmdHis');
+ $file = $import_dir.''.$binFile;
+ $filetmp_name = $file_details['tmp_name'];
+ $upload_status = move_uploaded_file($filetmp_name,$file);
+
+ $skip_fields = array(
+ 'Events'=>array('duration_hours'),
+ 'Calendar'=>array('eventstatus')
+ );
+ $required_fields = array();
+
+ $modules = array('Events','Calendar');
+ foreach($modules as $module){
+ $calendar = CRMEntity::getInstance('Calendar');
+ $calendar->initRequiredFields($module);
+ $val = array_keys($calendar->required_fields);
+ $required_fields[$module] = array_diff($val,$skip_fields[$module]);
+ }
+
+ $ical = new iCal();
+ $ical_activities = $ical->iCalReader($binFile);
+
+ $count['Events'] = $count['Calendar'] = $skip_count['Events'] = $skip_count['Calendar'] = 0;
+ for($i=0;$icolumn_fields = $activity->generateArray($ical_activities[$i]);
+ $calendar->column_fields['assigned_user_id'] = $current_user->id;
+ foreach($required_fields[$module] as $key){
+ if(empty($calendar->column_fields[$key])){
+ $skip_count[$module]++;
+ break;
+ }
+ }
+ $calendar->save('Calendar');
+ $last_import = new UsersLastImport();
+ $last_import->assigned_user_id = $current_user->id;
+ $last_import->bean_type = 'Calendar';
+ $last_import->bean_id = $calendar->id;
+ $last_import->save();
+ if(!empty($ical_activities[$i]['VALARM'])){
+ $calendar->activity_reminder($calendar->id,$calendar->column_fields['reminder_time'],0,'','');
+ }
+ }
+ unlink($file);
+ $smarty->assign("IMAGE_PATH", $last_imported);
+ $smarty = new vtigerCRM_Smarty;
+
+ $smarty->assign("MOD", $mod_strings);
+ $smarty->assign("APP", $app_strings);
+ $smarty->assign("IMP", $import_mod_strings);
+ $smarty->assign("THEME", $theme);
+ $smarty->assign("IMAGE_PATH", $image_path);
+ $parent_tab = vtlib_purify($_SESSION['import_parenttab']);
+ if(empty($parent_Tab)){
+ $parent_tab = getParentTab();
+ }
+ $smarty->assign("MODULE", vtlib_purify($_REQUEST['module']));
+ $smarty->assign("SINGLE_MOD", vtlib_purify($_REQUEST['module']));
+ $smarty->assign("CATEGORY", $parent_tab);
+ //@session_unregister("import_parenttab");
+ $smarty->display("Buttons_List1.tpl");
+
+ $imported_events = $count['Events'] - $skip_count['Events'];
+ $imported_tasks = $count['Calendar'] - $skip_count['Calendar'];
+ $message= "".$mod_strings['LBL_SUCCESS'].""
+ ."
" .$mod_strings['LBL_SUCCESS_EVENTS_1']." $imported_events"
+ ."
" .$mod_strings['LBL_SKIPPED_EVENTS_1'].$skip_count['Events']
+ ."
" .$mod_strings['LBL_SUCCESS_CALENDAR_1']." $imported_tasks"
+ ."
" .$mod_strings['LBL_SKIPPED_CALENDAR_1'].$skip_count['Calendar']
+ ."
";
+
+ $smarty->assign("MESSAGE", $message);
+ $smarty->assign("RETURN_MODULE", $currentModule);
+ $smarty->assign("RETURN_ACTION", 'ListView');
+ $smarty->assign("MODULE", $currentModule);
+ $smarty->assign("MODULENAME", $currentModule);
+ $smarty->display("iCalImport.tpl");
+
+} else {
+ $smarty->assign("IMAGE_PATH", $last_imported);
+ $smarty = new vtigerCRM_Smarty;
+
+ $smarty->assign("MOD", $mod_strings);
+ $smarty->assign("APP", $app_strings);
+ $smarty->assign("IMP", $import_mod_strings);
+ $smarty->assign("THEME", $theme);
+ $smarty->assign("IMAGE_PATH", $image_path);
+ $parent_tab = vtlib_purify($_SESSION['import_parenttab']);
+ if(empty($parent_Tab)){
+ $parent_tab = getParentTab();
+ }
+ $smarty->assign("MODULE", vtlib_purify($_REQUEST['module']));
+ $smarty->assign("SINGLE_MOD", vtlib_purify($_REQUEST['module']));
+ $smarty->assign("CATEGORY", $parent_tab);
+ //@session_unregister("import_parenttab");
+ $smarty->display("Buttons_List1.tpl");
+
+ $last_import = new UsersLastImport();
+ $ret_value = $last_import->undo($current_user->id);
+
+ if(!empty($ret_value)){
+ $message= "".$mod_strings['LBL_SUCCESS'].""
+ ."
" .$mod_strings['LBL_LAST_IMPORT_UNDONE']." ";
+ } else {
+ $message= "".$mod_strings['LBL_FAILURE'].""
+ ."
" .$mod_strings['LBL_NO_IMPORT_TO_UNDO']." ";
+ }
+
+ $smarty->assign("MESSAGE", $message);
+ $smarty->assign("UNDO", 'yes');
+ $smarty->assign("RETURN_MODULE", $currentModule);
+ $smarty->assign("RETURN_ACTION", 'ListView');
+ $smarty->assign("MODULE", $currentModule);
+ $smarty->assign("MODULENAME", $currentModule);
+ $smarty->display("iCalImport.tpl");
+}
+?>
\ No newline at end of file
diff --git a/oss/vtiger/trunk/modules/Calendar/index.php b/oss/vtiger/trunk/modules/Calendar/index.php
new file mode 100644
index 00000000..06bda1f8
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/index.php
@@ -0,0 +1,32 @@
+
diff --git a/oss/vtiger/trunk/modules/Calendar/language/en_us.lang.php b/oss/vtiger/trunk/modules/Calendar/language/en_us.lang.php
new file mode 100644
index 00000000..891c51aa
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/language/en_us.lang.php
@@ -0,0 +1,452 @@
+'Calendar',
+'LBL_MODULE_TITLE'=>'Calendar: Home',
+'LBL_MODULE_APPOINTMENT'=>'Calendar: Appointment',
+'LBL_MODULE_APPOINTMENT_DETAIL'=>'Calendar: Appointment Detail',
+'LBL_SAVE'=>'Save',
+'LBL_RESET'=>'Cancel',
+'LBL_LIST_USER_NAME'=>'User Name',
+'LBL_LIST_NAME'=>'Name',
+'LBL_CALENDAR_SHARED'=>'Calendar currently shared with',
+'LBL_CALENDAR_SHARING'=>'Share calendar with',
+'LBL_SHARING_OPTION'=>'Can see my calendar?',
+'LBL_LIST_TOOLS'=>'Tools',
+'LBL_SETTINGS'=>'Settings',
+'LBL_CALSETTINGS'=>'Calendar Settings',
+'LBL_USE24'=>'Use 24 hours format',
+'LBL_CALSTART'=>'Start my calendar time at',
+'LBL_TIMESETTINGS'=>'Time Settings',
+'LBL_HOLDFOLLOWUP'=>'Hold followup on',
+'LBL_CALL' => 'Call',
+'LBL_MEET' => 'Meeting',
+'LBL_APPNT' => 'Appointment',
+'LBL_NEW_APPNT' => 'New Appointment',
+'LBL_NEW_APPNT_INFO' => 'Create a new appointment',
+'LBL_VIEW_DAY_APPNT_INFO' => 'View appointment(s) for this day',
+'LBL_CHANGE_APPNT' => 'see or change this appointment (%s - %s)',
+
+'LBL_DAY' => 'Day',
+'LBL_DAY_BUTTON_KEY' => 'D',
+'LBL_DAY_BUTTON_TITLE' => 'Day [Alt+D]',
+'LBL_DAY1' => 'Monday',
+'LBL_DAY2' => 'Tuesday',
+'LBL_DAY3' => 'Wednesday',
+'LBL_DAY4' => 'Thursday',
+'LBL_DAY5' => 'Friday',
+'LBL_DAY6' => 'Saturday',
+'LBL_DAY0' => 'Sunday',
+
+'LBL_SM_MON' => 'Mon',
+'LBL_SM_TUE' => 'Tue',
+'LBL_SM_WED' => 'Wed',
+'LBL_SM_THU' => 'Thu',
+'LBL_SM_FRI' => 'Fri',
+'LBL_SM_SAT' => 'Sat',
+'LBL_SM_SUN' => 'Sun',
+
+'LBL_DATE_TITLE' => 'Day %d, %A',
+
+'LBL_WEEK' => 'Week',
+'LBL_WEEK_BUTTON_KEY' => 'W',
+'LBL_WEEK_BUTTON_TITLE' => 'Week [Alt+W]',
+'LBL_WEEKS' => 'Weeks',
+'LBL_NEXT_WEEK' => 'next week',
+'LBL_LAST_WEEK' => 'last week',
+'LBL_4WEEKS_BACK' => '4 weeks back',
+'LBL_4WEEKS_PLUS' => '4 weeks plus',
+'LBL_RELOAD' => 'Reload',
+
+
+'LBL_APPCREATED_BY' => 'Created by',
+'LBL_AT_DATE_TIME' => 'at',
+
+'LBL_MON' => 'Month',
+'LBL_MON_BUTTON_KEY' => 'M',
+'LBL_MON_BUTTON_TITLE' => 'Month [Alt+M]',
+'LBL_PREV_MON' => 'Previous Month',
+'LBL_NEXT_MON' => 'Next Month',
+
+'LBL_YEAR_BUTTON_KEY'=>'Y',
+'LBL_PREV_YEAR'=>'Previous Year',
+'LBL_NEXT_YEAR' => 'Next Year',
+
+'LBL_APP_LOCATION' => 'Location',
+'LBL_APP_IGNORE_TIME' => 'ignore above times',
+'LBL_SUBJECT'=>'Subject:',
+'LBL_APP_DESCRIPTION' => 'Description',
+'LBL_CONTACT'=>'Contact:',
+'LBL_CONTACT_LIST'=>'Contact List:',
+
+'LBL_APP_IGNORE_TIME2' => '(i.e. the appointment takes place at no particular time on these day(s) )',
+
+'LBL_APP_ERR001' =>'Invalid Date in field %s!',
+'LBL_APP_ERR002' =>'start after end !',
+'LBL_APP_ERR003' =>'Missing Contact !',
+'LBL_APP_ERR004' =>'Missing Subject !',
+'ERR_DELETE_RECORD'=>"A record number must be specified to delete the appointment.",
+'DELETE_CONFIRMATION'=>"Are you sure you want to delete this appointment?",
+
+'AppLoc'=> Array('0' => 'Office'
+ , '1' => 'Out'
+ , '2' => 'Vacation'
+ , '3' => 'sick'
+ , '4' => 'Postponed'
+ , '5' => 'Option'
+ , '6' => 'Private'),
+
+'cal_month_long'=>array(
+"",
+"January",
+"February",
+"March",
+"April",
+"May",
+"June",
+"July",
+"August",
+"September",
+"October",
+"November",
+"December",
+),
+
+'cal_weekdays_short'=>array(
+"Sun",
+"Mon",
+"Tue",
+"Wed",
+"Thu",
+"Fri",
+"Sat",
+),
+'cal_weekdays_long'=>array(
+"Sunday",
+"Monday",
+"Tuesday",
+"Wednesday",
+"Thursday",
+"Friday",
+"Saturday",
+),
+'cal_month_short'=>array(
+"",
+"Jan",
+"Feb",
+"Mar",
+"Apr",
+"May",
+"Jun",
+"Jul",
+"Aug",
+"Sep",
+"Oct",
+"Nov",
+"Dec",
+),
+
+'LBL_TIME'=>'Time',
+'LBL_START_TIME' => 'Start Time',
+'LBL_END_TIME' => 'End Time',
+'LBL_START_DATE'=>'Start Date',
+'LBL_TIME_START'=>'Time Start',
+'LBL_DUE_DATE'=>'Due Date',
+'LBL_START_DATE_TIME'=>'Start Date & Time',
+'LBL_END_DATE_TIME'=>'End Date & Time',
+'LBL_TODO'=>'To Do',
+'LBL_TODOS'=>'To Dos',
+'LBL_EVENTS'=>'Events',
+'LBL_TOTALEVENTS'=>'My Total Events :',
+'LBL_TOTALTODOS'=>'My Total To Dos :',
+'LBL_VIEW'=>'View',
+'LBL_LISTVIEW'=>'List View',
+'LBL_HRVIEW'=>'Hour View',
+'LBL_WEEKVIEW'=>'Weekly Calendar View',
+'LBL_MONTHVIEW'=>'Monthly Calendar View',
+'LBL_YEARVIEW'=>'Yearly Calendar View',
+'LBL_STATUS'=>'Status',
+'LBL_ACTION'=>'Actions',
+'LBL_ADD'=>'Add',
+'LBL_OPENCAL'=>'Open Calendar',
+
+
+'LBL_ADD_EVENT'=>'Add Event',
+'LBL_ADDCALL'=>'Call',
+'LBL_ADDMEETING'=>'Meeting',
+'LBL_ADDTODO'=>'To Do',
+'LBL_BEFOREEVENT'=>'before the event starts',
+'LBL_BEFORETASK'=>'before the task starts',
+'LBL_EVENTDETAILS'=>'Event Details',
+'LBL_CURSTATUS'=>'Current Status',
+'LBL_ASSINGEDTO'=>'Assigned To',
+'LBL_RELATEDTO'=>'Related To',
+'LBL_PENDING'=>'Pending',
+'LBL_PUBLIC'=>'Mark Public',
+'LBL_MORE'=>'More',
+'LBL_EDIT'=>'Edit',
+'LBL_EVERYDAY'=>'Every Day',
+'LBL_EVERYWEEK'=>'Every Week',
+'LBL_EVERYMON'=>'Every Month',
+'LBL_WEEKS'=>'Week(s)',
+'LBL_MONTHS'=>'Month(s)',
+'LBL_YEAR'=>'Year',
+'LBL_NONE_SCHEDULED'=>'None Scheduled',
+
+'LBL_INVITE_INST1'=>'To invite, select the users from the "Available Users" list and click the "Add" button.',
+'LBL_INVITE_SHARE'=>'To share, select the users from the "Available Users" list and click the "Add" button.',
+'LBL_INVITE_INST2'=>'To remove, select the users from the "Selected Users" list and the click "Remove" button.',
+'LBL_SELUSR_INFO'=>' Selected users will receive an email about the Event.',
+'LBL_CALSHAREMESSAGE'=>'Share my calendar with the following selected users',
+'LBL_CALSHARE'=>'Calendar Sharing',
+'LBL_SEL_USERS'=>'Selected Users',
+'LBL_AVL_USERS'=>'Available Users',
+'LBL_ADD_BUTTON'=>'Add',
+'LBL_USERS'=>'Users',
+'LBL_RMV_BUTTON'=>'Remove',
+'LBL_SDRMD'=>'Send Reminder to',
+'LBL_ENABLE_REPEAT'=>'Enable Repeat',
+'LBL_REPEAT_ONCE'=>'Repeat once in every',
+'LBL_ADD_TODO'=>'Create To Do',
+'LBL_TODONAME'=>'To Do',
+'LBL_TODODATETIME'=>'Time & Date',
+
+
+
+
+
+//DON'T CONVERT THESE THEY ARE MAPPINGS - STARTS
+'db_last_name' => 'LBL_LIST_LAST_NAME',
+'db_first_name' => 'LBL_LIST_FIRST_NAME',
+'db_title' => 'LBL_LIST_TITLE',
+'db_email1' => 'LBL_LIST_EMAIL_ADDRESS',
+'db_email2' => 'LBL_LIST_EMAIL_ADDRESS',
+//DON'T CONVERT THESE THEY ARE MAPPINGS -ENDS
+'LBL_COMPLETED'=>'Mark Completed',
+'LBL_DEFERRED'=>'Mark Deferred',
+'LBL_HELD'=>'Mark Held',
+'LBL_NOTHELD'=>'Mark Not Held',
+'LBL_POSTPONE'=>'Postpone',
+'LBL_CHANGEOWNER'=>'Change Owner',
+'LBL_DEL'=>'Delete',
+
+//Added for actvity merge with calendar
+'LBL_SEARCH_FORM_TITLE'=>'Activity Search',
+'LBL_LIST_FORM_TITLE'=>'Activity List',
+'LBL_NEW_FORM_TITLE'=>'New Activity',
+'LBL_TASK_INFORMATION'=>'Task Information',
+'LBL_EVENT_INFORMATION'=>'Event Information',
+'LBL_CALENDAR_INFORMATION'=>'Calendar Information',
+
+'LBL_NAME'=>'Subject:',
+'LBL_ACTIVITY_NOTIFICATION'=>'This is a notification that an activity is assigned to you that has been',
+'LBL_ACTIVITY_INVITATION'=>'You have been invited for an activity that has been ',
+'LBL_DETAILS_STRING'=>'The details are',
+'LBL_REGARDS_STRING'=>'Thanks & Regards',
+'LBL_CONTACT_NAME'=>'Contact Name',
+'LBL_OPEN_ACTIVITIES'=>'Open Activities',
+'LBL_ACTIVITY'=>'Activity:',
+'LBL_HISTORY'=>'History',
+'LBL_UPCOMING'=>"My Upcoming and Pending Activities",
+'LBL_TODAY'=>'through ',
+
+'LBL_NEW_TASK_BUTTON_TITLE'=>'New Task [Alt+N]',
+'LBL_NEW_TASK_BUTTON_KEY'=>'N',
+'LBL_NEW_TASK_BUTTON_LABEL'=>'New Task',
+'LBL_SCHEDULE_MEETING_BUTTON_TITLE'=>'Schedule Meeting [Alt+M]',
+'LBL_SCHEDULE_MEETING_BUTTON_KEY'=>'M',
+'LBL_SCHEDULE_MEETING_BUTTON_LABEL'=>'Schedule Meeting',
+'LBL_SCHEDULE_CALL_BUTTON_TITLE'=>'Schedule Call [Alt+C]',
+'LBL_SCHEDULE_CALL_BUTTON_KEY'=>'C',
+'LBL_SCHEDULE_CALL_BUTTON_LABEL'=>'Schedule Call',
+'LBL_NEW_NOTE_BUTTON_TITLE'=>'New Document [Alt+T]',
+'LBL_NEW_ATTACH_BUTTON_TITLE'=>'Attach File [Alt+F]',
+'LBL_NEW_NOTE_BUTTON_KEY'=>'T',
+'LBL_NEW_ATTACH_BUTTON_KEY'=>'F',
+'LBL_NEW_NOTE_BUTTON_LABEL'=>'New Document',
+'LBL_NEW_ATTACH_BUTTON_LABEL'=>'Attach File',
+'LBL_TRACK_EMAIL_BUTTON_TITLE'=>'Track Email [Alt+K]',
+'LBL_TRACK_EMAIL_BUTTON_KEY'=>'K',
+'LBL_TRACK_EMAIL_BUTTON_LABEL'=>'Track Email',
+
+'LBL_LIST_CLOSE'=>'Close',
+'LBL_LIST_STATUS'=>'Status',
+'LBL_LIST_CONTACT'=>'Contact',
+//Added for 4.2 release for Account column support as shown by Fredy
+'LBL_LIST_ACCOUNT'=>'Account',
+'LBL_LIST_RELATED_TO'=>'Related to',
+'LBL_LIST_DUE_DATE'=>'Due Date',
+'LBL_LIST_DATE'=>'Date',
+'LBL_LIST_SUBJECT'=>'Subject',
+'LBL_LIST_LAST_MODIFIED'=>'Last Modified',
+'LBL_LIST_RECURRING_TYPE'=>'Recurring Type',
+
+'ERR_DELETE_RECORD'=>"A record number must be specified to delete the vtiger_account.",
+'NTC_NONE_SCHEDULED'=>'None scheduled.',
+
+// Added vtiger_fields for Attachments in Activities/SubPanelView.php
+'LBL_ATTACHMENTS'=>'Attachments',
+'LBL_NEW_ATTACHMENT'=>'New Attachment',
+
+//Added vtiger_fields after RC1 - Release
+'LBL_ALL'=>'All',
+'LBL_CALL'=>'Call',
+'LBL_MEETING'=>'Meeting',
+'LBL_TASK'=>'Task',
+
+//Added for 4GA Release
+'Subject'=>'Subject',
+'Assigned To'=>'Assigned To',
+'Start Date & Time'=>'Start Date & Time',
+'Time Start'=>'Time Start',
+'Due Date'=>'Due Date',
+'Related To'=>'Related to',
+'Contact Name'=>'Contact Name',
+'Status'=>'Status',
+'Priority'=>'Priority',
+'Visibility'=>'Visibility',
+'Send Notification'=>'Send Notification',
+'Created Time'=>'Created Time',
+'Modified Time'=>'Modified Time',
+'Activity Type'=>'Activity Type',
+'Description'=>'Description',
+'Duration'=>'Duration',
+'Duration Minutes'=>'Duration Minutes',
+'Location'=>'Location',
+'No Time'=>'No Time',
+//Added for Send Reminder 4.2 release
+'Send Reminder'=>'Send Reminder',
+'LBL_YES'=>'Yes',
+'LBL_NO'=>'No',
+'LBL_DAYS'=>'day(s)',
+'LBL_MINUTES'=>'minutes',
+'LBL_HOURS'=>'hours',
+'LBL_BEFORE_EVENT'=>'before event',
+//Added for CustomView 4.2 Release
+'Close'=>'Close',
+'Start Date'=>'Start Date',
+'Type'=>'Type',
+'End Date'=>'End Date',
+'Recurrence'=> 'Recurring Events',
+'Recurring Type'=> 'Recurring Type',
+//Activities - Notification Error
+'LBL_NOTIFICATION_ERROR'=>'Mail Error : Please check your outgoing mail server configuration in Settings->Outgoing Mail Server Configuration OR MailId for the present user is not Configured',
+// Mike Crowe Mod --------------------------------------------------------added for generic search
+'LBL_GENERAL_INFORMATION'=>'General Information',
+
+'LBL_EVENTTYPE'=>'Event Type',
+'LBL_EVENTNAME'=>'Event Name',
+'LBL_EVENTSTAT'=>'Event starts at',
+'LBL_EVENTEDAT'=>'Event ends on',
+'LBL_INVITE'=>'Invite',
+'LBL_REPEAT'=>'Repeat',
+'LBL_REMINDER'=>'Reminder',
+'LBL_SENDREMINDER'=>'Send Reminder',
+'LBL_NOTIFICATION'=>'Notification',
+'LBL_SENDNOTIFICATION'=>'Send Notification',
+'LBL_RMD_ON'=>'Remind on',
+'LBL_REPEATEVENT'=>'Repeat once in every',
+'LBL_TIMEDATE'=>'Time & Date',
+'LBL_HR'=>'Hr',
+'LBL_MIN'=>'min',
+'LBL_EVENT'=>'Event',
+'Daily'=>'Day(s)',
+'Weekly'=>'Week(s)',
+'Monthly'=>'Month(s)',
+'Yearly'=>'Year',
+'createdtime'=>'Created Time',
+'modifiedtime'=>'Modified Time',
+'first'=>'First',
+'last'=>'Last',
+'High'=>'High',
+'Medium'=>'Medium',
+'Low'=>'Low',
+'LBL_SELECT'=>'Select',
+'LBL_ALL_EVENTS_TODOS'=>'All Events & Todos',
+'First'=>'First',
+'Last'=>'Last',
+'on'=>'on',
+'day of the month'=>'day of the month',
+'Private'=>'Private',
+'Public'=>'Public',
+
+//Added for existing Picklist entries
+
+'Planned'=>'Planned',
+'Held'=>'Held',
+'Not Held'=>'Not Held',
+'Completed'=>'Completed',
+'Deferred'=>'Deferred',
+'Not Started'=>'Not Started',
+'In Progress'=>'In Progress',
+'Pending Input'=>'Pending Input',
+'LBL_REMAINDER_DAY'=>'days',
+'LBL_REMAINDER_HRS'=>'hrs',
+'Call'=>'Call',
+'Meeting'=>'Meeting',
+
+//added to send dates and time in calendar notification/invitation mail.
+
+'Start date and time'=>'Start Date & Time',
+'End date and time'=>'End Date & Time',
+//this is for task
+'End date'=>'End date',
+'LBL_SET_DATE'=>'Set date..',
+'Recurrence'=>'Recurrence',
+
+//added to send invitation mail Subject.
+'INVITATION'=>' Invitation ',
+
+// Added/Updated for vtiger CRM 5.0.4
+'LBL_YEAR_BUTTON_TITLE'=>'Year [Alt+Y]',
+'LBL_SELECT_CONTACT'=>'Select Contacts',
+'SHARED_EVENT_DEL_MSG'=>'The User does not have permission to Edit/Delete Shared Event.',
+//added to fix ticket#4525
+'LBL_CREATED'=>'created',
+'LBL_UPDATED'=>'updated',
+
+//Added after 5.0.4 GA
+'LBL_BUSY' => 'Busy',
+
+//Custom Fields support for Calendar
+'LBL_CUSTOM_INFORMATION'=>'Custom Information',
+
+// Repeat Event support for Calendar
+'LBL_UNTIL' => 'Until',
+'LBL_SET_DATE'=>'Set Date',
+
+'LBL_MINE' =>'Mine',
+'LBL_SUCCESS_CALENDAR_1' => 'No. of Tasks Successfully Imported : ',
+'LBL_SKIPPED_CALENDAR_1' => 'No. of Tasks Skipped as they were missing one or more required fields : ',
+'LBL_SUCCESS_EVENTS_1' => 'No. of Events Successfully Imported : ',
+'LBL_SKIPPED_EVENTS_1' => 'No. of Events Skipped as they were missing one or more required fields : ',
+'LBL_FINISHED'=>'Finished',
+'LBL_UNDO_LAST_IMPORT'=>'Undo Last Import',
+'LBL_LAST_IMPORT'=>'Last Imported',
+'LBL_LAST_IMPORT_UNDONE'=>'Your Last Import Was Undone',
+'LBL_SUCCESS'=>'Success!',
+'LBL_NO_IMPORT_TO_UNDO'=>'There was no import to undo.',
+'LBL_FAILURE'=>'Failed!',
+);
+
+?>
\ No newline at end of file
diff --git a/oss/vtiger/trunk/modules/Calendar/language/zh_cn.lang.php b/oss/vtiger/trunk/modules/Calendar/language/zh_cn.lang.php
new file mode 100644
index 00000000..661071bb
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/language/zh_cn.lang.php
@@ -0,0 +1,453 @@
+'计划任务',
+'LBL_MODULE_TITLE'=>'计划任务:首页',
+'LBL_MODULE_APPOINTMENT'=>'计划任务:预约',
+'LBL_MODULE_APPOINTMENT_DETAIL'=>'计划任务:预约明细',
+'LBL_SAVE'=>'保存',
+'LBL_RESET'=>'取消',
+'LBL_LIST_USER_NAME'=>'账号',
+'LBL_LIST_NAME'=>'名称',
+'LBL_CALENDAR_SHARED'=>'计划目前分享给',
+'LBL_CALENDAR_SHARING'=>'分享计划给',
+'LBL_SHARING_OPTION'=>'可以检视我的计划?',
+'LBL_LIST_TOOLS'=>'工具',
+'LBL_SETTINGS'=>'设定',
+'LBL_CALSETTINGS'=>'计划任务设定',
+'LBL_USE24'=>'使用24小时制',
+'LBL_CALSTART'=>'计划任务开始时间',
+'LBL_TIMESETTINGS'=>'时间设定',
+'LBL_HOLDFOLLOWUP'=>'稍后处理',
+'LBL_CALL'=>'电话记录',
+'LBL_MEET'=>'会议',
+'LBL_APPNT'=>'行程',
+'LBL_NEW_APPNT'=>'新增行程',
+'LBL_NEW_APPNT_INFO'=>'建立一笔新的行程',
+'LBL_VIEW_DAY_APPNT_INFO'=>'浏览今天的行程',
+'LBL_CHANGE_APPNT'=>'察看或变更这个行程(%s-%s)',
+
+'LBL_DAY'=>'日',
+'LBL_DAY_BUTTON_KEY'=>'D',
+'LBL_DAY_BUTTON_TITLE'=>'日[Alt+D]',
+'LBL_DAY1'=>'星期一',
+'LBL_DAY2'=>'星期二',
+'LBL_DAY3'=>'星期三',
+'LBL_DAY4'=>'星期四',
+'LBL_DAY5'=>'星期五',
+'LBL_DAY6'=>'星期六',
+'LBL_DAY0'=>'星期日',
+
+'LBL_SM_MON'=>'一',
+'LBL_SM_TUE'=>'二',
+'LBL_SM_WED'=>'三',
+'LBL_SM_THU'=>'四',
+'LBL_SM_FRI'=>'五',
+'LBL_SM_SAT'=>'六',
+'LBL_SM_SUN'=>'日',
+
+'LBL_DATE_TITLE'=>'Day%d,%A',
+
+'LBL_WEEK'=>'周',
+'LBL_WEEK_BUTTON_KEY'=>'W',
+'LBL_WEEK_BUTTON_TITLE'=>'周[Alt+W]',
+'LBL_WEEKS'=>'周',
+'LBL_NEXT_WEEK'=>'下周',
+'LBL_LAST_WEEK'=>'上周',
+'LBL_4WEEKS_BACK'=>'四周前',
+'LBL_4WEEKS_PLUS'=>'四周后',
+'LBL_RELOAD'=>'重新载入',
+
+
+'LBL_APPCREATED_BY'=>'创建人:',
+'LBL_AT_DATE_TIME'=>'在',
+
+'LBL_MON'=>'月',
+'LBL_MON_BUTTON_KEY'=>'M',
+'LBL_MON_BUTTON_TITLE'=>'月[Alt+M]',
+'LBL_PREV_MON'=>'上个月',
+'LBL_NEXT_MON'=>'下个月',
+
+'LBL_YEAR_BUTTON_KEY'=>'Y',
+'LBL_PREV_YEAR'=>'去年',
+'LBL_NEXT_YEAR'=>'明年',
+
+'LBL_APP_LOCATION'=>'所在地',
+'LBL_APP_IGNORE_TIME'=>'忽略',
+'LBL_SUBJECT'=>'主题:',
+'LBL_APP_DESCRIPTION'=>'描述',
+'LBL_CONTACT'=>'联系方式:',
+'LBL_CONTACT_LIST'=>'联系人列表:',
+
+'LBL_APP_IGNORE_TIME2'=>'(注:这个行程在该期间没有特定的时间)',
+
+'LBL_APP_ERR001'=>'字段 %s 数据类型错误!',
+'LBL_APP_ERR002'=>'开始日期在结束日期之后!',
+'LBL_APP_ERR003'=>'联系人为空!',
+'LBL_APP_ERR004'=>'标题为空!',
+'ERR_DELETE_RECORD'=>'在删除行程前必须输入正确的记录编号.',
+'DELETE_CONFIRMATION'=>'您确定要删除这次的行程?',
+
+'AppLoc'=>Array('0'=>'Office'
+ , '1' => '户外'
+ , '2' => '休假'
+ , '3' => '病假'
+ , '4' => '延期'
+ , '5' => '任意'
+ , '6' => '私人'),
+
+'cal_month_long'=>array(
+"",
+"一月",
+"二月",
+"三月",
+"四月",
+"五月",
+"六月",
+"七月",
+"八月",
+"九月",
+"十月",
+"十一月",
+"十二月",
+),
+
+'cal_weekdays_short'=>array(
+"日",
+"一",
+"二",
+"三",
+"四",
+"五",
+"六",
+),
+'cal_weekdays_long'=>array(
+"星期日",
+"星期一",
+"星期二",
+"星期三",
+"星期四",
+"星期五",
+"星期六",
+),
+'cal_month_short'=>array(
+"",
+"一月",
+"二月",
+"三月",
+"四月",
+"五月",
+"六月",
+"七月",
+"八月",
+"九月",
+"十月",
+"十一月",
+"十二月",
+),
+
+'LBL_TIME'=>'时间',
+'LBL_START_TIME'=>'开始时间',
+'LBL_END_TIME'=>'结束时间',
+'LBL_START_DATE'=>'开始日期',
+'LBL_TIME_START'=>'时间开始',
+'LBL_DUE_DATE'=>'到期日',
+'LBL_START_DATE_TIME'=>'开始日期&时间',
+'LBL_END_DATE_TIME'=>'结束日期&时间',
+'LBL_TODO'=>'待办',
+'LBL_TODOS'=>'待办事项',
+'LBL_EVENTS'=>'事件',
+'LBL_TOTALEVENTS'=>'我的全部事件:',
+'LBL_TOTALTODOS'=>'我的待办事项:',
+'LBL_VIEW'=>'查看',
+'LBL_LISTVIEW'=>'列表查看',
+'LBL_HRVIEW'=>'查看时间',
+'LBL_WEEKVIEW'=>'查看周历',
+'LBL_MONTHVIEW'=>'查看月历',
+'LBL_YEARVIEW'=>'查看年历',
+'LBL_STATUS'=>'状态',
+'LBL_ACTION'=>'操作',
+'LBL_ADD'=>'添加',
+'LBL_OPENCAL'=>'打开日历',
+
+
+'LBL_ADD_EVENT'=>'添加事件',
+'LBL_ADDCALL'=>'呼叫',
+'LBL_ADDMEETING'=>'会议',
+'LBL_ADDTODO'=>'待办',
+'LBL_BEFOREEVENT'=>'在事件开始之前',
+'LBL_BEFORETASK'=>'在任务开始之前',
+'LBL_EVENTDETAILS'=>'事件细节',
+'LBL_CURSTATUS'=>'当前状态',
+'LBL_ASSINGEDTO'=>'分配给',
+'LBL_RELATEDTO'=>'关联于',
+'LBL_PENDING'=>'即将发生',
+'LBL_PUBLIC'=>'标记为公共',
+'LBL_MORE'=>'更多',
+'LBL_EDIT'=>'编辑',
+'LBL_EVERYDAY'=>'每天',
+'LBL_EVERYWEEK'=>'每周',
+'LBL_EVERYMON'=>'每月',
+'LBL_WEEKS'=>'周',
+'LBL_MONTHS'=>'月',
+'LBL_YEAR'=>'年',
+'LBL_NONE_SCHEDULED'=>'没有任何行程',
+
+'LBL_INVITE_INST1'=>'邀请的方式可以从目前使用者列表选择并且点选新增按钮',
+'LBL_INVITE_SHARE'=>'分享的方式可以从目前使用者列表选择并且点选新增按钮.',
+'LBL_INVITE_INST2'=>'移除邀请的人可以从选择的使用者列表选择并且点选移除按钮',
+'LBL_SELUSR_INFO'=>'选择的使用者会收到一封事件的通知。',
+'LBL_CALSHAREMESSAGE'=>'开放我的行事历给下面选择的使用者',
+'LBL_CALSHARE'=>'共享行事历',
+'LBL_SEL_USERS'=>'已选择用户',
+'LBL_AVL_USERS'=>'可选择用户',
+'LBL_ADD_BUTTON'=>'新增',
+'LBL_USERS'=>'用户',
+'LBL_RMV_BUTTON'=>'删除',
+'LBL_SDRMD'=>'发送提醒讯息',
+'LBL_ENABLE_REPEAT'=>'启用循环',
+'LBL_REPEAT_ONCE'=>'循环频率',
+'LBL_ADD_TODO'=>'建立待办事项',
+'LBL_TODONAME'=>'待办事项',
+'LBL_TODODATETIME'=>'时间与日期',
+
+
+
+
+
+//DON'T CONVERT THESE THEY ARE MAPPINGS - STARTS
+'db_last_name'=>'LBL_LIST_LAST_NAME',
+'db_first_name'=>'LBL_LIST_FIRST_NAME',
+'db_title'=>'LBL_LIST_TITLE',
+'db_email1'=>'LBL_LIST_EMAIL_ADDRESS',
+'db_email2'=>'LBL_LIST_EMAIL_ADDRESS',
+//DON'T CONVERT THESE THEY ARE MAPPINGS -ENDS
+'LBL_COMPLETED'=>'标示为完成',
+'LBL_DEFERRED'=>'标示为延缓',
+'LBL_HELD'=>'标示为执行',
+'LBL_NOTHELD'=>'标示为不执行',
+'LBL_POSTPONE'=>'延期',
+'LBL_CHANGEOWNER'=>'修改负责人',
+'LBL_DEL'=>'删除',
+
+//Added for actvity merge with calendar
+'LBL_SEARCH_FORM_TITLE'=>'搜索待办事项',
+'LBL_LIST_FORM_TITLE'=>'待办事项列表',
+'LBL_NEW_FORM_TITLE'=>'新增待办事项',
+'LBL_TASK_INFORMATION'=>'任务信息',
+'LBL_EVENT_INFORMATION'=>'事件信息',
+'LBL_CALENDAR_INFORMATION'=>'日历信息',
+
+'LBL_NAME'=>'主题:',
+'LBL_ACTIVITY_NOTIFICATION'=>'这是通知活动分配给你',
+'LBL_ACTIVITY_INVITATION'=>'你被邀请参与一个活动',
+'LBL_DETAILS_STRING'=>'细节是',
+'LBL_REGARDS_STRING'=>'感谢和问候',
+'LBL_CONTACT_NAME'=>'联系人',
+'LBL_OPEN_ACTIVITIES'=>'进行中事项',
+'LBL_ACTIVITY'=>'待办事项:',
+'LBL_HISTORY'=>'纪录',
+'LBL_UPCOMING'=>'即将到来与等待中待办事项',
+'LBL_TODAY'=>'到',
+
+'LBL_NEW_TASK_BUTTON_TITLE'=>'新增任务[Alt+N]',
+'LBL_NEW_TASK_BUTTON_KEY'=>'N',
+'LBL_NEW_TASK_BUTTON_LABEL'=>'新增任务',
+'LBL_SCHEDULE_MEETING_BUTTON_TITLE'=>'安排会议[Alt+M]',
+'LBL_SCHEDULE_MEETING_BUTTON_KEY'=>'M',
+'LBL_SCHEDULE_MEETING_BUTTON_LABEL'=>'安排会议',
+'LBL_SCHEDULE_CALL_BUTTON_TITLE'=>'安排电话[Alt+C]',
+'LBL_SCHEDULE_CALL_BUTTON_KEY'=>'C',
+'LBL_SCHEDULE_CALL_BUTTON_LABEL'=>'安排电话',
+'LBL_NEW_NOTE_BUTTON_TITLE'=>'新增记事[Alt+T]',
+'LBL_NEW_ATTACH_BUTTON_TITLE'=>'附加档案[Alt+F]',
+'LBL_NEW_NOTE_BUTTON_KEY'=>'T',
+'LBL_NEW_ATTACH_BUTTON_KEY'=>'F',
+'LBL_NEW_NOTE_BUTTON_LABEL'=>'新增记事',
+'LBL_NEW_ATTACH_BUTTON_LABEL'=>'附加档案',
+'LBL_TRACK_EMAIL_BUTTON_TITLE'=>'追踪邮件[Alt+K]',
+'LBL_TRACK_EMAIL_BUTTON_KEY'=>'K',
+'LBL_TRACK_EMAIL_BUTTON_LABEL'=>'追踪邮件',
+
+'LBL_LIST_CLOSE'=>'关闭',
+'LBL_LIST_STATUS'=>'状态',
+'LBL_LIST_CONTACT'=>'联系人',
+//Added for 4.2 release for Account column support as shown by Fredy
+'LBL_LIST_ACCOUNT'=>'客户',
+'LBL_LIST_RELATED_TO'=>'相关于',
+'LBL_LIST_DUE_DATE'=>'结束日期',
+'LBL_LIST_DATE'=>'日期',
+'LBL_LIST_SUBJECT'=>'主旨1',
+'LBL_LIST_LAST_MODIFIED'=>'最后更新',
+'LBL_LIST_RECURRING_TYPE'=>'循环类型',
+
+'ERR_DELETE_RECORD'=>"一个记录编号必须被指定删除vtiger_account.",
+'NTC_NONE_SCHEDULED'=>'没有安排.',
+
+// Added vtiger_fields for Attachments in Activities/SubPanelView.php
+'LBL_ATTACHMENTS'=>'附加档案',
+'LBL_NEW_ATTACHMENT'=>'新增附加档案',
+
+//Added vtiger_fields after RC1 - Release
+'LBL_ALL'=>'全部',
+'LBL_CALL'=>'呼叫',
+'LBL_MEETING'=>'会议',
+'LBL_TASK'=>'任务',
+
+//Added for 4GA Release
+'Subject'=>'主题',
+'Assigned To'=>'指定给',
+'Start Date & Time'=>'开始日期与时间',
+'Time Start'=>'开始时间',
+'Due Date'=>'到期日',
+'Related To'=>'相关于',
+'Contact Name'=>'联系人名称',
+'Status'=>'状态',
+'Priority'=>'优先级',
+'Visibility'=>'显示',
+'Send Notification'=>'发送邮件通知',
+'Created Time'=>'建立时间',
+'Modified Time'=>'修改时间',
+'Activity Type'=>'活动类型',
+'Description'=>'描述',
+'Duration'=>'期间',
+'Duration Minutes'=>'期间分钟',
+'Location'=>'位置',
+'No Time'=>'没有时间',
+//Added for Send Reminder 4.2 release
+'Send Reminder'=>'提醒通知',
+'LBL_YES'=>'是',
+'LBL_NO'=>'否',
+'LBL_DAYS'=>'日',
+'LBL_MINUTES'=>'分',
+'LBL_HOURS'=>'时',
+'LBL_BEFORE_EVENT'=>'时间前',
+//Added for CustomView 4.2 Release
+'Close'=>'关闭',
+'Start Date'=>'开始日期',
+'Type'=>'类型',
+'End Date'=>'结束日期',
+'Recurrence'=>'循环事件',
+'Recurring Type'=>'循环类型',
+//Activities - Notification Error
+'LBL_NOTIFICATION_ERROR'=>'邮件错误:请检查您的发送邮件服务器设置,在设定 > 发送邮件服务器设置或是目前使用者的邮件设置',
+// Mike Crowe Mod --------------------------------------------------------added for generic search
+'LBL_GENERAL_INFORMATION'=>'一般信息',
+
+'LBL_EVENTTYPE'=>'事件类型',
+'LBL_EVENTNAME'=>'事件名称',
+'LBL_EVENTSTAT'=>'事件开始于',
+'LBL_EVENTEDAT'=>'事件结束于',
+'LBL_INVITE'=>'邀请',
+'LBL_REPEAT'=>'重复',
+'LBL_REMINDER'=>'提示',
+'LBL_SENDREMINDER'=>'发送提示',
+'LBL_NOTIFICATION'=>'通知',
+'LBL_SENDNOTIFICATION'=>'发送通知',
+'LBL_RMD_ON'=>'提醒',
+'LBL_REPEATEVENT'=>'每个都重复一次',
+'LBL_TIMEDATE'=>'时间和日期',
+'LBL_HR'=>'时',
+'LBL_MIN'=>'分',
+'LBL_EVENT'=>'事件',
+'Daily'=>'天',
+'Weekly'=>'周',
+'Monthly'=>'月',
+'Yearly'=>'年',
+'createdtime'=>'建立时间',
+'modifiedtime'=>'修改时间',
+'first'=>'第一个',
+'last'=>'最后一个',
+'High'=>'高',
+'Medium'=>'中',
+'Low'=>'低',
+'LBL_SELECT'=>'选择',
+'LBL_ALL_EVENTS_TODOS'=>'所有事件与工作',
+'First'=>'第一笔',
+'Last'=>'最后一笔',
+'on'=>'于',
+'day of the month'=>'日',
+'Private'=>'私有',
+'Public'=>'公共',
+
+//Added for existing Picklist entries
+
+'Planned'=>'已规划',
+'Held'=>'保留',
+'Not Held'=>'不保留',
+'Completed'=>'完成',
+'Deferred'=>'延期',
+'Not Started'=>'未开始',
+'In Progress'=>'处理中',
+'Pending Input'=>'等待输入',
+'LBL_REMAINDER_DAY'=>'天',
+'LBL_REMAINDER_HRS'=>'小时',
+'Call'=>'电话',
+'Meeting'=>'会议',
+
+//added to send dates and time in calendar notification/invitation mail.
+
+'Start date and time'=>'开始日期和时间',
+'End date and time'=>'结束日期和时间',
+//this is for task
+'End date'=>'结束日期',
+'LBL_SET_DATE'=>'设置日期..',
+'Recurrence'=>'再现',
+
+//added to send invitation mail Subject.
+'INVITATION'=>'邀请',
+
+// Added/Updated for vtiger CRM 5.0.4
+'LBL_YEAR_BUTTON_TITLE'=>'Year[Alt+Y]',
+'LBL_SELECT_CONTACT'=>'选择联系人',
+'SHARED_EVENT_DEL_MSG'=>'用户没有允许删除这个纪录.',
+//added to fix ticket#4525
+'LBL_CREATED'=>'新建',
+'LBL_UPDATED'=>'更新',
+
+//Added after 5.0.4 GA
+'LBL_BUSY'=>'忙碌',
+
+//Custom Fields support for Calendar
+'LBL_CUSTOM_INFORMATION'=>'自定义信息',
+
+// Repeat Event support for Calendar
+'LBL_UNTIL'=>'至',
+'LBL_SET_DATE'=>'设置日期',
+
+'LBL_MINE'=>'我的',
+'LBL_SUCCESS_CALENDAR_1' => '成功导入任务数 : ',
+'LBL_SKIPPED_CALENDAR_1' => '忽略的任务数(一个字段或者多个字段丢失): ',
+'LBL_SUCCESS_EVENTS_1' => '成功导入事件数 : ',
+'LBL_SKIPPED_EVENTS_1' => '忽略的事件数(一个字段或者多个字段丢失): ',
+'LBL_FINISHED'=>'完成',
+'LBL_UNDO_LAST_IMPORT'=>'重做最后一次导入',
+'LBL_LAST_IMPORT'=>'最后导入',
+'LBL_LAST_IMPORT_UNDONE'=>'你的最后一次导入被重做',
+'LBL_SUCCESS'=>'成功!',
+'LBL_NO_IMPORT_TO_UNDO'=>'没有可重做的导入。',
+'LBL_FAILURE'=>'完成!',
+);
+
+?>
diff --git a/oss/vtiger/trunk/modules/Calendar/new_calendar.php b/oss/vtiger/trunk/modules/Calendar/new_calendar.php
new file mode 100644
index 00000000..afcf5490
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/new_calendar.php
@@ -0,0 +1,92 @@
+activity_view == "This Year"){
+ $mysel = 'year';
+ }else if($current_user->activity_view == "This Month"){
+ $mysel = 'month';
+ }else if($current_user->activity_view == "This Week"){
+ $mysel = 'week';
+ }else{
+ $mysel = 'day';
+ }
+}
+/* fix given by dartagnanlaf END --integrated by Minnie */
+$date_data = array();
+if ( isset($_REQUEST['day']))
+{
+
+ $date_data['day'] = $_REQUEST['day'];
+}
+
+if ( isset($_REQUEST['month']))
+{
+ $date_data['month'] = $_REQUEST['month'];
+}
+
+if ( isset($_REQUEST['week']))
+{
+ $date_data['week'] = $_REQUEST['week'];
+}
+
+if ( isset($_REQUEST['year']))
+{
+ if ($_REQUEST['year'] > 2037 || $_REQUEST['year'] < 1970)
+ {
+ print("".$app_strings['LBL_CAL_LIMIT_MSG']."");
+ exit;
+ }
+ $date_data['year'] = $_REQUEST['year'];
+}
+
+
+if(empty($date_data))
+{
+ $data_value=date('Y-m-d H:i:s');
+ preg_match('/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/',$data_value,$value);
+ $date_data = Array(
+ 'day'=>$value[3],
+ 'month'=>$value[2],
+ 'year'=>$value[1],
+ 'hour'=>$value[4],
+ 'min'=>$value[5],
+ );
+
+}
+$calendar_arr['calendar'] = new Calendar($mysel,$date_data);
+if($current_user->hour_format != '')
+ $calendar_arr['calendar']->hour_format=$current_user->hour_format;
+if ($viewBox == 'hourview' && ($mysel == 'day' || $mysel == 'week' || $mysel == 'month' || $mysel == 'year'))
+{
+ $calendar_arr['calendar']->add_Activities($current_user);
+}
+$calendar_arr['view'] = $mysel;
+calendar_layout($calendar_arr,$viewBox,$subtab);
+?>
\ No newline at end of file
diff --git a/oss/vtiger/trunk/modules/Calendar/script.js b/oss/vtiger/trunk/modules/Calendar/script.js
new file mode 100644
index 00000000..9a7bd799
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/script.js
@@ -0,0 +1,1400 @@
+/*********************************************************************************
+
+** The contents of this file are subject to the vtiger CRM Public License Version 1.0
+ * ("License"); You may not use this file except in compliance with the License
+ * The Original Code is: vtiger CRM Open Source
+ * The Initial Developer of the Original Code is vtiger.
+ * Portions created by vtiger are Copyright (C) vtiger.
+ * All Rights Reserved.
+ ********************************************************************************/
+
+function DisableSharing()
+{
+
+ x = document.SharedList.selected_id.length;
+ idstring = "";
+ xx = 0;
+ if ( x == undefined)
+ {
+
+ if (document.SharedList.selected_id.checked)
+ {
+ document.SharedList.idlist.value=document.SharedList.selected_id.value;
+ }
+ else
+ {
+ alert(alert_arr.SELECT_ATLEAST_ONE_USER);
+ return false;
+ }
+ }
+ else
+ {
+ for(i = 0; i < x ; i++)
+ {
+ if(document.SharedList.selected_id[i].checked)
+ {
+ idstring = document.SharedList.selected_id[i].value +";"+idstring
+ xx++
+ }
+ }
+ if (xx != 0)
+ {
+ document.SharedList.idlist.value=idstring;
+ }
+ else
+ {
+ alert(alert_arr.SELECT_ATLEAST_ONE_USER);
+ return false;
+ }
+ }
+ if(confirm(alert_arr.DISABLE_SHARING_CONFIRMATION+xx+alert_arr.USERS))
+ {
+ document.SharedList.action="index.php?module=Calendar&action=disable_sharing&return_module=Calendar&return_action=calendar_share";
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+
+function showhide(argg)
+{
+ var x=document.getElementById(argg).style;
+ if (x.display=="none")
+ {
+ x.display="block"
+
+ }
+ else {
+ x.display="none"
+ }
+}
+
+
+function showhideRepeat(argg1,argg2)
+{
+ var x=document.getElementById(argg2).style;
+ var y=document.getElementById(argg1).checked;
+
+ if (y)
+ {
+ x.display="block";
+ }
+ else {
+ x.display="none";
+ }
+
+}
+
+
+
+function gshow(argg1,type,startdate,enddate,starthr,startmin,startfmt,endhr,endmin,endfmt,viewOption,subtab)
+{
+ smin = parseInt(startmin,10);
+ smin = smin - (smin%5);
+ var y=document.getElementById(argg1).style;
+
+ if(type != 'todo' && type!='')
+ {
+ for(var i=0;;i++){
+ if( document.EditView.activitytype[i].value == type){
+ document.EditView.activitytype[i].selected='yes';
+ break;
+ }
+ }
+
+ smin = _2digit(smin);
+ document.EditView.date_start.value = startdate;
+ document.EditView.starthr.value = starthr;
+ document.EditView.startmin.value = smin;
+ document.EditView.startfmt.value = startfmt;
+ document.EditView.viewOption.value = viewOption;
+ document.EditView.subtab.value = subtab;
+ calDuedatetime(type);
+ }
+ if(type == 'todo')
+ {
+ smin = _2digit(smin);
+ document.createTodo.task_date_start.value = startdate;
+ document.createTodo.task_due_date.value = enddate;
+ document.createTodo.starthr.value = starthr;
+ document.createTodo.startmin.value = smin;
+ document.createTodo.startfmt.value = startfmt;
+ document.createTodo.viewOption.value = viewOption;
+ document.createTodo.subtab.value = subtab;
+ }
+ if (y.display=="none")
+ {
+ y.display="block";
+ }
+}
+
+function rptoptDisp(Opt){
+ var currOpt = Opt.options[Opt.selectedIndex].value;
+ if(currOpt == "Daily")
+ {
+ ghide('repeatWeekUI');
+ ghide('repeatMonthUI');
+ }
+ else if(currOpt == "Weekly")
+ {
+ if(document.getElementById('repeatWeekUI').style.display == "none");
+ document.getElementById('repeatWeekUI').style.display = "block";
+ ghide('repeatMonthUI');
+ }
+ else if(currOpt == "Monthly")
+ {
+ ghide('repeatWeekUI');
+ if(document.getElementById('repeatMonthUI').style.display == "none");
+ document.getElementById('repeatMonthUI').style.display = "block";
+ }
+ else if(currOpt == "Yearly")
+ {
+ ghide('repeatWeekUI');
+ ghide('repeatMonthUI');
+ }
+}
+
+function Taskshow(argg1,type,startdate,starthr,startmin,startfmt)
+{
+ var y=document.getElementById(argg1).style;
+ if (y.display=="none")
+ {
+ document.EditView.date_start.value = startdate;
+ document.EditView.starthr.value = starthr;
+ document.EditView.startmin.value = startmin;
+ document.EditView.startfmt.value = startfmt;
+ y.display="block";
+ }
+}
+
+function ghide(argg2)
+{
+ var z=document.getElementById(argg2).style;
+ if (z.display=="block" )
+ {
+ z.display="none"
+
+ }
+}
+
+ function moveMe(arg1) {
+ var posx = 0;
+ var posy = 0;
+ var e=document.getElementById(arg1);
+
+ if (!e) var e = window.event;
+
+ if (e.pageX || e.pageY)
+ {
+ posx = e.pageX;
+ posy = e.pageY;
+ }
+ else if (e.clientX || e.clientY)
+ {
+ posx = e.clientX + document.body.scrollLeft;
+ posy = e.clientY + document.body.scrollTop;
+ }
+ }
+
+function switchClass(myModule,toStatus) {
+ var x=document.getElementById(myModule);
+ if($(x))
+ {
+ if (toStatus=="on") {
+ x.className="dvtSelectedCell";
+ }
+ if (toStatus=="off") {
+ x.className="dvtUnSelectedCell";
+ }
+ }
+
+}
+
+function enableCalstarttime()
+{
+ if(document.SharingForm.sttime_check.checked == true)
+ document.SharingForm.start_hour.disabled = false;
+ else
+ document.SharingForm.start_hour.disabled = true;
+}
+function check_form()
+{
+ formSelectColumnString('inviteesid','selectedusers');
+ if(trim(document.EditView.subject.value) == "")
+ {
+ alert(alert_arr.MISSING_EVENT_NAME);
+ document.EditView.subject.focus()
+ return false;
+ }
+ else
+ {
+ if(document.EditView.record.value != '')
+ {
+ document.EditView.mode.value = 'edit';
+ }
+ else
+ {
+ document.EditView.mode.value = 'create';
+ }
+ starthour = parseInt(document.EditView.starthr.value,10);
+ startmin = parseInt(document.EditView.startmin.value,10);
+ startformat = document.EditView.startfmt.value;
+ endhour = parseInt(document.EditView.endhr.value,10);
+ endmin = parseInt(document.EditView.endmin.value,10);
+ endformat = document.EditView.endfmt.value;
+ followupformat = document.EditView.followup_startfmt.value;
+ followuphour = parseInt(document.EditView.followup_starthr.value,10);
+ followupmin = parseInt(document.EditView.followup_startmin.value,10);
+ if(startformat != '')
+ {
+ if(startformat == 'pm')
+ {
+ if(starthour == 12)
+ starthour = 12;
+ else
+ starthour = starthour + 12;
+ }
+ else
+ {
+ if(starthour == 12)
+ starthour = 0;
+ else
+ starthour = starthour;
+ }
+ }
+ if(endformat != '')
+ {
+ if(endformat == 'pm')
+ {
+ if(endhour == 12)
+ endhour = 12;
+ else
+ endhour = endhour + 12;
+ }
+ else
+ {
+ if(endhour == 12)
+ endhour = 0;
+ else
+ endhour = endhour;
+ }
+ }
+ if(!dateValidate('date_start','Start date','OTH'))
+ {
+ return false;
+ }
+ if(!dateValidate('due_date','End date','OTH'))
+ {
+ return false;
+ }
+ if(dateComparison('due_date','End date','date_start','Start date','GE'))
+ {
+ var dateval1=getObj('date_start').value.replace(/^\s+/g, '').replace(/\s+$/g, '');
+ var dateval2=getObj('due_date').value.replace(/^\s+/g, '').replace(/\s+$/g, '');
+ var dateval3=getObj('followup_date').value.replace(/^\s+/g, '').replace(/\s+$/g, '');
+
+ var dateelements1=splitDateVal(dateval1)
+ var dateelements2=splitDateVal(dateval2)
+ var dateelements3=splitDateVal(dateval3)
+
+ dd1=dateelements1[0]
+ mm1=dateelements1[1]
+ yyyy1=dateelements1[2]
+
+ dd2=dateelements2[0]
+ mm2=dateelements2[1]
+ yyyy2=dateelements2[2]
+
+ dd3=dateelements3[0]
+ mm3=dateelements3[1]
+ yyyy3=dateelements3[2]
+
+ var date1=new Date()
+ var date2=new Date()
+ var date3=new Date()
+
+ date1.setYear(yyyy1)
+ date1.setMonth(mm1-1)
+ date1.setDate(dd1)
+ date1.setHours(starthour)
+ date1.setMinutes(startmin)
+
+ date2.setYear(yyyy2)
+ date2.setMonth(mm2-1)
+ date2.setDate(dd2)
+ date2.setHours(endhour)
+ date2.setMinutes(endmin)
+
+ date3.setYear(yyyy3)
+ date3.setMonth(mm3-1)
+ date3.setDate(dd3)
+
+ diff_ms = Math.abs(date2.getTime()-date1.getTime())/(1000*60);
+ hour = Math.floor(diff_ms/(60));
+ minute = Math.floor(diff_ms % 60)
+ document.EditView.duration_hours.value = hour;
+ document.EditView.duration_minutes.value = minute;
+
+ event_starthour = _2digit(starthour);
+ event_startmin = _2digit(startmin);
+ event_endhour = _2digit(endhour);
+ event_endmin = _2digit(endmin);
+ document.EditView.time_start.value = event_starthour+':'+event_startmin;
+ document.EditView.time_end.value = event_endhour+':'+event_endmin;
+ // Added for Aydin Kurt-Elli requirement START -by Minnie
+ if (document.EditView.followup.checked == true && document.getElementById('date_table_thirdtd').style.display == 'block')
+ {
+ if(!dateValidate('followup_date','Followup Date','OTH'))
+ {
+ return false;
+ }
+ if(followupformat != '')
+ {
+ if(followupformat == 'pm')
+ {
+ if(followuphour == 12)
+ followuphour = 12;
+ else
+ followuphour = followuphour + 12;
+ }
+ else
+ {
+ if(followuphour == 12)
+ followuphour = 0;
+ else
+ followuphour = followuphour;
+ }
+ }
+
+ if ( compareDates(date3,'Followup Date',date2,'End Date','GE'))
+ {
+ if (date3 <= date2)
+ {
+ if((followuphour*60+followupmin) <= (endhour*60+endmin))
+ {
+ alert(alert_arr.FOLLOWUPTIME_GREATER_THAN_STARTTIME);
+ document.EditView.followup_starthr.focus();
+ return false;
+ }
+ }
+ }
+ else return false;
+ //modified to set followup end date depends on the event or todo. If it is Event, the difference between followup start date and end date is 1hr. If it is todo then difference is 5mins.
+ date3.setMinutes(followupmin);
+ date3.setHours(followuphour);
+ if(document.EditView.activitytype[0].checked == true)
+ {
+ date3.setMinutes(parseInt(date3.getMinutes(),10)+5);
+ }
+ if(document.EditView.activitytype[1].checked == true)
+ {
+ date3.setMinutes(parseInt(date3.getMinutes(),10)+60);
+ }
+ var tempdate = getdispDate(date3);
+
+ followuphour = _2digit(followuphour);
+ followupmin = _2digit(followupmin);
+ followupendhour = _2digit(date3.getHours());
+ followupendmin = _2digit(date3.getMinutes());
+ document.EditView.followup_due_date.value = tempdate;
+ document.EditView.followup_time_start.value = followuphour+':'+followupmin;
+ document.EditView.followup_time_end.value = followupendhour+':'+followupendmin;
+ //end
+ }
+ // Added for Aydin Kurt-Elli requirement END -by Minnie -->
+
+ //added to avoid db error while giving characters in the repeat "every n no of day in month" text box
+ if((getObj("recurringcheck")) && (document.EditView.recurringcheck.checked == true) && (document.EditView.recurringtype.value =="Monthly"))
+ {
+ if((document.EditView.repeatMonth[0].checked == true) && ((parseInt(parseFloat(document.EditView.repeatMonth_date.value))!=document.EditView.repeatMonth_date.value) || document.EditView.repeatMonth_date.value=='' || parseInt(document.EditView.repeatMonth_date.value)>'31' || document.EditView.repeatMonth_date.value<='0'))
+ {
+ alert(alert_arr.INVALID +' "'+document.EditView.repeatMonth_date.value+'" ');
+ document.EditView.repeatMonth_date.focus();
+ return false;
+ }
+ }
+ //end
+
+
+ //added to check Start Date & Time,if Activity Status is Planned.//start
+ if(document.EditView.eventstatus.value == "Planned")
+ {
+ var chkdate=new Date()
+ chkdate.setMinutes(event_startmin)
+ chkdate.setHours(event_starthour)
+ chkdate.setYear(yyyy1)
+ chkdate.setMonth(mm1-1)
+ chkdate.setDate(dd1)
+ if(!comparestartdate(chkdate)) return false;
+
+ }
+
+ }
+ else
+ return false;
+ if(getObj("recurringcheck") && document.EditView.recurringcheck.checked == false)
+ {
+ document.EditView.recurringtype.value = '--None--';
+ }
+ return true;
+ }
+}
+
+function task_check_form()
+{
+ starthour = parseInt(document.createTodo.starthr.value,10);
+ startmin = parseInt(document.createTodo.startmin.value,10);
+ startformat = document.createTodo.startfmt.value;
+ if(startformat != '')
+ {
+ if(startformat == 'pm')
+ {
+ if(starthour == 12)
+ starthour = 12;
+ else
+ starthour = starthour + 12;
+
+ }
+ else
+ {
+ if(starthour == 12)
+ starthour = 0;
+ else
+ starthour = starthour;
+ }
+ }
+ starthour = _2digit(starthour);
+ startmin = _2digit(startmin);
+ document.createTodo.task_time_start.value = starthour+':'+startmin;
+ if(document.createTodo.record.value != '')
+ {
+ document.createTodo.mode.value = 'edit';
+ }
+ else
+ {
+ document.createTodo.mode.value = 'create';
+ }
+
+}
+
+
+function maintask_check_form()
+{
+ starthour = parseInt(document.EditView.starthr.value,10);
+ startmin = parseInt(document.EditView.startmin.value,10);
+ startformat = document.EditView.startfmt.value;
+ if(startformat != '')
+ {
+ if(startformat == 'pm')
+ {
+ if(starthour == 12)
+ starthour = 12;
+ else
+ starthour = starthour + 12;
+ }
+ else
+ {
+ if(starthour == 12)
+ starthour = 0;
+ else
+ starthour = starthour;
+ }
+ }
+ starthour = _2digit(starthour);
+ startmin = _2digit(startmin);
+ document.EditView.time_start.value = starthour+':'+startmin;
+}
+
+
+var moveupLinkObj,moveupDisabledObj,movedownLinkObj,movedownDisabledObj;
+
+function userEventSharing(selectedusrid,selcolid)
+{
+ formSelectColumnString(selectedusrid,selcolid);
+}
+
+
+function incUser(avail_users,sel_users)
+{
+ availListObj=getObj(avail_users)
+ selectedColumnsObj=getObj(sel_users)
+ var selectlength=selectedColumnsObj.length
+ var availlength=availListObj.length
+
+ for (i=0;i= 0)
+ selectedColumnsObj.remove(selectedColumnsObj.options.selectedIndex)
+ }
+
+}
+
+
+// function to delete activity related contact in calendar
+var del_ids = new Array();
+function removeActContacts()
+{
+ var avail_contacts = getObj('parentid');
+ // this block is to remove contacts and get deleted contact ids
+ if(avail_contacts.options.selectedIndex > -1)
+ {
+ for(m = 0; m < avail_contacts.options.length; m++)
+ {
+ if(avail_contacts.options[m].selected == true)
+ {
+ del_ids.push(avail_contacts.options[m].value);
+ avail_contacts.options[m] = null;
+ removeActContacts();
+ }
+ }
+ }
+ document.EditView.deletecntlist.value = del_ids.join(";");
+
+ // this block is to get available id list
+ var avail_ids = new Array();
+ for(n=0; n window.innerWidth ){
+ leftSide = eval(leftSide) - eval(widthM);
+ tagName.style.left = leftSide + 'px';
+ }
+ else
+ tagName.style.left= leftSide + 'px';
+ tagName.style.top= topSide + 'px';
+ tagName.style.display = 'block';
+ tagName.style.visibility = "visible";
+ if(type == 'event')
+ {
+ var heldstatus = "eventstatus=Held";
+ var notheldstatus = "eventstatus=Not Held";
+ var activity_mode = "Events";
+ var complete = document.getElementById("complete");
+ var pending = document.getElementById("pending");
+ var postpone = document.getElementById("postpone");
+ var actdelete = document.getElementById("actdelete");
+ var changeowner = document.getElementById("changeowner");
+ var OptionData = document.getElementById('view_Option').options[document.getElementById('view_Option').selectedIndex].value;
+
+ }
+ if(type == 'todo')
+ {
+ var heldstatus = "status=Completed";
+ var notheldstatus = "status=Deferred";
+ var activity_mode = "Task";
+ var complete = document.getElementById("taskcomplete");
+ var pending = document.getElementById("taskpending");
+ var postpone = document.getElementById("taskpostpone");
+ var actdelete = document.getElementById("taskactdelete");
+ var changeowner = document.getElementById("taskchangeowner");
+ var OptionData = '';
+ }
+ document.getElementById("idlist").value = id;
+ document.change_owner.hour.value = hour;
+ document.change_owner.day.value = day;
+ document.change_owner.view.value = view;
+ document.change_owner.month.value = month;
+ document.change_owner.year.value = year;
+ document.change_owner.subtab.value = type;
+ if(complete) complete.href="javascript:updateStatus("+id+",'"+heldstatus+"','"+view+"',"+hour+","+day+","+month+","+year+",'"+type+"')";
+ if(pending) pending.href="javascript:updateStatus("+id+",'"+notheldstatus+"','"+view+"',"+hour+","+day+","+month+","+year+",'"+type+"')";
+
+ if(postpone) postpone.href="index.php?module=Calendar&action=EditView&record="+id+"&return_action=index&activity_mode="+activity_mode+"&view="+view+"&hour="+hour+"&day="+day+"&month="+month+"&year="+year+"&viewOption="+OptionData+"&subtab="+type+"&maintab=Calendar";
+
+ if(actdelete) actdelete.href="javascript:delActivity("+id+",'"+view+"',"+hour+","+day+","+month+","+year+",'"+type+"')";
+
+ if(changeowner) changeowner.href="javascript:dispLayer('act_changeowner');";
+
+}
+
+function dispLayer(lay)
+{
+ var tagName = document.getElementById(lay);
+ tagName.style.visibility = 'visible';
+ tagName.style.display = 'block';
+}
+
+//check whether user form selected or group form selected
+function checkgroup()
+{
+ if($("group_checkbox").checked)
+ {
+ document.change_owner.lead_group_owner.style.display = "block";
+ document.change_owner.lead_owner.style.display = "none";
+ }
+ else
+ {
+ document.change_owner.lead_group_owner.style.display = "none";
+ document.change_owner.lead_owner.style.display = "block";
+ }
+}
+
+function calendarChangeOwner()
+{
+ var idlist = document.change_owner.idlist.value;
+ var view = document.change_owner.view.value;
+ var day = document.change_owner.day.value;
+ var month = document.change_owner.month.value;
+ var year = document.change_owner.year.value;
+ var hour = document.change_owner.hour.value;
+ var subtab = document.change_owner.subtab.value;
+
+ //var checked = document.change_owner.user_lead_owner[0].checked;
+ if($("user_checkbox").checked)
+ {
+ var user_id = document.getElementById('lead_owner').options[document.getElementById('lead_owner').options.selectedIndex].value;
+ var url = 'module=Users&action=updateLeadDBStatus&return_module=Calendar&return_action=ActivityAjax&owner_id='+user_id+'&idlist='+idlist+'&view='+view+'&hour='+hour+'&day='+day+'&month='+month+'&year='+year+'&type=change_owner&owner_type=User';
+ }
+ else
+ {
+ var group_id = document.getElementById('lead_group_owner').options[document.getElementById('lead_group_owner').options.selectedIndex].value;
+ var url = 'module=Users&action=updateLeadDBStatus&return_module=Calendar&return_action=ActivityAjax&owner_id='+group_id+'&idlist='+idlist+'&view='+view+'&hour='+hour+'&day='+day+'&month='+month+'&year='+year+'&type=change_owner&owner_type=Group';
+ }
+
+ if(subtab == 'event')
+ {
+ var OptionData = $('view_Option').options[$('view_Option').selectedIndex].value;
+ var eventurl = url+'&viewOption='+OptionData+'&subtab=event&ajax=true';
+
+ new Ajax.Request(
+ 'index.php',
+ {queue: {position: 'end', scope: 'command'},
+ method: 'post',
+ postBody: eventurl,
+ onComplete: function(response) {
+ if(OptionData == 'listview')
+ {
+ result = response.responseText.split('####');
+ $("total_activities").innerHTML = result[1];
+ $("listView").innerHTML=result[0];
+ document.EventViewOption.action.value = "index";
+ window.document.EventViewOption.submit();
+ }
+ if(OptionData == 'hourview')
+ {
+ result = response.responseText.split('####');
+ $("total_activities").innerHTML = result[1];
+ $("hrView").innerHTML=result[0];
+ document.EventViewOption.action.value = "index";
+ window.document.EventViewOption.submit();
+ }
+ }
+ }
+ );
+ }
+ if(subtab == 'todo')
+ {
+
+ var todourl = url+'&subtab=todo&ajax=true';
+ new Ajax.Request(
+ 'index.php',
+ {queue: {position: 'end', scope: 'command'},
+ method: 'post',
+ postBody: todourl,
+ onComplete: function(response) {
+ result = response.responseText.split('####');
+ $("total_activities").innerHTML = result[1];
+ $("mnuTab2").innerHTML=result[0];
+ }
+ }
+ );
+ }
+}
+
+function delActivity(id,view,hour,day,month,year,subtab)
+{
+ if(subtab == 'event')
+ {
+ var OptionData = $('view_Option').options[$('view_Option').selectedIndex].value;
+ new Ajax.Request(
+ 'index.php',
+ {queue: {position: 'end', scope: 'command'},
+ method: 'post',
+ postBody: 'module=Users&action=massdelete&return_module=Calendar&return_action=ActivityAjax&idlist='+id+'&view='+view+'&hour='+hour+'&day='+day+'&month='+month+'&year='+year+'&type=activity_delete&viewOption='+OptionData+'&subtab=event&ajax=true',
+ onComplete: function(response) {
+ if(OptionData == 'listview')
+ {
+ result = response.responseText.split('####');
+ $("total_activities").innerHTML = result[1];
+ $("listView").innerHTML=result[0];
+ }
+ if(OptionData == 'hourview')
+ {
+ result = response.responseText.split('####');
+ $("total_activities").innerHTML = result[1];
+ $("hrView").innerHTML=result[0];
+ }
+ }
+ }
+ );
+ }
+ if(subtab == 'todo')
+ {
+ new Ajax.Request(
+ 'index.php',
+ {queue: {position: 'end', scope: 'command'},
+ method: 'post',
+ postBody: 'module=Users&action=massdelete&return_module=Calendar&return_action=ActivityAjax&idlist='+id+'&view='+view+'&hour='+hour+'&day='+day+'&month='+month+'&year='+year+'&type=activity_delete&subtab=todo&ajax=true',
+ onComplete: function(response) {
+ result = response.responseText.split('####');
+ $("total_activities").innerHTML = result[1];
+ $("mnuTab2").innerHTML=result[0];
+ }
+ }
+ );
+ }
+}
+
+
+/*
+* javascript function to display the div tag
+* @param divId :: div tag ID
+*/
+function cal_show(divId)
+
+{
+
+ var id = document.getElementById(divId);
+
+ id.style.visibility = 'visible';
+
+}
+
+function fnAssignTo(){
+ var option_Box = document.getElementById('parent_type');
+ var option_select = option_Box.options[option_Box.selectedIndex].value;
+ if(option_select == "Leads" || option_select == "Leads&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else if(option_select == "Accounts" || option_select == "Accounts&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else if(option_select == "Potentials" || option_select == "Potentials&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else if(option_select == "Quotes&action=Popup" || option_select == "Quotes&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else if(option_select == "PurchaseOrder" || option_select == "PurchaseOrder&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else if(option_select == "SalesOrder" || option_select == "SalesOrder&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else if(option_select == "Invoice" || option_select == "Invoice&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else if(option_select == "Campaigns" || option_select == "Campaigns&action=Popup")
+ {
+ document.getElementById('leadLay').style.visibility = 'visible';
+ }
+ else{
+ document.getElementById('leadLay').style.visibility = 'hidden';
+ }
+ }
+
+function fnShowPopup(){
+ document.getElementById('popupLay').style.display = 'block';
+}
+
+function fnHidePopup(){
+ document.getElementById('popupLay').style.display = 'none';
+}
+
+function getValidationarr(id,activity_mode,opmode,subtab,viewOption)
+{
+ new Ajax.Request(
+ 'index.php',
+ {queue: {position: 'end', scope: 'command'},
+ method: 'post',
+ postBody: 'module=Calendar&action=ActivityAjax&record='+id+'&activity_mode='+activity_mode+'&ajax=true&type=view&file=DetailView',
+ onComplete: function(response) {
+ $("dataArray").innerHTML=response.responseText;
+ setFieldvalues(opmode,subtab,viewOption);
+ }
+ }
+ );
+
+}
+
+function setFieldvalues(opmode,subtab,viewOption)
+{
+ var st = document.getElementById('activity_cont');
+ eval(st.innerHTML);
+ if(activity_type == 'Events')
+ {
+ document.EditView.viewOption.value = viewOption;
+ document.EditView.subtab.value = subtab;
+ for(x=0;x is a contact id
+ ltext ==> is a contact name
+**/
+function addOption(lvalue,ltext)
+{
+ var optObj = document.createElement('OPTION')
+ if (browser_ie) optObj.innerText = ltext;
+ else if(browser_nn4 || browser_nn6) optObj.text = ltext;
+ else optObj.text = ltext;
+ optObj.value = lvalue;
+ document.getElementById('parentid').appendChild(optObj);
+}
+
+function getdispDate(tempDate)
+{
+ var datefmt = document.EditView.dateformat.value;
+ var dd = _2digit(parseInt(tempDate.getDate(),10));
+ var mm = _2digit(parseInt(tempDate.getMonth(),10)+1);
+ var yy = tempDate.getFullYear();
+ if(datefmt == '%d-%m-%Y') return dd+'-'+mm+'-'+yy;
+ else if(datefmt == '%m-%d-%Y') return mm+'-'+dd+'-'+yy;
+ else return yy+'-'+mm+'-'+dd;
+}
diff --git a/oss/vtiger/trunk/modules/Calendar/updateCalendarSharing.php b/oss/vtiger/trunk/modules/Calendar/updateCalendarSharing.php
new file mode 100644
index 00000000..a1c09e71
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/updateCalendarSharing.php
@@ -0,0 +1,45 @@
+pquery($delquery, array($_REQUEST["current_userid"]));
+
+$selectedid = $_REQUEST['shar_userid'];
+$sharedid = explode (";",$selectedid);
+if(isset($sharedid) && $sharedid != null)
+{
+ foreach($sharedid as $sid)
+ {
+ if($sid != '')
+ {
+ $sql = "insert into vtiger_sharedcalendar values (?,?)";
+ $adb->pquery($sql, array($_REQUEST["current_userid"], $sid));
+ }
+ }
+}
+if(isset($_REQUEST['start_hour']) && $_REQUEST['start_hour'] != '')
+{
+ $sql = "update vtiger_users set start_hour=? where id=?";
+ $adb->pquery($sql, array($_REQUEST['start_hour'], $current_user->id));
+}
+
+$sql = "update vtiger_users set hour_format=? where id=?";
+$adb->pquery($sql, array($hour_format, $current_user->id));
+RecalculateSharingRules();
+header("Location: index.php?action=index&module=Calendar&view=".vtlib_purify($_REQUEST['view'])."&hour=".vtlib_purify($_REQUEST['hour'])."&day=".vtlib_purify($_REQUEST['day'])."&month=".vtlib_purify($_REQUEST['month'])."&year=".vtlib_purify($_REQUEST['year'])."&viewOption=".vtlib_purify($_REQUEST['viewOption'])."&subtab=".vtlib_purify($_REQUEST['subtab'])."&parenttab=".getParentTab());
+
+?>
\ No newline at end of file
diff --git a/oss/vtiger/trunk/modules/Calendar/updateRelations.php b/oss/vtiger/trunk/modules/Calendar/updateRelations.php
new file mode 100644
index 00000000..b6e17de7
--- /dev/null
+++ b/oss/vtiger/trunk/modules/Calendar/updateRelations.php
@@ -0,0 +1,64 @@
+pquery($sql, array($id, $_REQUEST["parentid"]));
+ }
+ }
+ header("Location: index.php?action=CallRelatedList&module=Calendar&activity_mode=Events&record=".$record);
+
+}
+elseif(isset($_REQUEST['entityid']) && $_REQUEST['entityid'] != '' && $_REQUEST['destination_module'] == 'Contacts')
+{
+ $record = vtlib_purify($_REQUEST["parentid"]);
+ $sql = "insert into vtiger_cntactivityrel values (?,?)";
+ $adb->pquery($sql, array($_REQUEST["entityid"], $_REQUEST["parentid"]));
+ header("Location: index.php?action=DetailView&module=Calendar&activity_mode=Events&record=".$record);
+}
+
+//This if for adding the vtiger_users
+if(isset($_REQUEST['idlist']) && $_REQUEST['idlist'] != '' && $_REQUEST['destination_module'] == 'Users')
+{
+ //split the string and store in an array
+ $storearray = explode (";",$idlist);
+ foreach($storearray as $id)
+ {
+ if($id != '')
+ {
+ $record = vtlib_purify($_REQUEST['parentid']);
+ $sql = "insert into vtiger_salesmanactivityrel values (?,?)";
+ $adb->pquery($sql, array($id, $_REQUEST["parentid"]));
+ }
+ }
+ header("Location: index.php?action=DetailView&module=Calendar&activity_mode=Events&record=".$record);
+}
+elseif(isset($_REQUEST['entityid']) && $_REQUEST['entityid'] != '' && $_REQUEST['destination_module'] == 'Users')
+{
+ $record = vtlib_purify($_REQUEST['parentid']);
+ $sql = "insert into vtiger_salesmanactivityrel values (?,?)";
+ $adb->pquery($sql, array($_REQUEST["entityid"], $_REQUEST["parentid"]));
+ header("Location: index.php?action=DetailView&module=Calendar&activity_mode=Events&record=".$record);
+
+}
+
+?>
\ No newline at end of file
| | |