0

我需要你的帮助。我正在编写.ics带有 php 函数的 iCal 文件格式。

如果我.ics用 iCal 打开文件,应用程序会说:“日历无法读取此日历文件。您的日历中没有添加任何活动。”

但是,如果我使用在线 .ics 验证器验证文件,它会说一切都应该没问题,除了line endings. 验证器是这样说的:

您的日历使用了无效的换行格式。确保使用 \r\n 来结束行,而不仅仅是 \n (RFC 2445 §4.1)。恭喜;您的日历已验证!

但我不确定这是否是 iCal 无法读取文件的“真正”问题。首先,我想知道如何更改此行结尾?

<?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;
}

?>

你能看出这有什么问题吗?什么可能导致日历不起作用?


更新 好吧,我修复了行尾,现在日历验证正常。所以验证它时没有错误,但我仍然无法让它在 iCal 中工作。当我打开它时,它仍然说日历文件不可读。这是我的脚本生成的实际文件…… <a href="http://cl.ly/383D3M3q3P32" rel="nofollow">http://cl.ly/383D3M3q3P32

4

2 回答 2

3

查看您的 ical 文件会带来 2 个主题:

  1. 如上所述,您的所有行都需要以 \r\n 结尾(即您需要确保

开始:VCALENDAR

版本:2.0

..

也正确结束

2.您需要在文本中转义逗号(参见 RFC5545 §3.3.11:https ://www.rfc-editor.org/rfc/rfc5545#section-3.3.11 )

您也可以通过在线 icalendar 验证器运行它们,请参阅此帖子答案:https ://stackoverflow.com/a/4812081/1167333

于 2012-10-01T17:35:11.210 回答
3

您具有wpse63611_esc_ical_text()标准化输出的功能,但您仅将其应用于某些输出片段。有趣的是,这样的函数需要 Unix 风格的输入 ( "\n"),但整个机制依赖于将源代码保存为 Windows 风格的 ( "\r\n")。此外,您有时会在同一文本上调用该函数两次。

我相信根本问题是你真的不知道行尾是什么。当您敲击键盘上的Enter键时,您实际上会得到不同的字符,具体取决于您的计算机运行的是 Windows 还是某种 Unix(例如 Linux 或 MacOS)。在 Windows 上,您实际上会得到两个字符,"\r\n"用 PHP 表示。在 Unix 上,你会得到一个字符,"\n"用 PHP 表示。如果您的编辑器足够好,它将允许您以您选择的行结尾保存文件,无论您的计算机运行什么。检查“另存为”对话框以获取更多信息。

由于您实际上并未键入 ICS 文件,因此您需要确保 PHP 生成适当的字符。最简单的方法是根据需要键入并保存源代码,然后将完整的输出转换一次:

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

您可能需要先清理代码。

于 2012-09-27T14:00:09.530 回答