Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
9 check-ins
|
2026-10-12
| ||
| 20:05 |
Hold text values in growable buffers instead of fixed arrays
ics_component_t carried 16 KiB per text value and 64 attendee slots per component, so the calendar structure weighed 28 MiB and ics_parse() faulted all of it in on every run: showing a one-event invitation cost 7273 page reclaims and a 30 MiB peak RSS. The text values are now sb_t buffers and the attendee list a vec_t, both taken from btk, and the component list is a vec_t as well, which also lifts the value limits. Content lines are split into strview_t views of the unfolded line instead of being copied into a 17 KiB ics_prop_t, and folding appends straight into a growable buffer, which removes MAX_LINE too. What is left are format bounds and two defensive ceilings: MAX_EVENTS, raised to 10000, and MAX_TZONES. Unescaping now happens on the way into the destination buffer (ics_sb_cat_unescaped) rather than mutating a private copy, so the views can stay const. ics_calendar_fini() releases the result and main() calls it. vendor/btk holds sb.{c,h}, strview.h and vec.h from btk at abaae1e5, unmodified but for a missing final newline in strview.h. hash, stringset, strhash and xmalloc are not needed here. The output is byte-identical to the previous revision on all thirteen fixtures. The visible differences are that the attendee list is no longer capped at 64 and that truncation now starts at 10000 components. MAX_INPUT was renamed to MAX_DOCUMENT because limits.h, now reached through strview.h, defines MAX_INPUT for terminal input. leaf check-in: 82f8351209 user: bapt tags: trunk | |
| 19:44 |
Resolve TZID from the VTIMEZONE the file carries
Outlook, libical and others attach a VTIMEZONE for every zone they name, which is how a TZID that exists in no time zone database still has a meaning. Those definitions were skipped, so a self-contained calendar showed "12:00 (Custom Zone)" where it could have shown the real instant. The VTIMEZONE blocks are now parsed and kept, and a date whose TZID the C library cannot resolve is rewritten as the equivalent UTC value before display. Normalising at parse time keeps the rest of the program unchanged: the display code and the duration computation already handle UTC values, and a field that stays unresolved is still shown as a wall clock followed by its zone name. Only the rule shape time zone definitions actually use is understood: FREQ=YEARLY with BYMONTH and either BYMONTHDAY or BYDAY=[[+-]n]DD. The DAYLIGHT and STANDARD transitions are evaluated for the year at hand, so the wrapped period of a southern hemisphere zone works too. Anything else, a single observance included, falls back to the fixed offset of the definition. The tests cover a southern hemisphere zone, a northern one that is still on DST after the local zone has switched, a constant offset, a BYMONTHDAY rule, a duration inside an embedded zone, and a rule that cannot be read and must fall back. check-in: 9776ef15d3 user: bapt tags: trunk | |
| 19:38 |
Read the stream in memory, accepting lone CR line endings
The reader used getline() and kept one line of look-ahead in static storage. It was therefore not reentrant, and it understood LF and CRLF only: a file using a bare CR, which RFC 5545 forbids but some producers emit, was not split at all, so the whole document looked like a single line and icsviewer reported that it held no calendar. The stream is now read into memory once and lines are handed out from that buffer, terminated by LF, CRLF or CR. Rewinding the position replaces the look-ahead buffer, so no parser state is left in static storage, and getline() is no longer needed. A 64 MiB ceiling guards against an implausibly large attachment. Adds icsviewer(1), installed into PREFIX/man/man1. Writing it turned up a missing MANDIR definition in the Makefile: the new recipe expanded it to nothing and make install wrote the page into $(DESTDIR) itself. The tests now cover CRLF, lone CR and mixed line endings, and the man page is checked with mandoc -Tlint. check-in: 3156f2d4ff user: bapt tags: trunk | |
| 19:33 |
Show recurrence exceptions, unescape calendar properties, fix the CLI
EXDATE, which removes occurrences from a recurring series, was parsed but never displayed; the dates are now listed under the recurrence, and only the first six to keep a long series readable. Several EXDATE lines are merged instead of the last one winning. TEXT values at calendar level were the only ones left escaped, so X-WR-CALNAME:Équipe\, développement kept its backslash. They now go through ics_unescape() like component properties already did. The command line was inconsistent: --help wrote to stderr, an unknown option was silently ignored and a second file name was silently dropped. --help now writes to stdout and exits 0, while an unknown option or more than one operand is reported on stderr with exit 1. "-" is accepted as an explicit request for stdin. check-in: ce532433d8 user: bapt tags: trunk | |
| 19:28 |
Resolve Windows time zone names, show durations and moved occurrences
Outlook and Exchange write TZID="W. Europe Standard Time" and other Windows zone names, which no tzdata installation can resolve, so such invitations showed the wall clock followed by the raw zone name. The names are now translated to their IANA equivalent through a table generated from the Unicode CLDR windowsZones data (territory="001", the default mapping). tools/gen-windows-zones.py regenerates tz_windows.c, the only generated file in the tree. The IANA path keeps its validation and the Windows path only ever passes setenv() a name coming from our own table. Adds a "Durée" line, taken from DURATION when it replaces DTEND (or DUE, for tasks) and otherwise computed from the start and end values. All-day intervals are counted in calendar days so that an event covering a DST change is not reported as 23 hours long. Adds a line marking RECURRENCE-ID, which designates one moved occurrence of a recurring event and was previously ignored. Raises the fixed-size limits: MAX_VAL from 8 to 16 KiB and MAX_LINE from 8 to 24 KiB, so that long descriptions survive; the calendar structure grows to 28 MiB and stays heap allocated. Bounds the numbers accepted by the new DURATION parser: strtol() saturates at LONG_MAX and the unbounded multiply overflowed, as reported by UBSan for DURATION:P99999999999999999999D. check-in: d75d71b8bd user: bapt tags: trunk | |
| 19:22 |
Parse nested components, honour quoted parameters, harden TZID handling
The viewer displayed the VALARM's DESCRIPTION instead of the VEVENT's: parse_component() knew nothing about nested components, so VALARM and VTIMEZONE properties leaked into the enclosing scope. Nested and unknown components are now skipped whole. ics_split_prop() split on the first colon wherever it occurred, including inside a DQUOTE-delimited parameter value, which is exactly what ORGANIZER;SENT-BY="..." looks like in Exchange invitations. It also derived the parameter length by subtracting pointers into two different objects (computed 9505 instead of 33), undefined behaviour that only appeared to work because strlcpy stops at NUL. TZID was passed to setenv("TZ", ...) unvalidated. TZ=":path" is POSIX for "read this file", so an attached ICS could name any file, and an unknown zone produced dates such as "30 Nov -001 00:09 LMT". TZIDs are now restricted to IANA-shaped names that exist in zoneinfo; anything else is shown as a wall clock followed by the zone name in parentheses. Other fixes: a stream with no VCALENDAR exited 0 claiming there were no events (now reported on stderr, exit 1); dates used the C locale's month names ("15 Jun 2026") while the whole UI is French (now fixed French names, independent of LC_TIME); components past 256 and attendees past 64 were dropped silently (now reported); the 20 MiB ics_calendar_t was a stack object in main(); a leading blank line was mistaken for EOF; unfolding removed every leading white space instead of the single one introduced by the fold (RFC 5545 section 3.1); RRULE was parsed with strstr(), ignoring INTERVAL for monthly/yearly rules and losing BYDAY ordinals such as "2SU"; ics_fold_line() was dead code and ics_attendee_t::is_organizer was never assigned. Build: bmake gives its built-in .c.o suffix rule precedence over a user "%.o: %.c" pattern rule, so the Makefile uses a suffix rule. It now honours CC/CFLAGS/CPPFLAGS/LDFLAGS from the environment, tracks header dependencies (-MMD -MP) and gains test, sanitize and debug targets. Adds tests/run.sh (65 checks) with fixtures covering folding, CRLF, blank lines, quoted parameters, nested components, hostile TZIDs, invalid dates and the size limits. check-in: 114adc47a6 user: bapt tags: trunk | |
|
2026-08-18
| ||
| 15:01 |
Fix build: drop -lbsd and fix strtonum err type
- Remove -lbsd from LDLIBS; not needed on native BSD (strtonum, strlcpy are in libc) and not available on this system. - Change strtonum error pointer from int* to const char** to match the prototype, clearing -Wincompatible-pointer-types warnings. check-in: b668103f97 user: bapt tags: trunk | |
| 14:49 | Initial import of icsviewer — ICS (iCalendar) viewer written in C check-in: 97fc3ff853 user: bapt tags: trunk | |
| 14:49 | initial empty check-in check-in: 3bb7962373 user: bapt tags: trunk | |