matt
matt

Reputation: 44293

Can't seem to write a valid .ics file?

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

Upvotes: 0

Views: 6195

Answers (2)

Auberon Vacher
Auberon Vacher

Reputation: 4775

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

Upvotes: 3

&#193;lvaro Gonz&#225;lez
&#193;lvaro Gonz&#225;lez

Reputation: 146450

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.

Upvotes: 2

Related Questions