Data-ICal-RDF

 view release on metacpan or  search on metacpan

lib/Data/ICal/RDF.pm  view on Meta::CPAN

    TZNAME             => 'TEXT',
    TZOFFSETFROM       => 'UTC-OFFSET',
    TZOFFSETTO         => 'UTC-OFFSET',
    TZURL              => 'URI',
    ATTENDEE           => 'CAL-ADDRESS',
    CONTACT            => 'TEXT',
    ORGANIZER          => 'CAL-ADDRES',
    'RECURRENCE-ID'    => 'DATE-TIME',
    'RELATED-TO'       => 'TEXT', # actually UID
    URL                => 'URI',
    UID                => 'TEXT',
    EXDATE             => 'DATE-TIME',
    RDATE              => 'DATE-TIME',
    RRULE              => 'RECUR',
    ACTION             => 'LIST*', # actually enum
    REPEAT             => 'INTEGER',
    TRIGGER            => 'DURATION',
    CREATED            => 'DATE-TIME',
    DTSTAMP            => 'DATE-TIME',
    'LAST-MODIFIED'    => 'DATE-TIME',
    SEQUENCE           => 'INTEGER',
    'REQUEST-STATUS'   => 'TEXT',
);

# the icaltzd spec (http://www.w3.org/2002/12/cal/icaltzd#) is pretty
# much derived deterministically from rfc 2445 (now 5445). properties
# are lower case unless hyphenated, in which event they are camelCased.

# however we don't want to use the ical properties on everything,
# notably: created, last modified, geo coords
my %PRED = (
    CREATED         => $NS->dct->created,
    'LAST-MODIFIED' => $NS->dct->modified,
);

# this gives us the correct predicate
sub _predicate_for {
    my ($self, $prop) = @_;

    # get the name
    my $name = lc $prop->key;

    return $PRED{uc $name} if $PRED{uc $name};

    my ($first, @rest) = split /-/, $name;
    $name = $first . join '', map { ucfirst $_ } @rest if @rest;

    $NS->ical->uri($name);
}

# this is a helper for BINARY values.
sub _decode_property {
    my $prop = shift;
    my $enc  = uc($prop->parameters->{ENCODING} || 'BASE64');
    if ($enc eq 'BASE64') {
        # for some reason base64 is not built into Data::ICal.
        return MIME::Base64::decode($prop->value);
    }
    elsif ($enc eq 'QUOTED-PRINTABLE') {
        # QP *is* built in, however.
        return $prop->decoded_value;
    }
    else {
        return;
    }
}

# these get run as faux methods and their job is to insert statements
# into the temporary store.
my %VALS = (
    BINARY        => sub {
        # ohhhhhh this one's gonna be fun.
        my ($self, $prop, $s) = @_;

        # get the literal value
        my $val = _decode_property($prop);
        return unless defined $val;

        my $param  = $prop->parameters;

        # get a suitable content type
        my ($type) = (lc($param->{FMTTYPE} || 'application/octet-stream') =~
                          /^\s*(.*?)(?:\s*;.*)?$/);

        # too bad there isn't a standardized parameter for file names
        my $name = $param->{'X-FILENAME'} || $param->{'X-APPLE-FILENAME'};

        # this is where the securi-tah happens, folks.
        if (defined $name) {
            # remove any space padding
            $name =~ s/^\s*(.*?)\s*$/$1/;
            # scrub the filename of any naughty path info
            $name = Path::Class::File->new($name)->basename if $name ne '';

            # kill the name if all that's left is an empty string
            undef $name if $name eq '';
        }

        # turn the val into an IO object
        my $io = IO::Scalar->new(\$val);

        # now try to resolve the attachment
        my $o = eval { $self->resolve_binary->($self, $io, $type, $name) };
        $self->throw("resolve_binary callback failed: $@") if $@;
        $self->throw('resolve_binary callback returned an invalid value')
              unless _is_really($o, 'RDF::Trine::Node');

        my $p = $self->_predicate_for($prop);
        $self->model->add_statement(statement($s, $p, $o));

        $val;
    },
    BOOLEAN       => sub {
        my ($self, $prop, $s) = @_;

        # postel's law
        my $x = 1 if $prop->value =~ /1|true|on|yes/i;

        # output
        my $o = literal($x ? 'true' : 'false', undef, $NS->xsd->boolean);
        my $p = $self->_predicate_for($prop);



( run in 0.943 second using v1.01-cache-2.11-cpan-df04353d9ac )