1<?php
2if(!defined('DOKU_INC')) die();
3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
4
5require_once(DOKU_PLUGIN.'action.php');
6
7class action_plugin_calendoku extends DokuWiki_Action_Plugin {
8    function register(&$controller) {
9        $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'handle_pagewrite');
10        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_deliverical');
11    }
12
13    function handle_deliverical(&$event, $param) {
14        if (!is_string($event->data) || strcmp($event->data, 'ical'))
15            return;
16        $INFO = pageinfo();
17
18        $namespaces = preg_split('/\s/', $this->getconf('icalnamespaces'));
19        $dohandle = false;
20        foreach ($namespaces as $namespace)
21            if (!strcmp($INFO['namespace'], $namespace)) {
22                $dohandle = true;
23                break;
24            }
25        if (!$dohandle)
26            return;
27
28        if (auth_quickaclcheck($INFO['id']) < AUTH_READ)
29            return;
30
31        header('Content-type: text/calendar');
32        header('Content-disposition: attachment; filename="'.$INFO['id'].'.ics"');
33        die(file_get_contents($INFO['filepath']));
34    }
35
36    function handle_pagewrite(&$event, $param) {
37        /* data[3] is false for the current page, set to revision otherwise. */
38        if ($event->data[3])
39            return;
40
41        if (!strcmp($this->getConf('icalnamespaces'), ''))
42            return;
43
44        /* Namespace. false if root ns. */
45        if (!isset($event->data[1]))
46            return;
47
48        $templates = preg_split('/\s/', $this->getConf('icaltemplates'));
49        foreach ($templates as $template)
50            if (!strcmp($template, $event->data[2]))
51                return;
52
53        $dohandle = false;
54        $namespaces = preg_split('/\s/', $this->getConf('icalnamespaces'));
55        foreach ($namespaces as $namespace)
56            if (!strcmp($event->data[1], $namespace)) {
57                $dohandle = true;
58                break;
59            }
60        if (!$dohandle)
61            return;
62
63        $event->data[0][1] = $this->reparseTemplateWrite($event->data[0][1]);
64    }
65
66    function reparseTemplateWrite($text) {
67        // XXX: BEGIN:VCALENDAR
68        $textlines = preg_split('/\n/', $text);
69        $newtext = '';
70
71        $inparse = false;
72        $now = new DateTime('now');
73        foreach ($textlines as $line) {
74            /* Get DTSTAMP or LAST-MODIFIED. They have to be changed. */
75            if (!$inparse && (preg_match('/^(DTSTAMP:)/', $line, $match)
76                    || preg_match('/^(LAST-MODIFIED:)/', $line, $match))) {
77                $newtext .= $match[1].$now->format('Ymd').'T'.$now->format('His')."\n";
78                continue;
79            }
80
81            /* Get datetime lines, i.e. YYYY-MM-DD hh:mm. */
82            if (!$inparse && preg_match('/^([[:alnum:]-]*?):@@([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9-]{1,2}):([0-9-]{1,2})@@$/', $line, $match)) {
83                if (!strcmp($match[5], '-') || !strcmp($match[6], '-')) {
84                    $newtext .= $match[1].':'.$match[2].$match[3].$match[4]."\n";
85                } else {
86                    if (count($match[5]) == 1)
87                        $match[5] = '0'.$match[5];
88                    if (count($match[6]) == 1)
89                        $match[6] = '0'.$match[6];
90                    $newtext .= $match[1].':'.$match[2].$match[3].$match[4].'T'.$match[5].$match[6].'00'."\n";
91                }
92                continue;
93            }
94
95            /* Single-line field. */
96            if (!$inparse && preg_match('/^([[:alnum:]-]*?):@@(.*)@@$/', $line, $match)) {
97                $newtext .= $match[1].':'.$match[2]."\n";
98                continue;
99            }
100
101            /* Start of some added field. */
102            if (!$inparse && preg_match('/^([[:alnum:]-]*?):@@(.*)$/', $line, $match)) {
103                $newtext .= $match[1].':'.$match[2]."\n";
104                $inparse = true;
105                continue;
106            }
107
108            /* End of a field. */
109            if ($inparse && preg_match('/^(.*)@@$/', $line, $match)) {
110                $newtext .= ' '.$match[1]."\n";
111                $inparse = false;
112                continue;
113            }
114
115            /* In the middle of some added field. */
116            if ($inparse) {
117                $newtext .= ' '.$line."\n";
118                continue;
119            }
120
121            /* Nothing found. */
122            $newtext .= $line."\n";
123        }
124
125        /* Remove trailing newline. */
126        $newtext = substr($newtext, 0, -1);
127
128        return $newtext;
129    }
130}
131
132// vim:ts=4:sw=4:et:enc=utf-8:
133