├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── afl ├── caldav │ └── in │ │ └── test001.xml ├── conf │ └── kcaldav.example.conf ├── ical │ ├── dict.sh │ ├── dict.txt │ └── in │ │ ├── event.ics │ │ ├── journal.ics │ │ └── todo.ics └── prncpl │ └── in │ └── kcaldav.passwd ├── archive.xml ├── atom-template.xml ├── caldav.c ├── collection.js ├── collection.xml ├── compats.c ├── conf.c ├── configure ├── database-update01.sql ├── datetime.c ├── db.c ├── db.h ├── delete.c ├── dynamic.c ├── get.c ├── home.js ├── home.xml ├── ical.c ├── index.css ├── index.xml ├── kcaldav.c ├── kcaldav.example.conf ├── kcaldav.h ├── kcaldav.passwd.c ├── kcaldav.sql ├── libkcaldav.h ├── man ├── caldav_free.3 ├── caldav_parse.3 ├── ical_free.3 ├── ical_parse.3 ├── ical_print.3 ├── kcaldav.conf.5 ├── kcaldav.in.8 └── kcaldav.passwd.in.1 ├── md5.js ├── options.c ├── property.c ├── propfind.c ├── proppatch.c ├── put.c ├── regress ├── caldav │ ├── oldsimple.xml │ └── simple.xml ├── conf │ ├── emptylines.in.conf │ ├── emptylines.out.conf │ ├── emptylines2.in.conf │ ├── emptylines2.out.conf │ ├── escaped.in.conf │ ├── escaped.out.conf │ ├── escaped2.in.conf │ ├── escaped2.out.conf │ ├── escaped3.in.conf │ ├── escaped3.out.conf │ ├── hash.in.conf │ ├── hash.out.conf │ ├── hash2.in.conf │ ├── hash2.out.conf │ ├── hash3.in.conf │ ├── hash3.out.conf │ ├── hash4.in.conf │ ├── hash4.out.conf │ ├── kcaldav.example.in.conf │ ├── kcaldav.example.out.conf │ ├── spaces.in.conf │ ├── spaces.out.conf │ ├── spaces2.in.conf │ └── spaces2.out.conf └── ical │ ├── 1106817412.ics │ ├── 3.ics │ ├── 4.ics │ ├── 6.ics │ ├── 7.ics │ ├── ArgentinaHolidays.ics │ ├── Australian32Holidays.ics │ ├── Australian_TV_Melbourne.ics │ ├── BCP321928.ics │ ├── Belgische32feestdagen.ics │ ├── Buddhist.ics │ ├── Christian32Holidays.ics │ ├── Dryway.ics │ ├── EXDATE-IN-UTC.ics │ ├── EXDATE.ics │ ├── Earth32Seasons.ics │ ├── EstoniaHolidays.ics │ ├── Misc.History.ics │ ├── OZMovies.ics │ ├── Packers.ics │ ├── Session6.ics │ ├── Standup.ics │ ├── SwedishHolidays2003-2006.ics │ ├── afl2004.ics │ ├── bears.ics │ ├── bhav23-1.ics │ ├── blalor.ics │ ├── calconnect.ics │ ├── calconnect10.ics │ ├── calconnect2.ics │ ├── calconnect3.ics │ ├── calconnect4.ics │ ├── calconnect5.ics │ ├── calconnect6.ics │ ├── calconnect7.ics │ ├── calconnect8.ics │ ├── calconnect9.ics │ ├── canada.ics │ ├── custom_component.ics │ ├── date-multiple-parts.ics │ ├── dst-only-vtimezone.ics │ ├── event.ics │ ├── evolution.ics │ ├── japan_west.ics │ ├── journal.ics │ ├── korganizer-lowercase.ics │ ├── korganizer.ics │ ├── korganizer_sample.ics │ ├── lotr-updated.ics │ ├── lotr.ics │ ├── mathBirthdays.ics │ ├── miked.ics │ ├── new-mozilla.ics │ ├── new_years_day.ics │ ├── oldevent.ics │ ├── oracle-personal-notes-test-empty.ics │ ├── oracle-personal-notes-test.ics │ ├── php-flp.ics │ ├── recur.ics │ ├── rfc5545-sec3.4.ics │ ├── rfc5545-sec3.6.1.ics │ ├── rfc5545-sec3.6.2.ics │ ├── rfc5545-sec3.6.3.ics │ ├── rfc5545-sec3.6.4.ics │ ├── rfc5545-sec3.6.5.ics │ ├── rfc5545-sec3.6.6.ics │ ├── rfc5545-sec4.1.ics │ ├── rfc5545-sec4.2.ics │ ├── rfc5545-sec4.3.ics │ ├── rfc5545-sec4.4.ics │ ├── rfc5545-sec4.5.ics │ ├── sunbird_sample.ics │ └── todo.ics ├── script.js ├── server.h ├── style.css ├── test-caldav.c ├── test-conf.c ├── test-ical.c ├── test-nonce.c ├── test-rrule.c ├── tests.c ├── util.c └── versions.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | Makefile.local 3 | Makefile.configure 4 | collection.html 5 | collection.min.js 6 | config.h 7 | config.log 8 | home.html 9 | home.min.js 10 | kcaldav 11 | kcaldav-sql.c 12 | kcaldav.8 13 | kcaldav.passwd 14 | kcaldav.passwd.1 15 | libkcaldav.a 16 | test-caldav 17 | test-conf 18 | test-ical 19 | test-nonce 20 | archive.html 21 | atom.xml 22 | index.html 23 | kcaldav.8.html 24 | kcaldav.passwd.1.html 25 | kcaldav.tgz 26 | kcaldav.tgz.sha512 27 | kcaldav.conf.5 28 | kcaldav.conf.5.html 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015--2016, Kristaps Dzonsons 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose 4 | with or without fee is hereby granted, provided that the above copyright notice 5 | and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 12 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 13 | THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | **kcaldav** is a simple, safe, and minimal CalDAV server running on the 4 | [BCHS](https://learnbchs.org) software stack. 5 | 6 | To keep up to date with the current stable release of **kcaldav**, visit 7 | https://kristaps.bsd.lv/kcaldav. The website also contains canonical 8 | installation, deployment, examples, and usage documentation. 9 | 10 | # Installation 11 | 12 | You'll need a C compiler ([gcc](https://gcc.gnu.org/) or 13 | [clang](https://clang.llvm.org/)), [zlib](https://zlib.net) (*zlib* or 14 | *zlib-dev* for some package managers), 15 | [libexpat](https://libexpat.github.io/) (*libexpat-dev*), 16 | [kcgi](https://kristaps.bsd.lv/kcgi), [sqlite3](https://sqlite3.org) 17 | (*libsqlite3-dev*), and BSD make (*bmake* for some managers) for 18 | building. 19 | 20 | Begin by cloning or downloading. Then configure with `./configure`, 21 | compile with `make` (BSD make, so it may be `bmake` on your system), 22 | then `make install` (or use `sudo` or `doas`, if applicable). 23 | 24 | If not done yet, optionally create a *Makefile.local* to override values 25 | in [Makefile](Makefile) for your target file-system. 26 | 27 | ```sh 28 | ./configure 29 | make install 30 | make installcgi 31 | ``` 32 | 33 | The database hasn't updated in a long, long time, so there are no 34 | special commands for updating it. When updates do happen, I'll work out 35 | a process for doing so. 36 | 37 | A common idiom for installing on Linux is to use 38 | [libbsd](https://libbsd.freedesktop.org/wiki/) as noted in the 39 | [oconfigure](https://github.com/kristapsdz/oconfigure) documentation: 40 | 41 | ``` 42 | CFLAGS=$(pkg-config --cflags libbsd-overlay) \ 43 | ./configure LDFLAGS=$(pkg-config --libs libbsd-overlay) 44 | make 45 | make install 46 | ``` 47 | 48 | # Deployment 49 | 50 | To create the database for initial use (or to manage it), follow 51 | [kcaldav.passwd(1)](man/kcaldav.passwd.in.1). 52 | 53 | If errors occur during operation, see 54 | [kcaldav.conf.5](man/kcaldav.conf.5) for how to configure the system for 55 | more debugging information. 56 | 57 | # Regression and fuzzing 58 | 59 | To contribute to **kcaldav**, write regression tests! 60 | 61 | Right now, the regression suite only parses valid iCalendar files from 62 | [ical4j](https://github.com/ical4j/ical4j), but in no way makes sure 63 | that the information has been properly parsed. Same with the CalDAV 64 | tests. To run these: 65 | 66 | ```sh 67 | make regress 68 | ``` 69 | 70 | A major missing component is a series of regression tests that actually 71 | makes sure that parsed content is sane. 72 | 73 | Most of the critical infrastructure can also be run through 74 | [AFL](https://lcamtuf.coredump.cx/afl/). To do this, run: 75 | 76 | ```sh 77 | make clean 78 | make afl CC=afl-clang 79 | ``` 80 | 81 | Or use `afl-gcc` instead---it shouldn't matter. This installs AFL-built 82 | binaries into the *afl* directory. To run these on the iCalendar 83 | library: 84 | 85 | ```sh 86 | cd ical 87 | sh ./dict.sh # Generates dictionary files. 88 | afl-fuzz -i in -x dict -o out -- ../test-ical @@ 89 | ``` 90 | 91 | For CalDAV: 92 | 93 | ```sh 94 | cd caldav 95 | afl-fuzz -i in -o out -- ../test-caldav @@ 96 | ``` 97 | 98 | I'd love for more tests on the server infrastructure itself, but am not 99 | sure how to effect this properly. 100 | 101 | # Sources 102 | 103 | The source code is laid out fairly consistently and easily. 104 | 105 | The centre of the system is in *libkcaldav.a*, which contains both the 106 | CalDAV and iCalendar functions in [libkcaldav.h](libkcaldav.h). It's 107 | implemented by [ical.c](ical.c) and [caldav.c](caldav.c). 108 | 109 | The database interface is [db.h](db.h), manipulating the schema in 110 | [kcaldav.sql](kcaldav.sql). This is used by server and by the 111 | built programs and manages users, collections, resources, proxies, etc. 112 | It internally uses the [libkcaldav.h](libkcaldav.h) functions. It is 113 | implemented in [db.c](db.c). 114 | 115 | The built programs are the command-line utility 116 | [kcaldav.passwd(1)](man/kcaldav.passwd.in.1) and CGI server 117 | [kcaldav(8)](man/kcaldav.in.8). 118 | 119 | The CGI server is described in [server.h](server.h) and implemented by 120 | the majority of the source code files with entry point 121 | [kcaldav.c](kcaldav.c]). 122 | 123 | The command-line utility is the standalone 124 | [kcaldav.passwd.c](kcaldav.passwd.c). 125 | 126 | The portability glue throughout the system (e.g., `HAVE_xxx` macros, 127 | *config.h*, etc.) is managed by 128 | [oconfigure](https://github.com/kristapsdz/oconfigure). 129 | 130 | # License 131 | 132 | All sources use the ISC (like OpenBSD) license. 133 | See the [LICENSE.md](LICENSE.md) file for details. 134 | -------------------------------------------------------------------------------- /afl/caldav/in/test001.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /afl/conf/kcaldav.example.conf: -------------------------------------------------------------------------------- 1 | # Instead of logging to stderr (usually stored in the web server's 2 | # error.log), log to a specific file. 3 | logfile=/logs/kcaldav.log 4 | 5 | # Set debug=3 to produce debugging information. 6 | # Set debug=2 for even more debugging information. 7 | # Set debug=3 to also trace network activity. 8 | debug=3 9 | -------------------------------------------------------------------------------- /afl/ical/dict.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -f dict/* 4 | 5 | for word in `cat dict.txt` 6 | do 7 | printf "$word" >dict/$word; 8 | done 9 | -------------------------------------------------------------------------------- /afl/ical/dict.txt: -------------------------------------------------------------------------------- 1 | VCALENDAR 2 | VEVENT 3 | VTODO 4 | VJOURNAL 5 | VFREEBUSY 6 | VTIMEZONE 7 | VALARM 8 | DAYLIGHT 9 | STANDARD 10 | SU 11 | MO 12 | TU 13 | WE 14 | TH 15 | FR 16 | SA 17 | SECONDLY 18 | MINUTELY 19 | HOURLY 20 | DAILY 21 | WEEKLY 22 | MONTHLY 23 | YEARLY 24 | VALUE 25 | DATE 26 | DATE-TIME 27 | TZID 28 | FREQ 29 | UNTIL 30 | COUNT 31 | INTERVAL 32 | BYDAY 33 | BYHOUR 34 | BYMINUTE 35 | BYSECOND 36 | BYWEEK 37 | BYMONTH 38 | BYSETPOS 39 | BYWEEKNO 40 | BYYEARDDAY 41 | WKST 42 | DTSTART 43 | TZOFFSETFROM 44 | TZOFFSETTO 45 | RRULE 46 | UID 47 | CREATED 48 | LAST-MODIFIED 49 | DTSTAMP 50 | DTSTART 51 | DTEND 52 | DURATION 53 | TZID 54 | -------------------------------------------------------------------------------- /afl/ical/in/event.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VEVENT 5 | UID:uid1@example.com 6 | DTSTAMP:19970714T170000Z 7 | ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com 8 | DTSTART:19970714T170000Z 9 | DTEND:19970715T035959Z 10 | SUMMARY:Bastille Day Party 11 | END:VEVENT 12 | END:VCALENDAR 13 | -------------------------------------------------------------------------------- /afl/ical/in/journal.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VJOURNAL 5 | DTSTAMP:19970324T120000Z 6 | UID:uid5@example.com 7 | ORGANIZER:MAILTO:jsmith@example.com 8 | STATUS:DRAFT 9 | CLASS:PUBLIC 10 | CATEGORIES:Project Report, XYZ, Weekly Meeting 11 | DESCRIPTION:Project xyz Review Meeting Minutes\n 12 | Agenda\n1. Review of project version 1.0 requirements.\n2. 13 | END:VJOURNAL 14 | END:VCALENDAR 15 | -------------------------------------------------------------------------------- /afl/ical/in/todo.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VTODO 5 | DTSTAMP:19980130T134500Z 6 | SEQUENCE:2 7 | UID:uid4@example.com 8 | ACTION:AUDIO 9 | TRIGGER:19980403T120000 10 | ATTACH;FMTTYPE=audio/basic:http://example.com/pub/audio- 11 | files/ssbanner.aud 12 | REPEAT:4 13 | DURATION:PT1H 14 | END:VTODO 15 | END:VCALENDAR 16 | -------------------------------------------------------------------------------- /afl/prncpl/in/kcaldav.passwd: -------------------------------------------------------------------------------- 1 | kristaps::::::::/kristaps/: 2 | Mufasa:asdf:::::::/kristaps/: 3 | -------------------------------------------------------------------------------- /archive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | kCalDAV: a simple CalDAV server 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 19 |
20 |

kCalDAV

21 | — 22 | simple CalDAV server 23 | 24 |
25 |
26 |
27 | 40 |
41 |
42 | 53 |
54 |
55 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /atom-template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | kcaldav version feed 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /collection.js: -------------------------------------------------------------------------------- 1 | (function(root) { 2 | 'use strict'; 3 | 4 | function loadSuccess(resp) 5 | { 6 | var res, id, i, sz; 7 | 8 | if (null === (res = parseJSON(resp))) 9 | return; 10 | 11 | id = parseInt(getQueryVariable('id')); 12 | for (i = 0, sz = res.principal.colns.length; i < sz; i++) 13 | if (res.principal.colns[i].id === id) 14 | break; 15 | 16 | if (i === sz) { 17 | location.href = '@HTDOCS@/home.html'; 18 | return; 19 | } 20 | 21 | classSet(document.getElementById('loading'), 'hide'); 22 | classUnset(document.getElementById('loaded'), 'hide'); 23 | principalFill(res.principal); 24 | colnFill(document, res.principal, res.principal.colns[i]); 25 | } 26 | 27 | function loadSetup() 28 | { 29 | 30 | classUnset(document.getElementById('loading'), 'hide'); 31 | classSet(document.getElementById('loaded'), 'hide'); 32 | } 33 | 34 | function load() 35 | { 36 | var id; 37 | 38 | if (null !== (id = getQueryVariable('id')) && 39 | NaN !== parseInt(id)) 40 | sendQuery('@CGIURI@/index.json', 41 | loadSetup, loadSuccess, null); 42 | else 43 | location.href = '@HTDOCS@/home.html'; 44 | } 45 | 46 | function setcolnpropsError(code, prefix) 47 | { 48 | var cls; 49 | 50 | cls = 'setcolnprops-error-sys'; 51 | if (400 === code) 52 | cls = 'setcolnprops-error-form'; 53 | 54 | classUnset(document.getElementById(cls), 'hide'); 55 | classUnset(document.getElementById(prefix + '-btn'), 'hide'); 56 | classSet(document.getElementById(prefix + '-pbtn'), 'hide'); 57 | } 58 | 59 | function setcolnpropsSetup(name) 60 | { 61 | var list, i, sz; 62 | 63 | list = document.getElementsByClassName('setcolnprops-error'); 64 | for (i = 0, sz = list.length; i < sz; i++) 65 | classSet(list[i], 'hide'); 66 | classSet(document.getElementById(name + '-btn'), 'hide'); 67 | classUnset(document.getElementById(name + '-pbtn'), 'hide'); 68 | } 69 | 70 | function setcolnprops(e, prefix) 71 | { 72 | 73 | return(sendForm(e, function() { setcolnpropsSetup(prefix); }, 74 | function(code) { setcolnpropsError(code, prefix); }, 75 | function() { document.location.reload(); })); 76 | } 77 | 78 | root.load = load; 79 | root.setcolnprops = setcolnprops; 80 | })(this); 81 | -------------------------------------------------------------------------------- /collection.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | kcaldav: collection 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |

16 | The nonce for this HTTP-authorised session has been deleted. 17 | To complete your logout, you'll need to close the browser window to destroy your credentials. 18 |

19 |
20 |
21 |

22 | Loading kCalDAV... 23 |

24 |
25 |
26 |
27 |
28 |

29 | CalDAV Management 30 |

34 |
35 |
36 |
37 |

38 | Welcome, . 39 | Your principal has used and available. 41 |

42 |
43 |

44 | Calendar Address 45 |

46 |
    47 |
  • 48 | 49 |
  • 50 |
51 |

52 | Missing or invalid fields. 53 |

54 |

55 | A system failure has occurred. 56 |

57 |
58 | 59 | 63 | 67 |
68 |

69 | Calendar Display Name 70 |

71 |

72 | This is the display name as defined in RFC 4918, 15.2. 73 | It can be any UTF-8 string less than 1024 bytes in length. 74 |

75 |
76 | 77 | 78 | 82 | 86 |
87 |

88 | Calendar Colour 89 |

90 |

91 | This is an Apple extension that will probably only work with Apple iCal systems. 92 |

93 |
94 | 95 | 96 | 100 | 104 |
105 |

106 | Calendar Description 107 |

108 |

109 | This is the calendar description as defined in RFC 4791, 5.2.1. 110 | It can be any UTF-8 string less than 4096 bytes in length. 111 |

112 |
113 | 114 | 115 | 119 | 123 |
124 |
125 |
126 |
127 | kCalDAV version @VERSION@ 128 |
129 |
130 | 131 | 132 | -------------------------------------------------------------------------------- /conf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include /* fopen, getline */ 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include "libkcaldav.h" 34 | #include "db.h" 35 | #include "server.h" 36 | 37 | /* 38 | * Parse a key-value pair. Return zero on nothing parsed (empty line), 39 | * -1 on failure, 1 on success where "key" and "val" are assigned 40 | * NUL-terminated values. 41 | */ 42 | static int 43 | conf_parse_keyval(char *buf, const char **key, const char **val) 44 | { 45 | char *cp; 46 | 47 | while (*buf != '\0' && isspace((unsigned char)*buf)) 48 | buf++; 49 | *key = buf; 50 | while (*buf != '\0' && *buf != '=') 51 | buf++; 52 | if (*buf == '\0' || buf == *key) 53 | return -1; 54 | 55 | /* Strip from before and after delim. */ 56 | 57 | assert(buf > *key && *buf == '='); 58 | for (cp = &buf[-1]; 59 | cp > *key && isspace((unsigned char)*cp); cp--) 60 | if (isspace((unsigned char)*cp)) 61 | *cp = '\0'; 62 | 63 | *buf++ = '\0'; 64 | while (*buf != '\0' && isspace((unsigned char)*buf)) 65 | buf++; 66 | 67 | *val = buf; 68 | return **val != '\0'; 69 | } 70 | 71 | /* 72 | * Optionally read our configuration. This is in a regular 73 | * configuration file format and has only two possible key-value pairs: 74 | * 75 | * logfile=/path/to/logfile 76 | * verbose=[0--3] 77 | * 78 | * If the configuration file does not exist, do not enact any processing 79 | * and accept this as not an error. 80 | * 81 | * Return -1 on system error (exit with err), 0 on soft error (exit with errx), 82 | * 1 on success. 83 | */ 84 | int 85 | conf_read(const char *fn, struct conf *conf) 86 | { 87 | const char *key, *val, *er; 88 | FILE *f = NULL; 89 | char *line = NULL; 90 | size_t linesize = 0, i; 91 | ssize_t linelen; 92 | int rc = 0, rrc; 93 | 94 | memset(conf, 0, sizeof(struct conf)); 95 | 96 | /* 97 | * Deprecated compile-time constants. Allow these to be overriden by 98 | * the configuration file. 99 | */ 100 | 101 | #ifdef LOGFILE 102 | #warning "LOGFILE" is deprecated: use "CFGFILE" instead. 103 | if ((conf->logfile = strdup(LOGFILE)) == NULL) 104 | return -1; 105 | #endif 106 | #if defined(DEBUG) && DEBUG >= 0 107 | #warning "DEBUG" is deprecated: use "CFGFILE" instead. 108 | conf->verbose = DEBUG; 109 | #endif 110 | 111 | if (fn != NULL && fn[0] != '\0') 112 | if ((f = fopen(fn, "r")) == NULL && errno != ENOENT) 113 | return -1; 114 | 115 | if (f == NULL) 116 | return 1; 117 | 118 | while ((linelen = getline(&line, &linesize, f)) != -1) { 119 | /* 120 | * Strip everything following the first 121 | * unescaped hash, un-escaping along the way. 122 | */ 123 | for (i = 0; line[i] != '\0'; ) { 124 | if (line[i] != '#') { 125 | i++; 126 | continue; 127 | } 128 | if (i == 0 || line[i - 1] != '\\') { 129 | line[i] = '\0'; 130 | linelen = i; 131 | break; 132 | } 133 | assert(i > 0); 134 | assert(line[i - 1] == '\\'); 135 | /* 136 | * Shift the buffer left, including the 137 | * trailing NUL terminator. 138 | */ 139 | memmove(&line[i - 1], &line[i], linelen - i); 140 | } 141 | 142 | /* Strip trailing white-space. */ 143 | 144 | while (linelen > 0 && 145 | isspace((unsigned char)line[linelen - 1])) 146 | line[--linelen] = '\0'; 147 | 148 | if (linelen == 0) 149 | continue; 150 | 151 | /* Parse key-value pairs. */ 152 | 153 | if ((rrc = conf_parse_keyval(line, &key, &val)) == -1) 154 | break; 155 | else if (rrc == 0) 156 | continue; 157 | 158 | if (strcmp(key, "logfile") == 0) { 159 | free(conf->logfile); 160 | if ((conf->logfile = strdup(val)) == NULL) 161 | return -1; 162 | } else if (strcmp(key, "debug") == 0) { 163 | conf->verbose = strtonum(val, 0, 10, &er); 164 | if (er != NULL) 165 | break; 166 | } else 167 | break; 168 | } 169 | 170 | free(line); 171 | if (!ferror(f) && fclose(f) != EOF) 172 | rc = 1; 173 | 174 | return rc; 175 | } 176 | -------------------------------------------------------------------------------- /database-update01.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE proxy ( 2 | principal INTEGER NOT NULL, 3 | proxy INTEGER NOT NULL, 4 | bits INTEGER NOT NULL DEFAULT(0), 5 | id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 6 | FOREIGN KEY (principal) REFERENCES principal(id) ON DELETE CASCADE, 7 | FOREIGN KEY (proxy) REFERENCES principal(id) ON DELETE CASCADE 8 | ); 9 | -------------------------------------------------------------------------------- /db.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #ifndef EXTERN_H 17 | #define EXTERN_H 18 | 19 | #define KREALM "kcaldav" 20 | 21 | /* 22 | * Resource in a calendar collection. 23 | */ 24 | struct res { 25 | char *data; 26 | struct ical *ical; 27 | char *etag; /* RFC 2616 etag */ 28 | char *url; 29 | int64_t collection; 30 | int64_t id; 31 | }; 32 | 33 | /* 34 | * A calendar collection. 35 | */ 36 | struct coln { 37 | char *url; /* name of collection */ 38 | char *displayname; /* displayname of collection */ 39 | char *colour; /* colour (RGBA) */ 40 | char *description; /* free-form description */ 41 | int64_t ctag; /* collection tag */ 42 | int64_t id; /* unique identifier */ 43 | }; 44 | 45 | /* 46 | * Proxies for a principal. 47 | * That is, the other principals who are allowed to read/write into the 48 | * current principal. 49 | */ 50 | struct proxy { 51 | int64_t proxy; /* principal with proxy access */ 52 | char *email; /* email of proxied principal */ 53 | char *name; /* name of proxied principal */ 54 | int64_t bits; /* type of proxy access */ 55 | #define PROXY_NONE 0x00 56 | #define PROXY_READ 0x01 57 | #define PROXY_WRITE 0x02 58 | int64_t id; /* unique identifier */ 59 | }; 60 | 61 | /* 62 | * A principal is a user of the system. 63 | */ 64 | struct prncpl { 65 | char *name; /* username */ 66 | char *hash; /* MD5 of name, realm, and password */ 67 | uint64_t quota_used; /* quota (VFS) */ 68 | uint64_t quota_avail; /* quota (VFS) */ 69 | char *email; /* email address */ 70 | struct coln *cols; /* owned collections */ 71 | size_t colsz; /* number of owned collections */ 72 | struct proxy *proxies; /* principals who can proxy as us */ 73 | size_t proxiesz; /* elements in proxies */ 74 | struct proxy *rproxies; /* principals as whom we proxy */ 75 | size_t rproxiesz; /* elements in rproxies */ 76 | int64_t id; /* unique identifier */ 77 | }; 78 | 79 | /* 80 | * Return codes for nonce operations. 81 | */ 82 | enum nonceerr { 83 | NONCE_ERR, /* generic error */ 84 | NONCE_NOTFOUND, /* nonce entry not found */ 85 | NONCE_REPLAY, /* replay attack detected! */ 86 | NONCE_OK /* nonce checks out */ 87 | }; 88 | 89 | typedef void (*db_msg)(void *, const char *, const char *, va_list); 90 | 91 | void db_set_msg_arg(void *); 92 | void db_set_msg_ident(const char *); 93 | void db_set_msg_dbg(db_msg); 94 | void db_set_msg_info(db_msg); 95 | void db_set_msg_err(db_msg); 96 | void db_set_msg_errx(db_msg); 97 | 98 | void db_collection_free(struct coln *); 99 | int db_collection_load(struct coln **, const char *, int64_t); 100 | int db_collection_loadid(struct coln **, int64_t, int64_t); 101 | int db_collection_new(const char *, const struct prncpl *); 102 | int db_collection_remove(int64_t, const struct prncpl *); 103 | int db_collection_resources(void (*)(const struct res *, void *), int64_t, void *); 104 | int db_collection_update(const struct coln *, const struct prncpl *); 105 | int db_init(const char *, int); 106 | int db_nonce_delete(const char *, const struct prncpl *); 107 | int db_nonce_new(char **); 108 | enum nonceerr db_nonce_update(const char *, int64_t); 109 | enum nonceerr db_nonce_validate(const char *, int64_t); 110 | int db_owner_check_or_set(int64_t); 111 | void db_prncpl_free(struct prncpl *); 112 | int64_t db_prncpl_identify(const char *); 113 | int db_prncpl_load(struct prncpl **, const char *); 114 | int db_prncpl_new(const char *, const char *, const char *, const char *); 115 | int db_prncpl_update(const struct prncpl *); 116 | int db_proxy(const struct prncpl *, int64_t, int64_t); 117 | int db_proxy_remove(const struct prncpl *, int64_t); 118 | int db_resource_delete(const char *, const char *, int64_t); 119 | void db_resource_free(struct res *); 120 | int db_resource_remove(const char *, int64_t); 121 | int db_resource_load(struct res **, const char *, int64_t); 122 | int db_resource_new(const char *, const char *, int64_t); 123 | int db_resource_update(const char *, const char *, const char *, int64_t); 124 | 125 | extern const char *db_sql; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /delete.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include "libkcaldav.h" 29 | #include "db.h" 30 | #include "server.h" 31 | 32 | void 33 | method_delete(struct kreq *r) 34 | { 35 | struct state *st = r->arg; 36 | int rc; 37 | const char *digest = NULL; 38 | char *buf = NULL; 39 | 40 | if (st->cfg == NULL) { 41 | kutil_warnx(r, st->prncpl->name, 42 | "DELETE of non-calendar collection"); 43 | http_error(r, KHTTP_403); 44 | return; 45 | } 46 | 47 | if (r->reqmap[KREQU_IF_MATCH] != NULL) { 48 | digest = http_etag_if_match 49 | (r->reqmap[KREQU_IF_MATCH]->val, &buf); 50 | 51 | /* 52 | * If the etag is not quoted and set to "*", this means 53 | * (according to RFC 7232 section 3.1) that the 54 | * condition is FALSE if the "listed representation" 55 | * (i.e., the resource name) is not matched. 56 | * Since we lookup based on the resource name, this 57 | * simply means that it's the unsafe behaviour, so set 58 | * the digest as NULL. 59 | */ 60 | 61 | if (digest != NULL && 62 | buf == NULL && strcmp(digest, "*") == 0) 63 | digest = NULL; 64 | } 65 | 66 | if (digest != NULL && st->resource[0] != '\0') { 67 | rc = db_resource_delete 68 | (st->resource, digest, st->cfg->id); 69 | if (rc == 0) { 70 | kutil_errx_noexit(r, st->prncpl->name, 71 | "cannot delete resource: %s", 72 | st->resource); 73 | http_error(r, KHTTP_505); 74 | } else { 75 | kutil_dbg(r, st->prncpl->name, 76 | "resource deleted: %s", 77 | st->resource); 78 | http_error(r, KHTTP_204); 79 | } 80 | } else if (digest == NULL && st->resource[0] != '\0') { 81 | rc = db_resource_remove 82 | (st->resource, st->cfg->id); 83 | if (rc == 0) { 84 | kutil_errx_noexit(r, st->prncpl->name, 85 | "cannot delete resource: %s", 86 | st->resource); 87 | http_error(r, KHTTP_505); 88 | } else { 89 | kutil_dbg(r, st->prncpl->name, 90 | "resource (unsafe) deleted: %s", 91 | st->resource); 92 | http_error(r, KHTTP_204); 93 | } 94 | } else { 95 | /* 96 | * FIXME: deleting the collection should do the same check with 97 | * the etag (using the ctag, in this case). 98 | */ 99 | 100 | if (db_collection_remove(st->cfg->id, st->prncpl) == 0) { 101 | kutil_errx_noexit(r, st->prncpl->name, 102 | "cannot delete collection"); 103 | http_error(r, KHTTP_505); 104 | } else { 105 | kutil_dbg(r, st->prncpl->name, 106 | "collection deleted"); 107 | http_error(r, KHTTP_204); 108 | } 109 | } 110 | 111 | free(buf); 112 | } 113 | -------------------------------------------------------------------------------- /get.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include "libkcaldav.h" 29 | #include "db.h" 30 | #include "server.h" 31 | 32 | /* 33 | * RFC 4791 doesn't specify any special behaviour for GET, and RFC 2518 34 | * just says it follows HTTP, RFC 2068. 35 | * So use those semantics. 36 | */ 37 | void 38 | method_get(struct kreq *r) 39 | { 40 | struct res *p; 41 | struct state *st = r->arg; 42 | int rc; 43 | char *buf = NULL; 44 | const char *digest = NULL; 45 | 46 | if (st->resource[0] == '\0') { 47 | kutil_warnx(r, st->prncpl->name, 48 | "GET for non-resource (collection?)"); 49 | http_error(r, KHTTP_404); 50 | return; 51 | } else if (st->cfg == NULL) { 52 | kutil_warnx(r, st->prncpl->name, 53 | "GET from non-calendar collection"); 54 | http_error(r, KHTTP_403); 55 | return; 56 | } 57 | 58 | rc = db_resource_load(&p, st->resource, st->cfg->id); 59 | 60 | if (rc < 0) { 61 | kutil_errx_noexit(r, st->prncpl->name, 62 | "cannot load resource: %s", st->resource); 63 | http_error(r, KHTTP_505); 64 | return; 65 | } else if (rc == 0) { 66 | kutil_warnx(r, st->prncpl->name, 67 | "GET for unknown resource: %s", st->resource); 68 | http_error(r, KHTTP_404); 69 | return; 70 | } 71 | 72 | /* 73 | * If we request with the If-None-Match header (see RFC 2068, 74 | * 14.26), then see if the ETag is consistent. 75 | * If it is, then indicate that the remote cache is ok. 76 | * If not, resend the data. 77 | */ 78 | 79 | if (r->reqmap[KREQU_IF_NONE_MATCH] != NULL) { 80 | digest = http_etag_if_match 81 | (r->reqmap[KREQU_IF_NONE_MATCH]->val, &buf); 82 | 83 | /* 84 | * If the etag is not quoted and set to "*", this means 85 | * (according to RFC 7232 section 3.1) that the 86 | * condition is FALSE if the "listed representation" 87 | * (i.e., the resource name) is not matched. 88 | * We know the listed resource matches, so require a 89 | * full resend. 90 | */ 91 | 92 | if (digest != NULL && 93 | buf == NULL && strcmp(digest, "*") == 0) 94 | digest = NULL; 95 | } 96 | 97 | if (digest != NULL && strcmp(p->etag, digest) == 0) { 98 | khttp_head(r, kresps[KRESP_STATUS], 99 | "%s", khttps[KHTTP_304]); 100 | khttp_head(r, kresps[KRESP_ETAG], "%s", p->etag); 101 | khttp_body(r); 102 | } else { 103 | khttp_head(r, kresps[KRESP_STATUS], 104 | "%s", khttps[KHTTP_200]); 105 | khttp_head(r, kresps[KRESP_CONTENT_TYPE], 106 | "%s", kmimetypes[KMIME_TEXT_CALENDAR]); 107 | khttp_head(r, kresps[KRESP_ETAG], "%s", p->etag); 108 | khttp_body(r); 109 | ical_print(p->ical, http_ical_putc, r); 110 | } 111 | 112 | db_resource_free(p); 113 | free(buf); 114 | } 115 | 116 | -------------------------------------------------------------------------------- /home.js: -------------------------------------------------------------------------------- 1 | (function(root) { 2 | 'use strict'; 3 | 4 | var res = null; 5 | 6 | function loadSuccess(resp) 7 | { 8 | 9 | if (null === (res = parseJSON(resp))) 10 | return; 11 | 12 | classSet(document.getElementById('loading'), 'hide'); 13 | classUnset(document.getElementById('loaded'), 'hide'); 14 | 15 | principalFill(res.principal); 16 | 17 | if ('https:' === location.protocol) 18 | classSet(document.getElementById('insecure'), 'hide'); 19 | else 20 | classUnset(document.getElementById('insecure'), 'hide'); 21 | } 22 | 23 | function loadSetup() 24 | { 25 | 26 | classUnset(document.getElementById('loading'), 'hide'); 27 | classSet(document.getElementById('loaded'), 'hide'); 28 | } 29 | 30 | function load() 31 | { 32 | 33 | sendQuery('@CGIURI@/index.json', 34 | loadSetup, loadSuccess, null); 35 | } 36 | 37 | function setemailError(code) 38 | { 39 | var cls; 40 | 41 | cls = 'setemail-error-sys'; 42 | if (400 === code) 43 | cls = 'setemail-error-form'; 44 | 45 | classUnset(document.getElementById(cls), 'hide'); 46 | classUnset(document.getElementById('setemail-btn'), 'hide'); 47 | classSet(document.getElementById('setemail-pbtn'), 'hide'); 48 | } 49 | 50 | function setemail(e) 51 | { 52 | 53 | return(sendForm(e, function() { genericSetup('setemail'); }, 54 | setemailError, function() { document.location.reload(); })); 55 | } 56 | 57 | function setpassError(code) 58 | { 59 | var cls; 60 | 61 | cls = 'setpass-error-sys'; 62 | if (400 === code) 63 | cls = 'setpass-error-form'; 64 | 65 | classUnset(document.getElementById(cls), 'hide'); 66 | classUnset(document.getElementById('setpass-btn'), 'hide'); 67 | classSet(document.getElementById('setpass-pbtn'), 'hide'); 68 | } 69 | 70 | function setpass(e) 71 | { 72 | 73 | return(sendForm(e, function() { genericSetup('setpass'); }, 74 | setpassError, function() { document.location.reload(); })); 75 | } 76 | 77 | function modproxyError(code) 78 | { 79 | var cls; 80 | 81 | cls = 'modproxy-error-sys'; 82 | if (400 === code) 83 | cls = 'modproxy-error-form'; 84 | 85 | classUnset(document.getElementById(cls), 'hide'); 86 | classUnset(document.getElementById('modproxy-btn'), 'hide'); 87 | classSet(document.getElementById('modproxy-pbtn'), 'hide'); 88 | } 89 | 90 | function delproxy(e) 91 | { 92 | 93 | console.log('here'); 94 | return(sendForm(e, function() { genericSetupClass(e); }, 95 | null, function() { document.location.reload(); })); 96 | } 97 | 98 | function modproxy(e) 99 | { 100 | 101 | return(sendForm(e, function() { genericSetup('modproxy'); }, 102 | modproxyError, function() { document.getElementById('modproxy').reset(); document.location.reload(); })); 103 | } 104 | 105 | function newcolnError(code) 106 | { 107 | var cls; 108 | 109 | cls = 'newcoln-error-sys'; 110 | if (400 === code) 111 | cls = 'newcoln-error-form'; 112 | 113 | classUnset(document.getElementById(cls), 'hide'); 114 | classUnset(document.getElementById('newcoln-btn'), 'hide'); 115 | classSet(document.getElementById('newcoln-pbtn'), 'hide'); 116 | } 117 | 118 | function newcoln(e) 119 | { 120 | 121 | return(sendForm(e, function() { genericSetup('newcoln'); }, 122 | newcolnError, function() { document.location.reload(); })); 123 | } 124 | 125 | function updateHash(input) 126 | { 127 | var e = document.getElementById('password'); 128 | 129 | if ('' == input.value) 130 | e.value = ''; 131 | else 132 | e.value = md5(res.principal.name + ':kcaldav:' + input.value); 133 | } 134 | 135 | function genericSetupClass(root) 136 | { 137 | var list, i, sz; 138 | 139 | list = root.getElementsByClassName('error'); 140 | for (i = 0, sz = list.length; i < sz; i++) 141 | classSet(list[i], 'hide'); 142 | 143 | list = root.getElementsByClassName('btn'); 144 | for (i = 0, sz = list.length; i < sz; i++) 145 | classSet(list[i], 'hide'); 146 | 147 | list = root.getElementsByClassName('pbtn'); 148 | for (i = 0, sz = list.length; i < sz; i++) 149 | classUnset(list[i], 'hide'); 150 | } 151 | 152 | function genericSetup(name) 153 | { 154 | var list, i, sz; 155 | 156 | list = document.getElementsByClassName(name + '-error'); 157 | for (i = 0, sz = list.length; i < sz; i++) 158 | classSet(list[i], 'hide'); 159 | classSet(document.getElementById(name + '-btn'), 'hide'); 160 | classUnset(document.getElementById(name + '-pbtn'), 'hide'); 161 | } 162 | 163 | root.load = load; 164 | root.updateHash = updateHash; 165 | root.newcoln = newcoln; 166 | root.setemail = setemail; 167 | root.setpass = setpass; 168 | root.modproxy = modproxy; 169 | root.delproxy = delproxy; 170 | })(this); 171 | -------------------------------------------------------------------------------- /index.css: -------------------------------------------------------------------------------- 1 | body, html { margin: 0; } 2 | body { font-family: 'Alegreya Sans', sans-serif; 3 | color: #333; } 4 | #breadcrumbs { text-align: center; 5 | margin-bottom: 2em; } 6 | #breadcrumbs > span { display: inline-block; 7 | color: #ddd; 8 | padding: 0.5em 2em; 9 | box-shadow: 0 0 6px #000; 10 | font-size: smaller; 11 | font-weight: 500; 12 | border-bottom-left-radius: 8pt; 13 | border-bottom-right-radius: 8pt; 14 | background-color: #222; } 15 | #breadcrumbs a { color: #fff; 16 | text-decoration: underline; } 17 | .standout { border: 3px solid #aaa; 18 | border-radius: 1rem; 19 | color: #000; 20 | padding: 0.5rem 1rem; } 21 | header { background-color: #6a6a6a; } 22 | header + nav { text-align: center; 23 | margin-bottom: 2em; } 24 | header + nav > div { padding: 0 1em; 25 | display: inline-block; } 26 | header + nav a { color: #000; } 27 | header + nav i.fa { font-size: smaller; } 28 | header + nav > div > span 29 | { color: #666; 30 | border-left: thin solid #ddd; 31 | display: inline-block; 32 | padding-left: 0.5em; } 33 | header + nav .navtext { font-size: smaller; } 34 | article > section { margin: 3em 0; } 35 | div.date { color: #666; } 36 | article a { color: blue; } 37 | footer { text-align: center; 38 | padding-bottom: 2rem; 39 | font-size: smaller; 40 | opacity: 0.7; } 41 | a { text-decoration: none; } 42 | #headline { font-size: 175%; 43 | text-align: center; 44 | padding: 1em 0 0.5em 0; 45 | color: #fff; } 46 | #headline span { color: #ddd; } 47 | #intro { color: #000; } 48 | h1 { margin: 0; 49 | display: inline-block; 50 | font-size: inherit; 51 | font-weight: inherit; } 52 | .file { font-style: italic; } 53 | #versions { margin: 3em 0; 54 | background-color: #fcfcfc; 55 | border-bottom: thin solid #eee; 56 | border-top: thin solid #eee; } 57 | #versions > div { text-align: center; } 58 | h2 { margin: 0; 59 | font-weight: inherit; 60 | font-variant: small-caps; 61 | display: inline-block; 62 | padding: 0.2em 3em; 63 | color: #000; 64 | font-size: 110%; 65 | text-align: center; } 66 | nav[data-sblg-nav] ul { list-style-type: none; 67 | color: #333; 68 | margin: 2em 0; 69 | padding-left: 0; } 70 | nav[data-sblg-nav] li { margin-bottom: 1.5em; 71 | opacity: 0.7; } 72 | nav[data-sblg-nav] li:first-child 73 | { opacity: 1.0; 74 | margin-bottom: 2em; } 75 | nav[data-sblg-nav] a { color: #05f; } 76 | nav[data-sblg-nav] div + div 77 | { margin-top: 8px; } 78 | nav[data-sblg-nav] .date i.fa 79 | { font-size: smaller; } 80 | aside { font-size: inherit; } 81 | pre,code { font-family: monospace; 82 | font-size: 11pt; } 83 | .nm { font-weight: 500; } 84 | 85 | @media only screen and (max-width: 768px), only screen and (max-device-width: 768px) { 86 | #headline { font-size: 115%; } 87 | } 88 | -------------------------------------------------------------------------------- /index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | kcaldav: a simple CalDAV server 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 19 | 20 | 21 |
22 |
23 | 26 |
27 |

kCalDAV

28 | — 29 | simple CalDAV server 30 | 31 |
32 |
33 |
34 | 48 |
49 |
50 |

51 | kcaldav is a simple, safe, and minimal CalDAV server depending only on kcgi, sqlite3, and expat. 55 | It is open source with friendly, 56 | auditable source code. 57 |

58 |

59 | To contribute to kcaldav, visit the 60 | GitHub page for source code layout, bug report tips, 61 | and so on. 62 |

63 |

64 | kcaldav is designed for simple setups, like sharing a calendar collection 65 | between Mozilla Lightning, Mac OS X iCal, DAVdroid forks, and iOS (iPhone) clients. 66 | It compiles and runs on OpenBSD, Linux, NetBSD, FreeBSD, Mac OS X, Solaris, and OmniOS. 67 |

68 |
    69 |
  1. 70 | Install dependencies kcgi, sqlite3, and expat. 73 | (On Mac OS X, these must be installed as third-party packages alongside the base utilities: the 74 | pkg-config scripts are not installed for the 75 | libraries in base.) 76 |
  2. 77 |
  3. 78 | Download the sources and verify the fingerprint. 80 |
  4. 81 |
  5. 82 | Configure for your installation by creating a Makefile.local using 83 | variables documented in the Makefile. 84 | (You will need to do this: installation paths for CGI scripts differ vastly!) 85 |
  6. 86 |
  7. 87 | Configure with ./configure. 88 | Compile with make, install with make install, then install the CGI 89 | script and its data files with make installcgi. 90 |
  8. 91 |
  9. 92 | If using Apache, make sure that HTTP authorisation is not 93 | interpreted by the web server. 94 | (Example.) 95 |
  10. 96 |
  11. 97 | Read and follow kcaldav(8). 98 |
  12. 99 |
100 |

101 | The kcaldav(8) manual has a complete description of supported CalDAV 102 | features. 103 | You'll also want to read kcaldav.passwd(1). 104 | If these manpages lack information or clarity, that's a bug. 105 |

106 |
107 |
108 |

recent versions

109 | 120 | 121 |
122 |
123 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /kcaldav.example.conf: -------------------------------------------------------------------------------- 1 | # Instead of logging to stderr (usually stored in the web server's 2 | # error.log), log to a specific file relative to the web server 3 | # chroot. 4 | logfile=/logs/kcaldav.log 5 | 6 | # Set debug=1 to also output informational messages. 7 | # Set debug=2 to also output database debug messages. 8 | # Set debug=3 to also output network debug messages. 9 | debug=1 10 | -------------------------------------------------------------------------------- /kcaldav.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #ifndef KCALDAV_H 17 | #define KCALDAV_H 18 | 19 | struct state { 20 | struct prncpl *prncpl; /* current user principal */ 21 | struct prncpl *rprncpl; /* requested user principal */ 22 | struct coln *cfg; /* (resource in?) requested collection */ 23 | int proxy; /* permission of this proxy request */ 24 | char caldir[PATH_MAX]; /* calendar root */ 25 | char *principal; /* principal in request */ 26 | char *collection; /* collection in request */ 27 | char *resource; /* resource in request */ 28 | const char *nonce; /* requested nonce */ 29 | }; 30 | 31 | enum xml { 32 | XML_CALDAV_CALENDAR, 33 | XML_CALDAV_CALENDAR_DATA, 34 | XML_CALDAV_COMP, 35 | XML_CALDAV_OPAQUE, 36 | XML_CALDAVSERV_PROXY_READ, 37 | XML_CALDAVSERV_PROXY_READ_FOR, 38 | XML_CALDAVSERV_PROXY_WRITE, 39 | XML_CALDAVSERV_PROXY_WRITE_FOR, 40 | XML_DAV_BIND, 41 | XML_DAV_COLLECTION, 42 | XML_DAV_HREF, 43 | XML_DAV_MULTISTATUS, 44 | XML_DAV_PRINCIPAL, 45 | XML_DAV_PRIVILEGE, 46 | XML_DAV_PROP, 47 | XML_DAV_PROPSTAT, 48 | XML_DAV_READ, 49 | XML_DAV_READ_CURRENT_USER_PRIVILEGE_SET, 50 | XML_DAV_RESOURCETYPE, 51 | XML_DAV_RESPONSE, 52 | XML_DAV_STATUS, 53 | XML_DAV_UNBIND, 54 | XML_DAV_WRITE, 55 | XML__MAX 56 | }; 57 | 58 | enum page { 59 | PAGE_DELCOLN = 0, 60 | PAGE_INDEX, 61 | PAGE_LOGOUT, 62 | PAGE_MODPROXY, 63 | PAGE_NEWCOLN, 64 | PAGE_SETCOLNPROPS, 65 | PAGE_SETEMAIL, 66 | PAGE_SETPASS, 67 | PAGE__MAX 68 | }; 69 | 70 | enum valid { 71 | VALID_BITS = 0, 72 | VALID_BODY, 73 | VALID_COLOUR, 74 | VALID_DESCRIPTION, 75 | VALID_EMAIL, 76 | VALID_ID, 77 | VALID_NAME, 78 | VALID_PASS, 79 | VALID_PATH, 80 | VALID__MAX 81 | }; 82 | 83 | typedef void (*principalfp)(struct kreq *, struct kxmlreq *); 84 | typedef void (*collectionfp)(struct kreq *, struct kxmlreq *, 85 | const struct coln *); 86 | typedef void (*resourcefp)(struct kreq *, struct kxmlreq *, 87 | const struct coln *, const struct res *); 88 | 89 | /* 90 | * This fully describes the properties that we handle and their various 91 | * callbacks and informational bits. 92 | */ 93 | struct property { 94 | unsigned int flags; 95 | collectionfp cgetfp; 96 | resourcefp rgetfp; 97 | principalfp pgetfp; 98 | }; 99 | 100 | __BEGIN_DECLS 101 | 102 | int xml_ical_putc(int, void *); 103 | int http_ical_putc(int, void *); 104 | 105 | void http_error(struct kreq *, enum khttp); 106 | int http_paths(const char *, char **, char **, char **); 107 | int http_safe_string(const char *); 108 | const char *http_etag_if_match(const char *, char **); 109 | 110 | void method_delete(struct kreq *); 111 | void method_get(struct kreq *); 112 | void method_json(struct kreq *); 113 | void method_options(struct kreq *); 114 | void method_propfind(struct kreq *); 115 | void method_proppatch(struct kreq *); 116 | void method_put(struct kreq *); 117 | void method_report(struct kreq *); 118 | 119 | extern const char *const pages[PAGE__MAX]; 120 | extern const char *const xmls[XML__MAX]; 121 | extern const char *const valids[VALID__MAX]; 122 | extern const struct property properties[CALPROP__MAX]; 123 | 124 | __END_DECLS 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /kcaldav.sql: -------------------------------------------------------------------------------- 1 | PRAGMA journal_mode=WAL; 2 | PRAGMA foreign_keys=ON; 3 | 4 | -- A resource is a ``file'' managed by the CalDAV server. 5 | -- For us, files are always iCal files. 6 | 7 | CREATE TABLE resource ( 8 | -- To which collection to be we belong? 9 | collection INTEGER NOT NULL, 10 | -- The URL of the resource component, e.g., ``foo.ics''. 11 | url TEXT NOT NULL, 12 | -- The file's current etag (in the HTTP sense). 13 | etag TEXT NOT NULL DEFAULT('1'), 14 | -- The iCal data as a nil-terminated string. 15 | data TEXT NOT NULL, 16 | id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 17 | -- Currently unused. 18 | flags INTEGER NOT NULL DEFAULT(0), 19 | unique (url,collection), 20 | FOREIGN KEY (collection) REFERENCES collection(id) ON DELETE CASCADE 21 | ); 22 | 23 | -- A collection is a calendar directory. 24 | -- Collections, in kCalDAV, only contain resources: we do not allow 25 | -- nested collections. 26 | -- This just keeps things simpler. 27 | 28 | CREATE TABLE collection ( 29 | -- Who owns this collection? 30 | principal INTEGER NOT NULL, 31 | -- The URL (path component), e.g., ``foobar'' of 32 | -- ``foobar/foo.ics''. 33 | url TEXT NOT NULL, 34 | -- The free-form name of the calendar. 35 | displayname TEXT NOT NULL DEFAULT('Calendar'), 36 | -- The colour (an Apple extension) for calendar showing. 37 | colour TEXT NOT NULL DEFAULT('#B90E28FF'), 38 | -- A free-form description of the calendar. 39 | description TEXT NOT NULL DEFAULT(''), 40 | -- The HTTP ctag of the collection. 41 | ctag INT NOT NULL DEFAULT(1), 42 | id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 43 | -- Currently unused. 44 | flags INTEGER NOT NULL DEFAULT(0), 45 | unique (url,principal), 46 | FOREIGN KEY (principal) REFERENCES principal(id) ON DELETE CASCADE 47 | ); 48 | 49 | -- Proxies function as a delegation mechanism: the @proxy.proxy user 50 | -- will have access to the collections and resources of 51 | -- @"proxy.principal". 52 | 53 | CREATE TABLE proxy ( 54 | -- The one whose stuff will be accessed by @"proxy.proxy". 55 | principal INTEGER NOT NULL, 56 | -- The one accessing the stuff of @"proxy.principal". 57 | proxy INTEGER NOT NULL, 58 | -- Mode bits PROXY_READ and PROXY_WRITE. 59 | bits INTEGER NOT NULL DEFAULT(0), 60 | id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 61 | -- Currently unused. 62 | flags INTEGER NOT NULL DEFAULT(0), 63 | unique (principal,proxy), 64 | FOREIGN KEY (principal) REFERENCES principal(id) ON DELETE CASCADE, 65 | FOREIGN KEY (proxy) REFERENCES principal(id) ON DELETE CASCADE 66 | ); 67 | 68 | -- A nonce is used by the HTTP digest authentication. 69 | -- We limit the size of this table in the software, since it's basically 70 | -- touchable by the open Internet. 71 | 72 | CREATE TABLE nonce ( 73 | -- The value of the nonce. 74 | nonce TEXT NOT NULL, 75 | -- How many times the nonce has been used. 76 | count INT NOT NULL DEFAULT(0), 77 | id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 78 | unique (nonce) 79 | ); 80 | 81 | -- A principal is a user. 82 | 83 | CREATE TABLE principal ( 84 | -- Free-form user name. 85 | name TEXT NOT NULL, 86 | -- Password hash. 87 | hash TEXT NOT NULL, 88 | -- E-mail address. 89 | email TEXT NOT NULL, 90 | -- Currently unused. 91 | flags INTEGER NOT NULL DEFAULT(0), 92 | id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 93 | unique (email), 94 | unique (name) 95 | ); 96 | 97 | -- We use this to determine first whether the database has been opened 98 | -- and created or not; second, to see whether the person accessing the 99 | -- database on the local system is allowed. 100 | -- Of course, root can override everything. 101 | 102 | CREATE TABLE database ( 103 | -- Owner uid. 104 | owneruid INTEGER NOT NULL 105 | ); 106 | -------------------------------------------------------------------------------- /man/caldav_free.3: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) Kristaps Dzonsons 2 | .\" 3 | .\" Permission to use, copy, modify, and distribute this software for any 4 | .\" purpose with or without fee is hereby granted, provided that the above 5 | .\" copyright notice and this permission notice appear in all copies. 6 | .\" 7 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | .\" 15 | .Dd $Mdocdate$ 16 | .Dt CALDAV_FREE 3 17 | .Os 18 | .Sh NAME 19 | .Nm caldav_free 20 | .Nd free a parsed CalDAV file 21 | .Sh LIBRARY 22 | .Lb libkcaldav 23 | .Sh SYNOPSIS 24 | .In libkcaldav.h 25 | .Ft void 26 | .Fo caldav_free 27 | .Fa struct caldav *p 28 | .Fc 29 | .Sh DESCRIPTION 30 | Frees a CalDAV object 31 | .Fa p 32 | as parsed with 33 | .Xr caldav_parse 3 . 34 | If passed 35 | .Dv NULL , 36 | this does nothing. 37 | .\" The following requests should be uncommented and used where appropriate. 38 | .\" .Sh CONTEXT 39 | .\" For section 9 functions only. 40 | .\" .Sh RETURN VALUES 41 | .\" For sections 2, 3, and 9 function return values only. 42 | .\" .Sh ENVIRONMENT 43 | .\" For sections 1, 6, 7, and 8 only. 44 | .\" .Sh FILES 45 | .\" .Sh EXIT STATUS 46 | .\" For sections 1, 6, and 8 only. 47 | .\" .Sh EXAMPLES 48 | .\" .Sh DIAGNOSTICS 49 | .\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only. 50 | .\" .Sh ERRORS 51 | .\" For sections 2, 3, 4, and 9 errno settings only. 52 | .Sh SEE ALSO 53 | .Xr caldav_parse 3 54 | .\" .Sh STANDARDS 55 | .\" .Sh HISTORY 56 | .\" .Sh AUTHORS 57 | .\" .Sh CAVEATS 58 | .\" .Sh BUGS 59 | -------------------------------------------------------------------------------- /man/caldav_parse.3: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) Kristaps Dzonsons 2 | .\" 3 | .\" Permission to use, copy, modify, and distribute this software for any 4 | .\" purpose with or without fee is hereby granted, provided that the above 5 | .\" copyright notice and this permission notice appear in all copies. 6 | .\" 7 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | .\" 15 | .Dd $Mdocdate$ 16 | .Dt CALDAV_PARSE 3 17 | .Os 18 | .Sh NAME 19 | .Nm ical_parse 20 | .Nd parse a CalDAV file 21 | .Sh LIBRARY 22 | .Lb libkcaldav 23 | .Sh SYNOPSIS 24 | .In libkcaldav.h 25 | .Ft struct caldav * 26 | .Fo caldav_parse 27 | .Fa const char *file 28 | .Fa const char *cp 29 | .Fa size_t len 30 | .Fa char **er 31 | .Fc 32 | .Sh DESCRIPTION 33 | Parse an CalDAV file given in 34 | .Fa cp , 35 | which may not be 36 | .Dv NULL , 37 | of length 38 | .Fa sz . 39 | If 40 | .Fa file 41 | is not 42 | .Dv NULL , 43 | it is used for reporting errors only. 44 | The 45 | .Fa er , 46 | if not 47 | .Dv NULL , 48 | is filled in with an error message on parse failure. 49 | .Pp 50 | The parsed CalDAV file must be freed with 51 | .Xr caldav_free 3 . 52 | If errors occur and 53 | .Fa er 54 | is set, the error string must be freed with 55 | .Xr free 3 . 56 | .Pp 57 | The returned 58 | .Vt struct caldav 59 | structure has the following members: 60 | .Bl -tag -width Ds -offset indent 61 | .It Va enum calreqtype type 62 | Type of CalDAV request. 63 | .It Va struct calprop *props 64 | Array of properties passed in the request. 65 | This is 66 | .Dv NULL 67 | if the request has no properties. 68 | .It Va size_t propsz 69 | The number of properties in 70 | .Fa props . 71 | .It Va char **hrefs 72 | Any URLs passed in with the request or 73 | .Dv NULL 74 | if not having an URLs. 75 | These are interpreted depending upon the request. 76 | .It Va size_t hrefsz 77 | The number of elements in 78 | .Fa hrefs . 79 | .El 80 | The calendar properties are encoded in 81 | .Vt struct calprop : 82 | .Bl -tag -width -Ds -offset indent 83 | .It Va enum calproptype key 84 | The property type or 85 | .Dv CALPROP__MAX 86 | if unknown. 87 | .It Va char *name 88 | The property name (without its XML namespace). 89 | .It Va char *xmlns 90 | The property XML namespace. 91 | .It Va char *val 92 | The value of the property or 93 | .Dv NULL 94 | if it has none. 95 | .It Va int valid 96 | Validity of property: if -1, invalid; if zero, not valid; if 1, valid. 97 | .El 98 | .\" The following requests should be uncommented and used where appropriate. 99 | .\" .Sh CONTEXT 100 | .\" For section 9 functions only. 101 | .Sh RETURN VALUES 102 | Returns the parse object on success. 103 | It must be freed with 104 | .Xr caldav_free 3 . 105 | On failure, returns 106 | .Dv NULL . 107 | .Pp 108 | The 109 | .Fa er 110 | pointer, if not 111 | .Dv NULL , 112 | is provided an error message. 113 | If the error message is 114 | .Dv NULL , 115 | memory allocation has failed. 116 | .\" For sections 2, 3, and 9 function return values only. 117 | .\" .Sh ENVIRONMENT 118 | .\" For sections 1, 6, 7, and 8 only. 119 | .\" .Sh FILES 120 | .\" .Sh EXIT STATUS 121 | .\" For sections 1, 6, and 8 only. 122 | .\" .Sh EXAMPLES 123 | .\" .Sh DIAGNOSTICS 124 | .\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only. 125 | .\" .Sh ERRORS 126 | .\" For sections 2, 3, 4, and 9 errno settings only. 127 | .Sh SEE ALSO 128 | .Xr caldav_free 3 129 | .Sh STANDARDS 130 | The CalDAV and underlying WebDAV formats are specified in RFC 4918 131 | .Pq WebDAV , 132 | RFC 4791 133 | .Pq CalDAV , 134 | caldav-ctag-02 135 | .Pq CalDAV ctags , 136 | RFC 3744 137 | .Pq the ACL component , 138 | RFC 5397 139 | .Pq current principal address , 140 | and RFC 4331 141 | .Pq file-system quota . 142 | .\" .Sh HISTORY 143 | .\" .Sh AUTHORS 144 | .\" .Sh CAVEATS 145 | .\" .Sh BUGS 146 | -------------------------------------------------------------------------------- /man/ical_free.3: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) Kristaps Dzonsons 2 | .\" 3 | .\" Permission to use, copy, modify, and distribute this software for any 4 | .\" purpose with or without fee is hereby granted, provided that the above 5 | .\" copyright notice and this permission notice appear in all copies. 6 | .\" 7 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | .\" 15 | .Dd $Mdocdate$ 16 | .Dt ICAL_FREE 3 17 | .Os 18 | .Sh NAME 19 | .Nm ical_free 20 | .Nd free a parsed iCalendar file 21 | .Sh LIBRARY 22 | .Lb libkcaldav 23 | .Sh SYNOPSIS 24 | .In libkcaldav.h 25 | .Ft void 26 | .Fo ical_free 27 | .Fa struct ical *p 28 | .Fc 29 | .Sh DESCRIPTION 30 | Frees an iCalendar 31 | .Fa p 32 | as parsed with 33 | .Xr ical_parse 3 . 34 | If passed 35 | .Dv NULL , 36 | this does nothing. 37 | .\" The following requests should be uncommented and used where appropriate. 38 | .\" .Sh CONTEXT 39 | .\" For section 9 functions only. 40 | .\" .Sh RETURN VALUES 41 | .\" For sections 2, 3, and 9 function return values only. 42 | .\" .Sh ENVIRONMENT 43 | .\" For sections 1, 6, 7, and 8 only. 44 | .\" .Sh FILES 45 | .\" .Sh EXIT STATUS 46 | .\" For sections 1, 6, and 8 only. 47 | .\" .Sh EXAMPLES 48 | .\" .Sh DIAGNOSTICS 49 | .\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only. 50 | .\" .Sh ERRORS 51 | .\" For sections 2, 3, 4, and 9 errno settings only. 52 | .Sh SEE ALSO 53 | .Xr ical_parse 3 54 | .\" .Sh STANDARDS 55 | .\" .Sh HISTORY 56 | .\" .Sh AUTHORS 57 | .\" .Sh CAVEATS 58 | .\" .Sh BUGS 59 | -------------------------------------------------------------------------------- /man/ical_print.3: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) Kristaps Dzonsons 2 | .\" 3 | .\" Permission to use, copy, modify, and distribute this software for any 4 | .\" purpose with or without fee is hereby granted, provided that the above 5 | .\" copyright notice and this permission notice appear in all copies. 6 | .\" 7 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | .\" 15 | .Dd $Mdocdate$ 16 | .Dt ICAL_PRINT 3 17 | .Os 18 | .Sh NAME 19 | .Nm ical_print , 20 | .Nm ical_printfile 21 | .Nd print out a parsed iCalendar file 22 | .Sh LIBRARY 23 | .Lb libkcaldav 24 | .Sh SYNOPSIS 25 | .In libkcaldav.h 26 | .Ft int 27 | .Fo ical_print 28 | .Fa const struct ical *p 29 | .Fa ical_putchar fp 30 | .Fa void *arg 31 | .Fc 32 | .Ft void 33 | .Fo ical_printfile 34 | .Fa int fd 35 | .Fa const struct ical *p 36 | .Fc 37 | .Sh DESCRIPTION 38 | Prints an iCalendar 39 | .Fa p 40 | as parsed with 41 | .Xr ical_parse 3 . 42 | .Pp 43 | The 44 | .Fn ical_printfile 45 | is a short form that uses 46 | .Xr putchar 3 47 | for writing to a file descriptor 48 | .Fa fd . 49 | .Pp 50 | The 51 | .Fn ical_print 52 | form takes a writing function 53 | .Fa fp , 54 | which is invoked with a character to write and the value of 55 | .Fa arg . 56 | .\" The following requests should be uncommented and used where appropriate. 57 | .\" .Sh CONTEXT 58 | .\" For section 9 functions only. 59 | .\" .Sh RETURN VALUES 60 | .\" For sections 2, 3, and 9 function return values only. 61 | .\" .Sh ENVIRONMENT 62 | .\" For sections 1, 6, 7, and 8 only. 63 | .\" .Sh FILES 64 | .\" .Sh EXIT STATUS 65 | .\" For sections 1, 6, and 8 only. 66 | .\" .Sh EXAMPLES 67 | .\" .Sh DIAGNOSTICS 68 | .\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only. 69 | .\" .Sh ERRORS 70 | .\" For sections 2, 3, 4, and 9 errno settings only. 71 | .Sh SEE ALSO 72 | .Xr ical_parse 3 73 | .\" .Sh STANDARDS 74 | .\" .Sh HISTORY 75 | .\" .Sh AUTHORS 76 | .\" .Sh CAVEATS 77 | .\" .Sh BUGS 78 | -------------------------------------------------------------------------------- /man/kcaldav.conf.5: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) Kristaps Dzonsons 2 | .\" 3 | .\" Permission to use, copy, modify, and distribute this software for any 4 | .\" purpose with or without fee is hereby granted, provided that the above 5 | .\" copyright notice and this permission notice appear in all copies. 6 | .\" 7 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | .\" 15 | .Dd $Mdocdate$ 16 | .Dt KCALDAV.CONF 5 17 | .Os 18 | .Sh NAME 19 | .Nm kcaldav.conf 20 | .Nd kcaldav configuration 21 | .\" .Sh LIBRARY 22 | .\" For sections 2, 3, and 9 only. 23 | .\" Not used in OpenBSD. 24 | .Sh SYNOPSIS 25 | .Nm kcaldav.conf 26 | .Sh DESCRIPTION 27 | The 28 | .Nm 29 | file specifies run-time configuration for 30 | .Xr kcaldav 8 . 31 | Its location relative to the web server root is set at compile-time. 32 | If not set, or the file does not exist, system defaults are used. 33 | .Pp 34 | The file is designed to be human readable and contains a list of keywords with 35 | values that represent run-time configuration. 36 | .Pp 37 | A keyword and its value must appear on a single line. 38 | The keyword and value are separated by the equal sign 39 | .Pq = . 40 | White-space at the start, end, and around the equal sign are stripped. 41 | A hash mark 42 | .Pq # 43 | in the file indicates the beginning of a comment; subsequent characters up to 44 | the end of the line are not interpereted by the routines that read the file. 45 | If the hash mark is preceded by a backslash 46 | .Pq \e , 47 | the backslash is stripped from input, but the hash mark is retained. 48 | Blank lines (even if containing spaces) are ignored. 49 | It is an error to specify unknown keywords or keywords without a equal sign. 50 | .Pp 51 | The configuration options are: 52 | .Bl -tag -width Ds 53 | .It Ic logfile 54 | File for writing log messages. 55 | This must already exist and be writable by the 56 | .Xr kcaldav 8 57 | process. 58 | If specified as an empty string or not specified, the default is writing log 59 | messages to 60 | .Dv stderr . 61 | .It Ic debug 62 | A non-negative number indicating log level. 63 | Zero, the default, outputs only warning and error messages. 64 | One additionally outputs informational messages. 65 | Two additionally outputs database debug messages. 66 | Three additionally outputs network debug messages. 67 | .El 68 | .\" .Sh CONTEXT 69 | .\" For section 9 functions only. 70 | .\" .Sh IMPLEMENTATION NOTES 71 | .\" .Sh RETURN VALUES 72 | .\" For sections 2, 3, and 9 function return values only. 73 | .\" .Sh ENVIRONMENT 74 | .\" For sections 1, 6, 7, and 8 only. 75 | .\" .Sh FILES 76 | .\" .Sh EXIT STATUS 77 | .\" For sections 1, 6, and 8 only. 78 | .Sh EXAMPLES 79 | A reasonable default configuration is as follows: 80 | .Bd -literal -offset indent 81 | # Instead of logging to stderr (usually stored in the web server's 82 | # error.log), log to a specific file relative to the web server 83 | # chroot. 84 | logfile=/logs/kcaldav.log 85 | 86 | # Set debug=1 to also output informational messages. 87 | # Set debug=2 to also output database debug messages. 88 | # Set debug=3 to also output network debug messages. 89 | debug=1 90 | .Ed 91 | .Pp 92 | For submitting bug reports, 93 | .Ic debug 94 | should be set to 3. 95 | .\" .Sh DIAGNOSTICS 96 | .\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only. 97 | .\" .Sh ERRORS 98 | .\" For sections 2, 3, 4, and 9 errno settings only. 99 | .Sh SEE ALSO 100 | .Xr kcaldav 8 101 | .\" .Sh STANDARDS 102 | .\" .Sh HISTORY 103 | .\" .Sh AUTHORS 104 | .\" .Sh CAVEATS 105 | .\" .Sh BUGS 106 | .\" .Sh SECURITY CONSIDERATIONS 107 | .\" Not used in OpenBSD. 108 | -------------------------------------------------------------------------------- /man/kcaldav.passwd.in.1: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) Kristaps Dzonsons 2 | .\" 3 | .\" Permission to use, copy, modify, and distribute this software for any 4 | .\" purpose with or without fee is hereby granted, provided that the above 5 | .\" copyright notice and this permission notice appear in all copies. 6 | .\" 7 | .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | .\" 15 | .Dd $Mdocdate$ 16 | .Dt KCALDAV.PASSWD 1 17 | .Os 18 | .Sh NAME 19 | .Nm kcaldav.passwd 20 | .Nd change kcaldav principal information 21 | .Sh SYNOPSIS 22 | .Nm kcaldav.passwd 23 | .Op Fl Cnv 24 | .Op Fl d Ar collection 25 | .Op Fl e Ar email 26 | .Op Fl f Ar caldir 27 | .Op Fl u Ar principal 28 | .Op Ar resource... 29 | .Sh DESCRIPTION 30 | Updates database entries for 31 | .Xr kcaldav 8 32 | principals. 33 | Its arguments are as follows: 34 | .Bl -tag -width Ds 35 | .It Fl C 36 | Create a new principal with an initial collection 37 | .Qq calendar . 38 | The e-mail address is the principal's name at the current host (see 39 | .Xr hostname 1 ) 40 | or 41 | .Qq localhost 42 | if there's no system-wide hostname set. 43 | .It Fl n 44 | Do not change the principal's password: only change attributes (such as 45 | with 46 | .Fl e ) . 47 | Ignored if used with 48 | .Fl C . 49 | .It Fl d Ar collection 50 | Add a collection for the principal, doing nothing if the collection 51 | already exists. 52 | If used with 53 | .Fl C , 54 | sets the initial collection. 55 | .It Fl e Ar email 56 | Set the principal's e-mail address. 57 | .It Fl f Ar caldir 58 | The database directory. 59 | .It Fl u Ar principal 60 | The principal to look up in the database. 61 | .It Fl v 62 | Verbose. 63 | Shows underlying database operations. 64 | .It Ar resource... 65 | A list of resources to add to the collection of 66 | .Fl d 67 | or 68 | .Qq calendar 69 | by default. 70 | The name of each resource is set from its filename component. 71 | .El 72 | .Pp 73 | By default, the password is changed for the principal matching the 74 | logged-in user (see 75 | .Xr logname 1 ) . 76 | The database 77 | .Pa kcaldav.db 78 | is looked for in 79 | .Pa @CALPREFIX@ . 80 | .Pp 81 | If the database is created with 82 | .Fl C , 83 | its owner is set to the current real user. 84 | If the database exists and 85 | .Fl C 86 | or 87 | .Fl u 88 | is used, the current real user (via 89 | .Xr getuid 2 ) 90 | must match the database owner or be root. 91 | .Pp 92 | The database must be read-writable by the web server. 93 | .\" .Sh IMPLEMENTATION NOTES 94 | .\" Not used in OpenBSD. 95 | .\" .Sh RETURN VALUES 96 | .\" For sections 2, 3, and 9 function return values only. 97 | .\" .Sh ENVIRONMENT 98 | .\" For sections 1, 6, 7, and 8 only. 99 | .\" .Sh FILES 100 | .Sh EXIT STATUS 101 | .Ex -std 102 | .Sh EXAMPLES 103 | In the simplest case, root creates and maintains the database. 104 | Assuming the database is in 105 | .Pa @CALPREFIX@ : 106 | .Bd -literal -offset indent 107 | # kcaldav.passwd -Cu kristaps 108 | New password: ********* 109 | Repeat new password: ********* 110 | .Ed 111 | .Pp 112 | After this time, the user 113 | .Qq kristaps 114 | can access their default calendar 115 | .Qq calendar . 116 | .Pp 117 | To have the database modifiable by local users, use a dummy 118 | .Qq kcaldav 119 | user owning the file and creating new users. 120 | Thi assumes that the database doesn't already exist. 121 | .Bd -literal -offset indent 122 | # chown _kcaldav @PREFIX@/bin/kcaldav.passwd 123 | # chmod u+s @PREFIX@/bin/kcaldav.passwd 124 | # doas -u _kcaldav kcaldav.passwd -Cu kristaps 125 | New password: ********* 126 | Repeat new password: ********* 127 | .Ed 128 | .Pp 129 | The user may then set their password: 130 | .Pp 131 | .Dl % kcaldav.passwd -ne kristaps@bsd.lv 132 | .Pp 133 | Or add calendars: 134 | .Bd -literal -offset indent 135 | % kcaldav.passwd -nd newcalendar 136 | % kcaldav.passwd -nd secondcalendar 137 | .Ed 138 | .Pp 139 | To add resources to a new or existing calendar: 140 | .Pp 141 | .Dl % kcaldav.passwd -nd newcalendar file1.ics file2.ics 142 | .\" .Sh DIAGNOSTICS 143 | .\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only. 144 | .\" .Sh ERRORS 145 | .\" For sections 2, 3, 4, and 9 errno settings only. 146 | .Sh SEE ALSO 147 | .Xr kcaldav 8 148 | .\" .Sh STANDARDS 149 | .\" .Sh HISTORY 150 | .\" .Sh AUTHORS 151 | .\" .Sh CAVEATS 152 | .\" .Sh BUGS 153 | .\" .Sh SECURITY CONSIDERATIONS 154 | .\" Not used in OpenBSD. 155 | -------------------------------------------------------------------------------- /md5.js: -------------------------------------------------------------------------------- 1 | function md5cycle(x, k) { 2 | var a = x[0], b = x[1], c = x[2], d = x[3]; 3 | 4 | a = ff(a, b, c, d, k[0], 7, -680876936); 5 | d = ff(d, a, b, c, k[1], 12, -389564586); 6 | c = ff(c, d, a, b, k[2], 17, 606105819); 7 | b = ff(b, c, d, a, k[3], 22, -1044525330); 8 | a = ff(a, b, c, d, k[4], 7, -176418897); 9 | d = ff(d, a, b, c, k[5], 12, 1200080426); 10 | c = ff(c, d, a, b, k[6], 17, -1473231341); 11 | b = ff(b, c, d, a, k[7], 22, -45705983); 12 | a = ff(a, b, c, d, k[8], 7, 1770035416); 13 | d = ff(d, a, b, c, k[9], 12, -1958414417); 14 | c = ff(c, d, a, b, k[10], 17, -42063); 15 | b = ff(b, c, d, a, k[11], 22, -1990404162); 16 | a = ff(a, b, c, d, k[12], 7, 1804603682); 17 | d = ff(d, a, b, c, k[13], 12, -40341101); 18 | c = ff(c, d, a, b, k[14], 17, -1502002290); 19 | b = ff(b, c, d, a, k[15], 22, 1236535329); 20 | 21 | a = gg(a, b, c, d, k[1], 5, -165796510); 22 | d = gg(d, a, b, c, k[6], 9, -1069501632); 23 | c = gg(c, d, a, b, k[11], 14, 643717713); 24 | b = gg(b, c, d, a, k[0], 20, -373897302); 25 | a = gg(a, b, c, d, k[5], 5, -701558691); 26 | d = gg(d, a, b, c, k[10], 9, 38016083); 27 | c = gg(c, d, a, b, k[15], 14, -660478335); 28 | b = gg(b, c, d, a, k[4], 20, -405537848); 29 | a = gg(a, b, c, d, k[9], 5, 568446438); 30 | d = gg(d, a, b, c, k[14], 9, -1019803690); 31 | c = gg(c, d, a, b, k[3], 14, -187363961); 32 | b = gg(b, c, d, a, k[8], 20, 1163531501); 33 | a = gg(a, b, c, d, k[13], 5, -1444681467); 34 | d = gg(d, a, b, c, k[2], 9, -51403784); 35 | c = gg(c, d, a, b, k[7], 14, 1735328473); 36 | b = gg(b, c, d, a, k[12], 20, -1926607734); 37 | 38 | a = hh(a, b, c, d, k[5], 4, -378558); 39 | d = hh(d, a, b, c, k[8], 11, -2022574463); 40 | c = hh(c, d, a, b, k[11], 16, 1839030562); 41 | b = hh(b, c, d, a, k[14], 23, -35309556); 42 | a = hh(a, b, c, d, k[1], 4, -1530992060); 43 | d = hh(d, a, b, c, k[4], 11, 1272893353); 44 | c = hh(c, d, a, b, k[7], 16, -155497632); 45 | b = hh(b, c, d, a, k[10], 23, -1094730640); 46 | a = hh(a, b, c, d, k[13], 4, 681279174); 47 | d = hh(d, a, b, c, k[0], 11, -358537222); 48 | c = hh(c, d, a, b, k[3], 16, -722521979); 49 | b = hh(b, c, d, a, k[6], 23, 76029189); 50 | a = hh(a, b, c, d, k[9], 4, -640364487); 51 | d = hh(d, a, b, c, k[12], 11, -421815835); 52 | c = hh(c, d, a, b, k[15], 16, 530742520); 53 | b = hh(b, c, d, a, k[2], 23, -995338651); 54 | 55 | a = ii(a, b, c, d, k[0], 6, -198630844); 56 | d = ii(d, a, b, c, k[7], 10, 1126891415); 57 | c = ii(c, d, a, b, k[14], 15, -1416354905); 58 | b = ii(b, c, d, a, k[5], 21, -57434055); 59 | a = ii(a, b, c, d, k[12], 6, 1700485571); 60 | d = ii(d, a, b, c, k[3], 10, -1894986606); 61 | c = ii(c, d, a, b, k[10], 15, -1051523); 62 | b = ii(b, c, d, a, k[1], 21, -2054922799); 63 | a = ii(a, b, c, d, k[8], 6, 1873313359); 64 | d = ii(d, a, b, c, k[15], 10, -30611744); 65 | c = ii(c, d, a, b, k[6], 15, -1560198380); 66 | b = ii(b, c, d, a, k[13], 21, 1309151649); 67 | a = ii(a, b, c, d, k[4], 6, -145523070); 68 | d = ii(d, a, b, c, k[11], 10, -1120210379); 69 | c = ii(c, d, a, b, k[2], 15, 718787259); 70 | b = ii(b, c, d, a, k[9], 21, -343485551); 71 | 72 | x[0] = add32(a, x[0]); 73 | x[1] = add32(b, x[1]); 74 | x[2] = add32(c, x[2]); 75 | x[3] = add32(d, x[3]); 76 | 77 | } 78 | 79 | function cmn(q, a, b, x, s, t) { 80 | a = add32(add32(a, q), add32(x, t)); 81 | return add32((a << s) | (a >>> (32 - s)), b); 82 | } 83 | 84 | function ff(a, b, c, d, x, s, t) { 85 | return cmn((b & c) | ((~b) & d), a, b, x, s, t); 86 | } 87 | 88 | function gg(a, b, c, d, x, s, t) { 89 | return cmn((b & d) | (c & (~d)), a, b, x, s, t); 90 | } 91 | 92 | function hh(a, b, c, d, x, s, t) { 93 | return cmn(b ^ c ^ d, a, b, x, s, t); 94 | } 95 | 96 | function ii(a, b, c, d, x, s, t) { 97 | return cmn(c ^ (b | (~d)), a, b, x, s, t); 98 | } 99 | 100 | function md51(s) { 101 | txt = ''; 102 | var n = s.length, 103 | state = [1732584193, -271733879, -1732584194, 271733878], i; 104 | for (i=64; i<=s.length; i+=64) { 105 | md5cycle(state, md5blk(s.substring(i-64, i))); 106 | } 107 | s = s.substring(i-64); 108 | var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; 109 | for (i=0; i>2] |= s.charCodeAt(i) << ((i%4) << 3); 111 | tail[i>>2] |= 0x80 << ((i%4) << 3); 112 | if (i > 55) { 113 | md5cycle(state, tail); 114 | for (i=0; i<16; i++) tail[i] = 0; 115 | } 116 | tail[14] = n*8; 117 | md5cycle(state, tail); 118 | return state; 119 | } 120 | 121 | /* there needs to be support for Unicode here, 122 | * unless we pretend that we can redefine the MD-5 123 | * algorithm for multi-byte characters (perhaps 124 | * by adding every four 16-bit characters and 125 | * shortening the sum to 32 bits). Otherwise 126 | * I suggest performing MD-5 as if every character 127 | * was two bytes--e.g., 0040 0025 = @%--but then 128 | * how will an ordinary MD-5 sum be matched? 129 | * There is no way to standardize text to something 130 | * like UTF-8 before transformation; speed cost is 131 | * utterly prohibitive. The JavaScript standard 132 | * itself needs to look at this: it should start 133 | * providing access to strings as preformed UTF-8 134 | * 8-bit unsigned value arrays. 135 | */ 136 | function md5blk(s) { /* I figured global was faster. */ 137 | var md5blks = [], i; /* Andy King said do it this way. */ 138 | for (i=0; i<64; i+=4) { 139 | md5blks[i>>2] = s.charCodeAt(i) 140 | + (s.charCodeAt(i+1) << 8) 141 | + (s.charCodeAt(i+2) << 16) 142 | + (s.charCodeAt(i+3) << 24); 143 | } 144 | return md5blks; 145 | } 146 | 147 | var hex_chr = '0123456789abcdef'.split(''); 148 | 149 | function rhex(n) 150 | { 151 | var s='', j=0; 152 | for(; j<4; j++) 153 | s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] 154 | + hex_chr[(n >> (j * 8)) & 0x0F]; 155 | return s; 156 | } 157 | 158 | function hex(x) { 159 | for (var i=0; i> 16) + (y >> 16) + (lsw >> 16); 182 | return (msw << 16) | (lsw & 0xFFFF); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /options.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include "libkcaldav.h" 28 | #include "db.h" 29 | #include "server.h" 30 | 31 | void 32 | method_options(struct kreq *r) 33 | { 34 | 35 | khttp_head(r, kresps[KRESP_STATUS], 36 | "%s", khttps[KHTTP_200]); 37 | khttp_head(r, kresps[KRESP_ALLOW], "%s", 38 | "OPTIONS, GET, PUT, PROPFIND, PROPPATCH"); 39 | khttp_head(r, "DAV", "%s", 40 | "1, access-control, calendar-access, calendar-proxy"); 41 | khttp_body(r); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /proppatch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include "libkcaldav.h" 29 | #include "db.h" 30 | #include "server.h" 31 | 32 | /* 33 | * This converts the request into a CalDav object. 34 | * We know that the request is a well-formed CalDav object because it 35 | * appears in the fieldmap and we parsed it during HTTP unpacking. 36 | * So we really only check its media type. 37 | */ 38 | static struct caldav * 39 | req2caldav(struct kreq *r, enum kmime *mime) 40 | { 41 | struct state *st = r->arg; 42 | 43 | if (r->fieldmap[VALID_BODY] == NULL) { 44 | kutil_warnx(r, st->prncpl->name, 45 | "failed CalDAV parse"); 46 | http_error(r, KHTTP_400); 47 | return NULL; 48 | } 49 | 50 | if (r->fieldmap[VALID_BODY]->ctypepos != KMIME_TEXT_XML && 51 | r->fieldmap[VALID_BODY]->ctypepos != KMIME_APP_XML) { 52 | kutil_warnx(r, st->prncpl->name, 53 | "bad CalDAV MIME type"); 54 | http_error(r, KHTTP_415); 55 | return NULL; 56 | } 57 | 58 | *mime = r->fieldmap[VALID_BODY]->ctypepos; 59 | 60 | /* This shouldn't fail now. */ 61 | 62 | return caldav_parse 63 | (r->fieldmap[VALID_BODY]->val, 64 | r->fieldmap[VALID_BODY]->valsz, NULL); 65 | } 66 | 67 | /* 68 | * Handle the PROPPATCH method, which is in its most general way 69 | * described in RFC 4918, section 9.2, accepting the "propertyupdate" 70 | * CalDAV XML (ibid., 14.9). 71 | */ 72 | void 73 | method_proppatch(struct kreq *r) 74 | { 75 | struct caldav *dav; 76 | struct state *st = r->arg; 77 | struct kxmlreq xml; 78 | size_t nf, df, bf, i; 79 | int accepted[CALPROP__MAX + 1]; 80 | struct coln cfg; 81 | enum kmime mime; 82 | 83 | if (st->cfg == NULL) { 84 | kutil_warnx(r, st->prncpl->name, 85 | "PROPPATCH of non-calendar collection"); 86 | http_error(r, KHTTP_403); 87 | return; 88 | } else if ((dav = req2caldav(r, &mime)) == NULL) 89 | return; 90 | 91 | cfg = *st->cfg; 92 | 93 | memset(accepted, 0, sizeof(accepted)); 94 | accepted[CALPROP_CALENDAR_COLOR] = 1; 95 | accepted[CALPROP_CALENDAR_DESCRIPTION] = 1; 96 | accepted[CALPROP_DISPLAYNAME] = 1; 97 | 98 | if (CALREQTYPE_PROPERTYUPDATE != dav->type) { 99 | kutil_warnx(r, st->prncpl->name, 100 | "unknown PROPPATCH request type"); 101 | http_error(r, KHTTP_415); 102 | caldav_free(dav); 103 | return; 104 | } 105 | 106 | khttp_head(r, kresps[KRESP_STATUS], 107 | "%s", khttps[KHTTP_207]); 108 | khttp_head(r, kresps[KRESP_CONTENT_TYPE], 109 | "%s", kmimetypes[mime]); 110 | khttp_head(r, "DAV", "1, access-control, " 111 | "calendar-access, calendar-proxy"); 112 | khttp_body(r); 113 | kxml_open(&xml, r, xmls, XML__MAX); 114 | kxml_prologue(&xml); 115 | kxml_pushattrs(&xml, XML_DAV_MULTISTATUS, 116 | "xmlns:B", "http://calendarserver.org/ns/", 117 | "xmlns:C", "urn:ietf:params:xml:ns:caldav", 118 | "xmlns:D", "DAV:", NULL); 119 | 120 | /* 121 | * Begin by looking over all of our properties and setting. 122 | * If we don't understand a property, skip it. 123 | * If we understand it but the value wasn't valid, skip it. 124 | * Otherwise, set into a temporary "struct config". 125 | */ 126 | 127 | kxml_push(&xml, XML_DAV_PROPSTAT); 128 | kxml_push(&xml, XML_DAV_PROP); 129 | 130 | for (nf = df = bf = i = 0; i < dav->propsz; i++) { 131 | if (!accepted[dav->props[i].key]) { 132 | nf++; 133 | bf += dav->props[i].valid < 0; 134 | continue; 135 | } else if (dav->props[i].valid < 0) { 136 | bf++; 137 | continue; 138 | } 139 | 140 | df++; 141 | switch (dav->props[i].key) { 142 | case CALPROP_DISPLAYNAME: 143 | cfg.displayname = dav->props[i].val; 144 | kutil_dbg(r, st->prncpl->name, 145 | "display name modified"); 146 | break; 147 | case CALPROP_CALENDAR_COLOR: 148 | cfg.colour = dav->props[i].val; 149 | kutil_dbg(r, st->prncpl->name, 150 | "calendar colour modified"); 151 | break; 152 | case CALPROP_CALENDAR_DESCRIPTION: 153 | cfg.description = dav->props[i].val; 154 | kutil_dbg(r, st->prncpl->name, 155 | "calendar description modified"); 156 | break; 157 | default: 158 | abort(); 159 | } 160 | } 161 | 162 | kxml_pop(&xml); 163 | kxml_push(&xml, XML_DAV_STATUS); 164 | kxml_puts(&xml, "HTTP/1.1 "); 165 | kxml_puts(&xml, khttps[KHTTP_200]); 166 | kxml_pop(&xml); 167 | kxml_pop(&xml); 168 | 169 | /* 170 | * In this event, we didn't understand one or more properties. 171 | * Serialise these as error 404 according to the spec. 172 | */ 173 | 174 | if (nf > 0) { 175 | kxml_push(&xml, XML_DAV_PROPSTAT); 176 | kxml_push(&xml, XML_DAV_PROP); 177 | for (i = 0; i < dav->propsz; i++) { 178 | if (accepted[dav->props[i].key]) 179 | continue; 180 | khttp_puts(r, "props[i].name); 182 | khttp_puts(r, " xmlns:X=\""); 183 | khttp_puts(r, dav->props[i].xmlns); 184 | khttp_puts(r, "\" />"); 185 | } 186 | kxml_pop(&xml); 187 | kxml_push(&xml, XML_DAV_STATUS); 188 | kxml_puts(&xml, "HTTP/1.1 "); 189 | kxml_puts(&xml, khttps[KHTTP_404]); 190 | kxml_pop(&xml); 191 | kxml_pop(&xml); 192 | } 193 | 194 | /* 195 | * Bad things: we're asked to set invalid data. 196 | * Use code 409 as specified by RFC 4918, 9.2.1. 197 | */ 198 | 199 | if (bf > 0) { 200 | kxml_push(&xml, XML_DAV_PROPSTAT); 201 | kxml_push(&xml, XML_DAV_PROP); 202 | for (i = 0; i < dav->propsz; i++) { 203 | if (dav->props[i].valid >= 0) 204 | continue; 205 | khttp_puts(r, "props[i].name); 207 | khttp_puts(r, " xmlns:X=\""); 208 | khttp_puts(r, dav->props[i].xmlns); 209 | khttp_puts(r, "\" />"); 210 | } 211 | kxml_pop(&xml); 212 | kxml_push(&xml, XML_DAV_STATUS); 213 | kxml_puts(&xml, "HTTP/1.1 "); 214 | kxml_puts(&xml, khttps[KHTTP_409]); 215 | kxml_pop(&xml); 216 | kxml_pop(&xml); 217 | } 218 | 219 | kxml_popall(&xml); 220 | kxml_close(&xml); 221 | 222 | /* FIXME: do this first to catch any HTTP 505 errors. */ 223 | 224 | if (df != 0 && !db_collection_update(&cfg, st->rprncpl)) 225 | kutil_errx_noexit(r, st->prncpl->name, 226 | "cannot update collection"); 227 | 228 | caldav_free(dav); 229 | } 230 | 231 | -------------------------------------------------------------------------------- /put.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include "libkcaldav.h" 29 | #include "db.h" 30 | #include "server.h" 31 | 32 | static struct ical * 33 | req2ical(struct kreq *r) 34 | { 35 | struct state *st = r->arg; 36 | 37 | if ( r->fieldmap[VALID_BODY] == NULL) { 38 | kutil_warnx(r, st->prncpl->name, 39 | "failed iCalendar parse"); 40 | http_error(r, KHTTP_400); 41 | return NULL; 42 | } 43 | 44 | if (r->fieldmap[VALID_BODY]->ctypepos != KMIME_TEXT_CALENDAR) { 45 | kutil_warnx(r, st->prncpl->name, 46 | "bad iCalendar MIME type"); 47 | http_error(r, KHTTP_415); 48 | return NULL; 49 | } 50 | 51 | /* This shouldn't fail now. */ 52 | 53 | return ical_parse(NULL, r->fieldmap[VALID_BODY]->val, 54 | r->fieldmap[VALID_BODY]->valsz, NULL, NULL); 55 | } 56 | 57 | /* 58 | * Satisfy RFC 4791, 5.3.2, PUT. 59 | */ 60 | void 61 | method_put(struct kreq *r) 62 | { 63 | struct ical *p; 64 | struct state *st = r->arg; 65 | size_t sz; 66 | int rc; 67 | char *buf = NULL; 68 | const char *digest = NULL; 69 | 70 | if (st->cfg == NULL) { 71 | kutil_warnx(r, st->prncpl->name, 72 | "PUT into non-calendar collection"); 73 | http_error(r, KHTTP_403); 74 | return; 75 | } else if ((p = req2ical(r)) == NULL) 76 | return; 77 | 78 | /* 79 | * Check if PUT is conditional upon existing etag. 80 | * Parse the etag contents, if specified in the "If" header, 81 | * according to RFC 2616. 82 | */ 83 | 84 | if (r->reqmap[KREQU_IF] != NULL) { 85 | buf = kstrdup(r->reqmap[KREQU_IF]->val); 86 | assert(buf != NULL); 87 | sz = strlen(buf); 88 | if (sz < 5 || 89 | buf[0] != '(' || buf[1] != '[' || 90 | buf[sz - 2] != ']' || buf[sz - 1] != ')' ) { 91 | kutil_warnx(r, st->prncpl->name, 92 | "malformed \"If\" statement"); 93 | http_error(r, KHTTP_400); 94 | ical_free(p); 95 | free(buf); 96 | return; 97 | } 98 | buf[sz - 2] = '\0'; 99 | buf[sz - 1] = '\0'; 100 | digest = &buf[2]; 101 | } else if (r->reqmap[KREQU_IF_MATCH] != NULL) { 102 | digest = http_etag_if_match 103 | (r->reqmap[KREQU_IF_MATCH]->val, &buf); 104 | 105 | /* 106 | * If the etag is not quoted and set to "*", this means 107 | * (according to RFC 7232 section 3.1) that the 108 | * condition is FALSE if the "listed representation" 109 | * (i.e., the resource name) is not matched. 110 | * In the "put", this means that we don't duplicate the name, 111 | * which we don't do anyway, so it's effectively the same as 112 | * not specifying an etag. 113 | */ 114 | 115 | if (digest != NULL && 116 | buf == NULL && strcmp(digest, "*") == 0) 117 | digest = NULL; 118 | } 119 | 120 | if (digest == NULL) 121 | rc = db_resource_new 122 | (r->fieldmap[VALID_BODY]->val, 123 | st->resource, st->cfg->id); 124 | else 125 | rc = db_resource_update 126 | (r->fieldmap[VALID_BODY]->val, 127 | st->resource, digest, st->cfg->id); 128 | 129 | if (rc < 0) { 130 | kutil_errx_noexit(r, st->prncpl->name, 131 | "cannot %s resource: %s", 132 | digest == NULL ? "create" : "update", 133 | r->fullpath); 134 | http_error(r, KHTTP_505); 135 | } else if (rc == 0) { 136 | kutil_warnx(r, st->prncpl->name, 137 | "duplicate resource: %s", r->fullpath); 138 | http_error(r, KHTTP_403); 139 | } else { 140 | kutil_dbg(r, st->prncpl->name, 141 | "resource %s: %s", 142 | digest == NULL ? "created" : "updated", 143 | r->fullpath); 144 | http_error(r, KHTTP_201); 145 | } 146 | 147 | ical_free(p); 148 | free(buf); 149 | } 150 | -------------------------------------------------------------------------------- /regress/caldav/oldsimple.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /regress/caldav/simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /regress/conf/emptylines.in.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /regress/conf/emptylines.out.conf: -------------------------------------------------------------------------------- 1 | debug=0 2 | -------------------------------------------------------------------------------- /regress/conf/emptylines2.in.conf: -------------------------------------------------------------------------------- 1 | 2 | # Nothing here. 3 | # 4 | # 5 | 6 | # And nothing here 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /regress/conf/emptylines2.out.conf: -------------------------------------------------------------------------------- 1 | debug=0 2 | -------------------------------------------------------------------------------- /regress/conf/escaped.in.conf: -------------------------------------------------------------------------------- 1 | logfile=a\#bc 2 | -------------------------------------------------------------------------------- /regress/conf/escaped.out.conf: -------------------------------------------------------------------------------- 1 | logfile=a#bc 2 | debug=0 3 | -------------------------------------------------------------------------------- /regress/conf/escaped2.in.conf: -------------------------------------------------------------------------------- 1 | logfile=a\#bc#d 2 | -------------------------------------------------------------------------------- /regress/conf/escaped2.out.conf: -------------------------------------------------------------------------------- 1 | logfile=a#bc 2 | debug=0 3 | -------------------------------------------------------------------------------- /regress/conf/escaped3.in.conf: -------------------------------------------------------------------------------- 1 | logfile=a\##def 2 | -------------------------------------------------------------------------------- /regress/conf/escaped3.out.conf: -------------------------------------------------------------------------------- 1 | logfile=a# 2 | debug=0 3 | -------------------------------------------------------------------------------- /regress/conf/hash.in.conf: -------------------------------------------------------------------------------- 1 | debug=1 # blah blah 2 | -------------------------------------------------------------------------------- /regress/conf/hash.out.conf: -------------------------------------------------------------------------------- 1 | debug=1 2 | -------------------------------------------------------------------------------- /regress/conf/hash2.in.conf: -------------------------------------------------------------------------------- 1 | debug=2# blah blah 2 | -------------------------------------------------------------------------------- /regress/conf/hash2.out.conf: -------------------------------------------------------------------------------- 1 | debug=2 2 | -------------------------------------------------------------------------------- /regress/conf/hash3.in.conf: -------------------------------------------------------------------------------- 1 | logfile=foo#bar#baz 2 | -------------------------------------------------------------------------------- /regress/conf/hash3.out.conf: -------------------------------------------------------------------------------- 1 | logfile=foo 2 | debug=0 3 | -------------------------------------------------------------------------------- /regress/conf/hash4.in.conf: -------------------------------------------------------------------------------- 1 | logfile=#foo 2 | -------------------------------------------------------------------------------- /regress/conf/hash4.out.conf: -------------------------------------------------------------------------------- 1 | debug=0 2 | -------------------------------------------------------------------------------- /regress/conf/kcaldav.example.in.conf: -------------------------------------------------------------------------------- 1 | # Instead of logging to stderr (usually stored in the web server's 2 | # error.log), log to a specific file. 3 | logfile=/logs/kcaldav.log 4 | 5 | # Set debug=3 to produce debugging information. 6 | # Set debug=2 for even more debugging information. 7 | # Set debug=3 to also trace network activity. 8 | debug=3 9 | -------------------------------------------------------------------------------- /regress/conf/kcaldav.example.out.conf: -------------------------------------------------------------------------------- 1 | logfile=/logs/kcaldav.log 2 | debug=3 3 | -------------------------------------------------------------------------------- /regress/conf/spaces.in.conf: -------------------------------------------------------------------------------- 1 | logfile= hi 2 | debug = 3 3 | -------------------------------------------------------------------------------- /regress/conf/spaces.out.conf: -------------------------------------------------------------------------------- 1 | logfile=hi 2 | debug=3 3 | -------------------------------------------------------------------------------- /regress/conf/spaces2.in.conf: -------------------------------------------------------------------------------- 1 | logfile =bar 2 | 3 | 4 | 5 | 6 | debug= 2 7 | 8 | -------------------------------------------------------------------------------- /regress/conf/spaces2.out.conf: -------------------------------------------------------------------------------- 1 | logfile=bar 2 | debug=2 3 | -------------------------------------------------------------------------------- /regress/ical/1106817412.ics: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kristapsdz/kcaldav/6111ef251a6633a399265d3b6ee03391da0adccf/regress/ical/1106817412.ics -------------------------------------------------------------------------------- /regress/ical/3.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VTODO 5 | DTSTAMP:19980130T134500Z 6 | SEQUENCE:2 7 | UID:uid4@host1.com 8 | ORGANIZER:MAILTO:unclesam@us.gov 9 | ATTENDEE;PARTSTAT=ACCEPTED:MAILTO:jqpublic@host.com 10 | DUE:19980415T235959 11 | STATUS:NEEDS-ACTION 12 | SUMMARY:Submit Income Taxes 13 | BEGIN:VALARM 14 | ACTION:AUDIO 15 | TRIGGER;VALUE=DATE-TIME:19980403T120000Z 16 | ATTACH;FMTTYPE=audio/basic:http://host.com/pub/audio-files/ssbanner.aud 17 | REPEAT:4 18 | DURATION:PT1H 19 | END:VALARM 20 | END:VTODO 21 | END:VCALENDAR 22 | -------------------------------------------------------------------------------- /regress/ical/4.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VJOURNAL 5 | DTSTAMP:19970324T120000Z 6 | UID:uid5@host1.com 7 | ORGANIZER:MAILTO:jsmith@host.com 8 | STATUS:DRAFT 9 | CLASS:PUBLIC 10 | CATEGORIES:Project Report, XYZ: Weekly Meeting 11 | DESCRIPTION:Project xyz Review Meeting Minutes\n 12 | Agenda\n1. Review of project version 1.0 requirements.\n2. 13 | Definition 14 | of project processes.\n3. Review of project schedule.\n 15 | Participants: John Smith\, Jane Doe\, Jim Dandy\n-It was 16 | decided that the requirements need to be signed off by 17 | product marketing.\n-Project processes were accepted.\n 18 | -Project schedule needs to account for scheduled holidays 19 | and employee vacation time. Check with HR for specific 20 | dates.\n-New schedule will be distributed by Friday.\n- 21 | Next weeks meeting is cancelled. No meeting until 3/23. 22 | END:VJOURNAL 23 | END:VCALENDAR 24 | -------------------------------------------------------------------------------- /regress/ical/6.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | METHOD:PUBLISH 3 | PRODID:-//ACME/DesktopCalendar//EN 4 | VERSION:2.0 5 | BEGIN:VEVENT 6 | ORGANIZER:mailto:a@example.com 7 | DTSTART:19970701T200000Z 8 | DTSTAMP:19970611T190000Z 9 | SUMMARY:ST. PAUL SAINTS -VS- DULUTH-SUPERIOR DUKES 10 | UID:0981234-1234234-23@example.com 11 | END:VEVENT 12 | END:VCALENDAR 13 | -------------------------------------------------------------------------------- /regress/ical/7.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | METHOD:PUBLISH 3 | VERSION:2.0 4 | PRODID:-//ACME/DesktopCalendar//EN 5 | BEGIN:VEVENT 6 | ORGANIZER:mailto:a@example.com 7 | DTSTAMP:19970612T190000Z 8 | DTSTART:19970701T210000Z 9 | DTEND:19970701T230000Z 10 | SEQUENCE:1 11 | UID:0981234-1234234-23@example.com 12 | SUMMARY:ST. PAUL SAINTS -VS- DULUTH-SUPERIOR DUKES 13 | END:VEVENT 14 | END:VCALENDAR 15 | -------------------------------------------------------------------------------- /regress/ical/ArgentinaHolidays.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION 3 | :2.0 4 | PRODID 5 | :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN 6 | METHOD 7 | :PUBLISH 8 | BEGIN:VEVENT 9 | UID 10 | :fea1e92e-5d8c-11d9-a7f1-fac9cd297670 11 | SUMMARY 12 | :Año Nuevo 13 | DESCRIPTION 14 | :Año Nuevo. Ley 21.329 15 | CATEGORIES 16 | :Public Holiday 17 | URL 18 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 19 | STATUS 20 | :CONFIRMED 21 | CLASS 22 | :PUBLIC 23 | X-MOZILLA-ALARM-DEFAULT-LENGTH 24 | :0 25 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 26 | :0 27 | DTSTART 28 | ;VALUE=DATE 29 | :20050101 30 | DTEND 31 | ;VALUE=DATE 32 | :20050102 33 | DTSTAMP 34 | :20050103T133937Z 35 | LAST-MODIFIED 36 | :20050103T135745Z 37 | END:VEVENT 38 | BEGIN:VEVENT 39 | UID 40 | :12a7e90a-5d8d-11d9-80c8-f19446aa65b2 41 | SUMMARY 42 | :Viernes Santo 43 | DESCRIPTION 44 | :Viernes Santo. Ley 21.329 45 | CATEGORIES 46 | :Public Holiday 47 | URL 48 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 49 | STATUS 50 | :CONFIRMED 51 | CLASS 52 | :PUBLIC 53 | X-MOZILLA-ALARM-DEFAULT-LENGTH 54 | :0 55 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 56 | :0 57 | DTSTART 58 | ;VALUE=DATE 59 | :20050325 60 | DTEND 61 | ;VALUE=DATE 62 | :20050326 63 | DTSTAMP 64 | :20050103T134021Z 65 | LAST-MODIFIED 66 | :20050103T135753Z 67 | END:VEVENT 68 | BEGIN:VEVENT 69 | UID 70 | :e216e164-5d8d-11d9-9254-835ffdc285ef 71 | SUMMARY 72 | :Día del Veterano y de los Caídos en la Guerra de Malvinas 73 | DESCRIPTION 74 | :Día del Veterano y de los Caídos en la Guerra de Malvinas. Ley 25.370 75 | CATEGORIES 76 | :Public Holiday 77 | URL 78 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 79 | STATUS 80 | :CONFIRMED 81 | CLASS 82 | :PUBLIC 83 | X-MOZILLA-ALARM-DEFAULT-LENGTH 84 | :0 85 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 86 | :0 87 | DTSTART 88 | ;VALUE=DATE 89 | :20050402 90 | DTEND 91 | ;VALUE=DATE 92 | :20050403 93 | DTSTAMP 94 | :20050103T134554Z 95 | LAST-MODIFIED 96 | :20050103T135758Z 97 | END:VEVENT 98 | BEGIN:VEVENT 99 | UID 100 | :2ca1678c-5d8d-11d9-b56a-a74a56d6c5b9 101 | SUMMARY 102 | :Día del Trabajador 103 | DESCRIPTION 104 | :Día del Trabajador. Ley 21.329 105 | CATEGORIES 106 | :Public Holiday 107 | URL 108 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 109 | STATUS 110 | :CONFIRMED 111 | CLASS 112 | :PUBLIC 113 | X-MOZILLA-ALARM-DEFAULT-LENGTH 114 | :0 115 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 116 | :0 117 | DTSTART 118 | ;VALUE=DATE 119 | :20050501 120 | DTEND 121 | ;VALUE=DATE 122 | :20050502 123 | DTSTAMP 124 | :20050103T134103Z 125 | LAST-MODIFIED 126 | :20050103T135806Z 127 | END:VEVENT 128 | BEGIN:VEVENT 129 | UID 130 | :3df3fd74-5d8d-11d9-b506-f0df72b6ade9 131 | SUMMARY 132 | :Primer Gobierno Patrio 133 | DESCRIPTION 134 | :Primer Gobierno Patrio. Ley 21.329 135 | CATEGORIES 136 | :Public Holiday 137 | URL 138 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 139 | STATUS 140 | :CONFIRMED 141 | CLASS 142 | :PUBLIC 143 | X-MOZILLA-ALARM-DEFAULT-LENGTH 144 | :0 145 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 146 | :0 147 | DTSTART 148 | ;VALUE=DATE 149 | :20050525 150 | DTEND 151 | ;VALUE=DATE 152 | :20050526 153 | DTSTAMP 154 | :20050103T134134Z 155 | LAST-MODIFIED 156 | :20050103T135811Z 157 | END:VEVENT 158 | BEGIN:VEVENT 159 | UID 160 | :f52c13be-5d8d-11d9-91f1-880553cef864 161 | SUMMARY 162 | :Paso a la Inmortalidad del General Manuel Belgrano 163 | DESCRIPTION 164 | :Paso a la Inmortalidad del General Manuel Belgrano. Ley 24.445. 165 | CATEGORIES 166 | :Public Holiday 167 | URL 168 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 169 | STATUS 170 | :CONFIRMED 171 | CLASS 172 | :PUBLIC 173 | X-MOZILLA-ALARM-DEFAULT-LENGTH 174 | :0 175 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 176 | :0 177 | DTSTART 178 | ;VALUE=DATE 179 | :20050620 180 | DTEND 181 | ;VALUE=DATE 182 | :20050621 183 | DTSTAMP 184 | :20050103T134640Z 185 | LAST-MODIFIED 186 | :20050103T135818Z 187 | END:VEVENT 188 | BEGIN:VEVENT 189 | UID 190 | :4cfc10e0-5d8d-11d9-919f-d7902c7da69f 191 | SUMMARY 192 | :Día de la Independencia 193 | DESCRIPTION 194 | :Día de la Independencia. Ley 21.329 195 | CATEGORIES 196 | :Public Holiday 197 | URL 198 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 199 | STATUS 200 | :CONFIRMED 201 | CLASS 202 | :PUBLIC 203 | X-MOZILLA-ALARM-DEFAULT-LENGTH 204 | :0 205 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 206 | :0 207 | DTSTART 208 | ;VALUE=DATE 209 | :20050709 210 | DTEND 211 | ;VALUE=DATE 212 | :20050710 213 | DTSTAMP 214 | :20050103T134206Z 215 | LAST-MODIFIED 216 | :20050103T135823Z 217 | END:VEVENT 218 | BEGIN:VEVENT 219 | UID 220 | :3ac2b69e-5d8e-11d9-9742-e5d226c31d19 221 | SUMMARY 222 | :Paso a la Inmortalidad del General José de San Martín 223 | DESCRIPTION 224 | :Paso a la Inmortalidad del General José de San Martín. Este evento 225 | se conmemora el 17.08.2004\, pero se traslada al 15.08.2004 por Ley 226 | 24.445. 227 | CATEGORIES 228 | :Public Holiday 229 | URL 230 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 231 | STATUS 232 | :CONFIRMED 233 | CLASS 234 | :PUBLIC 235 | X-MOZILLA-ALARM-DEFAULT-LENGTH 236 | :0 237 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 238 | :0 239 | DTSTART 240 | ;VALUE=DATE 241 | :20050815 242 | DTEND 243 | ;VALUE=DATE 244 | :20050816 245 | DTSTAMP 246 | :20050103T134728Z 247 | LAST-MODIFIED 248 | :20050103T135830Z 249 | END:VEVENT 250 | BEGIN:VEVENT 251 | UID 252 | :6a4936a4-5d8e-11d9-a63a-eaba95aacf8d 253 | SUMMARY 254 | :Día de la Raza 255 | DESCRIPTION 256 | :Día de la Raza. Este evento se conmemora el día 12.10.2004\, pero 257 | se traslada al 10.10.2004 por Ley 23.555. 258 | CATEGORIES 259 | :Public Holiday 260 | URL 261 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 262 | STATUS 263 | :CONFIRMED 264 | CLASS 265 | :PUBLIC 266 | X-MOZILLA-ALARM-DEFAULT-LENGTH 267 | :0 268 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 269 | :0 270 | DTSTART 271 | ;VALUE=DATE 272 | :20051010 273 | DTEND 274 | ;VALUE=DATE 275 | :20051011 276 | DTSTAMP 277 | :20050103T134915Z 278 | LAST-MODIFIED 279 | :20050103T135835Z 280 | END:VEVENT 281 | BEGIN:VEVENT 282 | UID 283 | :5ed1c81e-5d8d-11d9-ac20-f482638f425b 284 | SUMMARY 285 | :Inmaculada Concepción de María 286 | DESCRIPTION 287 | :Inmaculada Concepción de María. Ley 24.445. 288 | CATEGORIES 289 | :Public Holiday 290 | URL 291 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 292 | STATUS 293 | :CONFIRMED 294 | CLASS 295 | :PUBLIC 296 | X-MOZILLA-ALARM-DEFAULT-LENGTH 297 | :0 298 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 299 | :0 300 | DTSTART 301 | ;VALUE=DATE 302 | :20051208 303 | DTEND 304 | ;VALUE=DATE 305 | :20051209 306 | DTSTAMP 307 | :20050103T134233Z 308 | LAST-MODIFIED 309 | :20050103T135842Z 310 | END:VEVENT 311 | BEGIN:VEVENT 312 | UID 313 | :6a2c1aac-5d8d-11d9-b952-bbe67e436903 314 | SUMMARY 315 | :Navidad 316 | DESCRIPTION 317 | :Navidad. Ley 21.329. 318 | CATEGORIES 319 | :Public Holiday 320 | URL 321 | :http://www.mininterior.gov.ar/servicios/feriados2005.asp 322 | STATUS 323 | :CONFIRMED 324 | CLASS 325 | :PUBLIC 326 | X-MOZILLA-ALARM-DEFAULT-LENGTH 327 | :0 328 | X-MOZILLA-RECUR-DEFAULT-INTERVAL 329 | :0 330 | DTSTART 331 | ;VALUE=DATE 332 | :20051225 333 | DTEND 334 | ;VALUE=DATE 335 | :20051226 336 | DTSTAMP 337 | :20050103T134300Z 338 | LAST-MODIFIED 339 | :20050103T135847Z 340 | END:VEVENT 341 | END:VCALENDAR 342 | -------------------------------------------------------------------------------- /regress/ical/Australian32Holidays.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | CALSCALE:GREGORIAN 3 | METHOD:PUBLISH 4 | PRODID:-//Apple Computer\, Inc//iCal 1.0//EN 5 | X-WR-CALNAME;VALUE=TEXT:Australian Holidays 6 | X-WR-RELCALID;VALUE=TEXT:D4167B74-C414-11D6-BA97-003065F198AC 7 | X-WR-TIMEZONE;VALUE=TEXT:Asia/Hong_Kong 8 | BEGIN:VTIMEZONE 9 | TZID:Asia/Hong_Kong 10 | LAST-MODIFIED:20060117T163657Z 11 | BEGIN:STANDARD 12 | DTSTART:19321213T204552 13 | TZOFFSETTO:+0800 14 | TZOFFSETFROM:+0000 15 | TZNAME:HKT 16 | END:STANDARD 17 | BEGIN:DAYLIGHT 18 | DTSTART:19460420T033000 19 | TZOFFSETTO:+0900 20 | TZOFFSETFROM:+0800 21 | TZNAME:HKST 22 | END:DAYLIGHT 23 | BEGIN:STANDARD 24 | DTSTART:19461201T033000 25 | TZOFFSETTO:+0800 26 | TZOFFSETFROM:+0900 27 | TZNAME:HKT 28 | END:STANDARD 29 | END:VTIMEZONE 30 | VERSION:2.0 31 | BEGIN:VEVENT 32 | UID:D416469E-C414-11D6-BA97-003065F198AC 33 | DTSTAMP:20020906T094459Z 34 | SUMMARY:Australia Day 35 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=1 36 | DTSTART;VALUE=DATE:20020126 37 | DTEND;VALUE=DATE:20020127 38 | END:VEVENT 39 | BEGIN:VEVENT 40 | UID:D4164CA4-C414-11D6-BA97-003065F198AC 41 | DTSTAMP:20020906T094459Z 42 | SUMMARY:Good Friday 43 | DTSTART;VALUE=DATE:20020329 44 | DTEND;VALUE=DATE:20020330 45 | END:VEVENT 46 | BEGIN:VEVENT 47 | UID:D416509A-C414-11D6-BA97-003065F198AC 48 | DTSTAMP:20020906T094459Z 49 | SUMMARY:Easter Monday 50 | DTSTART;VALUE=DATE:20020401 51 | DTEND;VALUE=DATE:20020402 52 | END:VEVENT 53 | BEGIN:VEVENT 54 | UID:D41654CC-C414-11D6-BA97-003065F198AC 55 | DTSTAMP:20020906T094459Z 56 | SUMMARY:ANZAC Day 57 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=4 58 | DTSTART;VALUE=DATE:20020425 59 | DTEND;VALUE=DATE:20020426 60 | END:VEVENT 61 | BEGIN:VEVENT 62 | UID:D41658EB-C414-11D6-BA97-003065F198AC 63 | DTSTAMP:20020906T094459Z 64 | SUMMARY:Queen's Birthday 65 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=6 66 | DTSTART;VALUE=DATE:20020610 67 | DTEND;VALUE=DATE:20020611 68 | END:VEVENT 69 | BEGIN:VEVENT 70 | UID:D41661F7-C414-11D6-BA97-003065F198AC 71 | DTSTAMP:20020906T094459Z 72 | SUMMARY:Christmas 73 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=12 74 | DTSTART;VALUE=DATE:20021225 75 | DTEND;VALUE=DATE:20021226 76 | END:VEVENT 77 | BEGIN:VEVENT 78 | UID:D41666AF-C414-11D6-BA97-003065F198AC 79 | DTSTAMP:20020906T094459Z 80 | SUMMARY:Boxing Day 81 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=12 82 | DTSTART;VALUE=DATE:20021226 83 | DTEND;VALUE=DATE:20021227 84 | END:VEVENT 85 | BEGIN:VEVENT 86 | UID:D4166AA4-C414-11D6-BA97-003065F198AC 87 | DTSTAMP:20020906T094459Z 88 | SUMMARY:Good Friday 89 | DTSTART;VALUE=DATE:20030418 90 | DTEND;VALUE=DATE:20030419 91 | END:VEVENT 92 | BEGIN:VEVENT 93 | UID:D4166EA4-C414-11D6-BA97-003065F198AC 94 | DTSTAMP:20020906T094459Z 95 | SUMMARY:Easter Monday 96 | DTSTART;VALUE=DATE:20030421 97 | DTEND;VALUE=DATE:20030422 98 | END:VEVENT 99 | BEGIN:VEVENT 100 | UID:D41658EB-C414-11D6-BA97-003065F198AC 101 | DTSTAMP:20020906T094500Z 102 | RECURRENCE-ID;TZID=Asia/Hong_Kong:20030610T000000 103 | DTSTART;VALUE=DATE:20030609 104 | DTEND;VALUE=DATE:20030610 105 | END:VEVENT 106 | BEGIN:VEVENT 107 | UID:D41672C8-C414-11D6-BA97-003065F198AC 108 | DTSTAMP:20020906T094500Z 109 | SUMMARY:New Year 110 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=1 111 | DTSTART;VALUE=DATE:20020101 112 | DTEND;VALUE=DATE:20020102 113 | END:VEVENT 114 | END:VCALENDAR 115 | -------------------------------------------------------------------------------- /regress/ical/Belgische32feestdagen.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | X-WR-CALNAME:Belgische feestdagen 4 | PRODID:-//Apple Computer\, Inc//iCal 1.5//EN 5 | X-WR-RELCALID:440DCB50-039E-11D8-88DC-000A957CAA38-CALP 6 | X-WR-TIMEZONE:Europe/Brussels 7 | CALSCALE:GREGORIAN 8 | X-WR-CALDESC:Alle officiële Belgische feestdagen van 2001 tot en met 200 9 | 5. 10 | BEGIN:VEVENT 11 | DTSTART;VALUE=DATE:20041101 12 | DTEND;VALUE=DATE:20041102 13 | SUMMARY:Allerheiligen 14 | UID:8684B909-1F33-11D7-B218-000393A91E82-RID 15 | END:VEVENT 16 | BEGIN:VEVENT 17 | DTSTART;VALUE=DATE:20050101 18 | DTEND;VALUE=DATE:20050102 19 | SUMMARY:Nieuwjaar 20 | UID:868590B6-1F33-11D7-B218-000393A91E82-RID 21 | END:VEVENT 22 | BEGIN:VEVENT 23 | DTSTART;VALUE=DATE:20040520 24 | DTEND;VALUE=DATE:20040521 25 | SUMMARY:O.-L.-Heer Hemelvaart 26 | UID:8684D7A0-1F33-11D7-B218-000393A91E82-RID 27 | END:VEVENT 28 | BEGIN:VEVENT 29 | DTSTART;VALUE=DATE:20050711 30 | DTEND;VALUE=DATE:20050712 31 | SUMMARY:Feest van de Vlaamse Gemeenschap 32 | UID:86850D80-1F33-11D7-B218-000393A91E82-RID 33 | END:VEVENT 34 | BEGIN:VEVENT 35 | DTSTART;VALUE=DATE:20041115 36 | DTEND;VALUE=DATE:20041116 37 | SUMMARY:Feest van de Dynastie 38 | UID:86856160-1F33-11D7-B218-000393A91E82-RID 39 | END:VEVENT 40 | BEGIN:VEVENT 41 | DTSTART;VALUE=DATE:20040721 42 | DTEND;VALUE=DATE:20040722 43 | SUMMARY:Nationale Feestdag 44 | UID:86857F3C-1F33-11D7-B218-000393A91E82-RID 45 | END:VEVENT 46 | BEGIN:VEVENT 47 | DTSTART;VALUE=DATE:20040501 48 | DTEND;VALUE=DATE:20040502 49 | SUMMARY:Feest van de Arbeid 50 | UID:86857095-1F33-11D7-B218-000393A91E82-RID 51 | END:VEVENT 52 | BEGIN:VEVENT 53 | DTSTART;VALUE=DATE:20050721 54 | DTEND;VALUE=DATE:20050722 55 | SUMMARY:Nationale Feestdag 56 | UID:86858207-1F33-11D7-B218-000393A91E82-RID 57 | END:VEVENT 58 | BEGIN:VEVENT 59 | DTSTART;VALUE=DATE:20041225 60 | DTEND;VALUE=DATE:20041226 61 | SUMMARY:Christmas Day 62 | UID:8685BD6D-1F33-11D7-B218-000393A91E82-RID 63 | END:VEVENT 64 | BEGIN:VEVENT 65 | DTSTART;VALUE=DATE:20051115 66 | DTEND;VALUE=DATE:20051116 67 | SUMMARY:Feest van de Dynastie 68 | UID:8685648E-1F33-11D7-B218-000393A91E82-RID 69 | END:VEVENT 70 | BEGIN:VEVENT 71 | DTSTART;VALUE=DATE:20040711 72 | DTEND;VALUE=DATE:20040712 73 | SUMMARY:Feest van de Vlaamse Gemeenschap 74 | UID:86850AA0-1F33-11D7-B218-000393A91E82-RID 75 | END:VEVENT 76 | BEGIN:VEVENT 77 | DTSTART;VALUE=DATE:20050501 78 | DTEND;VALUE=DATE:20050502 79 | SUMMARY:Feest van de Arbeid 80 | UID:86857376-1F33-11D7-B218-000393A91E82-RID 81 | END:VEVENT 82 | BEGIN:VEVENT 83 | DTSTART;VALUE=DATE:20051101 84 | DTEND;VALUE=DATE:20051102 85 | SUMMARY:Allerheiligen 86 | UID:8684BC36-1F33-11D7-B218-000393A91E82-RID 87 | END:VEVENT 88 | BEGIN:VEVENT 89 | DTSTART;VALUE=DATE:20050327 90 | DTEND;VALUE=DATE:20050328 91 | SUMMARY:Pasen 92 | UID:8685327B-1F33-11D7-B218-000393A91E82-RID 93 | END:VEVENT 94 | BEGIN:VEVENT 95 | DTSTART;VALUE=DATE:20040531 96 | DTEND;VALUE=DATE:20040601 97 | SUMMARY:Pinkstermaandag 98 | UID:86859C8A-1F33-11D7-B218-000393A91E82-RID 99 | END:VEVENT 100 | BEGIN:VEVENT 101 | DTSTART;VALUE=DATE:20051111 102 | DTEND;VALUE=DATE:20051112 103 | SUMMARY:Wapenstilstand 104 | UID:8684CB8D-1F33-11D7-B218-000393A91E82-RID 105 | END:VEVENT 106 | BEGIN:VEVENT 107 | DTSTART;VALUE=DATE:20051225 108 | DTEND;VALUE=DATE:20051226 109 | SUMMARY:Kerstmis 110 | UID:8684FEAD-1F33-11D7-B218-000393A91E82-RID 111 | END:VEVENT 112 | BEGIN:VEVENT 113 | DTSTART;VALUE=DATE:20041225 114 | DTEND;VALUE=DATE:20041226 115 | SUMMARY:Kerstmis 116 | UID:8684FB9D-1F33-11D7-B218-000393A91E82-RID 117 | END:VEVENT 118 | BEGIN:VEVENT 119 | DTSTART;VALUE=DATE:20050927 120 | DTEND;VALUE=DATE:20050928 121 | SUMMARY:Feest van de Waalse Gemeenschap 122 | UID:868523A1-1F33-11D7-B218-000393A91E82-RID 123 | END:VEVENT 124 | BEGIN:VEVENT 125 | DTSTART;VALUE=DATE:20050516 126 | DTEND;VALUE=DATE:20050517 127 | SUMMARY:Pinkstermaandag 128 | UID:86859F92-1F33-11D7-B218-000393A91E82-RID 129 | END:VEVENT 130 | BEGIN:VEVENT 131 | DTSTART;VALUE=DATE:20050505 132 | DTEND;VALUE=DATE:20050506 133 | SUMMARY:O.-L.-Heer Hemelvaart 134 | UID:8684DA8A-1F33-11D7-B218-000393A91E82-RID 135 | END:VEVENT 136 | BEGIN:VEVENT 137 | DTSTART;VALUE=DATE:20040411 138 | DTEND;VALUE=DATE:20040412 139 | SUMMARY:Pasen 140 | UID:86852F70-1F33-11D7-B218-000393A91E82-RID 141 | END:VEVENT 142 | BEGIN:VEVENT 143 | DTSTART;VALUE=DATE:20040927 144 | DTEND;VALUE=DATE:20040928 145 | SUMMARY:Feest van de Waalse Gemeenschap 146 | UID:86852086-1F33-11D7-B218-000393A91E82-RID 147 | END:VEVENT 148 | BEGIN:VEVENT 149 | DTSTART;VALUE=DATE:20050328 150 | DTEND;VALUE=DATE:20050329 151 | SUMMARY:Paasmaandag 152 | UID:868542CD-1F33-11D7-B218-000393A91E82-RID 153 | END:VEVENT 154 | BEGIN:VEVENT 155 | DTSTART;VALUE=DATE:20041111 156 | DTEND;VALUE=DATE:20041112 157 | SUMMARY:Wapenstilstand 158 | UID:8684C881-1F33-11D7-B218-000393A91E82-RID 159 | END:VEVENT 160 | BEGIN:VEVENT 161 | DTSTART;VALUE=DATE:20040412 162 | DTEND;VALUE=DATE:20040413 163 | SUMMARY:Paasmaandag 164 | UID:86853FA8-1F33-11D7-B218-000393A91E82-RID 165 | END:VEVENT 166 | BEGIN:VEVENT 167 | DTSTART;VALUE=DATE:20050815 168 | DTEND;VALUE=DATE:20050816 169 | SUMMARY:Maria Tenhemelopneming 170 | UID:8684EE84-1F33-11D7-B218-000393A91E82-RID 171 | END:VEVENT 172 | BEGIN:VEVENT 173 | DTSTART;VALUE=DATE:20050515 174 | DTEND;VALUE=DATE:20050516 175 | SUMMARY:Pinksteren 176 | UID:8685B0B5-1F33-11D7-B218-000393A91E82-RID 177 | END:VEVENT 178 | BEGIN:VEVENT 179 | DTSTART;VALUE=DATE:20040530 180 | DTEND;VALUE=DATE:20040531 181 | SUMMARY:Pinksteren 182 | UID:8685AD9E-1F33-11D7-B218-000393A91E82-RID 183 | END:VEVENT 184 | BEGIN:VEVENT 185 | DTSTART;VALUE=DATE:20040815 186 | DTEND;VALUE=DATE:20040816 187 | SUMMARY:Maria Tenhemelopneming 188 | UID:8684E6C3-1F33-11D7-B218-000393A91E82-RID 189 | END:VEVENT 190 | END:VCALENDAR 191 | -------------------------------------------------------------------------------- /regress/ical/Buddhist.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | CALSCALE:GREGORIAN 3 | X-WR-TIMEZONE;VALUE=TEXT:US/Central 4 | PRODID:-//Apple Computer\, Inc//iCal 1.0//EN 5 | X-WR-RELCALID;VALUE=TEXT:5953A75C-28B8-11D7-B700-00306568757E-CALP 6 | X-WR-CALNAME;VALUE=TEXT:Buddhist 7 | VERSION:2.0 8 | BEGIN:VEVENT 9 | UID:6DB7B360-28B8-11D7-B700-00306568757E-RID 10 | DTSTAMP:20030115T183830Z 11 | SUMMARY:Buddha's Death and entrance to Nirvana. 12 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=2 13 | DTSTART;VALUE=DATE:20030215 14 | DTEND;VALUE=DATE:20030216 15 | END:VEVENT 16 | BEGIN:VEVENT 17 | UID:9C993136-28B8-11D7-B700-00306568757E-RID 18 | DTSTAMP:20030115T183928Z 19 | SUMMARY:Buddha's Birth 20 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=4 21 | DTSTART;VALUE=DATE:20030408 22 | DTEND;VALUE=DATE:20030409 23 | END:VEVENT 24 | BEGIN:VEVENT 25 | UID:BF95BD76-28B8-11D7-B700-00306568757E-RID 26 | DTSTAMP:20030115T184016Z 27 | SUMMARY:Buddha's Enlightenment 28 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=12 29 | DTSTART;VALUE=DATE:20031208 30 | DTEND;VALUE=DATE:20031209 31 | END:VEVENT 32 | BEGIN:VEVENT 33 | UID:74F0D26E-28B9-11D7-B700-00306568757E-RID 34 | DTSTAMP:20030115T184654Z 35 | SUMMARY:Day of Turning the Wheel of Teaching (Tib Chö-kor Düchen). 36 | DTSTART;VALUE=DATE:20020714 37 | DTEND;VALUE=DATE:20020715 38 | END:VEVENT 39 | END:VCALENDAR 40 | -------------------------------------------------------------------------------- /regress/ical/EXDATE-IN-UTC.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//PYVOBJECT//NONSGML Version 1//EN 4 | BEGIN:VEVENT 5 | UID:2a28c9d8-03d9-11dc-e7a0-e15339cb8fa7 6 | DTSTART:20070508T051500Z 7 | DURATION:PT1H 8 | DTSTAMP:20070516T181406Z 9 | RRULE:FREQ=WEEKLY;UNTIL=20090102T055900Z 10 | EXDATE:20070515T101500Z,20070522T101500Z 11 | STATUS:CONFIRMED 12 | SUMMARY:New Event 13 | END:VEVENT 14 | END:VCALENDAR 15 | -------------------------------------------------------------------------------- /regress/ical/EXDATE.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | X-WR-CALNAME:EXDATE Example 4 | PRODID:-//Apple Computer\, Inc//iCal 2.0//EN 5 | X-WR-RELCALID:6E3F1EC4-081F-4DBF-8261-8938E9B32A70 6 | X-WR-TIMEZONE:Australia/Brisbane 7 | CALSCALE:GREGORIAN 8 | METHOD:PUBLISH 9 | BEGIN:VTIMEZONE 10 | TZID:Australia/Brisbane 11 | LAST-MODIFIED:20051209T055354Z 12 | BEGIN:STANDARD 13 | DTSTART:19321213T204552 14 | TZOFFSETTO:+1000 15 | TZOFFSETFROM:+0000 16 | TZNAME:EST 17 | END:STANDARD 18 | BEGIN:DAYLIGHT 19 | DTSTART:19420101T030000 20 | TZOFFSETTO:+1100 21 | TZOFFSETFROM:+1000 22 | TZNAME:EST 23 | END:DAYLIGHT 24 | BEGIN:STANDARD 25 | DTSTART:19420329T020000 26 | TZOFFSETTO:+1000 27 | TZOFFSETFROM:+1100 28 | TZNAME:EST 29 | END:STANDARD 30 | BEGIN:DAYLIGHT 31 | DTSTART:19420927T030000 32 | TZOFFSETTO:+1100 33 | TZOFFSETFROM:+1000 34 | TZNAME:EST 35 | END:DAYLIGHT 36 | BEGIN:STANDARD 37 | DTSTART:19430328T020000 38 | TZOFFSETTO:+1000 39 | TZOFFSETFROM:+1100 40 | TZNAME:EST 41 | END:STANDARD 42 | BEGIN:DAYLIGHT 43 | DTSTART:19431003T030000 44 | TZOFFSETTO:+1100 45 | TZOFFSETFROM:+1000 46 | TZNAME:EST 47 | END:DAYLIGHT 48 | BEGIN:STANDARD 49 | DTSTART:19440326T020000 50 | TZOFFSETTO:+1000 51 | TZOFFSETFROM:+1100 52 | TZNAME:EST 53 | END:STANDARD 54 | BEGIN:DAYLIGHT 55 | DTSTART:19711031T030000 56 | TZOFFSETTO:+1100 57 | TZOFFSETFROM:+1000 58 | TZNAME:EST 59 | END:DAYLIGHT 60 | BEGIN:STANDARD 61 | DTSTART:19720227T030000 62 | TZOFFSETTO:+1000 63 | TZOFFSETFROM:+1100 64 | TZNAME:EST 65 | END:STANDARD 66 | BEGIN:DAYLIGHT 67 | DTSTART:19891029T030000 68 | TZOFFSETTO:+1100 69 | TZOFFSETFROM:+1000 70 | TZNAME:EST 71 | END:DAYLIGHT 72 | BEGIN:STANDARD 73 | DTSTART:19900304T030000 74 | TZOFFSETTO:+1000 75 | TZOFFSETFROM:+1100 76 | TZNAME:EST 77 | END:STANDARD 78 | BEGIN:DAYLIGHT 79 | DTSTART:19901028T030000 80 | TZOFFSETTO:+1100 81 | TZOFFSETFROM:+1000 82 | TZNAME:EST 83 | END:DAYLIGHT 84 | BEGIN:STANDARD 85 | DTSTART:19910303T030000 86 | TZOFFSETTO:+1000 87 | TZOFFSETFROM:+1100 88 | TZNAME:EST 89 | END:STANDARD 90 | BEGIN:DAYLIGHT 91 | DTSTART:19911027T030000 92 | TZOFFSETTO:+1100 93 | TZOFFSETFROM:+1000 94 | TZNAME:EST 95 | END:DAYLIGHT 96 | BEGIN:STANDARD 97 | DTSTART:19920301T030000 98 | TZOFFSETTO:+1000 99 | TZOFFSETFROM:+1100 100 | TZNAME:EST 101 | END:STANDARD 102 | END:VTIMEZONE 103 | BEGIN:VEVENT 104 | DURATION:PT1H 105 | DTSTAMP:20051209T055346Z 106 | EXDATE;TZID=Australia/Brisbane:20060103T120000 107 | EXDATE;TZID=Australia/Brisbane:20060104T120000 108 | UID:DDC5B090-1B46-4C1D-8A3C-D305516A0B90 109 | SEQUENCE:9 110 | DTSTART;TZID=Australia/Brisbane:20060101T120000 111 | SUMMARY:Repeating Event 112 | DESCRIPTION:This is a simple repeating event with a couple of days exclu 113 | ded. 114 | RRULE:FREQ=DAILY;INTERVAL=1;COUNT=7 115 | END:VEVENT 116 | END:VCALENDAR 117 | -------------------------------------------------------------------------------- /regress/ical/Session6.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN 3 | VERSION:2.0 4 | METHOD:PUBLISH 5 | X-MS-OLK-FORCEINSPECTOROPEN:TRUE 6 | BEGIN:VEVENT 7 | CLASS:PUBLIC 8 | CREATED:20061005T211037Z 9 | DESCRIPTION:Session #6: Signature distribution overview 10 | 3/14\, 9 a.m. (PST)\nhttps://www.livemeeting.com 11 | /cc/microsoft/join?id=4N3J77&role=attend&pw=Forefront+Client+Security\nMee 12 | ting ID: 4N3J77\nAttendee Meeting Key: Forefront Client Security\n\nToll- 13 | free: (866) 500-6738\nInternational: +001 (203) 480-8000\nParticipant p 14 | asscode: 458846\n\n 15 | DTEND:20070314T180000Z 16 | DTSTAMP:20061005T211037Z 17 | DTSTART:20070314T170000Z 18 | LAST-MODIFIED:20061005T211037Z 19 | PRIORITY:5 20 | SEQUENCE:0 21 | SUMMARY;LANGUAGE=en-us:Session #6: Signature distribution overview 22 | 23 | 24 | 25 | TRANSP:OPAQUE 26 | UID:040000008200E00074C5B7101A82E00800000000B036B088A7E8C601000000000000000 27 | 010000000F6E9BBD8393FE04E9FB949C12B24C7F9 28 | X-ALT-DESC;FMTTYPE=text/html:\n\n\n\n\n\n\n\n\n

Session #6:  Signature distr 35 | ibution overview                              36 |                 3/14\, 9 a.m. (PST)

\n\n

https://www.livemeeting.com/ 41 | cc/microsoft/join?id=4N3J77&\;role=attend&\;pw=Forefront+Client+Secu 42 | rity

\n\n

Meeting ID: 45 | 4N3J77

\n\n

Attendee Meeting Key:  Forefront Client Securit 47 | y 48 |

\n\n

\n\n

Toll-free:   (866) 51 | 500-6738

\n\n

International:  +001 (203) 480-8000

\n\n

Participant passcode: 54 |   458846

\n\n

\n 55 | \n\n 56 | X-MICROSOFT-CDO-BUSYSTATUS:BUSY 57 | X-MICROSOFT-CDO-IMPORTANCE:1 58 | X-MICROSOFT-DISALLOW-COUNTER:FALSE 59 | X-MS-OLK-ALLOWEXTERNCHECK:TRUE 60 | X-MS-OLK-CONFTYPE:0 61 | BEGIN:VALARM 62 | TRIGGER:-PT15M 63 | ACTION:DISPLAY 64 | DESCRIPTION:Reminder 65 | END:VALARM 66 | END:VEVENT 67 | END:VCALENDAR 68 | -------------------------------------------------------------------------------- /regress/ical/Standup.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN 3 | VERSION:2.0 4 | METHOD:PUBLISH 5 | BEGIN:VTIMEZONE 6 | TZID:Canberra, Melbourne, Sydney 7 | BEGIN:STANDARD 8 | DTSTART:20080406T030000 9 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=4 10 | TZOFFSETFROM:+1100 11 | TZOFFSETTO:+1000 12 | TZNAME:Standard Time 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:20081005T020000 16 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=10 17 | TZOFFSETFROM:+1000 18 | TZOFFSETTO:+1100 19 | TZNAME:Daylight Savings Time 20 | END:DAYLIGHT 21 | END:VTIMEZONE 22 | BEGIN:VEVENT 23 | ORGANIZER:MAILTO:Ben.Fortuna@example.com 24 | DTSTART;TZID="Canberra, Melbourne, Sydney":20090310T093000 25 | DTEND;TZID="Canberra, Melbourne, Sydney":20090310T094500 26 | RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;WKST=SU 27 | TRANSP:OPAQUE 28 | SEQUENCE:0 29 | UID:040000008200E00074C5B7101A82E008000000002079F2E4D4A3C9010000000000000000100 30 | 000006C4B4F5EBD28AD43BB7F772276780C54 31 | DTSTAMP:20090319T042432Z 32 | SUMMARY:Standup 33 | PRIORITY:5 34 | X-MICROSOFT-CDO-IMPORTANCE:1 35 | CLASS:PUBLIC 36 | BEGIN:VALARM 37 | TRIGGER:-PT5M 38 | ACTION:DISPLAY 39 | DESCRIPTION:Reminder 40 | END:VALARM 41 | END:VEVENT 42 | END:VCALENDAR 43 | -------------------------------------------------------------------------------- /regress/ical/bears.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | X-WR-CALNAME:2005 Chicago Bears Schedule 4 | PRODID:-//Apple Computer\, Inc//iCal 1.5//EN 5 | X-WR-RELCALID:202B7038-AFA2-11D9-A2CD-000A95AD128C 6 | X-WR-TIMEZONE:Canada/Mountain 7 | CALSCALE:GREGORIAN 8 | METHOD:PUBLISH 9 | BEGIN:VTIMEZONE 10 | TZID:Canada/Mountain 11 | LAST-MODIFIED:20050418T003804Z 12 | BEGIN:DAYLIGHT 13 | DTSTART:20050403T090000 14 | TZOFFSETTO:-0600 15 | TZOFFSETFROM:+0000 16 | TZNAME:MDT 17 | END:DAYLIGHT 18 | BEGIN:STANDARD 19 | DTSTART:20051030T020000 20 | TZOFFSETTO:-0700 21 | TZOFFSETFROM:-0600 22 | TZNAME:MST 23 | END:STANDARD 24 | BEGIN:DAYLIGHT 25 | DTSTART:20060402T010000 26 | TZOFFSETTO:-0600 27 | TZOFFSETFROM:-0700 28 | TZNAME:MDT 29 | END:DAYLIGHT 30 | END:VTIMEZONE 31 | BEGIN:VEVENT 32 | DTSTART;TZID=Canada/Mountain:20050808T180000 33 | DTEND;TZID=Canada/Mountain:20050808T210000 34 | SUMMARY:Dolphins @ Bears 35 | UID:202B352E-AFA2-11D9-A2CD-000A95AD128C 36 | SEQUENCE:2 37 | DTSTAMP:20050418T000046Z 38 | DESCRIPTION:Preseason 39 | END:VEVENT 40 | BEGIN:VEVENT 41 | DTSTART;TZID=Canada/Mountain:20050812T180000 42 | DTEND;TZID=Canada/Mountain:20050812T210000 43 | SUMMARY:Bears @ Rams 44 | UID:202B39C2-AFA2-11D9-A2CD-000A95AD128C 45 | SEQUENCE:2 46 | DTSTAMP:20050418T000056Z 47 | DESCRIPTION:Preseason 48 | END:VEVENT 49 | BEGIN:VEVENT 50 | DTSTART;TZID=Canada/Mountain:20050820T180000 51 | DTEND;TZID=Canada/Mountain:20050820T210000 52 | SUMMARY:Bears @ Colts 53 | UID:202B3BCB-AFA2-11D9-A2CD-000A95AD128C 54 | SEQUENCE:2 55 | DTSTAMP:20050418T000107Z 56 | DESCRIPTION:Preseason 57 | END:VEVENT 58 | BEGIN:VEVENT 59 | DTSTART;TZID=Canada/Mountain:20050826T180000 60 | DTEND;TZID=Canada/Mountain:20050826T210000 61 | SUMMARY:Bills @ Bears 62 | UID:202B3DA8-AFA2-11D9-A2CD-000A95AD128C 63 | SEQUENCE:3 64 | DTSTAMP:20050418T000120Z 65 | DESCRIPTION:Preseason 66 | END:VEVENT 67 | BEGIN:VEVENT 68 | DTSTART;TZID=Canada/Mountain:20050901T180000 69 | DTEND;TZID=Canada/Mountain:20050901T210000 70 | SUMMARY:Browns @ Bears 71 | UID:202B3F83-AFA2-11D9-A2CD-000A95AD128C 72 | SEQUENCE:2 73 | DTSTAMP:20050418T000134Z 74 | DESCRIPTION:Preseason 75 | END:VEVENT 76 | BEGIN:VEVENT 77 | DTSTART;TZID=Canada/Mountain:20050911T110000 78 | DTEND;TZID=Canada/Mountain:20050911T140000 79 | SUMMARY:Bears @ Redskins 80 | UID:202B4156-AFA2-11D9-A2CD-000A95AD128C 81 | SEQUENCE:4 82 | DTSTAMP:20050418T000400Z 83 | DESCRIPTION:Week #1 84 | END:VEVENT 85 | BEGIN:VEVENT 86 | DTSTART;TZID=Canada/Mountain:20050918T110000 87 | DTEND;TZID=Canada/Mountain:20050918T140000 88 | SUMMARY:Lions @ Bears 89 | UID:202B4354-AFA2-11D9-A2CD-000A95AD128C 90 | SEQUENCE:4 91 | DTSTAMP:20050418T000354Z 92 | DESCRIPTION:Week #2 93 | END:VEVENT 94 | BEGIN:VEVENT 95 | DTSTART;TZID=Canada/Mountain:20050925T110000 96 | DTEND;TZID=Canada/Mountain:20050925T140000 97 | SUMMARY:Bengals @ Bears 98 | UID:202B4522-AFA2-11D9-A2CD-000A95AD128C 99 | SEQUENCE:4 100 | DTSTAMP:20050418T000509Z 101 | DESCRIPTION:Week #3 102 | END:VEVENT 103 | BEGIN:VEVENT 104 | DTSTART;TZID=Canada/Mountain:20051009T110000 105 | DTEND;TZID=Canada/Mountain:20051009T140000 106 | SUMMARY:Bears @ Browns 107 | UID:202B46E9-AFA2-11D9-A2CD-000A95AD128C 108 | SEQUENCE:4 109 | DTSTAMP:20050418T000809Z 110 | DESCRIPTION:Week #4 111 | END:VEVENT 112 | BEGIN:VEVENT 113 | DTSTART;TZID=Canada/Mountain:20051016T110000 114 | DTEND;TZID=Canada/Mountain:20051016T140000 115 | SUMMARY:Vikings @ Bears 116 | UID:202B48CF-AFA2-11D9-A2CD-000A95AD128C 117 | SEQUENCE:4 118 | DTSTAMP:20050418T000821Z 119 | DESCRIPTION:Week #5 120 | END:VEVENT 121 | BEGIN:VEVENT 122 | DTSTART;TZID=Canada/Mountain:20051023T141500 123 | DTEND;TZID=Canada/Mountain:20051023T171500 124 | SUMMARY:Ravens @ Bears 125 | UID:202B4AA6-AFA2-11D9-A2CD-000A95AD128C 126 | SEQUENCE:4 127 | DTSTAMP:20050418T000838Z 128 | DESCRIPTION:Week #6 129 | END:VEVENT 130 | BEGIN:VEVENT 131 | DTSTART;TZID=Canada/Mountain:20051030T110000 132 | DTEND;TZID=Canada/Mountain:20051030T140000 133 | SUMMARY:Bears @ Lions 134 | UID:202B4C7A-AFA2-11D9-A2CD-000A95AD128C 135 | SEQUENCE:4 136 | DTSTAMP:20050418T001042Z 137 | DESCRIPTION:Week #7 138 | END:VEVENT 139 | BEGIN:VEVENT 140 | DTSTART;TZID=Canada/Mountain:20051106T110000 141 | DTEND;TZID=Canada/Mountain:20051106T140000 142 | SUMMARY:Bears @ Saints 143 | UID:202B4E54-AFA2-11D9-A2CD-000A95AD128C 144 | SEQUENCE:4 145 | DTSTAMP:20050418T001115Z 146 | DESCRIPTION:Week #8 147 | END:VEVENT 148 | BEGIN:VEVENT 149 | DTSTART;TZID=Canada/Mountain:20051113T110000 150 | DTEND;TZID=Canada/Mountain:20051113T140000 151 | SUMMARY:49ers @ Bears 152 | UID:202B5047-AFA2-11D9-A2CD-000A95AD128C 153 | SEQUENCE:4 154 | DTSTAMP:20050418T001149Z 155 | DESCRIPTION:Week #9 156 | END:VEVENT 157 | BEGIN:VEVENT 158 | DTSTART;TZID=Canada/Mountain:20051120T110000 159 | DTEND;TZID=Canada/Mountain:20051120T140000 160 | SUMMARY:Panthers @ Bears 161 | UID:202B5215-AFA2-11D9-A2CD-000A95AD128C 162 | SEQUENCE:4 163 | DTSTAMP:20050418T001229Z 164 | DESCRIPTION:Week #10 165 | END:VEVENT 166 | BEGIN:VEVENT 167 | DTSTART;TZID=Canada/Mountain:20051127T110000 168 | DTEND;TZID=Canada/Mountain:20051127T140000 169 | SUMMARY:Bears @ Buccaneers 170 | UID:202B53E0-AFA2-11D9-A2CD-000A95AD128C 171 | SEQUENCE:4 172 | DTSTAMP:20050418T001322Z 173 | DESCRIPTION:Week #11 174 | END:VEVENT 175 | BEGIN:VEVENT 176 | DTSTART;TZID=Canada/Mountain:20051204T110000 177 | DTEND;TZID=Canada/Mountain:20051204T140000 178 | SUMMARY:Packers @ Bears 179 | UID:202B55AB-AFA2-11D9-A2CD-000A95AD128C 180 | SEQUENCE:4 181 | DTSTAMP:20050418T001408Z 182 | DESCRIPTION:Week #12 183 | END:VEVENT 184 | BEGIN:VEVENT 185 | DTSTART;TZID=Canada/Mountain:20051211T110000 186 | DTEND;TZID=Canada/Mountain:20051211T140000 187 | SUMMARY:Bears @ Steelers 188 | UID:202B5795-AFA2-11D9-A2CD-000A95AD128C 189 | SEQUENCE:4 190 | DTSTAMP:20050418T001555Z 191 | DESCRIPTION:Week #13 192 | END:VEVENT 193 | BEGIN:VEVENT 194 | DTSTART;TZID=Canada/Mountain:20051218T193000 195 | DTEND;TZID=Canada/Mountain:20051218T223000 196 | SUMMARY:Falcons @ Bears 197 | UID:202B5963-AFA2-11D9-A2CD-000A95AD128C 198 | SEQUENCE:8 199 | DTSTAMP:20050418T001943Z 200 | DESCRIPTION:Week #14 201 | END:VEVENT 202 | BEGIN:VEVENT 203 | DTSTART;TZID=Canada/Mountain:20051225T150000 204 | DTEND;TZID=Canada/Mountain:20051225T180000 205 | SUMMARY:Bears @ Packers 206 | UID:202B5B31-AFA2-11D9-A2CD-000A95AD128C 207 | SEQUENCE:3 208 | DTSTAMP:20050418T001737Z 209 | DESCRIPTION:Week #15 210 | END:VEVENT 211 | BEGIN:VEVENT 212 | DTSTART;TZID=Canada/Mountain:20060101T110000 213 | DTEND;TZID=Canada/Mountain:20060101T140000 214 | SUMMARY:Bears @ Vikings 215 | UID:202B5D2A-AFA2-11D9-A2CD-000A95AD128C 216 | SEQUENCE:4 217 | DTSTAMP:20050418T001843Z 218 | DESCRIPTION:Week #16 219 | END:VEVENT 220 | END:VCALENDAR 221 | -------------------------------------------------------------------------------- /regress/ical/bhav23-1.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//Trumba Corporation//Trumba Calendar Services 0.11.9005//EN 3 | VERSION:2.0 4 | CALSCALE:GREGORIAN 5 | BEGIN:VEVENT 6 | LOCATION:Melbourne 7 | SUMMARY:Australian Grand Prix 8 | UID:http://2012.f1calendar.com#GP1_2012 9 | DTSTART;VALUE=DATE-TIME:20120318T060000Z 10 | DTEND;VALUE=DATE-TIME:20120318T080000Z 11 | DTSTAMP:20120318T060000Z 12 | CATEGORIES:Grand Prix 13 | GEO:-37.8373;144.9666 14 | SEQUENCE:2012 15 | END:VEVENT 16 | END:VCALENDAR 17 | -------------------------------------------------------------------------------- /regress/ical/blalor.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | X-WR-CALNAME:ical4j 4 | PRODID:-//Apple Computer\, Inc//iCal 1.5//EN 5 | X-WR-RELCALID:A8E2EE62-D67D-11D8-922A-000A9595B652 6 | X-WR-TIMEZONE:America/Indianapolis 7 | CALSCALE:GREGORIAN 8 | BEGIN:VEVENT 9 | DTSTART;VALUE=DATE:20040224 10 | DTEND;VALUE=DATE:20040225 11 | SUMMARY:Pay AmEx bill 12 | UID:D9182220 13 | SEQUENCE:1 14 | RECURRENCE-ID;VALUE=DATE:20040224 15 | DTSTAMP:20040715T164503Z 16 | BEGIN:VALARM 17 | X-WR-ALARMID:CALAlarm-0 18 | TRIGGER:-PT16H2M 19 | ACTION:AUDIO 20 | END:VALARM 21 | END:VEVENT 22 | BEGIN:VEVENT 23 | DTSTART;VALUE=DATE:20040324 24 | DTEND;VALUE=DATE:20040325 25 | SUMMARY:Pay AmEx bill 26 | UID:D9182220 27 | SEQUENCE:1 28 | RECURRENCE-ID;VALUE=DATE:20040324 29 | DTSTAMP:20040715T164503Z 30 | BEGIN:VALARM 31 | X-WR-ALARMID:CALAlarm-0 32 | ACTION:AUDIO 33 | TRIGGER:-PT16H46M 34 | END:VALARM 35 | END:VEVENT 36 | BEGIN:VEVENT 37 | EXDATE;VALUE=DATE:20040324 38 | EXDATE;VALUE=DATE:20040224 39 | DTSTAMP:20040715T164503Z 40 | UID:D9182220 41 | SEQUENCE:1 42 | DTSTART;VALUE=DATE:20040224 43 | SUMMARY:Pay AmEx bill 44 | DTEND;VALUE=DATE:20040225 45 | RRULE:FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=24 46 | BEGIN:VALARM 47 | X-WR-ALARMID:CALAlarm-0 48 | ACTION:AUDIO 49 | TRIGGER:-P1D 50 | END:VALARM 51 | END:VEVENT 52 | END:VCALENDAR 53 | -------------------------------------------------------------------------------- /regress/ical/calconnect.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050411T090000 23 | DTEND;TZID=Eastern:20050411T100000 24 | TRANSP:OPAQUE 25 | RRULE:FREQ=DAILY;COUNT=5 26 | DTSTAMP:20050406T201221Z 27 | SEQUENCE:0 28 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 29 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 30 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 31 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 32 | :mailto:iCalParticipant@coffeebean.com 33 | CLASS:PUBLIC 34 | SUMMARY:5 day daily repeating meeting 35 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 36 | UID:E88157FE01BE8A5C85256FDB006EBCC3-Lotus_Notes_Generated 37 | END:VEVENT 38 | END:VCALENDAR 39 | -------------------------------------------------------------------------------- /regress/ical/calconnect10.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-WR-RELCALID:611BB31A-AC2A-4FF1-B5B5-126E2895D7FC 3 | PRODID:-//Apple Computer\, Inc//iCal 3.0//EN 4 | CALSCALE:GREGORIAN 5 | X-WR-CALNAME:Recurring 6 | VERSION:2.0 7 | METHOD:PUBLISH 8 | X-WR-TIMEZONE:US/Pacific 9 | BEGIN:VEVENT 10 | SEQUENCE:8 11 | DTSTART;VALUE=DATE:20060831 12 | UID:E32D796B-E2AC-4DC5-AAA1-DBE6E3701F55-002 13 | DTSTAMP:20060927T001213Z 14 | SUMMARY:Recurring-2 15 | DTEND;VALUE=DATE:20060903 16 | RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20060930 17 | END:VEVENT 18 | END:VCALENDAR 19 | -------------------------------------------------------------------------------- /regress/ical/calconnect2.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050411T100000 23 | DTEND;TZID=Eastern:20050411T110000 24 | TRANSP:OPAQUE 25 | RDATE;TZID=Eastern;VALUE=PERIOD:20050411T100000/20050411T110000 26 | ,20050412T100000/20050412T110000,20050413T100000/20050413T110000 27 | ,20050414T100000/20050414T110000,20050415T100000/20050415T110000 28 | DTSTAMP:20050406T202303Z 29 | COMMENT;ALTREP="CID:":R 30 | eschedule of time only (+ 1 hr) 31 | SEQUENCE:1 32 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 33 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 34 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 35 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 36 | :mailto:iCalParticipant@coffeebean.com 37 | CLASS:PUBLIC 38 | DESCRIPTION;ALTREP="CID:": 39 | SUMMARY:5 day daily repeating meeting 40 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 41 | UID:E88157FE01BE8A5C85256FDB006EBCC3-Lotus_Notes_Generated 42 | END:VEVENT 43 | END:VCALENDAR 44 | -------------------------------------------------------------------------------- /regress/ical/calconnect3.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050418T090000 23 | DTEND;TZID=Eastern:20050418T100000 24 | TRANSP:OPAQUE 25 | RRULE:FREQ=DAILY;COUNT=5 26 | DTSTAMP:20050406T202326Z 27 | SEQUENCE:0 28 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 29 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 30 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 31 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 32 | :mailto:iCalParticipant@coffeebean.com 33 | CLASS:PUBLIC 34 | SUMMARY:5 day daily repeating meeting #2 35 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 36 | UID:6882C1FE92942DA785256FDB006FEE85-Lotus_Notes_Generated 37 | END:VEVENT 38 | END:VCALENDAR 39 | -------------------------------------------------------------------------------- /regress/ical/calconnect4.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050418T090000 23 | DTEND;TZID=Eastern:20050418T100000 24 | TRANSP:OPAQUE 25 | RDATE;TZID=Eastern;VALUE=PERIOD:20050418T090000/20050418T100000 26 | ,20050419T090000/20050419T100000,20050420T090000/20050420T100000 27 | ,20050421T090000/20050421T100000,20050422T090000/20050422T100000 28 | DTSTAMP:20050406T204234Z 29 | SEQUENCE:0 30 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 31 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 32 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 33 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 34 | :mailto:iCalParticipant@coffeebean.com 35 | CLASS:PUBLIC 36 | DESCRIPTION;ALTREP="CID:":B 37 | ody change (update) to the meeting - all instances 38 | SUMMARY:5 day daily repeating meeting #2 39 | X-LOTUS-UPDATE-SUBJECT:Information Update - Description has changed 40 | : 5 day daily repeating meeting #2 41 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 42 | UID:6882C1FE92942DA785256FDB006FEE85-Lotus_Notes_Generated 43 | END:VEVENT 44 | END:VCALENDAR 45 | -------------------------------------------------------------------------------- /regress/ical/calconnect5.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050425T090000 23 | DTEND;TZID=Eastern:20050425T100000 24 | TRANSP:OPAQUE 25 | RRULE:FREQ=DAILY;COUNT=5 26 | DTSTAMP:20050406T204303Z 27 | SEQUENCE:0 28 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 29 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 30 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 31 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 32 | :mailto:iCalParticipant@coffeebean.com 33 | CLASS:PUBLIC 34 | DESCRIPTION;ALTREP="CID:":b 35 | ody 36 | SUMMARY:More complicated stream (5 day recurring) 37 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 38 | UID:6BA1ECA4D58B306C85256FDB0071B664-Lotus_Notes_Generated 39 | END:VEVENT 40 | END:VCALENDAR 41 | -------------------------------------------------------------------------------- /regress/ical/calconnect6.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050426T100000 23 | DTEND;TZID=Eastern:20050426T110000 24 | TRANSP:OPAQUE 25 | RDATE;TZID=Eastern;VALUE=PERIOD:20050426T100000/20050426T110000 26 | RECURRENCE-ID:20050426T130000Z 27 | DTSTAMP:20050406T205010Z 28 | COMMENT;ALTREP="CID:":R 29 | eschedule of a single instance's time only (+ 1 hr) 30 | SEQUENCE:1 31 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 32 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 33 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 34 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 35 | :mailto:iCalParticipant@coffeebean.com 36 | CLASS:PUBLIC 37 | DESCRIPTION;ALTREP="CID:":b 38 | ody 39 | SUMMARY:More complicated stream (5 day recurring) 40 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 41 | UID:6BA1ECA4D58B306C85256FDB0071B664-Lotus_Notes_Generated 42 | END:VEVENT 43 | END:VCALENDAR 44 | -------------------------------------------------------------------------------- /regress/ical/calconnect7.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050428T110000 23 | DTEND;TZID=Eastern:20050428T120000 24 | TRANSP:OPAQUE 25 | RDATE;TZID=Eastern;VALUE=PERIOD:20050428T110000/20050428T120000 26 | RECURRENCE-ID:20050428T130000Z 27 | DTSTAMP:20050406T205055Z 28 | COMMENT;ALTREP="CID:":A 29 | nother single instance reschedule - time only (+2 hrs) 30 | SEQUENCE:1 31 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 32 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 33 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 34 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 35 | :mailto:iCalParticipant@coffeebean.com 36 | CLASS:PUBLIC 37 | DESCRIPTION;ALTREP="CID:":b 38 | ody 39 | SUMMARY:More complicated stream (5 day recurring) 40 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 41 | UID:6BA1ECA4D58B306C85256FDB0071B664-Lotus_Notes_Generated 42 | END:VEVENT 43 | END:VCALENDAR 44 | -------------------------------------------------------------------------------- /regress/ical/calconnect8.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050425T090000 23 | DTEND;TZID=Eastern:20050425T093000 24 | TRANSP:OPAQUE 25 | RDATE;TZID=Eastern;VALUE=PERIOD:20050425T090000/20050425T093000 26 | ,20050426T100000/20050426T103000,20050427T090000/20050427T093000 27 | ,20050428T110000/20050428T113000,20050429T090000/20050429T093000 28 | DTSTAMP:20050406T205343Z 29 | COMMENT;ALTREP="CID:":A 30 | djust the duration of all instances to be -1/2 hour 31 | SEQUENCE:2 32 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 33 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 34 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 35 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 36 | :mailto:iCalParticipant@coffeebean.com 37 | CLASS:PUBLIC 38 | DESCRIPTION;ALTREP="CID:":b 39 | ody 40 | SUMMARY:More complicated stream (5 day recurring) 41 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 42 | UID:6BA1ECA4D58B306C85256FDB0071B664-Lotus_Notes_Generated 43 | END:VEVENT 44 | END:VCALENDAR 45 | -------------------------------------------------------------------------------- /regress/ical/calconnect9.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | X-LOTUS-CHARSET:UTF-8 3 | VERSION:2.0 4 | PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN 5 | METHOD:REQUEST 6 | BEGIN:VTIMEZONE 7 | TZID:Eastern 8 | BEGIN:STANDARD 9 | DTSTART:19501029T020000 10 | TZOFFSETFROM:-0400 11 | TZOFFSETTO:-0500 12 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | DTSTART:19500402T020000 16 | TZOFFSETFROM:-0500 17 | TZOFFSETTO:-0400 18 | RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4 19 | END:DAYLIGHT 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | DTSTART;TZID=Eastern:20050425T090000 23 | DTEND;TZID=Eastern:20050425T091500 24 | TRANSP:OPAQUE 25 | RDATE;TZID=Eastern;VALUE=PERIOD:20050425T090000/20050425T091500 26 | ,20050426T090000/20050426T091500,20050427T090000/20050427T091500 27 | ,20050428T090000/20050428T091500,20050429T090000/20050429T091500 28 | DTSTAMP:20050406T205429Z 29 | COMMENT;ALTREP="CID:":S 30 | et the Start and End Time to be implicit - 9 to 9:15am 31 | SEQUENCE:3 32 | ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="iCal Chair/CoffeeBean" 33 | ;RSVP=FALSE:mailto:iCalChair@coffeebean.com 34 | ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION 35 | ;CN="iCal Participant/CoffeeBean";RSVP=TRUE 36 | :mailto:iCalParticipant@coffeebean.com 37 | CLASS:PUBLIC 38 | DESCRIPTION;ALTREP="CID:":b 39 | ody 40 | SUMMARY:More complicated stream (5 day recurring) 41 | ORGANIZER;CN="iCal Chair/CoffeeBean":mailto:iCalChair@coffeebean.com 42 | UID:6BA1ECA4D58B306C85256FDB0071B664-Lotus_Notes_Generated 43 | END:VEVENT 44 | END:VCALENDAR 45 | -------------------------------------------------------------------------------- /regress/ical/custom_component.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//Ben Fortuna//iCal4j 1.0//EN 4 | BEGIN:X-VVENUE 5 | X-VVENUE-INFO:http://evdb.com/docs/ical-venue/draft-norris-ical-venue.html 6 | X-NAME:Chan Shun Concert Hall\, Chan Centre for the Performing Arts 7 | X-ADDRESS:6265 Crescent Road\, UBC 8 | X-CITY:Vancouver 9 | X-REGION;X-ABBREV=bc:British Columbia 10 | X-COUNTRY;X-ABBREV=ca:Canada 11 | X-POSTALCODE: 12 | X-URL;X-LABEL=Venue Info:http://www.chancentre.com 13 | END:X-VVENUE 14 | END:VCALENDAR 15 | -------------------------------------------------------------------------------- /regress/ical/date-multiple-parts.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//PIMUTILS.ORG//NONSGML khal / icalendar //EN 4 | BEGIN:VTIMEZONE 5 | TZID:Europe/Paris 6 | BEGIN:STANDARD 7 | DTSTART;VALUE=DATE-TIME:20201025T010000 8 | TZNAME:GMT 9 | TZOFFSETFROM:+0100 10 | TZOFFSETTO:+0000 11 | END:STANDARD 12 | END:VTIMEZONE 13 | BEGIN:VEVENT 14 | SUMMARY:event 15 | DTSTART;VALUE=DATE-TIME;TZID=Europe/Paris:20210106T220000 16 | DTEND;VALUE=DATE-TIME;TZID=Europe/Paris:20210106T230000 17 | DTSTAMP;VALUE=DATE-TIME:20200611T093502Z 18 | UID:0TAM33GHBDAN2XJDS82J5THAV483ABUOVZVK 19 | SEQUENCE:0 20 | BEGIN:VALARM 21 | ACTION:DISPLAY 22 | DESCRIPTION:new event 23 | TRIGGER:-PT3H 24 | END:VALARM 25 | END:VEVENT 26 | END:VCALENDAR 27 | -------------------------------------------------------------------------------- /regress/ical/dst-only-vtimezone.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//Ben Fortuna//iCal4j 1.0//EN 4 | BEGIN:VTIMEZONE 5 | TZID:Europe/Berlin 6 | BEGIN:DAYLIGHT 7 | TZOFFSETFROM:+0100 8 | TZOFFSETTO:+0200 9 | DTSTART:20180325T030000 10 | TZNAME:CEST 11 | END:DAYLIGHT 12 | END:VTIMEZONE 13 | BEGIN:VEVENT 14 | UID:only-dst@example.com 15 | DTSTAMP:20180329T084939Z 16 | DTSTART;TZID=Europe/Berlin:20180403T090000 17 | DTEND;TZID=Europe/Berlin:20180403T101500 18 | SUMMARY:Sample Event 19 | CREATED:20180329T084939Z 20 | LAST-MODIFIED:20180329T084939Z 21 | END:VEVENT 22 | END:VCALENDAR 23 | -------------------------------------------------------------------------------- /regress/ical/event.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VEVENT 5 | UID:uid1@example.com 6 | DTSTAMP:19970714T170000Z 7 | ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com 8 | DTSTART:19970714T170000Z 9 | DTEND:19970715T035959Z 10 | SUMMARY:Bastille Day Party 11 | END:VEVENT 12 | END:VCALENDAR 13 | -------------------------------------------------------------------------------- /regress/ical/evolution.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | CALSCALE:GREGORIAN 3 | PRODID:-//Ximian//NONSGML Evolution Calendar//EN 4 | VERSION:2.0 5 | BEGIN:VEVENT 6 | UID:20080624T213648Z-4959-1000-1-6@randy-ubuntu 7 | DTSTAMP:20080624T213648Z 8 | DTSTART;TZID=/softwarestudio.org/Tzfile/America/Chicago:20080624T130000 9 | DTEND;TZID=/softwarestudio.org/Tzfile/America/Chicago:20080624T143000 10 | TRANSP:OPAQUE 11 | SEQUENCE:3 12 | SUMMARY:test 13 | LOCATION:test location 14 | CLASS:PUBLIC 15 | CREATED:20080624T213658Z 16 | LAST-MODIFIED:20080624T213702Z 17 | END:VEVENT 18 | BEGIN:VTIMEZONE 19 | TZID:/softwarestudio.org/Tzfile/America/Chicago 20 | X-LIC-LOCATION:America/Chicago 21 | BEGIN:STANDARD 22 | TZNAME:CST 23 | DTSTART:19701102T010000 24 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 25 | TZOFFSETFROM:-0500 26 | TZOFFSETTO:-0600 27 | END:STANDARD 28 | BEGIN:DAYLIGHT 29 | TZNAME:CDT 30 | DTSTART:19700308T030000 31 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 32 | TZOFFSETFROM:-0600 33 | TZOFFSETTO:-0500 34 | END:DAYLIGHT 35 | END:VTIMEZONE 36 | END:VCALENDAR 37 | -------------------------------------------------------------------------------- /regress/ical/journal.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VJOURNAL 5 | DTSTAMP:19970324T120000Z 6 | UID:uid5@example.com 7 | ORGANIZER:MAILTO:jsmith@example.com 8 | STATUS:DRAFT 9 | CLASS:PUBLIC 10 | CATEGORIES:Project Report, XYZ, Weekly Meeting 11 | DESCRIPTION:Project xyz Review Meeting Minutes\n 12 | Agenda\n1. Review of project version 1.0 requirements.\n2. 13 | END:VJOURNAL 14 | END:VCALENDAR 15 | -------------------------------------------------------------------------------- /regress/ical/korganizer-lowercase.ics: -------------------------------------------------------------------------------- 1 | BEGIN:Vcalendar 2 | pRoDiD:-//K Desktop Environment//NONSGML KOrganizer 3.3.2//EN 3 | VERSION:2.0 4 | BEGIN:VEVENT 5 | DTSTAMP:20050225T044602Z 6 | ORGANIZER;Cn=Tom:MAILTO:tom@eastmond.org 7 | CREATED:20050225T044545Z 8 | UID:KOrganizer-1441301191.241 9 | SEQUENCE:2 10 | LAST-MODIFIED:20050225T044554Z 11 | SUMMARY:Ted's Birthday 12 | CLASS:PUBLIC 13 | PRIORITY:3 14 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTHDAY=16;BYMONTH=1 15 | DTSTART;VALUE=DATE:20050116 16 | DTEND;VALUE=DATE:20050117 17 | TRANSP:OPAQUE 18 | END:VEVENT 19 | END:vCalendaR 20 | -------------------------------------------------------------------------------- /regress/ical/korganizer.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//K Desktop Environment//NONSGML KOrganizer 3.3.2//EN 3 | VERSION:2.0 4 | BEGIN:VEVENT 5 | DTSTAMP:20050225T044602Z 6 | ORGANIZER;CN=Tom:MAILTO:tom@eastmond.org 7 | CREATED:20050225T044545Z 8 | UID:KOrganizer-1441301191.241 9 | SEQUENCE:2 10 | LAST-MODIFIED:20050225T044554Z 11 | SUMMARY:Ted's Birthday 12 | CLASS:PUBLIC 13 | PRIORITY:3 14 | RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTHDAY=16;BYMONTH=1 15 | DTSTART;VALUE=DATE:20050116 16 | DTEND;VALUE=DATE:20050117 17 | TRANSP:OPAQUE 18 | END:VEVENT 19 | END:VCALENDAR 20 | -------------------------------------------------------------------------------- /regress/ical/korganizer_sample.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID 3 | :-//K Desktop Environment//NONSGML KOrganizer 3.1//EN 4 | VERSION 5 | :2.0 6 | BEGIN:VEVENT 7 | CREATED 8 | :20030304T185335Z 9 | UID 10 | :KOrganizer-1934107299.242 11 | SEQUENCE 12 | :2 13 | LAST-MODIFIED 14 | :20030304T185543Z 15 | DTSTAMP 16 | :20030304T190131Z 17 | ORGANIZER 18 | :MAILTO:osnut@pacbell.net 19 | DESCRIPTION 20 | :See http://www.sgvlug.org for details 21 | SUMMARY 22 | :San Gabriel Valley Linux User Group -- general meeting 23 | LOCATION 24 | :Caltech Campus\; room 101 Guggenheim 25 | CLASS 26 | :PUBLIC 27 | PRIORITY 28 | :3 29 | X-PILOTID 30 | :0 31 | X-PILOTSTAT 32 | :1 33 | RRULE 34 | :FREQ=MONTHLY;COUNT=12;INTERVAL=1;BYDAY=2TH 35 | DTSTART 36 | :20030314T030000Z 37 | DTEND 38 | :20030314T050000Z 39 | END:VEVENT 40 | BEGIN:VEVENT 41 | CREATED 42 | :20030304T185448Z 43 | UID 44 | :KOrganizer-500279590.953 45 | SEQUENCE 46 | :5 47 | LAST-MODIFIED 48 | :20030304T185715Z 49 | DTSTAMP 50 | :20030304T190131Z 51 | ORGANIZER 52 | :MAILTO:osnut@pacbell.net 53 | DESCRIPTION 54 | :See http://www.sgvlug.org for details\n 55 | SUMMARY 56 | :San Gabriel Valley Linux User Group -- DevSIG meeting 57 | LOCATION 58 | :The Coffee Gallery\; Altadena 59 | CLASS 60 | :PUBLIC 61 | PRIORITY 62 | :3 63 | X-PILOTID 64 | :0 65 | X-PILOTSTAT 66 | :1 67 | RRULE 68 | :FREQ=MONTHLY;COUNT=12;INTERVAL=1;BYDAY=1SA 69 | DTSTART 70 | :20030406T200000Z 71 | DTEND 72 | :20030406T220000Z 73 | END:VEVENT 74 | END:VCALENDAR 75 | -------------------------------------------------------------------------------- /regress/ical/miked.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//PYVOBJECT//NONSGML Version 1//EN 4 | BEGIN:VTIMEZONE 5 | BEGIN:DAYLIGHT 6 | DTSTART:19870405T020000 7 | RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4 8 | TZNAME:PDT 9 | TZOFFSETFROM:-0800 10 | TZOFFSETTO:-0700 11 | END:DAYLIGHT 12 | LAST-MODIFIED:19870101T000000Z 13 | BEGIN:STANDARD 14 | DTSTART:19671029T020000 15 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 16 | TZNAME:PST 17 | TZOFFSETFROM:-0700 18 | TZOFFSETTO:-0800 19 | END:STANDARD 20 | TZID:US/Pacific 21 | END:VTIMEZONE 22 | BEGIN:VEVENT 23 | DTEND;TZID=US/Pacific:20050913T110000 24 | DTSTART;TZID=US/Pacific:20050913T100000 25 | LOCATION:Durham 26 | STATUS:CONFIRMED 27 | SUMMARY:Meeting 1.1 28 | UID:cbaf6318-2481-11da-c314-0011246e17f0 29 | END:VEVENT 30 | END:VCALENDAR 31 | -------------------------------------------------------------------------------- /regress/ical/new-mozilla.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN 3 | VERSION:2.0 4 | BEGIN:VTIMEZONE 5 | TZID:America/Los_Angeles 6 | X-TZINFO:America/Los_Angeles[2023c] 7 | BEGIN:STANDARD 8 | TZOFFSETTO:-080000 9 | TZOFFSETFROM:-075258 10 | TZNAME:America/Los_Angeles(STD) 11 | DTSTART:18831118T120702 12 | RDATE:18831118T120702 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | TZOFFSETTO:-070000 16 | TZOFFSETFROM:-080000 17 | TZNAME:America/Los_Angeles(DST) 18 | DTSTART:19180331T020000 19 | RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU;UNTIL=19190330T020000 20 | END:DAYLIGHT 21 | BEGIN:STANDARD 22 | TZOFFSETTO:-080000 23 | TZOFFSETFROM:-070000 24 | TZNAME:America/Los_Angeles(STD) 25 | DTSTART:19181027T020000 26 | RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU;UNTIL=19191026T020000 27 | END:STANDARD 28 | BEGIN:DAYLIGHT 29 | TZOFFSETTO:-070000 30 | TZOFFSETFROM:-080000 31 | TZNAME:America/Los_Angeles(DST) 32 | DTSTART:19420209T020000 33 | RDATE:19420209T020000 34 | END:DAYLIGHT 35 | BEGIN:STANDARD 36 | TZOFFSETTO:-080000 37 | TZOFFSETFROM:-070000 38 | TZNAME:America/Los_Angeles(STD) 39 | DTSTART:19450930T020000 40 | RDATE:19450930T020000 41 | END:STANDARD 42 | BEGIN:DAYLIGHT 43 | TZOFFSETTO:-070000 44 | TZOFFSETFROM:-080000 45 | TZNAME:America/Los_Angeles(DST) 46 | DTSTART:19480314T020100 47 | RDATE:19480314T020100 48 | END:DAYLIGHT 49 | BEGIN:STANDARD 50 | TZOFFSETTO:-080000 51 | TZOFFSETFROM:-070000 52 | TZNAME:America/Los_Angeles(STD) 53 | DTSTART:19490101T020000 54 | RDATE:19490101T020000 55 | END:STANDARD 56 | BEGIN:STANDARD 57 | TZOFFSETTO:-080000 58 | TZOFFSETFROM:-070000 59 | TZNAME:America/Los_Angeles(STD) 60 | DTSTART:19500924T020000 61 | RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU;UNTIL=19610924T020000 62 | END:STANDARD 63 | BEGIN:DAYLIGHT 64 | TZOFFSETTO:-070000 65 | TZOFFSETFROM:-080000 66 | TZNAME:America/Los_Angeles(DST) 67 | DTSTART:19500430T010000 68 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19660424T010000 69 | END:DAYLIGHT 70 | BEGIN:DAYLIGHT 71 | TZOFFSETTO:-070000 72 | TZOFFSETFROM:-080000 73 | TZNAME:America/Los_Angeles(DST) 74 | DTSTART:19670430T020000 75 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19730429T020000 76 | END:DAYLIGHT 77 | BEGIN:DAYLIGHT 78 | TZOFFSETTO:-070000 79 | TZOFFSETFROM:-080000 80 | TZNAME:America/Los_Angeles(DST) 81 | DTSTART:19740106T020000 82 | RDATE:19740106T020000 83 | END:DAYLIGHT 84 | BEGIN:DAYLIGHT 85 | TZOFFSETTO:-070000 86 | TZOFFSETFROM:-080000 87 | TZNAME:America/Los_Angeles(DST) 88 | DTSTART:19750223T020000 89 | RDATE:19750223T020000 90 | END:DAYLIGHT 91 | BEGIN:DAYLIGHT 92 | TZOFFSETTO:-070000 93 | TZOFFSETFROM:-080000 94 | TZNAME:America/Los_Angeles(DST) 95 | DTSTART:19760425T020000 96 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19860427T020000 97 | END:DAYLIGHT 98 | BEGIN:DAYLIGHT 99 | TZOFFSETTO:-070000 100 | TZOFFSETFROM:-080000 101 | TZNAME:America/Los_Angeles(DST) 102 | DTSTART:19870405T020000 103 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU;UNTIL=20060402T020000 104 | END:DAYLIGHT 105 | BEGIN:STANDARD 106 | TZOFFSETTO:-080000 107 | TZOFFSETFROM:-070000 108 | TZNAME:America/Los_Angeles(STD) 109 | DTSTART:19621028T020000 110 | RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU;UNTIL=20061029T020000 111 | END:STANDARD 112 | BEGIN:DAYLIGHT 113 | TZOFFSETTO:-070000 114 | TZOFFSETFROM:-080000 115 | TZNAME:America/Los_Angeles(DST) 116 | DTSTART:20070311T020000 117 | RDATE:20070311T020000 118 | END:DAYLIGHT 119 | BEGIN:STANDARD 120 | TZOFFSETTO:-080000 121 | TZOFFSETFROM:-070000 122 | TZNAME:America/Los_Angeles(STD) 123 | DTSTART:20071104T020000 124 | RDATE:20071104T020000 125 | END:STANDARD 126 | BEGIN:DAYLIGHT 127 | TZOFFSETTO:-070000 128 | TZOFFSETFROM:-080000 129 | TZNAME:(DST) 130 | DTSTART:20080309T020000 131 | RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU 132 | END:DAYLIGHT 133 | BEGIN:STANDARD 134 | TZOFFSETTO:-080000 135 | TZOFFSETFROM:-070000 136 | TZNAME:(STD) 137 | DTSTART:20081102T020000 138 | RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU 139 | END:STANDARD 140 | END:VTIMEZONE 141 | BEGIN:VEVENT 142 | CREATED:20231110T224350Z 143 | LAST-MODIFIED:20231110T224404Z 144 | DTSTAMP:20231110T224404Z 145 | UID:ed913144-d35d-4b5d-af53-9da82830bbce 146 | SUMMARY:test 147 | DTSTART;TZID=America/Los_Angeles:20240702T150000 148 | DTEND;TZID=America/Los_Angeles:20240702T160000 149 | TRANSP:OPAQUE 150 | END:VEVENT 151 | END:VCALENDAR 152 | -------------------------------------------------------------------------------- /regress/ical/new_years_day.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN 3 | VERSION:2.0 4 | BEGIN:VTIMEZONE 5 | TZID:Australia/Melbourne 6 | X-LIC-LOCATION:Australia/Melbourne 7 | BEGIN:STANDARD 8 | TZOFFSETFROM:+1100 9 | TZOFFSETTO:+1000 10 | TZNAME:EST 11 | DTSTART:19700405T030000 12 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=4 13 | END:STANDARD 14 | BEGIN:DAYLIGHT 15 | TZOFFSETFROM:+1000 16 | TZOFFSETTO:+1100 17 | TZNAME:EST 18 | DTSTART:19701004T020000 19 | RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=10 20 | END:DAYLIGHT 21 | END:VTIMEZONE 22 | BEGIN:VEVENT 23 | CREATED:20081228T122718Z 24 | LAST-MODIFIED:20081228T122718Z 25 | DTSTAMP:20081228T122718Z 26 | UID:d5eb7c8b-3a23-4abc-b05c-1108e6460caa 27 | SUMMARY:New Years Day 28 | RECURRENCE-ID;TZID=Australia/Melbourne:20090101T090000 29 | CATEGORIES:Holidays 30 | DTSTART;TZID=Australia/Melbourne:20090101T090000 31 | DTEND;TZID=Australia/Melbourne:20090101T170000 32 | TRANSP:OPAQUE 33 | X-MOZ-GENERATION:1 34 | END:VEVENT 35 | END:VCALENDAR 36 | -------------------------------------------------------------------------------- /regress/ical/oldevent.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VEVENT 5 | UID:uid1@example.com 6 | DTSTAMP:18970714T170000Z 7 | ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com 8 | DTSTART:18970714T170000Z 9 | DTEND:18970715T035959Z 10 | SUMMARY:Something in the past. 11 | END:VEVENT 12 | END:VCALENDAR 13 | -------------------------------------------------------------------------------- /regress/ical/oracle-personal-notes-test-empty.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ORACLE//NONSGML CSDK10.1.2.3.4 - WiscCal Tools oracle-support 1.4//EN 4 | BEGIN:VEVENT 5 | X-ORACLE-EVENTINSTANCE-GUID:I1+1325+20000+1+625329112 6 | X-ORACLE-EVENT-GUID:E1+1325+20000+625329112 7 | X-ORACLE-EVENTTYPE:APPOINTMENT 8 | UID:20101025T143152Z-52d-4e20-1c19-Oracle 9 | TRANSP:OPAQUE 10 | SUMMARY:personal notes test 11 | STATUS:CONFIRMED 12 | SEQUENCE:0 13 | PRIORITY:5 14 | ORGANIZER;X-ORACLE-GUID=200000118219869582153896;CN=NICHOLAS BLAIR:mailto: 15 | nblair@doit.wisc.edu 16 | LAST-MODIFIED:20101025T143152Z 17 | DTSTART:20101025T170000Z 18 | DTSTAMP:20101025T145057Z 19 | DTEND:20101025T180000Z 20 | CREATED:20101025T143152Z 21 | X-ORACLE-CLASS:NORMAL 22 | CLASS:PRIVATE 23 | ATTENDEE;X-ORACLE-PERSONAL-COMMENT-RTF=AA==;X-ORACLE-PERSONAL-COMMENT=;X-O 24 | RACLE-ISTIMEOK=TRUE;X-ORACLE-PERSONAL-COMMENT-ISDIRTY=FALSE;X-ORACLE-SHOW 25 | ASFREE=BUSY;X-ORACLE-GUID=200000118219869582153896;CUTYPE=INDIVIDUAL;RSVP 26 | =FALSE;CN=NICHOLAS BLAIR;PARTSTAT=ACCEPTED:mailto:nblair@doit.wisc.edu 27 | END:VEVENT 28 | END:VCALENDAR 29 | -------------------------------------------------------------------------------- /regress/ical/oracle-personal-notes-test.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ORACLE//NONSGML CSDK10.1.2.3.4 - WiscCal Tools oracle-support 1.4//EN 4 | BEGIN:VEVENT 5 | X-ORACLE-EVENTINSTANCE-GUID:I1+1325+20000+1+625329112 6 | X-ORACLE-EVENT-GUID:E1+1325+20000+625329112 7 | X-ORACLE-EVENTTYPE:APPOINTMENT 8 | UID:20101025T143152Z-52d-4e20-1c19-Oracle 9 | TRANSP:OPAQUE 10 | SUMMARY:personal notes test 11 | STATUS:CONFIRMED 12 | SEQUENCE:0 13 | PRIORITY:5 14 | ORGANIZER;X-ORACLE-GUID=200000118219869582153896;CN=NICHOLAS BLAIR:mailto: 15 | nblair@doit.wisc.edu 16 | LAST-MODIFIED:20101025T143152Z 17 | DTSTART:20101025T170000Z 18 | DTSTAMP:20101025T145057Z 19 | DTEND:20101025T180000Z 20 | CREATED:20101025T143152Z 21 | X-ORACLE-CLASS:NORMAL 22 | CLASS:PRIVATE 23 | ATTENDEE;X-ORACLE-PERSONAL-COMMENT-RTF=e1xydGYxXHVjMCBteSBwZXJzb25hbCBub3R 24 | lc30A;X-ORACLE-PERSONAL-COMMENT=bXkgcGVyc29uYWwgbm90ZXM=;X-ORACLE-ISTIMEO 25 | K=TRUE;X-ORACLE-PERSONAL-COMMENT-ISDIRTY=FALSE;X-ORACLE-SHOWASFREE=BUSY;X 26 | -ORACLE-GUID=200000118219869582153896;CUTYPE=INDIVIDUAL;RSVP=FALSE;CN=NIC 27 | HOLAS BLAIR;PARTSTAT=ACCEPTED:mailto:nblair@doit.wisc.edu 28 | END:VEVENT 29 | END:VCALENDAR 30 | -------------------------------------------------------------------------------- /regress/ical/php-flp.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//flaimo.com//iCal Class MIMEDIR//EN 3 | VERSION:2.0 4 | METHOD:REQUEST 5 | BEGIN:VEVENT 6 | ORGANIZER;CN=TMS -- Calendar Publisher:MAILTO:cal_publisher@xxxx.xxxx.xxxx.com 7 | DTSTART:20030620T220000Z 8 | DTEND:20030620T220000Z 9 | TRANSP:TRANSPARENT 10 | SEQUENCE:0 11 | UID:TPACTIDSTREAMTASKID 12 | DTSTAMP:20030410T113400Z 13 | CATEGORIES;LANGUAGE=en;ENCODING=QUOTED-PRINTABLE:TMS Dates 14 | DESCRIPTION;LANGUAGE=en;ENCODING=QUOTED-PRINTABLE:View the status of this ACT ID:=0Ahttp://xxxx.xxxx.xxxx.com/public/view_detailed_status.php?act_id=3DACTID&stream=3DSTREAM&task_id=3DTASKID=0A 15 | SUMMARY;LANGUAGE=en;ENCODING=QUOTED-PRINTABLE:TP for Act ID XXXXX -- Not important : Stream -- Task ID 16 | PRIORITY:5 17 | CLASS:PUBLIC 18 | URL:http://xxxx.xxxx.xxxx.com/ 19 | STATUS:CONFIRMED 20 | BEGIN:VALARM 21 | ACTION:DISPLAY 22 | TRIGGER:-PT2880M 23 | DESCRIPTION:TP for Act ID XXXXX -- Vx.x Not important : Stream -- Task ID 24 | SUMMARY:TP for Act ID XXXXX -- Vx.x Not important : Stream -- Task ID 25 | DURATION:P3D 26 | REPEAT:3 27 | END:VALARM 28 | END:VEVENT 29 | END:VCALENDAR 30 | -------------------------------------------------------------------------------- /regress/ical/recur.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN 3 | VERSION:2.0 4 | BEGIN:VTIMEZONE 5 | TZID:Europe/Malta 6 | BEGIN:DAYLIGHT 7 | TZOFFSETFROM:+0100 8 | TZOFFSETTO:+0200 9 | TZNAME:CEST 10 | DTSTART:19700329T020000 11 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 12 | END:DAYLIGHT 13 | BEGIN:STANDARD 14 | TZOFFSETFROM:+0200 15 | TZOFFSETTO:+0100 16 | TZNAME:CET 17 | DTSTART:19701025T030000 18 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 19 | END:STANDARD 20 | END:VTIMEZONE 21 | BEGIN:VEVENT 22 | CREATED:20200720T093736Z 23 | LAST-MODIFIED:20200720T093755Z 24 | DTSTAMP:20200720T093755Z 25 | UID:1c2f5320-74bb-4a9c-aaec-eee9a339b944 26 | SUMMARY:New Event 27 | RRULE:FREQ=DAILY;UNTIL=20200726T100000Z 28 | DTSTART;TZID=Europe/Malta:20200721T120000 29 | DTEND;TZID=Europe/Malta:20200721T130000 30 | TRANSP:OPAQUE 31 | LOCATION:recurrence test 32 | DESCRIPTION:tetsetset 33 | END:VEVENT 34 | END:VCALENDAR 35 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec3.4.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VEVENT 5 | UID:19970610T172345Z-AF23B2@example.com 6 | DTSTAMP:19970610T172345Z 7 | DTSTART:19970714T170000Z 8 | DTEND:19970715T040000Z 9 | SUMMARY:Bastille Day Party 10 | END:VEVENT 11 | END:VCALENDAR 12 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec3.6.1.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VEVENT 5 | UID:19970901T130000Z-123401@example.com 6 | DTSTAMP:19970901T130000Z 7 | DTSTART:19970903T163000Z 8 | DTEND:19970903T190000Z 9 | SUMMARY:Annual Employee Review 10 | CLASS:PRIVATE 11 | CATEGORIES:BUSINESS,HUMAN RESOURCES 12 | END:VEVENT 13 | BEGIN:VEVENT 14 | UID:19970901T130000Z-123402@example.com 15 | DTSTAMP:19970901T130000Z 16 | DTSTART:19970401T163000Z 17 | DTEND:19970402T010000Z 18 | SUMMARY:Laurel is in sensitivity awareness class. 19 | CLASS:PUBLIC 20 | CATEGORIES:BUSINESS,HUMAN RESOURCES 21 | TRANSP:TRANSPARENT 22 | END:VEVENT 23 | BEGIN:VEVENT 24 | UID:19970901T130000Z-123403@example.com 25 | DTSTAMP:19970901T130000Z 26 | DTSTART;VALUE=DATE:19971102 27 | SUMMARY:Our Blissful Anniversary 28 | TRANSP:TRANSPARENT 29 | CLASS:CONFIDENTIAL 30 | CATEGORIES:ANNIVERSARY,PERSONAL,SPECIAL OCCASION 31 | RRULE:FREQ=YEARLY 32 | END:VEVENT 33 | BEGIN:VEVENT 34 | UID:20070423T123432Z-541111@example.com 35 | DTSTAMP:20070423T123432Z 36 | DTSTART;VALUE=DATE:20070628 37 | DTEND;VALUE=DATE:20070709 38 | SUMMARY:Festival International de Jazz de Montreal 39 | TRANSP:TRANSPARENT 40 | END:VEVENT 41 | END:VCALENDAR 42 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec3.6.2.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VTODO 5 | UID:20070313T123432Z-456553@example.com 6 | DTSTAMP:20070313T123432Z 7 | DUE;VALUE=DATE:20070501 8 | SUMMARY:Submit Quebec Income Tax Return for 2006 9 | CLASS:CONFIDENTIAL 10 | CATEGORIES:FAMILY,FINANCE 11 | STATUS:NEEDS-ACTION 12 | END:VTODO 13 | BEGIN:VTODO 14 | UID:20070514T103211Z-123404@example.com 15 | DTSTAMP:20070514T103211Z 16 | DTSTART:20070514T110000Z 17 | DUE:20070709T130000Z 18 | COMPLETED:20070707T100000Z 19 | SUMMARY:Submit Revised Internet-Draft 20 | PRIORITY:1 21 | STATUS:NEEDS-ACTION 22 | END:VTODO 23 | END:VCALENDAR 24 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec3.6.3.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VJOURNAL 5 | UID:19970901T130000Z-123405@example.com 6 | DTSTAMP:19970901T130000Z 7 | DTSTART;VALUE=DATE:19970317 8 | SUMMARY:Staff meeting minutes 9 | DESCRIPTION:1. Staff meeting: Participants include Joe\, 10 | Lisa\, and Bob. Aurora project plans were reviewed. 11 | There is currently no budget reserves for this project. 12 | Lisa will escalate to management. Next meeting on Tuesday.\n 13 | 2. Telephone Conference: ABC Corp. sales representative 14 | called to discuss new printer. Promised to get us a demo by 15 | Friday.\n3. Henry Miller (Handsoff Insurance): Car was 16 | totaled by tree. Is looking into a loaner car. 555-2323 17 | (tel). 18 | END:VJOURNAL 19 | END:VCALENDAR 20 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec3.6.4.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VFREEBUSY 5 | UID:19970901T082949Z-FA43EF@example.com 6 | ORGANIZER:mailto:jane_doe@example.com 7 | ATTENDEE:mailto:john_public@example.com 8 | DTSTART:19971015T050000Z 9 | DTEND:19971016T050000Z 10 | DTSTAMP:19970901T083000Z 11 | END:VFREEBUSY 12 | BEGIN:VFREEBUSY 13 | UID:19970901T095957Z-76A912@example.com 14 | ORGANIZER:mailto:jane_doe@example.com 15 | ATTENDEE:mailto:john_public@example.com 16 | DTSTAMP:19970901T100000Z 17 | FREEBUSY:19971015T050000Z/PT8H30M, 18 | 19971015T160000Z/PT5H30M,19971015T223000Z/PT6H30M 19 | URL:http://example.com/pub/busy/jpublic-01.ifb 20 | COMMENT:This iCalendar file contains busy time information for 21 | the next three months. 22 | END:VFREEBUSY 23 | BEGIN:VFREEBUSY 24 | UID:19970901T115957Z-76A912@example.com 25 | DTSTAMP:19970901T120000Z 26 | ORGANIZER:jsmith@example.com 27 | DTSTART:19980313T141711Z 28 | DTEND:19980410T141711Z 29 | FREEBUSY:19980314T233000Z/19980315T003000Z 30 | FREEBUSY:19980316T153000Z/19980316T163000Z 31 | FREEBUSY:19980318T030000Z/19980318T040000Z 32 | URL:http://www.example.com/calendar/busytime/jsmith.ifb 33 | END:VFREEBUSY 34 | END:VCALENDAR 35 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec3.6.5.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VTIMEZONE 5 | TZID:America/New_York 6 | LAST-MODIFIED:20050809T050000Z 7 | BEGIN:DAYLIGHT 8 | DTSTART:19670430T020000 9 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19730429T070000Z 10 | TZOFFSETFROM:-0500 11 | TZOFFSETTO:-0400 12 | TZNAME:EDT 13 | END:DAYLIGHT 14 | BEGIN:STANDARD 15 | DTSTART:19671029T020000 16 | RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU;UNTIL=20061029T060000Z 17 | TZOFFSETFROM:-0400 18 | TZOFFSETTO:-0500 19 | TZNAME:EST 20 | END:STANDARD 21 | BEGIN:DAYLIGHT 22 | DTSTART:19740106T020000 23 | RDATE:19750223T020000 24 | TZOFFSETFROM:-0500 25 | TZOFFSETTO:-0400 26 | TZNAME:EDT 27 | END:DAYLIGHT 28 | BEGIN:DAYLIGHT 29 | DTSTART:19760425T020000 30 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19860427T070000Z 31 | TZOFFSETFROM:-0500 32 | TZOFFSETTO:-0400 33 | TZNAME:EDT 34 | END:DAYLIGHT 35 | BEGIN:DAYLIGHT 36 | DTSTART:19870405T020000 37 | RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU;UNTIL=20060402T070000Z 38 | TZOFFSETFROM:-0500 39 | TZOFFSETTO:-0400 40 | TZNAME:EDT 41 | END:DAYLIGHT 42 | BEGIN:DAYLIGHT 43 | DTSTART:20070311T020000 44 | RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU 45 | TZOFFSETFROM:-0500 46 | TZOFFSETTO:-0400 47 | TZNAME:EDT 48 | END:DAYLIGHT 49 | BEGIN:STANDARD 50 | DTSTART:20071104T020000 51 | RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU 52 | TZOFFSETFROM:-0400 53 | TZOFFSETTO:-0500 54 | TZNAME:EST 55 | END:STANDARD 56 | END:VTIMEZONE 57 | BEGIN:VTIMEZONE 58 | TZID:America/New_York 59 | LAST-MODIFIED:20050809T050000Z 60 | BEGIN:STANDARD 61 | DTSTART:20071104T020000 62 | TZOFFSETFROM:-0400 63 | TZOFFSETTO:-0500 64 | TZNAME:EST 65 | END:STANDARD 66 | BEGIN:DAYLIGHT 67 | DTSTART:20070311T020000 68 | TZOFFSETFROM:-0500 69 | TZOFFSETTO:-0400 70 | TZNAME:EDT 71 | END:DAYLIGHT 72 | END:VTIMEZONE 73 | BEGIN:VTIMEZONE 74 | TZID:America/New_York 75 | LAST-MODIFIED:20050809T050000Z 76 | TZURL:http://zones.example.com/tz/America-New_York.ics 77 | BEGIN:STANDARD 78 | DTSTART:20071104T020000 79 | RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU 80 | TZOFFSETFROM:-0400 81 | TZOFFSETTO:-0500 82 | TZNAME:EST 83 | END:STANDARD 84 | BEGIN:DAYLIGHT 85 | DTSTART:20070311T020000 86 | RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU 87 | TZOFFSETFROM:-0500 88 | TZOFFSETTO:-0400 89 | TZNAME:EDT 90 | END:DAYLIGHT 91 | END:VTIMEZONE 92 | BEGIN:VTIMEZONE 93 | TZID:Fictitious 94 | LAST-MODIFIED:19870101T000000Z 95 | BEGIN:STANDARD 96 | DTSTART:19671029T020000 97 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 98 | TZOFFSETFROM:-0400 99 | TZOFFSETTO:-0500 100 | TZNAME:EST 101 | END:STANDARD 102 | BEGIN:DAYLIGHT 103 | DTSTART:19870405T020000 104 | RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=19980404T070000Z 105 | TZOFFSETFROM:-0500 106 | TZOFFSETTO:-0400 107 | TZNAME:EDT 108 | END:DAYLIGHT 109 | END:VTIMEZONE 110 | BEGIN:VTIMEZONE 111 | TZID:Fictitious 112 | LAST-MODIFIED:19870101T000000Z 113 | BEGIN:STANDARD 114 | DTSTART:19671029T020000 115 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 116 | TZOFFSETFROM:-0400 117 | TZOFFSETTO:-0500 118 | TZNAME:EST 119 | END:STANDARD 120 | BEGIN:DAYLIGHT 121 | DTSTART:19870405T020000 122 | RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=19980404T070000Z 123 | TZOFFSETFROM:-0500 124 | TZOFFSETTO:-0400 125 | TZNAME:EDT 126 | END:DAYLIGHT 127 | BEGIN:DAYLIGHT 128 | DTSTART:19990424T020000 129 | RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=4 130 | TZOFFSETFROM:-0500 131 | TZOFFSETTO:-0400 132 | TZNAME:EDT 133 | END:DAYLIGHT 134 | END:VTIMEZONE 135 | END:VCALENDAR 136 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec3.6.6.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//hacksw/handcal//NONSGML v1.0//EN 4 | BEGIN:VALARM 5 | TRIGGER:-PT30M 6 | REPEAT:2 7 | DURATION:PT15M 8 | ACTION:DISPLAY 9 | DESCRIPTION:Breakfast meeting with executive\n 10 | team at 8:30 AM EST. 11 | END:VALARM 12 | BEGIN:VALARM 13 | TRIGGER;RELATED=END:-P2D 14 | ACTION:EMAIL 15 | ATTENDEE:mailto:john_doe@example.com 16 | SUMMARY:*** REMINDER: SEND AGENDA FOR WEEKLY STAFF MEETING *** 17 | DESCRIPTION:A draft agenda needs to be sent out to the attendees 18 | to the weekly managers meeting (MGR-LIST). Attached is a 19 | pointer the document template for the agenda file. 20 | ATTACH;FMTTYPE=application/msword:http://example.com/ 21 | templates/agenda.doc 22 | END:VALARM 23 | END:VCALENDAR 24 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec4.1.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//xyz Corp//NONSGML PDA Calendar Version 1.0//EN 3 | VERSION:2.0 4 | BEGIN:VEVENT 5 | DTSTAMP:19960704T120000Z 6 | UID:uid1@example.com 7 | ORGANIZER:mailto:jsmith@example.com 8 | DTSTART:19960918T143000Z 9 | DTEND:19960920T220000Z 10 | STATUS:CONFIRMED 11 | CATEGORIES:CONFERENCE 12 | SUMMARY:Networld+Interop Conference 13 | DESCRIPTION:Networld+Interop Conference 14 | and Exhibit\nAtlanta World Congress Center\n 15 | Atlanta\, Georgia 16 | END:VEVENT 17 | END:VCALENDAR 18 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec4.2.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | PRODID:-//RDU Software//NONSGML HandCal//EN 3 | VERSION:2.0 4 | BEGIN:VTIMEZONE 5 | TZID:America/New_York 6 | BEGIN:STANDARD 7 | DTSTART:19981025T020000 8 | TZOFFSETFROM:-0400 9 | TZOFFSETTO:-0500 10 | TZNAME:EST 11 | END:STANDARD 12 | BEGIN:DAYLIGHT 13 | DTSTART:19990404T020000 14 | TZOFFSETFROM:-0500 15 | TZOFFSETTO:-0400 16 | TZNAME:EDT 17 | END:DAYLIGHT 18 | END:VTIMEZONE 19 | BEGIN:VEVENT 20 | DTSTAMP:19980309T231000Z 21 | UID:guid-1.example.com 22 | ORGANIZER:mailto:mrbig@example.com 23 | ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP: 24 | mailto:employee-A@example.com 25 | DESCRIPTION:Project XYZ Review Meeting 26 | CATEGORIES:MEETING 27 | CLASS:PUBLIC 28 | CREATED:19980309T130000Z 29 | SUMMARY:XYZ Project Review 30 | DTSTART;TZID=America/New_York:19980312T083000 31 | DTEND;TZID=America/New_York:19980312T093000 32 | LOCATION:1CP Conference Room 4350 33 | END:VEVENT 34 | END:VCALENDAR 35 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec4.3.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | METHOD:PUBLISH 3 | VERSION:2.0 4 | PRODID:-//ABC Corporation//NONSGML My Product//EN 5 | BEGIN:VEVENT 6 | DTSTAMP:19970324T120000Z 7 | SEQUENCE:0 8 | UID:uid3@example.com 9 | ORGANIZER:mailto:jdoe@example.com 10 | ATTENDEE;RSVP=TRUE:mailto:jsmith@example.com 11 | DTSTART:19970324T123000Z 12 | DTEND:19970324T210000Z 13 | CATEGORIES:MEETING,PROJECT 14 | CLASS:PUBLIC 15 | SUMMARY:Calendaring Interoperability Planning Meeting 16 | DESCRIPTION:Discuss how we can test c&s interoperability\n 17 | using iCalendar and other IETF standards. 18 | LOCATION:LDB Lobby 19 | ATTACH;FMTTYPE=application/postscript:ftp://example.com/pub/ 20 | conf/bkgrnd.ps 21 | END:VEVENT 22 | END:VCALENDAR 23 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec4.4.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VTODO 5 | DTSTAMP:19980130T134500Z 6 | SEQUENCE:2 7 | UID:uid4@example.com 8 | ORGANIZER:mailto:unclesam@example.com 9 | ATTENDEE;PARTSTAT=ACCEPTED:mailto:jqpublic@example.com 10 | DUE:19980415T000000 11 | STATUS:NEEDS-ACTION 12 | SUMMARY:Submit Income Taxes 13 | BEGIN:VALARM 14 | ACTION:AUDIO 15 | TRIGGER;VALUE=DATE-TIME:19980403T120000Z 16 | ATTACH;FMTTYPE=audio/basic:http://example.com/pub/audio- 17 | files/ssbanner.aud 18 | REPEAT:4 19 | DURATION:PT1H 20 | END:VALARM 21 | END:VTODO 22 | END:VCALENDAR 23 | -------------------------------------------------------------------------------- /regress/ical/rfc5545-sec4.5.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VJOURNAL 5 | DTSTAMP:19970324T120000Z 6 | UID:uid5@example.com 7 | ORGANIZER:mailto:jsmith@example.com 8 | STATUS:DRAFT 9 | CLASS:PUBLIC 10 | CATEGORIES:Project Report,XYZ,Weekly Meeting 11 | DESCRIPTION:Project xyz Review Meeting Minutes\n 12 | Agenda\n1. Review of project version 1.0 requirements.\n2. 13 | Definition 14 | of project processes.\n3. Review of project schedule.\n 15 | Participants: John Smith\, Jane Doe\, Jim Dandy\n-It was 16 | decided that the requirements need to be signed off by 17 | product marketing.\n-Project processes were accepted.\n 18 | -Project schedule needs to account for scheduled holidays 19 | and employee vacation time. Check with HR for specific 20 | dates.\n-New schedule will be distributed by Friday.\n- 21 | Next weeks meeting is cancelled. No meeting until 3/23. 22 | END:VJOURNAL 23 | END:VCALENDAR 24 | -------------------------------------------------------------------------------- /regress/ical/todo.ics: -------------------------------------------------------------------------------- 1 | BEGIN:VCALENDAR 2 | VERSION:2.0 3 | PRODID:-//ABC Corporation//NONSGML My Product//EN 4 | BEGIN:VTODO 5 | DTSTAMP:19980130T134500Z 6 | SEQUENCE:2 7 | UID:uid4@example.com 8 | ACTION:AUDIO 9 | TRIGGER:19980403T120000 10 | ATTACH;FMTTYPE=audio/basic:http://example.com/pub/audio- 11 | files/ssbanner.aud 12 | REPEAT:4 13 | DURATION:PT1H 14 | END:VTODO 15 | END:VCALENDAR 16 | -------------------------------------------------------------------------------- /server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #ifndef KCALDAV_H 17 | #define KCALDAV_H 18 | 19 | enum xml { 20 | XML_CALDAV_CALENDAR, 21 | XML_CALDAV_CALENDAR_DATA, 22 | XML_CALDAV_COMP, 23 | XML_CALDAV_OPAQUE, 24 | XML_CALDAVSERV_PROXY_READ, 25 | XML_CALDAVSERV_PROXY_READ_FOR, 26 | XML_CALDAVSERV_PROXY_WRITE, 27 | XML_CALDAVSERV_PROXY_WRITE_FOR, 28 | XML_DAV_BIND, 29 | XML_DAV_COLLECTION, 30 | XML_DAV_HREF, 31 | XML_DAV_MULTISTATUS, 32 | XML_DAV_PRINCIPAL, 33 | XML_DAV_PRIVILEGE, 34 | XML_DAV_PROP, 35 | XML_DAV_PROPSTAT, 36 | XML_DAV_READ, 37 | XML_DAV_READ_CURRENT_USER_PRIVILEGE_SET, 38 | XML_DAV_RESOURCETYPE, 39 | XML_DAV_RESPONSE, 40 | XML_DAV_STATUS, 41 | XML_DAV_UNBIND, 42 | XML_DAV_WRITE, 43 | XML__MAX 44 | }; 45 | 46 | enum page { 47 | PAGE_DELCOLN = 0, 48 | PAGE_DELPROXY, 49 | PAGE_INDEX, 50 | PAGE_LOGOUT, 51 | PAGE_MODPROXY, 52 | PAGE_NEWCOLN, 53 | PAGE_SETCOLNPROPS, 54 | PAGE_SETEMAIL, 55 | PAGE_SETPASS, 56 | PAGE__MAX 57 | }; 58 | 59 | enum valid { 60 | VALID_BITS = 0, 61 | VALID_BODY, 62 | VALID_COLOUR, 63 | VALID_DESCRIPTION, 64 | VALID_EMAIL, 65 | VALID_ID, 66 | VALID_NAME, 67 | VALID_PASS, 68 | VALID_PATH, 69 | VALID__MAX 70 | }; 71 | 72 | /* 73 | * Run-time configuration. 74 | */ 75 | struct conf { 76 | char *logfile; /* logfile or NULL (ptr needs free) */ 77 | int verbose; /* assign to verbose */ 78 | }; 79 | 80 | /* 81 | * State carried through the system for a single operator. 82 | */ 83 | struct state { 84 | struct prncpl *prncpl; /* current user principal */ 85 | struct prncpl *rprncpl; /* requested user principal */ 86 | struct coln *cfg; /* (resource in?) requested collection */ 87 | int proxy; /* permission of this proxy request */ 88 | char caldir[PATH_MAX]; /* calendar root */ 89 | char *principal; /* principal in request */ 90 | char *collection; /* collection in request */ 91 | char *resource; /* resource in request */ 92 | const char *nonce; /* requested nonce */ 93 | }; 94 | 95 | typedef void (*principalfp)(struct kreq *, struct kxmlreq *); 96 | typedef void (*collectionfp)(struct kreq *, 97 | struct kxmlreq *, const struct coln *); 98 | typedef void (*resourcefp)(struct kreq *, 99 | struct kxmlreq *, const struct coln *, const struct res *); 100 | 101 | /* 102 | * This fully describes the properties that we handle and their various 103 | * callbacks and informational bits. 104 | */ 105 | struct property { 106 | unsigned int flags; 107 | collectionfp cgetfp; 108 | resourcefp rgetfp; 109 | principalfp pgetfp; 110 | }; 111 | 112 | int conf_read(const char *, struct conf *); 113 | 114 | int xml_ical_putc(int, void *); 115 | int http_ical_putc(int, void *); 116 | 117 | void http_error(struct kreq *, enum khttp); 118 | int http_paths(const char *, char **, char **, char **); 119 | int http_safe_string(const char *); 120 | const char *http_etag_if_match(const char *, char **); 121 | 122 | void method_delete(struct kreq *); 123 | void method_get(struct kreq *); 124 | void method_json(struct kreq *); 125 | void method_options(struct kreq *); 126 | void method_propfind(struct kreq *); 127 | void method_proppatch(struct kreq *); 128 | void method_put(struct kreq *); 129 | void method_report(struct kreq *); 130 | 131 | void kutil_err_noexit(struct kreq *, 132 | const char *, const char *, ...); 133 | void kutil_errx_noexit(struct kreq *, 134 | const char *, const char *, ...); 135 | void kutil_dbg(struct kreq *, 136 | const char *, const char *, ...); 137 | 138 | extern const char *const xmls[XML__MAX]; 139 | extern const struct property properties[CALPROP__MAX]; 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .hide { display: none; } 2 | .button-xsmall { font-size: 70%; } 3 | .button-small { font-size: 85%; } 4 | .button-large { font-size: 110%; } 5 | .button-xlarge { font-size: 125%; } 6 | a { text-decoration: none; 7 | color: blue; } 8 | ul { list-style-type: none; 9 | padding: 0; } 10 | html, body { height: 100%; } 11 | header { background-color: #313131; 12 | padding: 2em 1em 1em 1em; } 13 | header > div { width: 100%; 14 | color: #fff; } 15 | header a { color: inherit; } 16 | header nav a { padding: 0ex 1ex; 17 | display: inline-block; } 18 | header nav { color: #FFBB51; 19 | width: 50%; 20 | text-align: right; 21 | white-space: nowrap; 22 | display: inline-block; } 23 | h1 { margin: 0; 24 | margin-bottom: -6px; 25 | width: 50%; 26 | white-space: nowrap; 27 | display: inline-block; 28 | font-family: Georgia,Times,Times New Roman,serif; 29 | font-size: 32px; 30 | font-style: normal; 31 | font-variant: normal; 32 | font-weight: 500; 33 | line-height: 26.4px; } 34 | h1 i { letter-spacing: 2pt; } 35 | h2 { font-family: Georgia,Times,Times New Roman,serif; 36 | font-size: 18px; 37 | font-style: normal; 38 | font-variant: normal; 39 | font-weight: 500; 40 | line-height: 22px; } 41 | h3 { font-family: Georgia,Times,Times New Roman,serif; 42 | font-size: 16px; 43 | font-style: normal; 44 | font-variant: normal; 45 | font-weight: 300; 46 | line-height: 26.4px; } 47 | footer { padding: 2em; 48 | text-align: center; 49 | color: #888; } 50 | footer a { color: #666; } 51 | footer a:hover { color: #444; } 52 | article { padding: 1em; } 53 | #loggedout, #loading { height: 100%; 54 | width: 100%; 55 | display: table; } 56 | #loggedout.hide, #loading.hide { display: none; } 57 | #loggedout >*, #loading >* { display: table-cell; 58 | text-align: center; 59 | font-size: larger; 60 | vertical-align: middle; 61 | height: 100%; 62 | width: 100%; } 63 | .error { color: #ff3333; } 64 | .pure-form .pure-radio { display: inline-block; } 65 | aside { font-style: italic; } 66 | 67 | @media only screen and (max-width: 480px) { 68 | .bigonly { display: none; } 69 | .pure-form input[type="password"], 70 | .pure-form label, 71 | .pure-form input[type="color"], 72 | .pure-form input[type="email"], 73 | .pure-form input[type="text"] { display: inline-block; 74 | margin-bottom: 0; } 75 | .pure-form button[type="submit"] { margin: 0; } 76 | h2 { font-size: 14px; } 77 | h3 { font-size: 13px; } 78 | } 79 | -------------------------------------------------------------------------------- /test-caldav.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | 21 | #if HAVE_ERR 22 | # include 23 | #endif 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "libkcaldav.h" 31 | 32 | int 33 | main(int argc, char *argv[]) 34 | { 35 | int fd, c; 36 | struct stat st; 37 | size_t sz; 38 | char *map, *er = NULL; 39 | struct caldav *p; 40 | 41 | #if HAVE_PLEDGE 42 | if (pledge("stdio rpath", NULL) == -1) 43 | err(EXIT_FAILURE, "pledge"); 44 | #endif 45 | 46 | if ((c = getopt(argc, argv, "")) != -1) 47 | return EXIT_FAILURE; 48 | 49 | argc -= optind; 50 | argv += optind; 51 | 52 | if (argc == 0) 53 | return EXIT_FAILURE; 54 | 55 | if ((fd = open(argv[0], O_RDONLY, 0)) == -1) 56 | err(EXIT_FAILURE, "%s", argv[0]); 57 | 58 | #if HAVE_PLEDGE 59 | if (pledge("stdio", NULL) == -1) 60 | err(EXIT_FAILURE, "pledge"); 61 | #endif 62 | 63 | if (fstat(fd, &st) == -1) 64 | err(EXIT_FAILURE, "%s", argv[0]); 65 | 66 | sz = st.st_size; 67 | map = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); 68 | close(fd); 69 | 70 | if (map == MAP_FAILED) 71 | err(EXIT_FAILURE, "%s", argv[0]); 72 | 73 | if ((p = caldav_parse(map, sz, &er)) == NULL) 74 | warnx("%s", er == NULL ? "memory failure" : er); 75 | 76 | munmap(map, sz); 77 | caldav_free(p); 78 | free(er); 79 | 80 | return p == NULL ? EXIT_FAILURE : EXIT_SUCCESS; 81 | } 82 | -------------------------------------------------------------------------------- /test-conf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | 20 | #if HAVE_ERR 21 | # include 22 | #endif 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include /* pledge */ 29 | 30 | #include 31 | #include 32 | 33 | #include "libkcaldav.h" 34 | #include "db.h" 35 | #include "server.h" 36 | 37 | int 38 | main(int argc, char *argv[]) 39 | { 40 | int c; 41 | struct conf conf; 42 | 43 | #if HAVE_PLEDGE 44 | if (pledge("stdio rpath", NULL) == -1) 45 | err(1, NULL); 46 | #endif 47 | 48 | if (argc < 2) 49 | return 1; 50 | 51 | if ((c = conf_read(argv[1], &conf)) <= 0) 52 | return 1; 53 | 54 | if (conf.logfile != NULL) 55 | printf("logfile=%s\n", conf.logfile); 56 | 57 | printf("debug=%d\n", conf.verbose); 58 | 59 | free(conf.logfile); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /test-ical.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #if HAVE_ERR 24 | # include 25 | #endif 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "libkcaldav.h" 36 | 37 | static void 38 | ical_printrrule(const struct icalcomp *c, 39 | enum icaltztype type, const struct icalrrule *r) 40 | { 41 | char buf[32]; 42 | size_t j; 43 | 44 | if (ICALTZ__MAX != type) 45 | snprintf(buf, sizeof(buf), "[%s:%s] RRULE:", 46 | icaltypes[c->type], icaltztypes[type]); 47 | else 48 | snprintf(buf, sizeof(buf), "[%s] RRULE:", 49 | icaltypes[c->type]); 50 | 51 | if (ICALFREQ_NONE != r->freq) 52 | printf("%sFREQ = %s\n", buf, icalfreqs[r->freq]); 53 | if (r->until.type != ICAL_DT_UNSET) 54 | printf("%sUNTIL = %s", buf, ctime(&r->until.tm)); 55 | if (0 != r->count) 56 | printf("%sCOUNT = %lu\n", buf, r->count); 57 | if (0 != r->interval) 58 | printf("%sINTERVAL = %lu\n", buf, r->interval); 59 | if (0 != r->bwkdsz) { 60 | printf("%sBYDAY =", buf); 61 | for (j = 0; j < r->bwkdsz; j++) 62 | printf(" %ld%s", r->bwkd[j].wk, 63 | icalwkdays[r->bwkd[j].wkday]); 64 | printf("\n"); 65 | } 66 | if (0 != r->bhrsz) { 67 | printf("%sBYHOUR =", buf); 68 | for (j = 0; j < r->bhrsz; j++) 69 | printf(" %lu", r->bhr[j]); 70 | printf("\n"); 71 | } 72 | if (0 != r->bminsz) { 73 | printf("%sBYMINUTE =", buf); 74 | for (j = 0; j < r->bminsz; j++) 75 | printf(" %ld", r->bmin[j]); 76 | printf("\n"); 77 | } 78 | if (0 != r->bmonsz) { 79 | printf("%sBYMONTH =", buf); 80 | for (j = 0; j < r->bmonsz; j++) 81 | printf(" %lu", r->bmon[j]); 82 | printf("\n"); 83 | } 84 | if (0 != r->bmndsz) { 85 | printf("%sBYMONTHDAY =", buf); 86 | for (j = 0; j < r->bmndsz; j++) 87 | printf(" %ld", r->bmnd[j]); 88 | printf("\n"); 89 | } 90 | if (0 != r->bsecsz) { 91 | printf("%sBYSECOND =", buf); 92 | for (j = 0; j < r->bsecsz; j++) 93 | printf(" %lu", r->bsec[j]); 94 | printf("\n"); 95 | } 96 | if (0 != r->bspsz) { 97 | printf("%sBYSETPOS =", buf); 98 | for (j = 0; j < r->bspsz; j++) 99 | printf(" %ld", r->bsp[j]); 100 | printf("\n"); 101 | } 102 | if (0 != r->bwkn) { 103 | printf("%sBYWEEKNO =", buf); 104 | for (j = 0; j < r->bwknsz; j++) 105 | printf(" %ld", r->bwkn[j]); 106 | printf("\n"); 107 | } 108 | if (0 != r->byrdsz) { 109 | printf("%sBYYEARDAY =", buf); 110 | for (j = 0; j < r->byrdsz; j++) 111 | printf(" %ld", r->byrd[j]); 112 | printf("\n"); 113 | } 114 | if (ICALWKDAY_NONE != r->wkst) 115 | printf("%sWKST = %s\n", buf, icalwkdays[r->wkst]); 116 | } 117 | 118 | static void 119 | ical_printcomp(const struct icalcomp *c) 120 | { 121 | size_t i; 122 | 123 | if (c == NULL) 124 | return; 125 | 126 | assert(ICALTYPE__MAX != c->type); 127 | 128 | printf("[%s] Parsed...\n", icaltypes[c->type]); 129 | if (NULL != c->uid) 130 | printf("[%s] UID = %s\n", 131 | icaltypes[c->type], c->uid); 132 | if (NULL != c->tzid) 133 | printf("[%s] TZID = %s\n", 134 | icaltypes[c->type], c->tzid); 135 | if (c->created.type != ICAL_DT_UNSET) 136 | printf("[%s] CREATED = %s", 137 | icaltypes[c->type], 138 | ctime(&c->created.tm)); 139 | if (c->lastmod.type != ICAL_DT_UNSET) 140 | printf("[%s] LASTMODIFIED = %s", 141 | icaltypes[c->type], 142 | ctime(&c->lastmod.tm)); 143 | if (c->dtstamp.type != ICAL_DT_UNSET) 144 | printf("[%s] DTSTAMP = %s", 145 | icaltypes[c->type], 146 | ctime(&c->dtstamp.tm)); 147 | if (0 != c->duration.sign) 148 | printf("[%s] DURATION = P%c%ldW%ldD%ldH%ldM%ldS\n", 149 | icaltypes[c->type], 150 | c->duration.sign > 0 ? '+' : '-', 151 | c->duration.week, c->duration.day, 152 | c->duration.hour, c->duration.min, 153 | c->duration.sec); 154 | if (0 != c->rrule.set) 155 | ical_printrrule(c, ICALTZ__MAX, &c->rrule); 156 | if (c->dtstart.time.type != ICAL_DT_UNSET) 157 | printf("[%s] DTSTART = %s: %s", 158 | icaltypes[c->type], 159 | NULL != c->dtstart.tz ? 160 | c->dtstart.tz->tzid : "(no TZ)", 161 | ctime(&c->dtstart.time.tm)); 162 | for (i = 0; i < c->tzsz; i++) { 163 | if (c->tzs[i].dtstart.type != ICAL_DT_UNSET) 164 | printf("[%s:%s] DTSTART = %s", 165 | icaltypes[c->type], 166 | icaltztypes[c->tzs[i].type], 167 | ctime(&c->tzs[i].dtstart.tm)); 168 | if (0 != c->tzs[i].tzto) 169 | printf("[%s:%s] TZOFFSETTO = %d\n", 170 | icaltypes[c->type], 171 | icaltztypes[c->tzs[i].type], 172 | c->tzs[i].tzto); 173 | if (0 != c->tzs[i].tzfrom) 174 | printf("[%s:%s] TZOFFSETFROM = %d\n", 175 | icaltypes[c->type], 176 | icaltztypes[c->tzs[i].type], 177 | c->tzs[i].tzfrom); 178 | if (0 != c->tzs[i].rrule.set) 179 | ical_printrrule(c, c->tzs[i].type, &c->tzs[i].rrule); 180 | } 181 | 182 | ical_printcomp(c->next); 183 | } 184 | 185 | int 186 | main(int argc, char *argv[]) 187 | { 188 | int fd, c; 189 | struct stat st; 190 | size_t i, sz, rsz = 0; 191 | char *map, *er = NULL; 192 | struct ical *p = NULL; 193 | 194 | #if HAVE_PLEDGE 195 | if (pledge("stdio rpath", NULL) == -1) 196 | err(EXIT_FAILURE, "pledge"); 197 | #endif 198 | 199 | if ((c = getopt(argc, argv, "")) != -1) 200 | return EXIT_FAILURE; 201 | 202 | argc -= optind; 203 | argv += optind; 204 | 205 | if (argc == 0) 206 | return EXIT_FAILURE; 207 | 208 | if ((fd = open(argv[0], O_RDONLY, 0)) == -1) 209 | err(EXIT_FAILURE, "%s", argv[0]); 210 | 211 | #if HAVE_PLEDGE 212 | if (pledge("stdio", NULL) == -1) 213 | err(EXIT_FAILURE, "pledge"); 214 | #endif 215 | 216 | if (fstat(fd, &st) == -1) 217 | err(EXIT_FAILURE, "%s", argv[0]); 218 | 219 | sz = st.st_size; 220 | map = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); 221 | close(fd); 222 | 223 | if (map == MAP_FAILED) 224 | err(EXIT_FAILURE, "%s", argv[0]); 225 | 226 | while (rsz < sz) { 227 | p = ical_parse(argv[0], map, sz, &rsz, &er); 228 | if (p != NULL) { 229 | for (i = 0; i < ICALTYPE__MAX; i++) 230 | ical_printcomp(p->comps[i]); 231 | fflush(stdout); 232 | ical_printfile(STDOUT_FILENO, p); 233 | } else { 234 | warnx("%s", er == NULL ? "memory failure" : er); 235 | break; 236 | } 237 | 238 | /* Skip whitespace. */ 239 | 240 | while (rsz < sz && isspace((unsigned char)map[rsz])) 241 | rsz++; 242 | } 243 | 244 | munmap(map, sz); 245 | ical_free(p); 246 | free(er); 247 | 248 | return p == NULL ? EXIT_FAILURE : EXIT_SUCCESS; 249 | } 250 | -------------------------------------------------------------------------------- /test-nonce.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #if HAVE_ERR 19 | # include 20 | #endif 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "db.h" 30 | 31 | int 32 | main(int argc, char *argv[]) 33 | { 34 | char nonce[17]; 35 | char *np; 36 | size_t i; 37 | enum nonceerr er; 38 | 39 | if (getopt(argc, argv, "") != -1) 40 | return 1; 41 | 42 | argc -= optind; 43 | argv += optind; 44 | 45 | if (argc != 1) 46 | return 1; 47 | 48 | if (!db_init(argv[0], 0)) 49 | errx(1, "db_init"); 50 | 51 | for (i = 0; i < 100; i++) { 52 | snprintf(nonce, sizeof(nonce), "%016zu", i); 53 | if ((er = db_nonce_update(nonce, 0)) == NONCE_ERR) 54 | errx(1, "nonce database failure"); 55 | if (er != NONCE_NOTFOUND) 56 | errx(1, "found nonce!?"); 57 | } 58 | 59 | for (i = 0; i < 100; i++) { 60 | if (!db_nonce_new(&np)) 61 | errx(1, "nonce database failure"); 62 | if ((er = db_nonce_update(np, 1)) == NONCE_ERR) 63 | errx(1, "nonce database failure"); 64 | if (er == NONCE_NOTFOUND) 65 | errx(1, "didn't find nonce!?"); 66 | if ((er = db_nonce_update(np, 1)) == NONCE_ERR) 67 | errx(1, "nonce database failure"); 68 | if (er != NONCE_REPLAY) 69 | errx(1, "replay attack!?"); 70 | } 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /test-rrule.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "libkcaldav.h" 32 | 33 | static void 34 | ical_printcomp(const struct icalcomp *c) 35 | { 36 | size_t i; 37 | 38 | assert(NULL != c); 39 | assert(ICALTYPE_VTIMEZONE == c->type); 40 | assert(NULL != c->tzid); 41 | 42 | printf("TZID = %s\n", c->tzid); 43 | for (i = 0; i < c->tzsz; i++) { 44 | if ( ! c->tzs[i].rrule.set) { 45 | printf("(RRULE not defined.)\n"); 46 | continue; 47 | } 48 | ical_rrule_generate(&c->tzs[i].dtstart, &c->tzs[i].rrule); 49 | } 50 | 51 | if (NULL != c->next) 52 | ical_printcomp(c->next); 53 | } 54 | 55 | int 56 | main(int argc, char *argv[]) 57 | { 58 | int fd, c; 59 | struct stat st; 60 | size_t sz; 61 | char *map; 62 | struct ical *p = NULL; 63 | 64 | if (-1 != (c = getopt(argc, argv, ""))) 65 | return(EXIT_FAILURE); 66 | 67 | argc -= optind; 68 | argv += optind; 69 | 70 | if (0 == argc) 71 | return(EXIT_FAILURE); 72 | 73 | if (-1 == (fd = open(argv[0], O_RDONLY, 0))) { 74 | perror(argv[0]); 75 | return(EXIT_FAILURE); 76 | } else if (-1 == fstat(fd, &st)) { 77 | perror(argv[0]); 78 | close(fd); 79 | return(EXIT_FAILURE); 80 | } 81 | 82 | sz = st.st_size; 83 | map = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); 84 | close(fd); 85 | 86 | if (MAP_FAILED == map) { 87 | perror(argv[0]); 88 | return(EXIT_FAILURE); 89 | } else if (NULL != (p = ical_parse(argv[0], map, sz))) { 90 | if (NULL != p->comps[ICALTYPE_VTIMEZONE]) 91 | ical_printcomp(p->comps[ICALTYPE_VTIMEZONE]); 92 | } 93 | 94 | munmap(map, sz); 95 | ical_free(p); 96 | return(NULL == p ? EXIT_FAILURE : EXIT_SUCCESS); 97 | } 98 | -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Kristaps Dzonsons 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "config.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "libkcaldav.h" 31 | #include "db.h" 32 | #include "server.h" 33 | 34 | const char *const xmls[XML__MAX] = { 35 | "C:calendar", /* XML_CALDAV_CALENDAR */ 36 | "C:calendar-data", /* XML_CALDAV_CALENDAR_DATA */ 37 | "C:comp", /* XML_CALDAV_COMP */ 38 | "C:opaque", /* XML_CALDAV_OPAQUE */ 39 | "B:calendar-proxy-read", /* XML_CALDAVSERV_PROXY_READ */ 40 | "B:calendar-proxy-read-for", /* XML_CALDAVSERV_PROXY_READ_FOR */ 41 | "B:calendar-proxy-write", /* XML_CALDAVSERV_PROXY_WRITE */ 42 | "B:calendar-proxy-write-for", /* XML_CALDAVSERV_PROXY_WRIT... */ 43 | "D:bind", /* XML_DAV_BIND */ 44 | "D:collection", /* XML_DAV_COLLECTION */ 45 | "D:href", /* XML_DAV_HREF */ 46 | "D:multistatus", /* XML_DAV_MULTISTATUS */ 47 | "D:principal", /* XML_DAV_PRINCIPAL */ 48 | "D:privilege", /* XML_DAV_PRIVILEGE */ 49 | "D:prop", /* XML_DAV_PROP */ 50 | "D:propstat", /* XML_DAV_PROPSTAT */ 51 | "D:read", /* XML_DAV_READ */ 52 | "D:read-current-user-privilege-set", /* XML_DAV_READ_CUR... */ 53 | "D:resourcetype", /* XML_DAV_RESOURCETYPE */ 54 | "D:response", /* XML_DAV_RESPONSE */ 55 | "D:status", /* XML_DAV_STATUS */ 56 | "D:unbind", /* XML_DAV_UNBIND */ 57 | "D:write", /* XML_DAV_WRITE */ 58 | }; 59 | 60 | /* 61 | * Provided mainly for Linux that doesn't have arc4random. 62 | * Returns a (non-cryptographic) random number between [0, sz). 63 | */ 64 | static uint32_t 65 | get_random_uniform(size_t sz) 66 | { 67 | #if HAVE_ARC4RANDOM 68 | return arc4random_uniform(sz); 69 | #else 70 | return random() % sz; 71 | #endif 72 | } 73 | 74 | int 75 | xml_ical_putc(int c, void *arg) 76 | { 77 | struct kxmlreq *r = arg; 78 | 79 | return kxml_putc(r, c) == KCGI_OK; 80 | } 81 | 82 | static char 83 | parsehex(char ch) 84 | { 85 | 86 | return(isdigit((unsigned char)ch) ? ch - '0' : 87 | tolower((unsigned char)ch) - 'a' + 10); 88 | } 89 | 90 | static void 91 | http_decode(const char *in, char **rp) 92 | { 93 | size_t i, j, sz; 94 | 95 | sz = strlen(in); 96 | *rp = kcalloc(sz + 1, 1); 97 | 98 | for (i = j = 0; i < sz; i++, j++) { 99 | if ('+' == in[i]) { 100 | (*rp)[j] = ' '; 101 | continue; 102 | } else if ('%' != in[i]) { 103 | (*rp)[j] = in[i]; 104 | continue; 105 | } 106 | if ('\0' == in[i + 1] || 107 | '\0' == in[i + 2] || 108 | ! isalnum((unsigned char)in[i + 1]) || 109 | ! isalnum((unsigned char)in[i + 2])) { 110 | (*rp)[j] = in[i]; 111 | continue; 112 | } 113 | (*rp)[j] = 114 | parsehex(in[i + 1]) << 4 | 115 | parsehex(in[i + 2]); 116 | i += 2; 117 | } 118 | } 119 | 120 | /* 121 | * Decompose a path into the principal, collection, and resource parts. 122 | * We manage this as follows: 123 | * /principal/collection/resource 124 | * For now, the collection can't have directories of its own. 125 | * Return zero on failure (no leading slash), non-zero on success. 126 | * All pointers will be set. 127 | */ 128 | int 129 | http_paths(const char *in, char **pp, char **cp, char **rp) 130 | { 131 | const char *p; 132 | 133 | *pp = *cp = *rp = NULL; 134 | 135 | /* Strip leading absolute path. */ 136 | 137 | if ('/' != in[0]) 138 | return 0; 139 | 140 | in++; 141 | 142 | if ((p = strchr(in, '/')) != NULL) { 143 | *pp = kmalloc(p - in + 1); 144 | memcpy(*pp, in, p - in); 145 | (*pp)[p - in] = '\0'; 146 | in = p + 1; 147 | 148 | if ((p = strrchr(in, '/')) != NULL) { 149 | *cp = kmalloc(p - in + 1); 150 | memcpy(*cp, in, p - in); 151 | (*cp)[p - in] = '\0'; 152 | in = p + 1; 153 | http_decode(in, rp); 154 | } else { 155 | *cp = kstrdup(""); 156 | http_decode(in, rp); 157 | } 158 | } else { 159 | *pp = kstrdup(in); 160 | *cp = kstrdup(""); 161 | *rp = kstrdup(""); 162 | } 163 | 164 | return 1; 165 | } 166 | 167 | /* 168 | * Check the safety of the string according to RFC 3986, section 3.3. 169 | * Note that we don't allow percent-encodings, `&', and the apostrophe. 170 | * This ensures that all words that will show up as path components 171 | * (e.g., the principal name) are in fact already well-formed and 172 | * needn't be re-encoded. 173 | */ 174 | int 175 | http_safe_string(const char *cp) 176 | { 177 | 178 | if ('\0' == *cp) 179 | return(0); 180 | else if (0 == strcmp(cp, ".") || 0 == strcmp(cp, "..")) 181 | return(0); 182 | 183 | for (; '\0' != *cp; cp++) 184 | switch (*cp) { 185 | case ('.'): 186 | case ('-'): 187 | case ('_'): 188 | case ('~'): 189 | case ('!'): 190 | case ('$'): 191 | case ('('): 192 | case (')'): 193 | case ('*'): 194 | case ('+'): 195 | case (','): 196 | case (';'): 197 | case ('='): 198 | case (':'): 199 | case ('@'): 200 | break; 201 | default: 202 | if (isalnum((unsigned char)*cp)) 203 | break; 204 | return(0); 205 | } 206 | 207 | return(1); 208 | } 209 | 210 | int 211 | http_ical_putc(int c, void *arg) 212 | { 213 | struct kreq *r = arg; 214 | 215 | return khttp_putc(r, c) == KCGI_OK; 216 | } 217 | 218 | void 219 | http_error(struct kreq *r, enum khttp c) 220 | { 221 | char nonce[17]; 222 | size_t i; 223 | 224 | khttp_head(r, kresps[KRESP_STATUS], "%s", khttps[c]); 225 | switch (c) { 226 | case (KHTTP_200): 227 | case (KHTTP_201): 228 | case (KHTTP_204): 229 | case (KHTTP_207): 230 | case (KHTTP_304): 231 | khttp_head(r, "DAV", "1, access-control, calendar-access"); 232 | break; 233 | case (KHTTP_401): 234 | /* 235 | * FIXME: we essentially throw away the nonce 236 | * We should be keeping nonces in a database of client 237 | * sessions, then using the increasing (not necessarily 238 | * linearly, apparently) nonce-count value. 239 | */ 240 | for (i = 0; i < sizeof(nonce) - 1; i++) 241 | snprintf(nonce + i, 2, "%01X", 242 | get_random_uniform(128)); 243 | khttp_head(r, kresps[KRESP_WWW_AUTHENTICATE], 244 | "Digest realm=\"%s\", " 245 | "algorithm=\"MD5-sess\", " 246 | "qop=\"auth,auth-int\", " 247 | "nonce=\"%s\"", KREALM, nonce); 248 | break; 249 | default: 250 | break; 251 | } 252 | 253 | khttp_body(r); 254 | } 255 | 256 | /* 257 | * Parse an etag as described in HTTP 7232. 258 | * This simply strips out quotes and returns non-empty strings. 259 | * If the value is a literal, "buf" is set to non-NULL and must be 260 | * freed. 261 | * It works for both "If-Match" and "If-None-Match". 262 | * Returns the parsed etag or NULL on failure. 263 | */ 264 | const char * 265 | http_etag_if_match(const char *val, char **buf) 266 | { 267 | size_t sz; 268 | 269 | assert(val != NULL); 270 | 271 | *buf = NULL; 272 | 273 | /* Zero-length is a no-no. */ 274 | 275 | if ((sz = strlen(val)) == 0) 276 | return NULL; 277 | 278 | /* Quoted-string needs to be \"[.+]\". */ 279 | 280 | if (sz > 1 && val[0] == '"' && val[sz - 1] == '"') { 281 | val++; 282 | sz--; 283 | if (sz == 1) 284 | return NULL; 285 | *buf = kstrdup(val); 286 | (*buf)[sz - 1] = '\0'; 287 | return (*buf); 288 | } 289 | 290 | /* Un-quoted (or badly-quoted) value. */ 291 | 292 | return val; 293 | } 294 | --------------------------------------------------------------------------------