caldav::calendars proc parse (public)

 caldav::calendars[i] parse text

Defined in packages/xotcl-core/tcl/01-debug-procs.tcl

Parse the ical file passed in as string and output a list of CalItem objects. The attributes specified in opaque_tags are passed as opaque values. Opaque attributes are not shown in OpenACS, but output when the calendar item is requested in ical format.

Parameters:
text (required)
the text do be parsed TODO: this should go into ical-procs..... but first check dependencies - $item add_ical_var .... - ::caldav::calitem new

Testcases:
No testcase defined.
Source code:
#
# Parse the ical file passed in as string and output a list of
# CalItem objects. The attributes specified in opaque_tags are
# passed as opaque values. Opaque attributes are not shown in
# OpenACS, but output when the calendar item is requested in
# ical format.
#
# @param text the text do be parsed
#
# TODO: this should go into ical-procs..... but first check dependencies
# - $item add_ical_var ....
# - ::caldav::calitem new

set parse_error 0
set in_valarm 0
set in_vevent 0
set item_list {}
#opaque_tags are the tags that will be persisted in ical_vars
set opaque_re ^([join ${:opaque_tags} |]):(.*)$
:debug opaque_re=$opaque_re
set prefix ""
regsub -all "\n " $text "" text
regsub -all "\r" $text "" text
foreach line [split $text \n] {
    ns_log notice "======== <$line>"
    if {$in_valarm} {
        #
        # treat everything in an VALARM as opaque for the time being
        #
        append :OPAQUE-VALARM $line\r\n
        if { $line eq "END:VALARM"} {
            # end of valarm section
            set in_valarm 0
            $item add_ical_var OPAQUE-VALARM "" [set :OPAQUE-VALARM]
        }
    } elseif$in_vevent && [regexp $opaque_re $line _ tag value] } {
        $item add_ical_var $tag "" [::xo::ical ical_to_text $value]
    } elseif$line eq "BEGIN:VEVENT" } {
        # reset values
        set in_valarm 0
        set in_vevent 1
        set r_error 0
        #
        #setting a creation date is only needed for debugging
        #
        # GN TODO: DO NOT HARDCODE calitem HERE!
        #
        set item [::caldav::calitem new  -description ""  -creation_date [xo::ical clock_to_utc [clock seconds]]]
        $item destroy_on_cleanup
        #$item set description ""
        #$item set creation_date  [xo::ical clock_to_utc [clock seconds]]
        lappend item_list $item
    } elseif$line eq {BEGIN:VALARM} } {
        # begin of VALARM section
        set in_valarm 1
        set :OPAQUE-VALARM $line\r\n
    } elseif$in_vevent && [regexp {^LOCATION[^:]*:(.*)$} $line _ location] } {
        $item location set [::xo::ical ical_to_text $location]
    } elseif$in_vevent && [regexp {^SUMMARY[^:]*:(.*)$} $line _ title] } {
        $item summary set [::xo::ical ical_to_text $title]
    } elseif$in_vevent && [regexp {^(DTSTAMP|UID|LAST-MODIFIED)[^:]*:(.*)$} $line _ field entry] } {
        $item [string tolower $field] set $entry
    } elseif$in_vevent && [regexp {^DTSTART(\;TZID.*)?:([0-9]+)T+([0-9]+)(Z?).*$} $line _ tz date time utc] } {
        if {[string length $date] != 8 || [string length $time] != 6} {
            set parse_error 1
        } else {
            $item dtstart set [:set_date_time $date $time [expr {$utc ne ""}] $tz]
        }
    } elseif$in_vevent && [regexp {^DTSTART.+DATE[^:]*:([0-9]+).*$} $line _ date] } {
        if {[string length $date] != 8} {
            set parse_error 1
        } else {
            $item dtstart set [:set_date_time $date "0000" 0 ""]
        }
    } elseif$in_vevent && [regexp {^DTEND(\;TZID.*)?[^:]*:([0-9]+)T+([0-9]+)(Z?).*$} $line _ tz date time utc] } {
        if {[string length $date] != 8 || [string length $time] != 6} {
            set parse_error 1
        } else {
            $item dtend set [:set_date_time $date $time [expr {$utc ne ""}] $tz]
        }
    } elseif$in_vevent && [regexp {^DTEND.+?DATE[^:]*:([0-9]+).*$} $line _ date ] } {
        if {[string length $date] != 8} {
            set parse_error 1
        } else {
            $item dtend set [:set_date_time $date "0000" 0 ""]
        }
    } elseif {$in_vevent && [regexp {^DURATION[^:]*:P(.*)$} $line _ duration] } {
        $item duration set 0
        if {[regexp {^([0-9]+)W(.*)$} $duration _ units duration]} {
            $item incr duration [expr {[util::trim_leading_zeros $units]*24*3600*7}]
        }
        if {[regexp {([0-9]+)D(.*)$} $duration _ units duration]} {
            $item incr duration [expr {[util::trim_leading_zeros $units]*24*3600}]
        }
        if {[regexp {([0-9]+)H(.*)$} $duration _ units duration]} {
            $item incr duration [expr {[util::trim_leading_zeros $units]*3600}]
        }
        if {[regexp {([0-9]+)M(.*)$} $duration _ units duration]} {
            $item incr duration [expr {[util::trim_leading_zeros $units]*60}]
        }
        if {[regexp {([0-9]+)S(.*)$} $duration _ units duration]} {
            $item incr duration [util::trim_leading_zeros $units]
        }
    } elseif {$in_vevent && [regexp {^DESCRIPTION[^:]*:(.*)$} $line _ desc] } {
        $item description set [::xo::ical ical_to_text $desc]
    }  elseif {$in_vevent && [regexp {^URL[^:]*:(.*)$} $line _ desc] } {
        $item add_ical_var URL "" [::xo::ical ical_to_text $desc]
    } elseif$in_vevent && [regexp {^RRULE[^:]*:(.*)$} $line _ recurrule] } {
        $item parse RRULE $recurrule
    } elseif$in_vevent && $line eq "END:VEVENT" } {
        set in_vevent 0
        $item finish $parse_error
    } elseif {$in_vevent && [regexp {^X-APPLE-STRUCTURED-LOCATION(\;[^:]+|):(.*)$} $line . params value]} {
        #
        # Special handling for Apple ical implementations
        #
        $item add_ical_var X-APPLE-STRUCTURED-LOCATION $params $value
    } else {
        # Ignore unused ical lines
        :debug "ical parse ignores <$line>"
    }
}
return $item_list
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: