/monket-cal-source/icalcreator/iCalcreator.class.php
PHP | 7382 lines | 5553 code | 8 blank | 1821 comment | 1357 complexity | 33abf23ad639818738178066a5f5d4a7 MD5 | raw file
Possible License(s): AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /*********************************************************************************/
- /**
- * iCalcreator class v2.4.3
- * copyright (c) 2007-2008 Kjell-Inge Gustafsson kigkonsult
- * www.kigkonsult.se/iCalcreator/index.php
- * ical@kigkonsult.se
- *
- * Description:
- * This file is a PHP implementation of RFC 2445.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- /*********************************************************************************/
- /*********************************************************************************/
- /* A little setup */
- /*********************************************************************************/
- /* your local language code */
- // define( 'ICAL_LANG', 'sv' );
- // alt. autosetting
- /*
- $langstr = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
- $pos = strpos( $langstr, ';' );
- if ($pos !== false) {
- $langstr = substr( $langstr, 0, $pos );
- $pos = strpos( $langstr, ',' );
- if ($pos !== false) {
- $pos = strpos( $langstr, ',' );
- $langstr = substr( $langstr, 0, $pos );
- }
- define( 'ICAL_LANG', $langstr );
- }
- */
- /* only for phpversion 5.x, date management, default timezone setting */
- if( substr( phpversion(), 0, 1) >= '5' ) // && ( 'UTC' == date_default_timezone_get() )) {
- date_default_timezone_set( 'Europe/Stockholm' );
- /* version string, do NOT remove!! */
- define( 'ICALCREATOR_VERSION', 'iCalcreator 2.4.3' );
- /*********************************************************************************/
- /*********************************************************************************/
- /**
- * vcalendar class
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.13 - 2007-12-30
- */
- class vcalendar {
- // calendar property variables
- var $calscale;
- var $method;
- var $prodid;
- var $version;
- var $xprop;
- // container for calendar components
- var $components;
- // component config variables
- var $allowEmpty;
- var $unique_id;
- var $language;
- var $directory;
- var $filename;
- var $url;
- var $delimiter;
- var $nl;
- var $format;
- // component internal variables
- var $attributeDelimiter;
- var $valueInit;
- // component xCal declaration container
- var $xcaldecl;
- /*
- * constructor for calendar object
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.13 - 2007-12-30
- * @return void
- */
- function vcalendar () {
- $this->_makeVersion();
- $this->calscale = null;
- $this->method = null;
- $this->_makeUnique_id();
- $this->prodid = null;
- $this->xprop = array();
- /**
- * language = <Text identifying a language, as defined in [RFC 1766]>
- */
- if( defined( 'ICAL_LANG' ))
- $this->setConfig( 'language', ICAL_LANG );
- $this->setConfig( 'allowEmpty', TRUE );
- $this->setConfig( 'nl', "\n" );
- $this->setConfig( 'format', 'iCal');
- $this->directory = null;
- $this->filename = null;
- $this->url = null;
- $this->setConfig( 'delimiter', DIRECTORY_SEPARATOR );
- $this->xcaldecl = array();
- $this->components = array();
- }
- /*********************************************************************************/
- /**
- * Property Name: CALSCALE
- */
- /**
- * creates formatted output for calendar property calscale
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.9.7 - 2006-11-20
- * @return string
- */
- function createCalscale() {
- if( !isset( $this->calscale ))
- return;
- switch( $this->format ) {
- case 'xcal':
- return ' calscale="'.$this->calscale.'"'.$this->nl;
- break;
- default:
- return 'CALSCALE:'.$this->calscale.$this->nl;
- break;
- }
- }
- /**
- * set calendar property calscale
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.3.0 - 2006-08-13
- * @param string $value
- * @return void
- */
- function setCalscale( $value ) {
- $this->calscale = $value;
- }
- /*********************************************************************************/
- /**
- * Property Name: METHOD
- */
- /**
- * creates formatted output for calendar property method
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.9.7 - 2006-11-20
- * @return string
- */
- function createMethod() {
- if( !isset( $this->method ))
- return;
- switch( $this->format ) {
- case 'xcal':
- return ' method="'.$this->method.'"'.$this->nl;
- break;
- default:
- return 'METHOD:'.$this->method.$this->nl;
- break;
- }
- }
- /**
- * set calendar property method
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.3.0 - 2006-08-13
- * @param string $method
- * @return void
- */
- function setMethod( $method ) {
- $this->method = $method;
- }
- /*********************************************************************************/
- /**
- * Property Name: PRODID
- *
- * The identifier is RECOMMENDED to be the identical syntax to the
- * [RFC 822] addr-spec. A good method to assure uniqueness is to put the
- * domain name or a domain literal IP address of the host on which.. .
- */
- /**
- * creates formatted output for calendar property prodid
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.9.7 - 2006-11-20
- * @return string
- */
- function createProdid() {
- if( !isset( $this->prodid ))
- $this->_makeProdid();
- switch( $this->format ) {
- case 'xcal':
- return ' prodid="'.$this->prodid.'"'.$this->nl;
- break;
- default:
- return 'PRODID:'.$this->prodid.$this->nl;
- break;
- }
- }
- /**
- * make default value for calendar prodid
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.3.0 - 2006-08-10
- * @return void
- */
- function _makeProdid() {
- $this->prodid = '-//'.$this->unique_id.'//NONSGML '.ICALCREATOR_VERSION.'//'.strtoupper( $this->language );
- }
- /**
- * Conformance: The property MUST be specified once in an iCalendar object.
- * Description: The vendor of the implementation SHOULD assure that this
- * is a globally unique identifier; using some technique such as an FPI
- * value, as defined in [ISO 9070].
- */
- /**
- * make default unique_id for calendar prodid
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.3.0 - 2006-08-10
- * @return void
- */
- function _makeUnique_id() {
- $this->unique_id = gethostbyname( $_SERVER['SERVER_NAME'] );
- }
- /*********************************************************************************/
- /**
- * Property Name: VERSION
- *
- * Description: A value of "2.0" corresponds to this memo.
- */
- /**
- * creates formatted output for calendar property version
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.9.7 - 2006-11-20
- * @return string
- */
- function createVersion() {
- if( !isset( $this->version ))
- $this->_makeVersion();
- switch( $this->format ) {
- case 'xcal':
- return ' version="'.$this->version.'"'.$this->nl;
- break;
- default:
- return 'VERSION:'.$this->version.$this->nl;
- break;
- }
- }
- /**
- * set default calendar version
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.3.0 - 2006-08-10
- * @return void
- */
- function _makeVersion() {
- $this->version = '2.0';
- }
- /**
- * set calendar version
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 0.3.0 - 2006-08-10
- * @param string version
- * @return void
- */
- function setVersion( $version ) {
- $this->version = $version;
- }
- /*********************************************************************************/
- /**
- * Property Name: x-prop
- */
- /**
- * creates formatted output for calendar property x-prop, iCal format only
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.3.2 - 2007-11-25
- * @return string
- */
- function createXprop() {
- if( 'xcal' == $this->format )
- return false;
- if( 0 >= count( $this->xprop ))
- return;
- $xprop = null;
- $toolbox = new calendarComponent();
- $toolbox->setConfig( 'language', $this->getConfig( 'language' ));
- $toolbox->setConfig( 'nl', $this->getConfig( 'nl' ));
- $toolbox->_createFormat( $this->getConfig( 'format' ));
- foreach( $this->xprop as $label => $xpropPart ) {
- $attributes = $toolbox->_createParams( $xpropPart['params'], array( 'LANGUAGE' ));
- if( is_array( $xpropPart['value'] )) {
- foreach( $xpropPart['value'] as $pix => $theXpart )
- $xpropPart['value'][$pix] = $toolbox->_strrep( $theXpart );
- $xpropPart['value'] = implode( ',', $xpropPart['value'] );
- }
- else
- $xpropPart['value'] = $toolbox->_strrep( $xpropPart['value'] );
- $xprop .= $toolbox->_createElement( strtoupper( $label ), $attributes, $xpropPart['value'] );
- }
- return $xprop;
- }
- /**
- * set calendar property x-prop
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.0.7 - 2007-06-21
- * @param string $label
- * @param string $value
- * @param array $params optional
- * @return void
- */
- function setXprop( $label, $value, $params=FALSE ) {
- if( empty( $label ) || empty( $value ))
- return;
- $xprop = array( 'value' => $value );
- $toolbox = new calendarComponent();
- $xprop['params'] = $toolbox->_setParams( $params );
- $this->xprop[$label] = $xprop;
- }
- /*********************************************************************************/
- /**
- * delete calendar property value
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.15 - 2007-10-29
- * @param string $propName
- * @param int @propix, optional, if specific property is wanted in case of multiply occurences
- * @return bool, if successfull delete
- */
- function deleteProperty( $propName, $propix=FALSE ) {
- $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
- if( !$propix )
- $propix = ( isset( $this->propdelix[$propName] )) ? $this->propdelix[$propName] + 2 : 1;
- $this->propdelix[$propName] = --$propix;
- $return = FALSE;
- switch( $propName ) {
- case 'CALSCALE':
- $this->calscale = null;
- $return = TRUE;
- break;
- case 'METHOD':
- $this->method = null;
- $return = TRUE;
- break;
- default:
- if( $propName != 'X-PROP' ) {
- if( !isset( $this->xprop[$propName] )) return FALSE;
- unset( $this->xprop[$propName] );
- $return = TRUE;
- }
- else {
- if( count( $this->xprop ) <= $propix ) return FALSE;
- $xpropno = 0;
- foreach( $this->xprop as $xpropkey => $xpropvalue ) {
- if( $propix == $xpropno ) {
- unset( $this->xprop[$xpropkey] );
- $return = TRUE;
- break 2;
- }
- else
- $xpropno++;
- }
- }
- }
- return $return;
- }
- /**
- * get calendar property value/params
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.0.8 - 2007-07-07
- * @param string $propName, optional
- * @param int @propix, optional, if specific property is wanted in case of multiply occurences
- * @param bool $inclParam=FALSE
- * @return mixed
- */
- function getProperty( $propName=FALSE, $propix=FALSE, $inclParam=FALSE ) {
- $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
- if( !$propix )
- $propix = ( isset( $this->propix[$propName] )) ? $this->propix[$propName] + 2 : 1;
- $this->propix[$propName] = --$propix;
- switch( $propName ) {
- case 'CALSCALE':
- if( 0 < $propix ) return FALSE;
- return ( !empty( $this->calscale )) ? $this->calscale : null;
- break;
- case 'METHOD':
- if( 0 < $propix ) return FALSE;
- return ( !empty( $this->method )) ? $this->method : null;
- break;
- case 'PRODID':
- if( 0 < $propix ) return FALSE;
- if( empty( $this->prodid ))
- $this->_makeProdid();
- return $this->prodid;
- break;
- case 'VERSION':
- if( 0 < $propix ) return FALSE;
- return ( !empty( $this->version )) ? $this->version : null;
- break;
- default:
- if( $propName != 'X-PROP' ) {
- if( !isset( $this->xprop[$propName] )) return FALSE;
- return ( $inclParam ) ? array( $propName, $this->xprop[$propName] )
- : array( $propName, $this->xprop[$propName]['value'] );
- }
- else {
- if( count( $this->xprop ) <= $propix ) return FALSE;
- $xpropno = 0;
- foreach( $this->xprop as $xpropkey => $xpropvalue ) {
- if( $propix == $xpropno )
- return ( $inclParam ) ? array( $xpropkey, $this->xprop[$xpropkey] )
- : array( $xpropkey, $this->xprop[$xpropkey]['value'] );
- else
- $xpropno++;
- }
- return FALSE; // not found ??
- }
- }
- return FALSE;
- }
- /**
- * general vcalendar property setting
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.13 - 2007-10-23
- * @param mixed $args variable number of function arguments,
- * first argument is ALWAYS component name,
- * second ALWAYS component value!
- * @return void
- */
- function setProperty () {
- $numargs = func_num_args();
- if( 1 >= $numargs )
- return FALSE;
- $arglist = func_get_args();
- if( !$this->getConfig( 'allowEmpty' ) && ( !isset( $arglist[1] ) || empty( $arglist[1] )))
- return;
- $arglist[0] = strtoupper( $arglist[0] );
- for( $argix=$numargs; $argix < 3; $argix++ ) {
- if( !isset( $arglist[$argix] ))
- $arglist[$argix] = null;
- }
- switch( $arglist[0] ) {
- case 'CALSCALE':
- $this->setCalscale( $arglist[1] );
- break;
- case 'METHOD':
- $this->setMethod( $arglist[1] );
- break;
- case 'VERSION':
- $this->setVersion( $arglist[1] );
- break;
- default:
- $this->setXprop( $arglist[0], $arglist[1], $arglist[2] );
- break;
- }
- }
- /*********************************************************************************/
- /**
- * get vcalendar config values or * calendar components
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.13 - 2007-12-30
- * @param string $config
- * @return value
- */
- function getConfig( $config ) {
- switch( strtoupper( $config )) {
- case 'ALLOWEMPTY':
- return $this->allowEmpty;
- break;
- case 'COMPSINFO':
- unset( $this->compix );
- $info = array();
- foreach( $this->components as $cix => $component ) {
- unset( $component->propix );
- $info[$cix]['ordno'] = $cix + 1;
- $info[$cix]['type'] = $component->objName;
- $info[$cix]['uid'] = $component->getProperty( 'uid' );
- $info[$cix]['props'] = $component->getConfig( 'propinfo' );
- $info[$cix]['sub'] = $component->getConfig( 'compsinfo' );
- unset( $component->propix );
- }
- return $info;
- break;
- case 'DELIMITER':
- return $this->delimiter;
- break;
- case 'DIRECTORY':
- if( empty( $this->directory ))
- $this->directory = '.';
- return $this->directory;
- break;
- case 'DIRFILE':
- return $this->getConfig( 'directory' ).$this->getConfig( 'delimiter' ).$this->getConfig( 'filename' );
- break;
- case 'FILEINFO':
- return array( $this->getConfig( 'directory' )
- , $this->getConfig( 'filename' )
- , $this->getConfig( 'filesize' ));
- break;
- case 'FILENAME':
- if( empty( $this->filename )) {
- if( 'xcal' == $this->format )
- $this->filename = date( 'YmdHis' ).'.xml'; // recommended xcs.. .
- else
- $this->filename = date( 'YmdHis' ).'.ics';
- }
- return $this->filename;
- break;
- case 'FILESIZE':
- $size = 0;
- if( empty( $this->url )) {
- $dirfile = $this->getConfig( 'dirfile' );
- if( FALSE === ( $size = filesize( $dirfile )))
- $size = 0;
- clearstatcache();
- }
- return $size;
- break;
- case 'FORMAT':
- return $this->format;
- break;
- case 'LANGUAGE':
- /* get language for calendar component as defined in [RFC 1766] */
- return $this->language;
- break;
- case 'NL':
- case 'NEWLINECHAR':
- return $this->nl;
- break;
- case 'UNIQUE_ID':
- return $this->unique_id;
- break;
- case 'URL':
- if( !empty( $this->url ))
- return $this->url;
- else
- return FALSE;
- break;
- }
- }
- /**
- * general vcalendar config setting
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.13 - 2007-12-30
- * @param string $config
- * @param string $value
- * @return void
- */
- function setConfig( $config, $value ) {
- switch( strtoupper( $config )) {
- case 'ALLOWEMPTY':
- $this->allowEmpty = $value;
- break;
- case 'DELIMITER':
- $this->delimiter = $value;
- break;
- case 'DIRECTORY':
- $value = trim( $value );
- $nl = $this->getConfig('delimiter');
- if( $nl == substr( $value, ( 0 - strlen( $nl ))))
- $value = substr( $value, 0, ( strlen( $value ) - strlen( $nl )));
- if( is_dir( $value )) {
- /* local directory */
- clearstatcache();
- $this->directory = $value;
- $this->url = null;
- return TRUE;
- }
- else
- return FALSE;
- break;
- case 'FILENAME':
- $value = trim( $value );
- if( !empty( $this->url )) {
- /* remote directory+file - URL */
- $this->filename = $value;
- return TRUE;
- }
- $dirfile = $this->getConfig( 'directory' ).$this->getConfig( 'delimiter' ).$value;
- if( file_exists( $dirfile )) {
- /* local existing file */
- if( is_readable( $dirfile ) || is_writable( $dirfile )) {
- clearstatcache();
- $this->filename = $value;
- return TRUE;
- }
- else
- return FALSE;
- }
- elseif( FALSE !== touch( $dirfile )) {
- /* new local file created */
- $this->filename = $value;
- return TRUE;
- }
- else
- return FALSE;
- break;
- case 'FORMAT':
- $value = trim( $value );
- if( 'xcal' == strtolower( $value )) {
- $this->format = 'xcal';
- $this->attributeDelimiter = $this->nl;
- $this->valueInit = null;
- }
- else {
- $this->format = null;
- $this->attributeDelimiter = ';';
- $this->valueInit = ':';
- }
- break;
- case 'LANGUAGE':
- // set language for calendar component as defined in [RFC 1766]
- $value = trim( $value );
- $this->language = $value;
- break;
- case 'NL':
- case 'NEWLINECHAR':
- $this->nl = $value;
- break;
- case 'UNIQUE_ID':
- $value = trim( $value );
- $this->unique_id = $value;
- break;
- case 'URL':
- /* remote file - URL */
- $value = trim( $value );
- $value = str_replace( 'HTTP://', 'http://', $value );
- $value = str_replace( 'WEBCAL://', 'http://', $value );
- $value = str_replace( 'webcal://', 'http://', $value );
- $this->url = $value;
- $this->directory = null;
- $parts = pathinfo( $value );
- return $this->setConfig( 'filename', $parts['basename'] );
- break;
- }
- }
- /*********************************************************************************/
- /**
- * validDate
- *
- * convert input parameters to (valid) iCalcreator date in array format (or FALSE)
- * if $utc=TRUE and $tz = utc offset ([[+/]-]HHmm) input (local) date array + UTC offset
- * returns ouput in UTC format date
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.2 - 2007-07-29
- * @param mixed $year
- * @param mixed $month optional
- * @param int $day optional
- * @param int $hour optional
- * @param int $min optional
- * @param int $sec optional
- * @param mixed $tz optional
- * @param bool $utc optional
- * @return bool false / array $date
- */
- function validDate( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $utc=FALSE ) {
- $input = array();
- $toolbox = new calendarComponent();
- $parno = null;
- if( is_array( $year ) && isset( $year['timestamp'] )) {
- $input = $toolbox->_date_time_string( date( 'Y-m-d H:i:s', $year['timestamp'] ), 6 );
- $input['tz'] = ( isset( $year['tz'] )) ? $year['tz'] : null;
- $utc = ( TRUE === $month ) ? TRUE : FALSE;
- }
- elseif( is_array( $year ) && ( in_array( count( $year ), array( 3, 4, 6, 7 )))) {
- if( isset( $year['tz'] ) || ( 4 == count( $year )) || ( 7 == count( $year )))
- $parno = 7;
- elseif( isset( $year['hour'] ) || isset( $year['min'] ) || isset( $year['sec'] ) ||
- ( 6 == count( $year )))
- $parno = 6;
- else
- $parno = 3;
- $input = $toolbox->_date_time_array( $year, $parno );
- $utc = ( TRUE === $month ) ? TRUE : FALSE;
- }
- elseif( 8 <= strlen( trim( $year ))) { // ex. 2006-08-03 10:12:18
- $input = $toolbox->_date_time_string( $year );
- $utc = ( TRUE === $month ) ? TRUE : FALSE;
- }
- elseif(( $year !== FALSE ) && ( $month !== FALSE ) && ( $day !== FALSE )) {
- if(( 0 > (int) $year ) || (2100 < (int) $year ))
- return FALSE;
- $month = (int) $month;
- if(( 1 > $month ) || ( 12 < $month ))
- return FALSE;
- $day = (int) $day;
- if(( 1 > $day ) || ( 31 < $day ))
- return FALSE;
- $input['year'] = $year;
- $input['month'] = $month;
- $input['day'] = $day;
- if(( $hour !== FALSE ) || ( $min !== FALSE ) || ( $sec !== FALSE )) {
- $parno = 6;
- if( $hour !== FALSE )
- $input['hour'] = $hour;
- if( $min !== FALSE )
- $input['min'] = $min;
- if( $sec !== FALSE )
- $input['sec'] = $sec;
- }
- if( $tz !== FALSE ) {
- $parno = 7;
- $input['tz'] = $tz;
- }
- elseif( !$parno )
- $parno = 3;
- $input = $toolbox->_date_time_array( $input, $parno );
- }
- else
- return FALSE;
- if( !checkdate ( $input['month'], $input['day'], $input['year'] ))
- return FALSE;
- if( isset( $input['hour'] ) &&
- (( 0 > $input['hour'] ) || ( 23 < $input['hour'] )))
- return FALSE;
- if( isset( $input['min'] ) &&
- (( 0 > $input['min'] ) || ( 59 < $input['min'] )))
- return FALSE;
- if( isset( $input['sec'] ) &&
- (( 0 > $input['sec'] ) || ( 59 < $input['sec'] )))
- return FALSE;
- if( isset( $input['tz'] ) && ( '' < trim ( $input['tz'] ))) {
- $input['tz'] = (string) trim( $input['tz'] );
- if( ctype_digit( $input['tz']{1} )) { // only numeric tz=offset
- $offset = 0;
- if( ctype_digit( $input['tz']{0} ))
- $input['tz'] = '+'.$input['tz'];
- $offset = $toolbox->_tz2offset( $input['tz'] );
- if( 0 != $offset) {
- if( !isset( $input['hour'] ))
- $input['hour'] = 0;
- if( !isset( $input['min'] ))
- $input['min'] = 0;
- if( !isset( $input['sec'] ))
- $input['sec'] = 0;
- $input = date('Y-m-d H:i:s\Z', mktime( $input['hour']
- , $input['min']
- , $input['sec'] + $offset
- , $input['month']
- , $input['day']
- , $input['year']));
- $parno = ( $utc ) ? 7 : 6 ;
- $input = $toolbox->_date_time_string( $input, $parno );
- if( !$utc && isset( $input['tz'] ) && ( 'Z' == $input['tz'] ))
- unset( $input['tz'] );
- }
- }
- }
- return $input;
- }
- /*********************************************************************************/
- /**
- * add calendar component to container
- *
- * alias to setComponent
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 1.x.x - 2007-04-24
- * @param object $component calendar component
- * @return void
- */
- function addComponent( $component ) {
- $this->setComponent( $component );
- }
- /**
- * delete calendar component from container
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.0.4 - 2007-06-14
- * @param mixed $arg1 ordno / component type / component uid
- * @param mixed $arg2 optional, ordno if arg1 = component type
- * @return void
- */
- function deleteComponent( $arg1, $arg2=FALSE ) {
- $argType = $index = null;
- if ( ctype_digit( (string) $arg1 )) {
- $argType = 'INDEX';
- $index = (int) $arg1 - 1;
- }
- elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
- $argType = strtolower( $arg1 );
- $index = ( !empty( $arg2 ) && ctype_digit( (string) $arg2 )) ? (( int ) $arg2 - 1 ) : 1;
- }
- $cix1dC = 0;
- foreach ( $this->components as $cix => $component) {
- unset( $component->propix );
- if(( 'INDEX' == $argType ) && ( $index == $cix )) {
- unset( $this->components[$cix] );
- return TRUE;
- }
- elseif( $argType == $component->objName ) {
- if( $index == $cix1dC ) {
- unset( $this->components[$cix] );
- return TRUE;
- }
- $cix1dC++;
- }
- elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
- unset( $this->components[$cix] );
- return TRUE;
- }
- }
- return FALSE;
- }
- /**
- * get calendar component from container
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.16 - 2007-11-11
- * @param mixed $arg1 optional, ordno/component type/ component uid
- * @param mixed $arg2 optional, ordno if arg1 = component type
- * @return object
- */
- function getComponent( $arg1=FALSE, $arg2=FALSE ) {
- $index = $argType = null;
- if ( !$arg1 ) {
- $argType = 'INDEX';
- $index = $this->compix['INDEX'] =
- ( isset( $this->compix['INDEX'] )) ? $this->compix['INDEX'] + 1 : 1;
- }
- elseif ( ctype_digit( (string) $arg1 )) {
- $argType = 'INDEX';
- $index = (int) $arg1;
- unset( $this->compix );
- }
- elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
- unset( $this->compix['INDEX'] );
- $argType = strtolower( $arg1 );
- if( !$arg2 )
- $index = $this->compix[$argType] =
- ( isset( $this->compix[$argType] )) ? $this->compix[$argType] + 1 : 1;
- else
- $index = (int) $arg2;
- }
- $index -= 1;
- $ckeys = array_keys( $this->components );
- if( !empty( $index) && ( $index > end( $ckeys )))
- return FALSE;
- $cix1gC = 0;
- foreach ( $this->components as $cix => $component) {
- unset( $component->propix );
- if(( 'INDEX' == $argType ) && ( $index == $cix ))
- return $component->copy();
- elseif( $argType == $component->objName ) {
- if( $index == $cix1gC )
- return $component->copy();
- $cix1gC++;
- }
- elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
- unset( $component->propix );
- return $component->copy();
- }
- }
- /* not found.. . */
- unset( $this->compix );
- return false;
- }
- /**
- * select components from calendar on date basis
- *
- * Ensure DTSTART is set for every component.
- * No date controls occurs.
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.4.1 - 2008-02-05
- * @param int $startY optional, start Year, default current Year
- * @param int $startM optional, start Month, default current Month
- * @param int $startD optional, start Day, default current Day
- * @param int $endY optional, end Year, default $startY
- * @param int $endY optional, end Month, default $startM
- * @param int $endY optional, end Day, default $startD
- * @param mixed $cType optional, calendar component type(-s), default FALSE=all else string/array type(-s)
- * @param bool $flat optional, FALSE (default) => output : array[Year][Month][Day][]
- * TRUE => output : array[] (ignores split)
- * @param bool $any optional, TRUE (default) - select component that take place within period
- * FALSE - only components that starts within period
- * @param bool $split optional, TRUE (default) - one component copy every day it take place during the
- * period (implies flat=FALSE)
- * FALSE - one occurance of component only in output array</tr>
- * @return array or FALSE
- */
- function selectComponents( $startY=FALSE, $startM=FALSE, $startD=FALSE, $endY=FALSE, $endM=FALSE, $endD=FALSE, $cType=FALSE, $flat=FALSE, $any=TRUE, $split=TRUE ) {
- /* check if empty calendar */
- if( 0 >= count( $this->components ))
- return FALSE;
- /* check default dates */
- if( !$startY ) $startY = date( 'Y' );
- if( !$startM ) $startM = date( 'm' );
- if( !$startD ) $startD = date( 'd' );
- $startDate = mktime( 0, 0, 0, $startM, $startD, $startY );
- if( !$endY ) $endY = $startY;
- if( !$endM ) $endM = $startM;
- if( !$endD ) $endD = $startD;
- $endDate = mktime( 23, 59, 59, $endM, $endD, $endY );
- /* check component types */
- $validTypes = array('vevent', 'vtodo', 'vjournal', 'vfreebusy' );
- if( is_array( $cType )) {
- foreach( $cType as $cix => $theType ) {
- $cType[$cix] = $theType = strtolower( $theType );
- if( !in_array( $theType, $validTypes ))
- $cType[$cix] = 'vevent';
- }
- $cType = array_unique( $cType );
- }
- elseif( !empty( $cType )) {
- $cType = strtolower( $cType );
- if( !in_array( $cType, $validTypes ))
- $cType = array( 'vevent' );
- else
- $cType = array( $cType );
- }
- else
- $cType = $validTypes;
- if( 0 >= count( $cType ))
- $cType = $validTypes;
- /* iterate components */
- $result = array();
- foreach ( $this->components as $cix => $component ) {
- unset( $component->propix, $start );
- /* deselect unvalid type components */
- if( !in_array( $component->objName, $cType ))
- continue;
- /* deselect components without dtstart set */
- if( FALSE === ( $start = $component->getProperty( 'dtstart' )))
- continue;
- $dtendExist = $dueExist = FALSE;
- unset( $end, $startWdate, $endWdate, $rdurWsecs, $rdur, $exdatelist, $workstart, $workend ); // clean up
- $startWdate = $component->_date2timestamp( $start );
- /* get end date from dtend/due/duration properties */
- $end = $component->getProperty( 'dtend' );
- if( !empty( $end ))
- $dtendExist = TRUE;
- //if( !empty($end)) echo 'selectComponents 1 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
- if( empty($end) && ( $component->objName == 'vtodo' )) {
- $end = $component->getProperty( 'due' );
- if( !empty( $end ))
- $dueExist = TRUE;
- //if( !empty($end)) echo 'selectComponents 2 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
- }
- elseif( !empty($end) && !isset( $end['hour'] )) {
- /* a DTEND without time part regards an event that ends the day before,
- for an all-day event DTSTART=20071201 DTEND=20071202 (taking place 20071201!!! */
- $end = array( 'year' => $end['year'], 'month' => $end['month'], 'day' => ($end['day'] - 1), 'hour' => 23, 'min' => 59, 'sec' => 59 );
- //if( !empty($end)) echo 'selectComponents 3 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
- }
- if( empty( $end )) {
- $end = $component->getProperty( 'duration', FALSE, FALSE, TRUE );// in dtend (array) format
- //if( !empty($end)) echo 'selectComponents 4 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
- }
- if( empty( $end )) { // assume one day duration if missing end date
- $end = array( 'year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59 );
- //if( isset($end)) echo 'selectComponents 5 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
- }
- $endWdate = $component->_date2timestamp( $end );
- if( $endWdate < $startWdate ) { // MUST be after start date!!
- $end = array( 'year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59 );
- $endWdate = $component->_date2timestamp( $end );
- }
- $rdurWsecs = $endWdate - $startWdate; // compute component duration in seconds
- $rdur = $component->_date2duration( $start, $end ); // compute component duration, array
- /* make a list of optional exclude dates for component occurence, exrule, exdate */
- $exdatelist = array();
- $workstart = $component->_date_time_string( date('Y-m-d H:i:s', ( $startDate - $rdurWsecs )), 6);
- $workend = $component->_date_time_string( date('Y-m-d H:i:s', ( $endDate + $rdurWsecs )), 6);
- while( FALSE !== ( $exrule = $component->getProperty( 'exrule' )))
- $component->_recur2date( $exdatelist, $exrule, $start, $workstart, $workend );
- while( FALSE !== ( $exdate = $component->getProperty( 'exdate' ))) {
- foreach( $exdate as $theExdate ) {
- $exWdate = $component->_date2timestamp( $theExdate );
- if((( $startDate - $rdurWsecs ) <= $exWdate ) && ( $endDate >= $exWdate ))
- $exdatelist[$exWdate] = TRUE;
- }
- }
- /* if 'any' components, check repeating components, removing all excluding dates */
- if( TRUE === $any ) {
- /* make a list of optional repeating dates for component occurence, rrule, rdate */
- $recurlist = array();
- while( FALSE !== ( $rrule = $component->getProperty( 'rrule' ))) // check rrule
- $component->_recur2date( $recurlist, $rrule, $start, $workstart, $workend );
- foreach( $recurlist as $recurkey => $recurvalue ) // key=match date as timestamp
- $recurlist[$recurkey] = $rdurWsecs; // add duration in seconds
- while( FALSE !== ( $rdate = $component->getProperty( 'rdate' ))) { // check rdate
- foreach( $rdate as $theRdate ) {
- if( is_array( $theRdate ) && ( 2 == count( $theRdate )) && // PERIOD
- array_key_exists( '0', $theRdate ) && array_key_exists( '1', $theRdate )) {
- $rstart = $component->_date2timestamp( $theRdate[0] );
- if(( $rstart < ( $startDate - $rdurWsecs )) || ( $rstart > $endDate ))
- continue;
- if( isset( $theRdate[1]['year'] )) // date-date period
- $rend = $component->_date2timestamp( $theRdate[1] );
- else { // date-duration period
- $rend = $component->duration2date( $theRdate[0], $theRdate[1] );
- $rend = $component->_date2timestamp( $rend );
- }
- if((( $startDate - $rdurWsecs ) <= $rstart ) && ( $endDate >= $rstart ))
- $recurlist[$rstart] = ( $rstart - $rend ); // set start date + rdate duration in seconds
- }
- else { // single date
- $theRdate = $component->_date2timestamp( $theRdate );
- if((( $startDate - $rdurWsecs ) <= $theRdate ) && ( $endDate >= $theRdate ))
- $recurlist[$theRdate] = $rdurWsecs; // set start date + event duration in seconds
- }
- }
- }
- if( 0 < count( $recurlist )) {
- ksort( $recurlist );
- foreach( $recurlist as $recurkey => $durvalue ) {
- if((( $startDate - $rdurWsecs ) > $recurkey ) || ( $endDate < $recurkey )) // not within period
- continue;
- if( isset( $exdatelist[$recurkey] )) // check excluded dates
- continue;
- if( $startWdate >= $recurkey ) // exclude component start date
- continue;
- $component2 = $component->copy();
- $rstart = $component2->_date_time_string( date('Y-m-d H:i:s', $recurkey ), 6);
- $datevalue = $rstart['month'].'/'.$rstart['day'].'/'.$rstart['year'];
- $dateformat = 'Y-m-d';
- if( isset( $start['hour'] ) || isset( $start['min'] ) || isset( $start['sec'] )) {
- $datevalue .= ( isset( $rstart['hour'] )) ? ' '.$rstart['hour'] : ' 00';
- $datevalue .= ( isset( $rstart['min'] )) ? ':'.$rstart['min'] : ':00';
- $datevalue .= ( isset( $rstart['sec'] )) ? ':'.$rstart['sec'] : ':00';
- $dateformat .= ' H:i:s';
- }
- $datestring = date( $dateformat, strtotime( $datevalue ));
- if( isset( $start['tz'] ))
- $datestring .= ' '.$start['tz'];
- $component2->setProperty( 'x-current-dtstart', $datestring );
- $rend = $component2->_date_time_string( date('Y-m-d H:i:s', ( $recurkey + $durvalue )), 6);
- if( isset( $datevalue ) && ( $dtendExist || $dueExist )) {
- $datevalue = $rend['month'].'/'.$rend['day'].'/'.$rend['year'];
- $dateformat = 'Y-m-d';
- if( isset( $end['hour'] ) || isset( $end['min'] ) || isset( $end['sec'] )) {
- $datevalue .= ( isset( $rend['hour'] )) ? ' '.$rend['hour'] : ' 00';
- $datevalue .= ( isset( $rend['min'] )) ? ':'.$rend['min'] : ':00';
- $datevalue .= ( isset( $rend['sec'] )) ? ':'.$rend['sec'] : ':00';
- $dateformat .= ' H:i:s';
- }
- $datestring = date( $dateformat, strtotime( $datevalue ));
- if( isset( $end['tz'] ))
- $datestring .= ' '.$end['tz'];
- if( $dtendExist )
- $component2->setProperty( 'x-current-dtend', $datestring );
- else
- $component2->setProperty( 'x-current-due', $datestring );
- }
- $rend = $component2->_date2timestamp( $rend );
- $rstart = $recurkey;
- /* add repeating components within valid dates to output array, only start date */
- if( $flat )
- $result[] = $component2; // copy to output
- elseif( $split ) {
- if( $rend > $endDate )
- $rend = $endDate;
- while( $rstart <= $rend ) { // iterate
- $wd = getdate( $rstart );
- // if(( $rstart >= $startDate ) && // date within period
- if(( $rstart > $startDate ) && // date after dtstart
- !isset( $exdatelist[$rstart] )) // check exclude date
- $result[$wd['year']][$wd['mon']][$wd['mday']][] = $component2->copy(); // copy to output
- $rstart += ( 24*60*60 ); // step one day
- }
- }
- elseif(( $rstart >= $startDate ) && // date within period
- !isset( $exdatelist[$rstart] )) { // check exclude date
- $wd = getdate( $rstart );
- $result[$wd['year']][$wd['mon']][$wd['mday']][] = $component2->copy(); // copy to output
- }
- }
- }
- /* deselect components with startdate/enddate not within period */
- if(( $endWdate < $startDate ) || ( $startWdate > $endDate ))
- continue;
- }
- /* deselect components with startdate not within period */
- elseif(( $startWdate < $startDate ) || ( $startWdate > $endDate ))
- continue;
- /* add selected components within valid dates to output array */
- if( $flat ) {
- $result[] = $component->copy(); // copy to output;
- }
- elseif( $split ) {
- if( $endWdate > $endDate )
- $endWdate = $endDate; // use period end date
- if( !isset( $exdatelist[$startWdate] )) { // check excluded dates
- if( $startWdate < $startDate )
- $startWdate = $startDate; // use period start date
- while( $startWdate <= $endWdate ) { // iterate
- $wd = getdate( $startWdate );
- $result[$wd['year']][$wd['mon']][$wd['mday']][] = $component->copy(); // copy to output
- $startWdate += ( 24*60*60 ); // step one day
- }
- }
- } // use component date
- elseif( !isset( $exdatelist[$startWdate] ) && // check excluded dates
- ( $startWdate >= $startDate )) { // within period
- $wd = getdate( $startWdate );
- $result[$wd['year']][$wd['mon']][$wd['mday']][] = $component->copy(); // copy to output
- }
- }
- if( 0 >= count( $result ))
- return FALSE;
- elseif( !$flat ) {
- foreach( $result as $y => $yeararr ) {
- foreach( $yeararr as $m => $montharr ) {
- ksort( $result[$y][$m] );
- }
- ksort( $result[$y] );
- }
- ksort( $result );
- }
- return $result;
- }
- /**
- * add calendar component to container
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.16 - 2007-11-11
- * @param object $component calendar component
- * @param mixed $arg1 optional, ordno/component type/ component uid
- * @param mixed $arg2 optional, ordno if arg1 = component type
- * @return void
- */
- function setComponent( $component, $arg1=FALSE, $arg2=FALSE ) {
- if( '' >= $component->getConfig( 'language'))
- $component->setConfig( 'language', $this->getConfig( 'language' ));
- $component->setConfig( 'allowEmpty', $this->getConfig( 'allowEmpty' ));
- $component->setConfig( 'nl', $this->getConfig( 'nl' ));
- $component->setConfig( 'unique_id', $this->getConfig( 'unique_id' ));
- $component->setConfig( 'format', $this->getConfig( 'format' ));
- if( !in_array( $component->objName, array( 'valarm', 'vtimezone' ))) {
- unset( $component->propix );
- /* make sure dtstamp and uid is set */
- $dummy = $component->getProperty( 'dtstamp' );
- $dummy = $component->getProperty( 'uid' );
- }
- if( !$arg1 ) {
- $this->components[] = $component->copy();
- return TRUE;
- }
- $argType = $index = null;
- if ( ctype_digit( (string) $arg1 )) {
- $argType = 'INDEX';
- $index = (int) $arg1 - 1;
- }
- elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
- $argType = strtolower( $arg1 );
- $index = ( ctype_digit( (string) $arg2 )) ? ((int) $arg2) - 1 : 0;
- }
- $cix1sC = 0;
- foreach ( $this->components as $cix => $component2) {
- unset( $component2->propix );
- if(( 'INDEX' == $argType ) && ( $index == $cix )) {
- $this->components[$cix] = $component->copy();
- return TRUE;
- }
- elseif( $argType == $component2->objName ) {
- if( $index == $cix1sC ) {
- $this->components[$cix] = $component->copy();
- return TRUE;
- }
- $cix1sC++;
- }
- elseif( !$argType && ( $arg1 == $component2->getProperty( 'uid' ))) {
- $this->components[$cix] = $component->copy();
- return TRUE;
- }
- }
- /* not found.. . insert last in chain anyway .. .*/
- $this->components[] = $component->copy();
- }
- /**
- * sort iCal compoments, only local date sort
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.2.9 - 2007-10-02
- * @return sort param
- *
- */
- function _cmpfcn( $a, $b ) {
- if( 'vtimezone' == $a->objName) return -1;
- if( 'vtimezone' == $b->objName) return 1;
- if( isset( $a->dtstart['value'] ) ||
- isset( $b->dtstart['value'] )) {
- foreach( $this->_sortkeys as $key ) {
- if( !isset( $a->dtstart['value'][$key] )) return -1;
- elseif( !isset( $b->dtstart['value'][$key] )) return 1;
- if ( $a->dtstart['value'][$key]
- == $b->dtstart['value'][$key] )
- continue;
- if (( (int) $a->dtstart['value'][$key] ) <
- ( (int) $b->dtstart['value'][$key] )) return -1;
- elseif(( (int) $a->dtstart['value'][$key] ) >
- ( (int) $b->dtstart['value'][$key] )) return 1;
- }
- }
- if( isset( $a->dtend['value'] ))
- $c = $a->dtend['value'];
- if( empty( $c ) && !empty( $a->due['value'] ))
- $c = $a->due['value'];
- if( empty( $c ) && !empty( $a->duration['value'] ))
- $c = $a->duration2date();
- if( isset( $b->dtend['value'] ))
- $d = $b->dtend['value'];
- if( empty( $d ) && !empty( $b->due['value'] ))
- $d = $b->due['value'];
- if( empty( $d ) && !empty( $b->duration['value'] ))
- $d = $b->duration2date();
- if( isset( $c ) || isset( $d )) {
- if( !isset( $c ) && isset( $d )) return -1;
- if( isset( $c ) && !isset( $d )) return 1;
- foreach( $this->_sortkeys as $key ) {
- if ( !isset( $c[$key] )) return -1;
- elseif( !isset( $d[$key] )) return 1;
- if ( $c[$key]
- == $d[$key] )
- continue;
- if (( (int) $c[$key] ) <
- ( (int) $d[$key] )) return -1;
- elseif(( (int) $c[$key] ) >
- ( (int) $d[$key] )) return 1;
- }
- }
- $c = ( isset( $a->created['value'] )) ? $a->created['value'] : $a->dtstamp['value'];
- $d = ( isset( $b->created['value'] )) ? $b->created['value'] : $b->dtstamp['value'];
- foreach( $this->_sortkeys as $key ) {
- if( !isset( $a->created['value'][$key] )) return -1;
- elseif( !isset( $b->created['value'][$key] )) return 1;
- if ( $a->created['value'][$key]
- == $b->created['value'][$key] )
- continue;
- if (( (int) $a->created['value'][$key] ) <
- ( (int) $b->created['value'][$key] )) return -1;
- elseif(( (int) $a->created['value'][$key] ) >
- ( (int) $b->created['value'][$key] )) return 1;
- }
- if (( $a->uid['value'] ) <
- ( $b->uid['value'] )) return -1;
- elseif(( $a->uid['value'] ) >
- ( $b->uid['value'] )) return 1;
- return 0;
- }
- function sort() {
- if( is_array( $this->components )) {
- $this->_sortkeys = array( 'year', 'month', 'day', 'hour', 'min', 'sec' );
- usort( $this->components, array( $this, '_cmpfcn' ));
- }
- }
- /**
- * parse iCal file into vcalendar, components, properties and parameters
- *
- * @author Kjell-Inge Gustafsson <ical@kigkonsult.se>
- * @since 2.4.3 - 2008-02-13
- * @param string $filename optional filname (incl. opt. directory/path) or URL
- * @return bool FALSE if error occurs during parsing
- *
- */
- function parse( $filename=FALSE ) {
- if( !$filename ) {
- /* directory/filename previous set via setConfig directory+filename / url */
- if( FALSE === ( $filename = $this->getConfig( 'url' )))
- $filename = $this->getConfig( 'dirfile' );
- }
- elseif(( 'http://' == strtolower( substr( $filename, 0, 7 ))) ||
- ( 'webcal://' == strtolower( substr( $filename, 0, 9 )))) {
- /* remote file - URL */
- $this->setConfig( 'URL', $filename );
- if( !$filename = $this->getConfig( 'url' ))
- return FALSE; /* err 2 */
- }
- else {
- /* local directory/filename */
- $parts = pathinfo( $filename );
- if( !empty( $parts['dirname'] ) && ( '.' != $parts['dirname'] )) {
- if( !$this->setConfig( 'directory', $parts['dirname'] ))
- return FALSE; /* err 3 */
- }
- if( !$this->setConfig( 'filename', $parts['basename'] ))
- return FALSE; /* err 4 */
- }
- if( 'http://' != substr( $filename, 0, 7 )) {
- /* local file error tests */
- if( !is_file( $filename )) /* err 5 */
- return FALSE;
- if( !is_readable( $filename ))
- return FALSE; /* err 6 */
- if( !filesize( $filename ))
- return FALSE; /* err 7 */
- clearstatcache();
- }
- /* READ FILE */
- if( FALSE === ( $rows = file( $filename )))
- return FALSE; /* err 1 */
- /* identify BEGIN:VCALENDAR, MUST be first row */
- if( 'BEGIN:VCALENDAR' != strtoupper( trim( $rows[0] )))
- return FALSE; /* err 8 */
- /* remove empty trailing lines */
- while( '' == trim( $rows[count( $rows ) - 1] )) {
- unset( $rows[count( $rows ) - 1] );
- $rows = array_values( $rows );
- }
- /* identify ending END:VCALENDAR row */
- if( 'END:VCALENDAR' != strtoupper( trim( $rows[count( $rows ) - 1] ))) {
- return FALSE; /* err 9 */
- }
- if( 3 > count( $rows ))
- return FALSE; …
Large files files are truncated, but you can click here to view the full file