| Server IP : 180.180.241.3 / Your IP : 216.73.216.35 Web Server : Microsoft-IIS/7.5 System : Windows NT NETWORK-NHRC 6.1 build 7601 (Windows Server 2008 R2 Standard Edition Service Pack 1) i586 User : IUSR ( 0) PHP Version : 5.3.28 Disable Function : NONE MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/AppServ/www/news/components/com_jevents/libraries/ |
Upload File : |
<?php
/**
* JEvents Component for Joomla 1.5.x
*
* @version $Id: iCalImport.php 1465 2009-06-09 14:36:43Z geraint $
* @package JEvents
* @copyright Copyright (C) 2008-2009 GWE Systems Ltd, 2006-2008 JEvents Project Group
* @license GNU/GPLv2, see http://www.gnu.org/licenses/gpl-2.0.html
* @link http://www.jevents.net
*/
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
// This class doesn't yet deal with repeating events
class iCalImport
{
/**
* This array saves the iCalendar parsed data as an array - may make a class later!
*
* @var array
*/
var $cal = array();
var $key;
var $rawData = '';
var $srcURL = '';
var $eventCount = -1;
var $todoCount = -1;
var $vevents = array();
function __construct () {
}
// constructor
function import($filename,$rawtext="")
{
$cfg = & JEVConfig::getInstance();
$option = JEV_COM_COMPONENT;
// resultant data goes here
if ($filename!=""){
$file = $filename;
if (!file_exists($file)) {
global $mainframe;
$file = JPATH_SITE."/components/$option/".$filename;
}
if (!file_exists($file)) {
echo "I hope this is a URL!!<br/>";
$file = $filename;
}
// get name
$isFile = false;
if (isset($_FILES['upload']) && is_array($_FILES['upload']) ) {
$uploadfile = $_FILES['upload'];
// MSIE sets a mime-type of application/octet-stream
if ($uploadfile['size']!=0 && ($uploadfile['type']=="text/calendar" || $uploadfile['type']=="application/octet-stream")){
$this->srcURL = $uploadfile['name'];
$isFile = true;
}
}
if ($this->srcURL =="") {
$this->srcURL = $file;
}
// $this->rawData = iconv("ISO-8859-1","UTF-8",file_get_contents($file));
if (is_callable("curl_exec")){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,($isFile?"file://":"").$file);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$this->rawData = curl_exec($ch);
curl_close ($ch);
}
else {
$this->rawData = @file_get_contents($file);
}
if ($this->rawData === false) {
// file_get_contents: no or blocked wrapper for $file
JError::raiseNotice(0, 'file_get_contents() failed, try fsockopen');
$parsed_url = parse_url($file);
if ($parsed_url === false) {
JError::raiseWarning(0, 'url not parsed: ' . $file);
} else {
if ($parsed_url['scheme'] == 'http' || $parsed_url['scheme'] == 'https') {
// try socked connection
$fsockhost = $parsed_url['host'];
$fsockport = 80;
if ($parsed_url['scheme'] == 'https') {
$fsockhost = 'ssl://' . $fsockhost;
$fsockport = 443;
}
if (array_key_exists('port', $parsed_url)) $fsockport = $parsed_url['port'];
$fh = @fsockopen($fsockhost, $fsockport, $errno, $errstr, 3);
if ($fh === false) {
// fsockopen: no connect
JError::raiseWarning(0, 'fsockopen: no connect for ' . $file.' - '.$errstr );
return false;
} else {
$fsock_path = ((array_key_exists('path', $parsed_url)) ? $parsed_url['path'] : '')
. ((array_key_exists('query', $parsed_url)) ? $parsed_url['query'] : '')
. ((array_key_exists('fragment', $parsed_url)) ? $parsed_url['fragment'] : '');
fputs($fh, "GET $fsock_path HTTP/1.0\r\n");
fputs($fh, "Host: ".$parsed_url['host']."\r\n\r\n");
while(!feof($fh)) {
$this->rawData .= fread($fh,4096);
}
fclose($fh);
$this->rawData = substr($this->rawData, strpos($this->rawData, "\r\n\r\n")+4);
}
}
}
}
// Returns true if $string is valid UTF-8 and false otherwise.
/*
$isutf8 = $this->detectUTF8($this->rawData);
if ($isutf8) {
$this->rawData = iconv("ISO-8859-1","UTF-8",$this->rawData);
}
*/
}
else {
$this->srcURL="n/a";
$this->rawData = $rawtext;
}
;
// get rid of spurious carriage returns and spaces
//$this->rawData = preg_replace("/[\r\n]+ ([:;])/","$1",$this->rawData);
// simplify line feed
$this->rawData = str_replace("\r\n","\n",$this->rawData);
// remove spurious lines before calendar start
if (!stristr($this->rawData,'BEGIN:VCALENDAR')) {
JError::raiseWarning(0, 'Not a valid VCALENDAR data file: ' . $this->srcURL);
}
$begin = strpos($this->rawData,"BEGIN:VCALENDAR",0);
$this->rawData = substr($this->rawData,$begin);
// $this->rawData = preg_replace('/^.*\n(BEGIN:VCALENDAR)/s', '$1', $this->rawData, 1);
// unfold content lines according the unfolding procedure of rfc2445
$this->rawData = str_replace("\n ","",$this->rawData);
$this->rawData = str_replace("\n\t","",$this->rawData);
// TODO make sure I can always ignore the second line
// Some google calendars has spaces and carriage returns in their UIDs
// Convert string into array for easier processing
$this->rawData = explode("\n", $this->rawData);
$skipuntil = null;
foreach ($this->rawData as $vcLine) {
//$vcLine = trim($vcLine); // trim one line
if (!empty($vcLine))
{
// skip unhandled block
if ($skipuntil) {
if (trim($vcLine) == $skipuntil) {
// found end of block to skip
$skipuntil = null;
}
continue;
}
$matches = explode(":",$vcLine,2);
if (count($matches) == 2) {
list($this->key,$value)= $matches;
//$value = str_replace('\n', "\n", $value);
//$value = stripslashes($value);
$append=false;
// Treat Accordingly
switch ($vcLine) {
case "BEGIN:VTODO":
// start of VTODO section
$this->todoCount++;
$parent = "VTODO";
break;
case "BEGIN:VEVENT":
// start of VEVENT section
$this->eventCount++;
$parent = "VEVENT";
break;
case "BEGIN:VCALENDAR":
case "BEGIN:DAYLIGHT":
case "BEGIN:VTIMEZONE":
case "BEGIN:STANDARD":
$parent = $value; // save tu array under value key
break;
case "END:VTODO":
case "END:VEVENT":
case "END:VCALENDAR":
case "END:DAYLIGHT":
case "END:VTIMEZONE":
case "END:STANDARD":
$parent = "VCALENDAR";
break;
default:
// skip unknown BEGIN/END blocks
if ($this->key == 'BEGIN') {
$skipuntil = 'END:' . $value;
break;
}
// Generic processing
$this->add_to_cal($parent, $this->key, $value,$append);
break;
}
} else {
// ignore these lines go
}
}
}
// Sort the events into start date order
// there's little point in doing this id an RRULE is present!
// usort($this->cal['VEVENT'], array("iCalImport","comparedates"));
// Populate vevent class - should do this first trawl through !!
if (array_key_exists("VEVENT",$this->cal)) {
foreach ($this->cal["VEVENT"] as $vevent){
$this->vevents[] = iCalEvent::iCalEventFromData($vevent);
}
}
return $this;
}
function add_to_cal($parent, $key, $value, $append)
{
// I'm not interested in when the events were created/modified
if (($key == "DTSTAMP") or ($key == "LAST-MODIFIED") or ($key == "CREATED")) return;
if ($key == "RRULE" && $value!="") {
$value = $this->parseRRULE($value,$parent);
}
$rawkey="";
if (stristr($key,"DTSTART") || stristr($key,"DTEND") || stristr($key,"EXDATE")) {
list($key,$value,$rawkey,$rawvalue) = $this->handleDate($key,$value);
if (stristr($key,"DTEND") == "DTEND" && strlen($rawvalue) == 8) {
// all day event detected YYYYMMDD, set DTEND to last second of previous day
$value -= 1;
}
}
if (stristr($key,"DURATION")) {
list($key,$value,$rawkey,$rawvalue) = $this->handleDuration($key,$value);
}
switch ($parent)
{
case "VTODO":
$this->cal[$parent][$this->todoCount][$key] = $value;
break;
case "VEVENT":
// strip off unnecessary quoted printable encoding message
$parts = explode(';',$key);
if (count($parts)>1 ){
$key=$parts[0];
for ($i=1; $i<count($parts);$i++) {
if ($parts[$i]=="ENCODING=QUOTED-PRINTABLE"){
//$value=str_replace("=0D=0A","<br/>",$value);
$value=quoted_printable_decode($value);
}
// drop other ibts like language etc.
}
}
// Special treatment of
if (strpos($key,"EXDATE")===false){
$target =& $this->cal[$parent][$this->eventCount][$key];
$rawtarget =& $this->cal[$parent][$this->eventCount][$rawkey];
}
else {
// TODO timezone info is dropped here
if (!array_key_exists("EXDATE",$this->cal[$parent][$this->eventCount])){
$this->cal[$parent][$this->eventCount]["EXDATE"]=array();
$this->cal[$parent][$this->eventCount]["RAWEXDATE"]=array();
}
$target =& $this->cal[$parent][$this->eventCount]["EXDATE"][count($this->cal[$parent][$this->eventCount]["EXDATE"])];
$rawtarget =& $this->cal[$parent][$this->eventCount]["RAWEXDATE"][count($this->cal[$parent][$this->eventCount]["RAWEXDATE"])];
}
// Remove escaping of text
$value = str_replace('\,',',',$value);
$value = str_replace('\;',';',$value);
// convert URLs to links
//$value = ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]","<a href=\"\\0\">\\0</a>", $value);
//$value = preg_replace('@(?<![">])\b(?:(?:https?|ftp)://|www\.|ftp\.)[-A-Z0-9+&@#/%=~_|$?!:,.]*[A-Z0-9+&@#/%=~_|$]@',"<a href=\"\\0\">\\0</a>", $value);
if (is_string($value)){
if (strpos(str_replace(" ","",strtolower($value)),"<ahref=")===false){
$value = preg_replace('@(https?://([\w-.]+)+(:\d+)?(/([\w/_.]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $value);
}
}
// THIS IS NEEDED BECAUSE OF DODGY carriage returns in google calendar UID
// TODO check its enough
if ($append){
$target .= $value;
}
else {
$target = $value;
}
if ($rawkey!=""){
$rawtarget = $rawvalue;
}
break;
default:
$this->cal[$parent][$key] = $value;
break;
}
}
function parseRRULE($value, $parent)
{
$result = array();
$parts = explode(';',$value);
foreach ($parts as $part) {
if (strlen($part)==0) continue;
$portion = explode('=', $part);
if (stristr($portion[0],"UNTIL")){
$untilArray = $this->handleDate($portion[0],$portion[1]);
$result[$untilArray[0]] = $untilArray[1];
$result[$untilArray[2]] = $untilArray[3];
}
else $result[$portion[0]] = $portion[1];
}
return $result;
}
/**
* iCal spec represents date in ISO 8601 format followed by "T" then the time
* a "Z at the end means the time is UTC and not local time zone
*
* TODO make sure if time is UTC we take account of system time offset properly
*
*/
function unixTime($ical_date)
{
static $offset = null;
if (is_null($offset)) {
$config =& JFactory::getConfig();
$offset = $config->getValue('config.offset', 0);
}
$isUTC = false;
if (strpos($ical_date,"Z")!== false){
$isUTC = true;
}
// strip "T" and "Z" from the string
$ical_date = str_replace('T', '', $ical_date);
$ical_date = str_replace('Z', '', $ical_date);
// split it out intyo YYYY MM DD HH MM SS
ereg("([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{0,2})([0-9]{0,2})([0-9]{0,2})", $ical_date,$date);
list($temp,$y,$m,$d,$h,$min,$s)=$date;
if (!$min) $min=0;
if (!$d) $d=0;
if (!$s) $s=0;
// Trap unix dated beofre 1970
$y = max($y,1970);
if ($isUTC) {
$t = gmmktime($h,$min,$s,$m,$d,$y) + 3600 * $offset;
$result = strtotime(gmdate('Y-m-d H:i:s', $t));
} else {
$result = mktime($h,$min,$s,$m,$d,$y);
}
// double check!!
//list($y1,$m1,$d1,$h1,$min1,$s1)=explode(":",strftime('%Y:%m:%d:%H:%M:%S',$result));
return $result;
}
function handleDate($key, $value)
{
$rawvalue = $value;
$value = $this->unixTime($value);
$parts = explode(";",$key);
if (count($parts)<2 || strlen($parts[1])==0)
{
$rawkey=$key."RAW";
return array($key,$value, $rawkey, $rawvalue);
}
$key = $parts[0];
$rawkey=$key."RAW";
return array($key,$value, $rawkey, $rawvalue);
}
function handleDuration($key,$value)
{
$rawvalue = $value;
// strip "P" from the string
$value = str_replace('P', '', $value);
// split it out intyo W D H M S
preg_match("/([0-9]*W)*([0-9]*D)*T?([0-9]*H)*([0-9]*M)*([0-9]*S)*/",$value,$details);
list($temp,$w,$d,$h,$min,$s)=$details;
$duration = 0;
$multiplier=1;
$duration += intval(str_replace('S','',$s))*$multiplier;
$multiplier=60;
$duration += intval(str_replace('M','',$min))*$multiplier;
$multiplier=3600;
$duration += intval(str_replace('H','',$h))*$multiplier;
$multiplier=86400;
$duration += intval(str_replace('D','',$d))*$multiplier;
$multiplier=604800;
$duration += intval(str_replace('W','',$w))*$multiplier;
$rawkey=$key."RAW";
return array($key, $duration, $rawkey, $rawvalue);
}
/**
* Compare two unix timestamp
*
* @param array $a
* @param array $b
* @return integer
*/
function comparedates($a, $b)
{
if (!array_key_exists('DTSTART',$a) || !array_key_exists('DTSTART',$b) ){
echo "help<br/>";
}
if ($a['DTSTART'] == $b['DTSTART']) return 0;
return ($a['DTSTART'] > $b['DTSTART'])? +1 : -1;
}
// from http://fr3.php.net/manual/en/function.mb-detect-encoding.php#50087
function is_utf8($string) {
// From http://w3.org/International/questions/qa-forms-utf-8.html
$result = preg_match('%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs', $string);
return $result;
} // function is_utf8
// from http://fr3.php.net/manual/en/function.mb-detect-encoding.php#68607
function detectUTF8($string)
{
return preg_match('%(?:
[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
|\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
|\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
|\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
|[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
|\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)+%xs', $string);
}
}