1<?php 2 3namespace Sabre\VObject; 4 5class ReaderTest extends \PHPUnit_Framework_TestCase { 6 7 function testReadComponent() { 8 9 $data = "BEGIN:VCALENDAR\r\nEND:VCALENDAR"; 10 11 $result = Reader::read($data); 12 13 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 14 $this->assertEquals('VCALENDAR', $result->name); 15 $this->assertEquals(0, count($result->children())); 16 17 } 18 19 function testReadStream() { 20 21 $data = "BEGIN:VCALENDAR\r\nEND:VCALENDAR"; 22 23 $stream = fopen('php://memory', 'r+'); 24 fwrite($stream, $data); 25 rewind($stream); 26 27 $result = Reader::read($stream); 28 29 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 30 $this->assertEquals('VCALENDAR', $result->name); 31 $this->assertEquals(0, count($result->children())); 32 33 } 34 35 function testReadComponentUnixNewLine() { 36 37 $data = "BEGIN:VCALENDAR\nEND:VCALENDAR"; 38 39 $result = Reader::read($data); 40 41 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 42 $this->assertEquals('VCALENDAR', $result->name); 43 $this->assertEquals(0, count($result->children())); 44 45 } 46 47 function testReadComponentLineFold() { 48 49 $data = "BEGIN:\r\n\tVCALENDAR\r\nE\r\n ND:VCALENDAR"; 50 51 $result = Reader::read($data); 52 53 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 54 $this->assertEquals('VCALENDAR', $result->name); 55 $this->assertEquals(0, count($result->children())); 56 57 } 58 59 /** 60 * @expectedException Sabre\VObject\ParseException 61 */ 62 function testReadCorruptComponent() { 63 64 $data = "BEGIN:VCALENDAR\r\nEND:FOO"; 65 66 $result = Reader::read($data); 67 68 } 69 70 /** 71 * @expectedException Sabre\VObject\ParseException 72 */ 73 function testReadCorruptSubComponent() { 74 75 $data = "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:FOO\r\nEND:VCALENDAR"; 76 77 $result = Reader::read($data); 78 79 } 80 81 function testReadProperty() { 82 83 $data = "BEGIN:VCALENDAR\r\nSUMMARY:propValue\r\nEND:VCALENDAR"; 84 $result = Reader::read($data); 85 86 $result = $result->SUMMARY; 87 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 88 $this->assertEquals('SUMMARY', $result->name); 89 $this->assertEquals('propValue', $result->getValue()); 90 91 } 92 93 function testReadPropertyWithNewLine() { 94 95 $data = "BEGIN:VCALENDAR\r\nSUMMARY:Line1\\nLine2\\NLine3\\\\Not the 4th line!\r\nEND:VCALENDAR"; 96 $result = Reader::read($data); 97 98 $result = $result->SUMMARY; 99 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 100 $this->assertEquals('SUMMARY', $result->name); 101 $this->assertEquals("Line1\nLine2\nLine3\\Not the 4th line!", $result->getValue()); 102 103 } 104 105 function testReadMappedProperty() { 106 107 $data = "BEGIN:VCALENDAR\r\nDTSTART:20110529\r\nEND:VCALENDAR"; 108 $result = Reader::read($data); 109 110 $result = $result->DTSTART; 111 $this->assertInstanceOf('Sabre\\VObject\\Property\\ICalendar\\DateTime', $result); 112 $this->assertEquals('DTSTART', $result->name); 113 $this->assertEquals('20110529', $result->getValue()); 114 115 } 116 117 function testReadMappedPropertyGrouped() { 118 119 $data = "BEGIN:VCALENDAR\r\nfoo.DTSTART:20110529\r\nEND:VCALENDAR"; 120 $result = Reader::read($data); 121 122 $result = $result->DTSTART; 123 $this->assertInstanceOf('Sabre\\VObject\\Property\\ICalendar\\DateTime', $result); 124 $this->assertEquals('DTSTART', $result->name); 125 $this->assertEquals('20110529', $result->getValue()); 126 127 } 128 129 /** 130 * @expectedException Sabre\VObject\ParseException 131 */ 132 function testReadBrokenLine() { 133 134 $data = "BEGIN:VCALENDAR\r\nPROPNAME;propValue"; 135 $result = Reader::read($data); 136 137 } 138 139 function testReadPropertyInComponent() { 140 141 $data = [ 142 "BEGIN:VCALENDAR", 143 "PROPNAME:propValue", 144 "END:VCALENDAR" 145 ]; 146 147 $result = Reader::read(implode("\r\n", $data)); 148 149 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 150 $this->assertEquals('VCALENDAR', $result->name); 151 $this->assertEquals(1, count($result->children())); 152 $this->assertInstanceOf('Sabre\\VObject\\Property', $result->children()[0]); 153 $this->assertEquals('PROPNAME', $result->children()[0]->name); 154 $this->assertEquals('propValue', $result->children()[0]->getValue()); 155 156 } 157 158 function testReadNestedComponent() { 159 160 $data = [ 161 "BEGIN:VCALENDAR", 162 "BEGIN:VTIMEZONE", 163 "BEGIN:DAYLIGHT", 164 "END:DAYLIGHT", 165 "END:VTIMEZONE", 166 "END:VCALENDAR" 167 ]; 168 169 $result = Reader::read(implode("\r\n", $data)); 170 171 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 172 $this->assertEquals('VCALENDAR', $result->name); 173 $this->assertEquals(1, count($result->children())); 174 $this->assertInstanceOf('Sabre\\VObject\\Component', $result->children()[0]); 175 $this->assertEquals('VTIMEZONE', $result->children()[0]->name); 176 $this->assertEquals(1, count($result->children()[0]->children())); 177 $this->assertInstanceOf('Sabre\\VObject\\Component', $result->children()[0]->children()[0]); 178 $this->assertEquals('DAYLIGHT', $result->children()[0]->children()[0]->name); 179 180 181 } 182 183 function testReadPropertyParameter() { 184 185 $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue:propValue\r\nEND:VCALENDAR"; 186 $result = Reader::read($data); 187 188 $result = $result->PROPNAME; 189 190 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 191 $this->assertEquals('PROPNAME', $result->name); 192 $this->assertEquals('propValue', $result->getValue()); 193 $this->assertEquals(1, count($result->parameters())); 194 $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name); 195 $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue()); 196 197 } 198 199 function testReadPropertyRepeatingParameter() { 200 201 $data = "BEGIN:VCALENDAR\r\nPROPNAME;N=1;N=2;N=3,4;N=\"5\",6;N=\"7,8\";N=9,10;N=^'11^':propValue\r\nEND:VCALENDAR"; 202 $result = Reader::read($data); 203 204 $result = $result->PROPNAME; 205 206 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 207 $this->assertEquals('PROPNAME', $result->name); 208 $this->assertEquals('propValue', $result->getValue()); 209 $this->assertEquals(1, count($result->parameters())); 210 $this->assertEquals('N', $result->parameters['N']->name); 211 $this->assertEquals('1,2,3,4,5,6,7,8,9,10,"11"', $result->parameters['N']->getValue()); 212 $this->assertEquals([1, 2, 3, 4, 5, 6, "7,8", 9, 10, '"11"'], $result->parameters['N']->getParts()); 213 214 } 215 216 function testReadPropertyRepeatingNamelessGuessedParameter() { 217 218 $data = "BEGIN:VCALENDAR\r\nPROPNAME;WORK;VOICE;PREF:propValue\r\nEND:VCALENDAR"; 219 $result = Reader::read($data); 220 221 $result = $result->PROPNAME; 222 223 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 224 $this->assertEquals('PROPNAME', $result->name); 225 $this->assertEquals('propValue', $result->getValue()); 226 $this->assertEquals(1, count($result->parameters())); 227 $this->assertEquals('TYPE', $result->parameters['TYPE']->name); 228 $this->assertEquals('WORK,VOICE,PREF', $result->parameters['TYPE']->getValue()); 229 $this->assertEquals(['WORK', 'VOICE', 'PREF'], $result->parameters['TYPE']->getParts()); 230 231 } 232 233 function testReadPropertyNoName() { 234 235 $data = "BEGIN:VCALENDAR\r\nPROPNAME;PRODIGY:propValue\r\nEND:VCALENDAR"; 236 $result = Reader::read($data); 237 238 $result = $result->PROPNAME; 239 240 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 241 $this->assertEquals('PROPNAME', $result->name); 242 $this->assertEquals('propValue', $result->getValue()); 243 $this->assertEquals(1, count($result->parameters())); 244 $this->assertEquals('TYPE', $result->parameters['TYPE']->name); 245 $this->assertTrue($result->parameters['TYPE']->noName); 246 $this->assertEquals('PRODIGY', $result->parameters['TYPE']); 247 248 } 249 250 function testReadPropertyParameterExtraColon() { 251 252 $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue:propValue:anotherrandomstring\r\nEND:VCALENDAR"; 253 $result = Reader::read($data); 254 255 $result = $result->PROPNAME; 256 257 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 258 $this->assertEquals('PROPNAME', $result->name); 259 $this->assertEquals('propValue:anotherrandomstring', $result->getValue()); 260 $this->assertEquals(1, count($result->parameters())); 261 $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name); 262 $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue()); 263 264 } 265 266 function testReadProperty2Parameters() { 267 268 $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue;PARAMNAME2=paramvalue2:propValue\r\nEND:VCALENDAR"; 269 $result = Reader::read($data); 270 271 $result = $result->PROPNAME; 272 273 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 274 $this->assertEquals('PROPNAME', $result->name); 275 $this->assertEquals('propValue', $result->getValue()); 276 $this->assertEquals(2, count($result->parameters())); 277 $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name); 278 $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue()); 279 $this->assertEquals('PARAMNAME2', $result->parameters['PARAMNAME2']->name); 280 $this->assertEquals('paramvalue2', $result->parameters['PARAMNAME2']->getValue()); 281 282 } 283 284 function testReadPropertyParameterQuoted() { 285 286 $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=\"paramvalue\":propValue\r\nEND:VCALENDAR"; 287 $result = Reader::read($data); 288 289 $result = $result->PROPNAME; 290 291 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 292 $this->assertEquals('PROPNAME', $result->name); 293 $this->assertEquals('propValue', $result->getValue()); 294 $this->assertEquals(1, count($result->parameters())); 295 $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name); 296 $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue()); 297 298 } 299 300 function testReadPropertyParameterNewLines() { 301 302 $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue1^nvalue2^^nvalue3:propValue\r\nEND:VCALENDAR"; 303 $result = Reader::read($data); 304 305 $result = $result->PROPNAME; 306 307 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 308 $this->assertEquals('PROPNAME', $result->name); 309 $this->assertEquals('propValue', $result->getValue()); 310 311 $this->assertEquals(1, count($result->parameters())); 312 $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name); 313 $this->assertEquals("paramvalue1\nvalue2^nvalue3", $result->parameters['PARAMNAME']->getValue()); 314 315 } 316 317 function testReadPropertyParameterQuotedColon() { 318 319 $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=\"param:value\":propValue\r\nEND:VCALENDAR"; 320 $result = Reader::read($data); 321 $result = $result->PROPNAME; 322 323 $this->assertInstanceOf('Sabre\\VObject\\Property', $result); 324 $this->assertEquals('PROPNAME', $result->name); 325 $this->assertEquals('propValue', $result->getValue()); 326 $this->assertEquals(1, count($result->parameters())); 327 $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name); 328 $this->assertEquals('param:value', $result->parameters['PARAMNAME']->getValue()); 329 330 } 331 332 function testReadForgiving() { 333 334 $data = [ 335 "BEGIN:VCALENDAR", 336 "X_PROP:propValue", 337 "END:VCALENDAR" 338 ]; 339 340 $caught = false; 341 try { 342 $result = Reader::read(implode("\r\n", $data)); 343 } catch (ParseException $e) { 344 $caught = true; 345 } 346 347 $this->assertEquals(true, $caught); 348 349 $result = Reader::read(implode("\r\n", $data), Reader::OPTION_FORGIVING); 350 351 $expected = implode("\r\n", [ 352 "BEGIN:VCALENDAR", 353 "X_PROP:propValue", 354 "END:VCALENDAR", 355 "" 356 ]); 357 358 $this->assertEquals($expected, $result->serialize()); 359 360 } 361 362 function testReadWithInvalidLine() { 363 364 $data = [ 365 "BEGIN:VCALENDAR", 366 "DESCRIPTION:propValue", 367 "Yes, we've actually seen a file with non-idented property values on multiple lines", 368 "END:VCALENDAR" 369 ]; 370 371 $caught = false; 372 try { 373 $result = Reader::read(implode("\r\n", $data)); 374 } catch (ParseException $e) { 375 $caught = true; 376 } 377 378 $this->assertEquals(true, $caught); 379 380 $result = Reader::read(implode("\r\n", $data), Reader::OPTION_IGNORE_INVALID_LINES); 381 382 $expected = implode("\r\n", [ 383 "BEGIN:VCALENDAR", 384 "DESCRIPTION:propValue", 385 "END:VCALENDAR", 386 "" 387 ]); 388 389 $this->assertEquals($expected, $result->serialize()); 390 391 } 392 393 /** 394 * Reported as Issue 32. 395 * 396 * @expectedException \Sabre\VObject\ParseException 397 */ 398 function testReadIncompleteFile() { 399 400 $input = <<<ICS 401BEGIN:VCALENDAR 402VERSION:1.0 403BEGIN:VEVENT 404X-FUNAMBOL-FOLDER:DEFAULT_FOLDER 405X-FUNAMBOL-ALLDAY:0 406DTSTART:20111017T110000Z 407DTEND:20111017T123000Z 408X-MICROSOFT-CDO-BUSYSTATUS:BUSY 409CATEGORIES: 410LOCATION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Netviewer Meeting 411PRIORITY:1 412STATUS:3 413X-MICROSOFT-CDO-REPLYTIME:20111017T064200Z 414SUMMARY;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Kopieren: test 415CLASS:PUBLIC 416AALARM: 417RRULE: 418X-FUNAMBOL-BILLINGINFO: 419X-FUNAMBOL-COMPANIES: 420X-FUNAMBOL-MILEAGE: 421X-FUNAMBOL-NOAGING:0 422ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Heino' heino@test.com 423ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Markus' test@test.com 424ATTENDEE;STATUS=NEEDS AC 425ICS; 426 427 Reader::read($input); 428 429 } 430 431 /** 432 * @expectedException \InvalidArgumentException 433 */ 434 function testReadBrokenInput() { 435 436 Reader::read(false); 437 438 } 439 440 function testReadBOM() { 441 442 $data = chr(0xef) . chr(0xbb) . chr(0xbf) . "BEGIN:VCALENDAR\r\nEND:VCALENDAR"; 443 $result = Reader::read($data); 444 445 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 446 $this->assertEquals('VCALENDAR', $result->name); 447 $this->assertEquals(0, count($result->children())); 448 449 } 450 451 function testReadXMLComponent() { 452 453 $data = <<<XML 454<?xml version="1.0" encoding="utf-8"?> 455<icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0"> 456 <vcalendar> 457 </vcalendar> 458</icalendar> 459XML; 460 461 $result = Reader::readXML($data); 462 463 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 464 $this->assertEquals('VCALENDAR', $result->name); 465 $this->assertEquals(0, count($result->children())); 466 467 } 468 469 function testReadXMLStream() { 470 471 $data = <<<XML 472<?xml version="1.0" encoding="utf-8"?> 473<icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0"> 474 <vcalendar> 475 </vcalendar> 476</icalendar> 477XML; 478 479 $stream = fopen('php://memory', 'r+'); 480 fwrite($stream, $data); 481 rewind($stream); 482 483 $result = Reader::readXML($stream); 484 485 $this->assertInstanceOf('Sabre\\VObject\\Component', $result); 486 $this->assertEquals('VCALENDAR', $result->name); 487 $this->assertEquals(0, count($result->children())); 488 489 } 490 491} 492