module CalDAV
class Calendar
attr_accessor :uri, :options
def initialize(uri, options = {})
self.uri = URI.parse(uri)
self.options = options
end
# Create a new calendar
#
# == Options
#
# * :displayname: A display name for the calendar
# * :description: A description for the calendar
# * :username: Username used for authentication
# * :password: Password used for authentication
#
def self.create(uri, options = {})
parsed_uri = URI.parse(uri)
response = Net::HTTP.start(parsed_uri.host, parsed_uri.port) do |http|
request = Net::HTTP::Mkcalendar.new(parsed_uri.path)
request.body = CalDAV::Request::Mkcalendar.new(options[:displayname], options[:description]).to_xml
request.basic_auth options[:username], options[:password] unless options[:username].blank? && options[:password].blank?
http.request request
end
raise CalDAV::Error.new(response.message, response) if response.code != '201'
self.new(uri, options)
end
def delete
perform_request Net::HTTP::Delete
end
def properties
perform_request Net::HTTP::Propfind
end
def add_event(calendar)
request = Net::HTTP::Put.new("#{uri.path}/#{calendar.events.first.uid}.ics")
request.add_field "If-None-Match", "*"
request.body = calendar.to_ical
response = perform_request request
raise CalDAV::Error.new(response.message, response) if response.code != '201'
true
end
# TODO: check that supported-report-set includes REPORT
def events(param)
request = new_request Net::HTTP::Report do |request|
request.body = CalendarQuery.new.event(param).to_xml
end
response = perform_request request
events = []
body = REXML::Document.new(response.body)
body.root.add_namespace 'dav', 'DAV:'
body.root.add_namespace 'caldav', 'urn:ietf:params:xml:ns:caldav'
body.elements.each("dav:multistatus/dav:response") do |element|
calendar = Icalendar::Parser.new(element.elements["dav:propstat/dav:prop/caldav:calendar-data"].text).parse.first
calendar.events.each do |event|
event.caldav = {
:etag => element.elements["dav:propstat/dav:prop/dav:getetag"].text,
:href => element.elements["dav:href"].text
}
events += calendar.events
end
end
events
end
private
def new_request(clazz, &block)
returning clazz.new(uri.path) do |request|
yield request if block_given?
end
end
def prepare_request(request)
request.basic_auth options[:username], options[:password] unless options[:username].blank? && options[:password].blank?
request
end
def perform_request(request)
request = new_request(request) if request.is_a? Class
Net::HTTP.start(uri.host, uri.port) do |http|
http.request prepare_request(request)
end
end
end
end