0

I need your help. I'm writing a iCal .ics File-format with a php function.

If I open the .ics file with iCal it says the application says: "Calendar can’t read this calendar file. No events have been added to your calendar."

However if I validate the file with an online .ics validator it says everything should be fine except the line endings. The validator says this:

Your calendar is using an invalid newline format. Make sure to use \r\n to end lines rather than just \n (RFC 2445 §4.1). Congratulations; your calendar validated!

But I'm not sure if this is the "real" problem why my iCal can't read the file. First off, I wonder how to change this line endings?

<?php

function wpse63611_events_feed_output(){
    $filename = urlencode( 'My-Events-' . date('Y') . '.ics' );

    // Start collecting output
    ob_start();

    header( 'Content-Description: File Transfer' );
    header( 'Content-Disposition: attachment; filename=' . $filename );
    header( 'Content-type: text/calendar' );
    header( "Pragma: 0" );
    header( "Expires: 0" );
?>
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//<?php  get_bloginfo('name'); ?>//NONSGML Events //EN
CALSCALE:GREGORIAN
X-WR-CALNAME:<?php echo get_bloginfo('name');?> - Events
<?php
    if ( have_posts() ):
        $now = new DateTime();
        $datestamp =$now->format('Ymd\THis\Z');
        while( have_posts() ): the_post();
            global $post;
            $uid = md5(uniqid(mt_rand(), true))."@mydomain.com";
            $start = unixToiCal(get_event_date($post, true, true), 2.0);
            $end = unixToiCal(get_event_end_date($post, true, true), 2.0);
            $summary = wpse63611_esc_ical_text(get_the_title());
            $description = apply_filters('the_excerpt_rss',  get_the_content());
            $description = wpse63611_esc_ical_text($description); ?>
BEGIN:VEVENT
UID:<?php echo $uid; ?>
<?php echo "\r\n"; ?>
DTSTAMP:<?php echo $datestamp; ?>
<?php echo "\r\n"; ?>
DTSTART:<?php echo $start; ?>
<?php echo "\r\n"; ?>
DTEND:<?php echo $end; ?>
<?php echo "\r\n"; ?>
SUMMARY:<?php echo $summary; ?>
<?php echo "\r\n"; ?>
DESCRIPTION:<?php echo $description; ?>
<?php echo "\r\n"; ?>
END:VEVENT
<?php endwhile; endif; ?>
END:VCALENDAR
<?php
    // Collect output and echo 
    $eventsical = ob_get_contents();
    ob_end_clean();
    echo $eventsical;
    exit();
}

function unixToiCal( $uStamp = 0, $tzone = 0.0 ) {
    $uStampUTC = $uStamp + ($tzone * 3600);       
    $stamp  = date("Ymd\THis\Z", $uStampUTC);
    return $stamp;       
}

function wpse63611_esc_ical_text( $text='' ) {
    $text = str_replace("\\", "", $text);
    $text = str_replace("\r", "\r\n ", $text);
    $text = str_replace("\n", "\r\n ", $text);
    return $text;
}

?>

Can you see any problem with this? What could cause the calendar not to work?


UPDATE Well, I fixed the line endings and the calendar validates fine now. So no errors when validating it, but I still can't get it working in iCal. When I open it it still says the calendar file is not readable. Here is the actual file that is generated by my script … http://cl.ly/383D3M3q3P32

matt
  • 42,713
  • 103
  • 264
  • 397

2 Answers2

3

You have the wpse63611_esc_ical_text() function to normalize output but you only apply it to some output fragments. The funny thing is that such function expects Unix-style input ("\n") but the whole mechanism relies in saving your source code as Windows-style ("\r\n"). Additionally, you sometimes call the function twice on the same text.

I believe the root problem is the you don't really know what a line ending is. When you hit your keyboard's Enter key, you'll actually get a different character depending on whether your computer runs Windows or some kind of Unix (such as Linux or MacOS). On Windows, you'll actually get two characters, represented as "\r\n" in PHP. On Unix, you'll get one character, represented as "\n" in PHP. If your editor is good enough, it'll allow you to save the file with the line ending of your choice, no matter what your computer runs. Check the "Save as" dialogue for further info.

Since you aren't actually typing the ICS file, you need to ensure that PHP generates the appropriate characters. The simplest way is to type and save the source code as you please and then convert the complete output once:

$output = strtr($output, array(
    "\r\n" => "\r\n",
    "\r" => "\r\n",
    "\n" => "\r\n",
));

You'll probably need to clean up your code first.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • Thank, I already updated that. It validates now fine and every .ics validator tells me the file is 100% correct. However something must be missing. – matt Oct 01 '12 at 06:32
3

looking at your ical file brings 2 topics:

  1. as mentionned above, all your lines need to be ended by \r\n (i.e. you need to ensure

BEGIN:VCALENDAR

VERSION:2.0

..

are also ended properly

2.you need to escape commas in text (see RFC5545 §3.3.11: https://www.rfc-editor.org/rfc/rfc5545#section-3.3.11 )

you can also run those through online icalendar validators see this post answer: https://stackoverflow.com/a/4812081/1167333

Community
  • 1
  • 1
Auberon Vacher
  • 4,655
  • 1
  • 24
  • 36
  • Alright, I updated my code to look like this … http://cl.ly/code/1i2P080v2s1G … and the outputted calendar validates just perfectly in all those validatars. Scores 100 out of 100. However I can't open it on my mac in my "Calendar" Application. Meanwhile under Mac OSX Mountain Lion "iCal" was renamed to "Calendar" … the outputted file looks like this: http://cl.ly/3c2w1Z462d2o The ".ics" file can be opened in an older version of iCal but doesn't seem to really work their either. No events get added, but the calendar file can be read (so no error message when opening it, but no events added) – matt Oct 01 '12 at 17:52
  • issue is not your code but the underlying data: dtstart is *after* dtend, see: DTSTART:20121018T022000Z DTEND:20120904T162842Z SUMMARY:Title\, Number 1? – Auberon Vacher Oct 01 '12 at 20:16