|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* EGroupware: Iterator for iCal files |
|
4
|
|
|
* |
|
5
|
|
|
* @link http://www.egroupware.org |
|
6
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
|
7
|
|
|
* @package api |
|
8
|
|
|
* @subpackage caldav |
|
9
|
|
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> |
|
10
|
|
|
* @copyright (c) 2010-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de> |
|
11
|
|
|
* @version $Id$ |
|
12
|
|
|
*/ |
|
13
|
|
|
|
|
14
|
|
|
namespace EGroupware\Api\CalDAV; |
|
15
|
|
|
|
|
16
|
|
|
use EGroupware\Api; |
|
17
|
|
|
use Horde_Icalendar; |
|
18
|
|
|
|
|
19
|
|
|
// required for tests at the end of this file (run if file called directly) |
|
20
|
|
|
if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) |
|
21
|
|
|
{ |
|
22
|
|
|
$GLOBALS['egw_info'] = array( |
|
23
|
|
|
'flags' => array( |
|
24
|
|
|
'currentapp' => 'login', |
|
25
|
|
|
'nonavbar' => 'true', |
|
26
|
|
|
), |
|
27
|
|
|
); |
|
28
|
|
|
include('../../../header.inc.php'); |
|
29
|
|
|
} |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* Iterator for iCal files |
|
33
|
|
|
* |
|
34
|
|
|
* try { |
|
35
|
|
|
* $ical_file = fopen($path,'r'); |
|
36
|
|
|
* $ical_it = new Api\CalDAV\IcalIterator($ical_file,'VCALENDAR'); |
|
37
|
|
|
* } |
|
38
|
|
|
* catch (Exception $e) |
|
39
|
|
|
* { |
|
40
|
|
|
* // could not open $path or no valid iCal file |
|
41
|
|
|
* } |
|
42
|
|
|
* foreach($ical_it as $vevent) |
|
43
|
|
|
* { |
|
44
|
|
|
* // do something with $vevent |
|
45
|
|
|
* } |
|
46
|
|
|
* fclose($ical_file) |
|
47
|
|
|
*/ |
|
48
|
|
|
class IcalIterator extends Horde_Icalendar implements \Iterator |
|
49
|
|
|
{ |
|
50
|
|
|
/** |
|
51
|
|
|
* File we work on |
|
52
|
|
|
* |
|
53
|
|
|
* @var resource |
|
54
|
|
|
*/ |
|
55
|
|
|
protected $ical_file; |
|
56
|
|
|
|
|
57
|
|
|
/** |
|
58
|
|
|
* Base name of container, eg. 'VCALENDAR', as passed to the constructor |
|
59
|
|
|
* |
|
60
|
|
|
* @var string |
|
61
|
|
|
*/ |
|
62
|
|
|
protected $base; |
|
63
|
|
|
|
|
64
|
|
|
/** |
|
65
|
|
|
* Does ical_file contain a container: BEGIN:$base ... END:$base |
|
66
|
|
|
* |
|
67
|
|
|
* @var boolean |
|
68
|
|
|
*/ |
|
69
|
|
|
protected $container; |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Charset passed to the constructor |
|
73
|
|
|
* |
|
74
|
|
|
* @var string |
|
75
|
|
|
*/ |
|
76
|
|
|
protected $charset; |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* Current component, as it get's returned by current() method |
|
80
|
|
|
* |
|
81
|
|
|
* @var Horde_Icalendar |
|
82
|
|
|
*/ |
|
83
|
|
|
protected $component; |
|
84
|
|
|
|
|
85
|
|
|
/** |
|
86
|
|
|
* Callback to call with component in current() method, if returning false, item get's ignored |
|
87
|
|
|
* |
|
88
|
|
|
* @var callback |
|
89
|
|
|
*/ |
|
90
|
|
|
protected $callback; |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* Further parameters for the callback, 1. parameter is component |
|
94
|
|
|
* |
|
95
|
|
|
* @var array |
|
96
|
|
|
*/ |
|
97
|
|
|
protected $callback_params = array(); |
|
98
|
|
|
|
|
99
|
|
|
/** |
|
100
|
|
|
* Constructor |
|
101
|
|
|
* |
|
102
|
|
|
* @param string|resource $ical_file file opened for reading or string |
|
103
|
|
|
* @param string $base ='VCALENDAR' container |
|
104
|
|
|
* @param string $charset =null |
|
105
|
|
|
* @param callback $callback =null callback to call with component in current() method, if returning false, item get's ignored |
|
106
|
|
|
* @param array $callback_params =array() further parameters for the callback, 1. parameter is component |
|
107
|
|
|
* @param boolean $add_container =false true, add container / $this as last parameter to callback |
|
108
|
|
|
*/ |
|
109
|
|
|
public function __construct($ical_file,$base='VCALENDAR',$charset=null,$callback=null,array $callback_params=array(), $add_container=false) |
|
110
|
|
|
{ |
|
111
|
|
|
// call parent constructor |
|
112
|
|
|
parent::__construct(); |
|
113
|
|
|
|
|
114
|
|
|
$this->base = $base; |
|
115
|
|
|
$this->charset = $charset; |
|
116
|
|
|
if (is_callable($callback)) |
|
117
|
|
|
{ |
|
118
|
|
|
$this->callback = $callback; |
|
119
|
|
|
if ($add_container) $callback_params[] = $this; |
|
120
|
|
|
$this->callback_params = $callback_params; |
|
121
|
|
|
} |
|
122
|
|
|
if (is_string($ical_file)) |
|
123
|
|
|
{ |
|
124
|
|
|
$this->ical_file = fopen('php://temp', 'w+'); |
|
|
|
|
|
|
125
|
|
|
fwrite($this->ical_file, $ical_file); |
|
126
|
|
|
fseek($this->ical_file, 0, SEEK_SET); |
|
127
|
|
|
} |
|
128
|
|
|
else |
|
129
|
|
|
{ |
|
130
|
|
|
$this->ical_file = $ical_file; |
|
131
|
|
|
} |
|
132
|
|
|
if (!is_resource($this->ical_file)) |
|
133
|
|
|
{ |
|
134
|
|
|
throw new Api\Exception\WrongParameter(__METHOD__.'($ical_file, ...) NO resource! $ical_file='.substr(array2string($ical_file),0,100)); |
|
135
|
|
|
} |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
/** |
|
139
|
|
|
* Stack with not yet processed lines |
|
140
|
|
|
* |
|
141
|
|
|
* @var string |
|
142
|
|
|
*/ |
|
143
|
|
|
protected $unread_lines = array(); |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* Read and return one line from file (or line-buffer) |
|
147
|
|
|
* |
|
148
|
|
|
* We do NOT handle folding, that's done by Horde_Icalendar and not necessary for us as BEGIN: or END: component is never folded |
|
149
|
|
|
* |
|
150
|
|
|
* @return string|boolean string with line or false if end-of-file or end-of-container reached |
|
151
|
|
|
*/ |
|
152
|
|
|
protected function read_line() |
|
153
|
|
|
{ |
|
154
|
|
|
if ($this->unread_lines) |
|
155
|
|
|
{ |
|
156
|
|
|
$line = array_shift($this->unread_lines); |
|
157
|
|
|
} |
|
158
|
|
|
elseif(feof($this->ical_file)) |
|
159
|
|
|
{ |
|
160
|
|
|
$line = false; |
|
161
|
|
|
} |
|
162
|
|
|
else |
|
163
|
|
|
{ |
|
164
|
|
|
$line = ltrim(fgets($this->ical_file), "\xef\xbb\xbf"); |
|
165
|
|
|
} |
|
166
|
|
|
// check if end of container reached |
|
167
|
|
|
if ($this->container && $line && substr($line,0,4+strlen($this->base)) === 'END:'.$this->base) |
|
168
|
|
|
{ |
|
169
|
|
|
$this->unread_line($line); // put back end-of-container, to continue to return false |
|
170
|
|
|
$line = false; |
|
171
|
|
|
} |
|
172
|
|
|
//error_log(__METHOD__."() returning ".($line === false ? 'FALSE' : "'$line'")); |
|
173
|
|
|
|
|
174
|
|
|
return $line; |
|
175
|
|
|
} |
|
176
|
|
|
|
|
177
|
|
|
/** |
|
178
|
|
|
* Take back on line, already read with read_line |
|
179
|
|
|
* |
|
180
|
|
|
* @param string $line |
|
181
|
|
|
*/ |
|
182
|
|
|
protected function unread_line($line) |
|
183
|
|
|
{ |
|
184
|
|
|
//error_log(__METHOD__."('$line')"); |
|
185
|
|
|
array_unshift($this->unread_lines,$line); |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
/** |
|
189
|
|
|
* Return the current element |
|
190
|
|
|
* |
|
191
|
|
|
* @return Horde_Icalendar or whatever a given callback returns |
|
192
|
|
|
*/ |
|
193
|
|
|
public function current() |
|
194
|
|
|
{ |
|
195
|
|
|
//error_log(__METHOD__."() returning a ".gettype($this->component)); |
|
196
|
|
|
if ($this->callback) |
|
197
|
|
|
{ |
|
198
|
|
|
$ret = is_a($this->component,'Horde_Icalendar'); |
|
199
|
|
|
do { |
|
200
|
|
|
if ($ret === false) $this->next(); |
|
201
|
|
|
if (!is_a($this->component,'Horde_Icalendar')) return false; |
|
202
|
|
|
$params = $this->callback_params; |
|
203
|
|
|
array_unshift($params,$this->component); |
|
204
|
|
|
} |
|
205
|
|
|
while(($ret = call_user_func_array($this->callback,$params)) === false); |
|
206
|
|
|
|
|
207
|
|
|
return $ret; |
|
208
|
|
|
} |
|
209
|
|
|
return $this->component; |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
/** |
|
213
|
|
|
* Return the key of the current element |
|
214
|
|
|
* |
|
215
|
|
|
* @return int|string |
|
216
|
|
|
*/ |
|
217
|
|
|
public function key() |
|
218
|
|
|
{ |
|
219
|
|
|
//error_log(__METHOD__."() returning ".$this->component->getAttribute('UID')); |
|
220
|
|
|
return $this->component ? $this->component->getAttribute('UID') : false; |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
|
|
/** |
|
224
|
|
|
* Move forward to next component (called after each foreach loop) |
|
225
|
|
|
*/ |
|
226
|
|
|
public function next() |
|
227
|
|
|
{ |
|
228
|
|
|
unset($this->component); |
|
229
|
|
|
|
|
230
|
|
|
while (($line = $this->read_line()) && substr($line,0,6) !== 'BEGIN:') |
|
231
|
|
|
{ |
|
232
|
|
|
error_log("'".$line."'"); |
|
|
|
|
|
|
233
|
|
|
// ignore it |
|
234
|
|
|
} |
|
235
|
|
|
if ($line === false) // end-of-file or end-of-container |
|
236
|
|
|
{ |
|
237
|
|
|
$this->component = false; |
|
|
|
|
|
|
238
|
|
|
return; |
|
239
|
|
|
} |
|
240
|
|
|
$type = substr(trim($line),6); |
|
241
|
|
|
|
|
242
|
|
|
//error_log(__METHOD__."() found $type component"); |
|
243
|
|
|
|
|
244
|
|
|
$data = $line; |
|
245
|
|
|
while (($line = $this->read_line()) && substr($line,0,4+strlen($type)) !== 'END:'.$type) |
|
246
|
|
|
{ |
|
247
|
|
|
$data .= $line; |
|
248
|
|
|
} |
|
249
|
|
|
$data .= $line; |
|
250
|
|
|
|
|
251
|
|
|
$this->component = Horde_Icalendar::newComponent($type, $this); |
|
252
|
|
|
//error_log(__METHOD__."() this->component = Horde_Icalendar::newComponent('$type', \$this) = ".array2string($this->component)); |
|
253
|
|
|
if ($this->component === false) |
|
|
|
|
|
|
254
|
|
|
{ |
|
255
|
|
|
error_log(__METHOD__."() Horde_Icalendar::newComponent('$type', \$this) returned FALSE"); |
|
256
|
|
|
return; |
|
257
|
|
|
//return PEAR::raiseError("Unable to create object for type $type"); |
|
258
|
|
|
} |
|
259
|
|
|
if ($this->charset && $this->charset != 'utf-8') |
|
260
|
|
|
{ |
|
261
|
|
|
$data = Api\Translation::convert($data, $this->charset, 'utf-8'); |
|
262
|
|
|
} |
|
263
|
|
|
//error_log(__METHOD__."() about to call parsevCalendar('".substr($data,0,100)."...','$type')"); |
|
264
|
|
|
$this->component->parsevCalendar($data, $type); |
|
265
|
|
|
|
|
266
|
|
|
// VTIMEZONE components are NOT returned, they are only processed internally |
|
267
|
|
|
if ($type == 'VTIMEZONE') |
|
268
|
|
|
{ |
|
269
|
|
|
$this->addComponent($this->component); |
|
270
|
|
|
// calling ourself recursive, to set next non-VTIMEZONE component |
|
271
|
|
|
$this->next(); |
|
272
|
|
|
} |
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
|
|
/** |
|
276
|
|
|
* Rewind the Iterator to the first element (called at beginning of foreach loop) |
|
277
|
|
|
*/ |
|
278
|
|
|
public function rewind() |
|
279
|
|
|
{ |
|
280
|
|
|
@fseek($this->ical_file,0,SEEK_SET); |
|
|
|
|
|
|
281
|
|
|
|
|
282
|
|
|
// advance to begin of container |
|
283
|
|
|
while(($line = $this->read_line()) && substr($line,0,6+strlen($this->base)) !== 'BEGIN:'.$this->base) |
|
284
|
|
|
{ |
|
285
|
|
|
|
|
286
|
|
|
} |
|
287
|
|
|
// if no container start found --> use whole file (rewind) and set container marker |
|
288
|
|
|
if (!($this->container = $line !== false)) |
|
289
|
|
|
{ |
|
290
|
|
|
fseek($this->ical_file,0,SEEK_SET); |
|
291
|
|
|
} |
|
292
|
|
|
//error_log(__METHOD__."() $this->base container ".($this->container ? 'found' : 'NOT found')); |
|
293
|
|
|
|
|
294
|
|
|
$data = $line; |
|
295
|
|
|
// advance to first component |
|
296
|
|
|
while (($line = $this->read_line()) && substr($line,0,6) !== 'BEGIN:') |
|
297
|
|
|
{ |
|
298
|
|
|
$matches = null; |
|
299
|
|
|
if (preg_match('/^VERSION:(\d\.\d)\s*$/ism', $line, $matches)) |
|
300
|
|
|
{ |
|
301
|
|
|
// define the version asap |
|
302
|
|
|
$this->setAttribute('VERSION', $matches[1]); |
|
303
|
|
|
} |
|
304
|
|
|
$data .= $line; |
|
305
|
|
|
} |
|
306
|
|
|
// fake end of container to get it parsed by Horde code |
|
307
|
|
|
if ($this->container) |
|
308
|
|
|
{ |
|
309
|
|
|
$data .= "END:$this->base\n"; |
|
310
|
|
|
//error_log(__METHOD__."() about to call this->parsevCalendar('$data','$this->base','$this->charset')"); |
|
311
|
|
|
$this->parsevCalendar($data,$this->base,$this->charset); |
|
312
|
|
|
} |
|
313
|
|
|
if ($line) $this->unread_line($line); |
|
314
|
|
|
|
|
315
|
|
|
// advance to first element |
|
316
|
|
|
$this->next(); |
|
317
|
|
|
} |
|
318
|
|
|
|
|
319
|
|
|
/** |
|
320
|
|
|
* Checks if current position is valid |
|
321
|
|
|
* |
|
322
|
|
|
* @return boolean |
|
323
|
|
|
*/ |
|
324
|
|
|
public function valid () |
|
325
|
|
|
{ |
|
326
|
|
|
//error_log(__METHOD__."() returning ".(is_a($this->component,'Horde_Icalendar') ? 'TRUE' : 'FALSE').' get_class($this->component)='.get_class($this->component)); |
|
327
|
|
|
return is_a($this->component,'Horde_Icalendar'); |
|
328
|
|
|
} |
|
329
|
|
|
} |
|
330
|
|
|
|
|
331
|
|
|
// some tests run if file called directly |
|
332
|
|
|
if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) |
|
333
|
|
|
{ |
|
334
|
|
|
$ical_file = 'BEGIN:VCALENDAR |
|
335
|
|
|
PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN |
|
336
|
|
|
VERSION:2.0 |
|
337
|
|
|
METHOD:PUBLISH |
|
338
|
|
|
X-CALSTART:19980101T000000 |
|
339
|
|
|
X-WR-RELCALID:{0000002E-1BB2-8F0F-1203-47B98FEEF211} |
|
340
|
|
|
X-WR-CALNAME:Fxlxcxtxsxxxxxxxxxxxxx |
|
341
|
|
|
X-PRIMARY-CALENDAR:TRUE |
|
342
|
|
|
X-OWNER;CN="Fxlxcxtxsxxxxxxx":mailto:xexixixax.xuxaxa@xxxxxxxxxxxxxxx-berli |
|
343
|
|
|
n.de |
|
344
|
|
|
X-MS-OLK-WKHRSTART;TZID="Westeuropäische Normalzeit":080000 |
|
345
|
|
|
X-MS-OLK-WKHREND;TZID="Westeuropäische Normalzeit":170000 |
|
346
|
|
|
X-MS-OLK-WKHRDAYS:MO,TU,WE,TH,FR |
|
347
|
|
|
BEGIN:VTIMEZONE |
|
348
|
|
|
TZID:Westeuropäische Normalzeit |
|
349
|
|
|
BEGIN:STANDARD |
|
350
|
|
|
DTSTART:16011028T030000 |
|
351
|
|
|
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 |
|
352
|
|
|
TZOFFSETFROM:+0200 |
|
353
|
|
|
TZOFFSETTO:+0100 |
|
354
|
|
|
END:STANDARD |
|
355
|
|
|
BEGIN:DAYLIGHT |
|
356
|
|
|
DTSTART:16010325T020000 |
|
357
|
|
|
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 |
|
358
|
|
|
TZOFFSETFROM:+0100 |
|
359
|
|
|
TZOFFSETTO:+0200 |
|
360
|
|
|
END:DAYLIGHT |
|
361
|
|
|
END:VTIMEZONE |
|
362
|
|
|
BEGIN:VEVENT |
|
363
|
|
|
ATTENDEE;CN=Vorstand;RSVP=TRUE:mailto:[email protected] |
|
364
|
|
|
ATTENDEE;CN=\'[email protected]\';RSVP=TRUE:mailto:[email protected] |
|
365
|
|
|
ATTENDEE;CN=Pressestelle;RSVP=TRUE:mailto:xrxsxexxexlx@xxxxxxxxxxxxxxx-berl |
|
366
|
|
|
in.de |
|
367
|
|
|
ATTENDEE;CN="Dxuxe Nxcxxlxxx";ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:xjxkx.x |
|
368
|
|
|
[email protected] |
|
369
|
|
|
ATTENDEE;CN="Mxxxaxx Sxxäxxr";ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:xixhxe |
|
370
|
|
|
[email protected] |
|
371
|
|
|
CLASS:PUBLIC |
|
372
|
|
|
CREATED:20100408T232652Z |
|
373
|
|
|
DESCRIPTION:\n |
|
374
|
|
|
DTEND;TZID="Westeuropäische Normalzeit":20100414T210000 |
|
375
|
|
|
DTSTAMP:20100406T125856Z |
|
376
|
|
|
DTSTART;TZID="Westeuropäische Normalzeit":20100414T190000 |
|
377
|
|
|
LAST-MODIFIED:20100408T232653Z |
|
378
|
|
|
LOCATION:Axtx Fxuxrxaxhx\, Axex-Sxrxnxxxxxxxxxxxxxx |
|
379
|
|
|
ORGANIZER;CN="Exixaxexhxxxxxxxxxxxräxx":mailto:xxx.xxxxxxxxxxx@xxxxxxxxxxx |
|
380
|
|
|
xxxx-berlin.de |
|
381
|
|
|
PRIORITY:5 |
|
382
|
|
|
RECURRENCE-ID;TZID="Westeuropäische Normalzeit":20100414T190000 |
|
383
|
|
|
SEQUENCE:0 |
|
384
|
|
|
SUMMARY;LANGUAGE=de:Aktualisiert: LA - mit Ramona |
|
385
|
|
|
TRANSP:OPAQUE |
|
386
|
|
|
UID:040000008200E00074C5B7101A82E00800000000D0AFE96CB462CA01000000000000000 |
|
387
|
|
|
01000000019F8AF4D13C91844AA9CE63190D3408D |
|
388
|
|
|
X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//E |
|
389
|
|
|
N">\n<HTML>\n<HEAD>\n<META NAME="Generator" CONTENT="MS Exchange Server ve |
|
390
|
|
|
rsion 08.00.0681.000">\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n<!-- Converted f |
|
391
|
|
|
rom text/rtf format -->\n<BR>\n\n</BODY>\n</HTML> |
|
392
|
|
|
X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE |
|
393
|
|
|
X-MICROSOFT-CDO-IMPORTANCE:1 |
|
394
|
|
|
X-MICROSOFT-DISALLOW-COUNTER:FALSE |
|
395
|
|
|
X-MS-OLK-ALLOWEXTERNCHECK:TRUE |
|
396
|
|
|
X-MS-OLK-APPTSEQTIME:20091111T085039Z |
|
397
|
|
|
X-MS-OLK-AUTOSTARTCHECK:FALSE |
|
398
|
|
|
X-MS-OLK-CONFTYPE:0 |
|
399
|
|
|
END:VEVENT |
|
400
|
|
|
BEGIN:VEVENT |
|
401
|
|
|
CLASS:PUBLIC |
|
402
|
|
|
CREATED:20100331T125400Z |
|
403
|
|
|
DTEND:20100409T110000Z |
|
404
|
|
|
DTSTAMP:20100409T123209Z |
|
405
|
|
|
DTSTART:20100409T080000Z |
|
406
|
|
|
LAST-MODIFIED:20100331T125400Z |
|
407
|
|
|
PRIORITY:5 |
|
408
|
|
|
SEQUENCE:0 |
|
409
|
|
|
SUMMARY;LANGUAGE=de:Marissa |
|
410
|
|
|
TRANSP:OPAQUE |
|
411
|
|
|
UID:AAAAAEyulq85HfZCtWDOITo5tZQHABE65KS0gg5Fu6X1g2z9eWUAAAAA3BAAABE65KS0gg5 |
|
412
|
|
|
Fu6X1g2z9eWUAAAIQ6D0AAA== |
|
413
|
|
|
X-MICROSOFT-CDO-BUSYSTATUS:BUSY |
|
414
|
|
|
X-MICROSOFT-CDO-IMPORTANCE:1 |
|
415
|
|
|
X-MS-OLK-ALLOWEXTERNCHECK:TRUE |
|
416
|
|
|
X-MS-OLK-AUTOSTARTCHECK:FALSE |
|
417
|
|
|
X-MS-OLK-CONFTYPE:0 |
|
418
|
|
|
END:VEVENT |
|
419
|
|
|
BEGIN:VEVENT |
|
420
|
|
|
CLASS:PUBLIC |
|
421
|
|
|
CREATED:20100331T124848Z |
|
422
|
|
|
DTEND;VALUE=DATE:20100415 |
|
423
|
|
|
DTSTAMP:20100409T123209Z |
|
424
|
|
|
DTSTART;VALUE=DATE:20100414 |
|
425
|
|
|
LAST-MODIFIED:20100331T124907Z |
|
426
|
|
|
PRIORITY:5 |
|
427
|
|
|
SEQUENCE:0 |
|
428
|
|
|
SUMMARY;LANGUAGE=de:MELANIE wieder da |
|
429
|
|
|
TRANSP:TRANSPARENT |
|
430
|
|
|
UID:AAAAAEyulq85HfZCtWDOITo5tZQHABE65KS0gg5Fu6X1g2z9eWUAAAAA3BAAABE65KS0gg5 |
|
431
|
|
|
Fu6X1g2z9eWUAAAIQ6DsAAA== |
|
432
|
|
|
X-MICROSOFT-CDO-BUSYSTATUS:FREE |
|
433
|
|
|
X-MICROSOFT-CDO-IMPORTANCE:1 |
|
434
|
|
|
X-MS-OLK-ALLOWEXTERNCHECK:TRUE |
|
435
|
|
|
X-MS-OLK-AUTOSTARTCHECK:FALSE |
|
436
|
|
|
X-MS-OLK-CONFTYPE:0 |
|
437
|
|
|
END:VEVENT |
|
438
|
|
|
END:VCALENDAR |
|
439
|
|
|
'; |
|
440
|
|
|
echo $GLOBALS['egw']->framework->header(); |
|
441
|
|
|
//$ical_file = fopen('/tmp/KalenderFelicitasKubala.ics'); |
|
442
|
|
|
if (!is_resource($ical_file)) echo "<pre>$ical_file</pre>\n"; |
|
|
|
|
|
|
443
|
|
|
//$calendar_ical = new calendar_ical(); |
|
444
|
|
|
//$calendar_ical->setSupportedFields('file'); |
|
445
|
|
|
$ical_it = new IcalIterator($ical_file);//,'VCALENDAR','iso-8859-1',array($calendar_ical,'_ical2egw_callback'),array('Europe/Berlin')); |
|
446
|
|
|
foreach($ical_it as $uid => $vevent) |
|
447
|
|
|
{ |
|
448
|
|
|
echo "$uid<pre>".print_r($vevent->toHash(), true)."</pre>\n"; |
|
449
|
|
|
} |
|
450
|
|
|
if (is_resource($ical_file)) fclose($ical_file); |
|
|
|
|
|
|
451
|
|
|
} |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.