sabredav_client 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/CHANGELOG.rdoc +8 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +46 -0
- data/README.md +131 -0
- data/Rakefile +6 -0
- data/lib/sabredav_client/calendar.rb +111 -0
- data/lib/sabredav_client/client.rb +57 -0
- data/lib/sabredav_client/errors/errors.rb +38 -0
- data/lib/sabredav_client/events.rb +97 -0
- data/lib/sabredav_client/format.rb +54 -0
- data/lib/sabredav_client/net.rb +15 -0
- data/lib/sabredav_client/principal.rb +36 -0
- data/lib/sabredav_client/request.rb +97 -0
- data/lib/sabredav_client/version.rb +3 -0
- data/lib/sabredav_client/xml_request_builder/base.rb +17 -0
- data/lib/sabredav_client/xml_request_builder/mkcalendar.rb +25 -0
- data/lib/sabredav_client/xml_request_builder/mkcol_principal.rb +28 -0
- data/lib/sabredav_client/xml_request_builder/post_sharing.rb +41 -0
- data/lib/sabredav_client/xml_request_builder/propfind_calendar.rb +41 -0
- data/lib/sabredav_client/xml_request_builder/propfind_owner.rb +19 -0
- data/lib/sabredav_client/xml_request_builder/proppatch_owner.rb +23 -0
- data/lib/sabredav_client/xml_request_builder/report_event_changes.rb +22 -0
- data/lib/sabredav_client/xml_request_builder/report_vevent.rb +30 -0
- data/lib/sabredav_client/xml_request_builder/report_vtodo.rb +20 -0
- data/lib/sabredav_client/xml_request_builder.rb +6 -0
- data/lib/sabredav_client.rb +12 -0
- data/sabredav_client.gemspec +33 -0
- data/spec/fixtures/calendar_fetch_changes.xml +26 -0
- data/spec/fixtures/calendar_info.xml +14 -0
- data/spec/fixtures/event.ics +23 -0
- data/spec/fixtures/events_find_multiple.xml +51 -0
- data/spec/fixtures/events_owner.xml +12 -0
- data/spec/fixtures/xml_request_builder/mkcalendar.xml +9 -0
- data/spec/fixtures/xml_request_builder/mkcol_principal.xml +12 -0
- data/spec/fixtures/xml_request_builder/post_sharing.xml +18 -0
- data/spec/fixtures/xml_request_builder/propfind_calendar/all_properties.xml +8 -0
- data/spec/fixtures/xml_request_builder/propfind_owner.xml +6 -0
- data/spec/fixtures/xml_request_builder/proppatch_owner.xml +8 -0
- data/spec/fixtures/xml_request_builder/report_event_changes.xml +8 -0
- data/spec/sabredav_client/calendar_spec.rb +101 -0
- data/spec/sabredav_client/client_spec.rb +41 -0
- data/spec/sabredav_client/events_spec.rb +91 -0
- data/spec/sabredav_client/principal_spec.rb +38 -0
- data/spec/sabredav_client/request_spec.rb +55 -0
- data/spec/sabredav_client/xml_request_builder_specs/base_spec.rb +30 -0
- data/spec/sabredav_client/xml_request_builder_specs/mkcalendar_spec.rb +13 -0
- data/spec/sabredav_client/xml_request_builder_specs/mkcol_principal_spec.rb +13 -0
- data/spec/sabredav_client/xml_request_builder_specs/post_sharing_spec.rb +15 -0
- data/spec/sabredav_client/xml_request_builder_specs/propfind_calendar_spec.rb +24 -0
- data/spec/sabredav_client/xml_request_builder_specs/propfind_owner_spec.rb +14 -0
- data/spec/sabredav_client/xml_request_builder_specs/proppatch_owner_spec.rb +14 -0
- data/spec/sabredav_client/xml_request_builder_specs/report_event_changes_spec.rb +15 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +8 -0
- metadata +185 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5a3c684d5190fe9608d786b4619fc6494ead48b7
|
4
|
+
data.tar.gz: b44836242e58f0ed59c074f71b76b1ac1f145fa2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 31bb29f8199f0a2e1fc1c3fc46120951aa79131d631637eedcf3e5d61acf463418f39684a24341a24cecb9050e6b7bdfd0a1f744aa89c07f193e05fc91ecc955
|
7
|
+
data.tar.gz: 2ac0d0920b6ae3500f8cef24e6396756fba06bcafda200bafe0e0cf3509ff27839528f75af580fd0c716dc4640da226143bfb88f4886bf751de27dd9601d1b00
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/CHANGELOG.rdoc
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sabredav_client (0.2.6.0)
|
5
|
+
builder (~> 3.2)
|
6
|
+
icalendar (~> 2.4)
|
7
|
+
net-http-digest_auth (~> 1.4)
|
8
|
+
uuid (~> 2.3)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
builder (3.2.2)
|
14
|
+
diff-lcs (1.2.5)
|
15
|
+
fakeweb (1.3.0)
|
16
|
+
icalendar (2.4.0)
|
17
|
+
macaddr (1.7.1)
|
18
|
+
systemu (~> 2.6.2)
|
19
|
+
net-http-digest_auth (1.4)
|
20
|
+
rspec (3.5.0)
|
21
|
+
rspec-core (~> 3.5.0)
|
22
|
+
rspec-expectations (~> 3.5.0)
|
23
|
+
rspec-mocks (~> 3.5.0)
|
24
|
+
rspec-core (3.5.2)
|
25
|
+
rspec-support (~> 3.5.0)
|
26
|
+
rspec-expectations (3.5.0)
|
27
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
+
rspec-support (~> 3.5.0)
|
29
|
+
rspec-mocks (3.5.0)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.5.0)
|
32
|
+
rspec-support (3.5.0)
|
33
|
+
systemu (2.6.5)
|
34
|
+
uuid (2.3.8)
|
35
|
+
macaddr (~> 1.0)
|
36
|
+
|
37
|
+
PLATFORMS
|
38
|
+
ruby
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
fakeweb (~> 1.3)
|
42
|
+
rspec (~> 3.5)
|
43
|
+
sabredav_client!
|
44
|
+
|
45
|
+
BUNDLED WITH
|
46
|
+
1.12.5
|
data/README.md
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
#Ruby CalDAV library named "agcaldav"
|
2
|
+
**agcaldav is a CalDAV library based on martinpovolny/ruby-caldav and 4fthawaiian/ruby-caldav and collectiveidea/caldav**
|
3
|
+
|
4
|
+
**Please keep in mind, agcaldav ist still under heavy development and still not finished...**
|
5
|
+
|
6
|
+
##Usage Events
|
7
|
+
|
8
|
+
First, you've to install the gem
|
9
|
+
|
10
|
+
gem install agcaldav
|
11
|
+
|
12
|
+
and require it
|
13
|
+
|
14
|
+
require "agcaldav"
|
15
|
+
|
16
|
+
Next you have to obtain the URI, username and password to a CalDAV-Server. If you don't have one try RADICALE (https://github.com/agilastic/Radicale). It's small, simple and written in python. In the following steps I'm using the default params of Radical.
|
17
|
+
|
18
|
+
|
19
|
+
Now you can e.g. create a new AgCalDAV-Client:
|
20
|
+
|
21
|
+
cal = AgCalDAV::Client.new(:uri => "http://localhost:5232/user/calendar", :user => "user" , :password => "")
|
22
|
+
|
23
|
+
Alternatively, the proxy parameters can be specified:
|
24
|
+
|
25
|
+
cal = AgCalDAV::Client.new(:uri => "http://localhost:5232/user/calendar",:user => "user" , :password => "password", :proxy_uri => "http://my-proxy.com:8080")
|
26
|
+
|
27
|
+
|
28
|
+
####Create an Event
|
29
|
+
|
30
|
+
result = cal.create_event(:start => "2012-12-29 10:00", :end => "2012-12-30 12:00", :title => "12345", :description => "12345 12345")
|
31
|
+
|
32
|
+
Analyze result:
|
33
|
+
|
34
|
+
>> result
|
35
|
+
=> #<Icalendar::Event:0x007ff653b47520 @name="VEVENT", @components={}, @properties={"sequence"=>0, "dtstamp"=>#<DateTime: 2012-12-30T19:59:04+00:00 (26527957193/10800,0/1,2299161)>, "description"=>"sdkvjsdf sdkf sdkfj sdkf dsfj", "dtend"=>#<DateTime: 2012-12-30T12:00:00+00:00 (2456292/1,0/1,2299161)>, "dtstart"=>#<DateTime: 2012-12-29T10:00:00+00:00 (29475491/12,0/1,2299161)>, "summary"=>"12345", "uid"=>"e795c480-34e0-0130-7d1d-109add70606c", "x-radicale_name"=>"e795c480-34e0-0130-7d1d-109add70606c.ics"}>
|
36
|
+
|
37
|
+
>> result.class
|
38
|
+
=> Icalendar::Event
|
39
|
+
|
40
|
+
|
41
|
+
get UID of this Event:
|
42
|
+
|
43
|
+
>> result.uid
|
44
|
+
=> "e795c480-34e0-0130-7d1d-109add70606c"
|
45
|
+
|
46
|
+
|
47
|
+
####Find an Event (via UUID)
|
48
|
+
|
49
|
+
result = cal.find_event("e795c480-34e0-0130-7d1d-109add70606c")
|
50
|
+
|
51
|
+
>> result.class
|
52
|
+
=> Icalendar::Event
|
53
|
+
|
54
|
+
|
55
|
+
####Find Events within time interval
|
56
|
+
|
57
|
+
result = cal.find_events(:start => "2012-10-01 08:00", :end => "2013-01-01")
|
58
|
+
|
59
|
+
>> result
|
60
|
+
=> [#<Icalendar::Event:0x007f8ad11cfdf0 @name="VEVENT", @components={}, @properties={"sequence"=>0, "dtstamp"=>#<DateTime: 2012-12-31T13:44:10+00:00 (4244474429/1728,0/1,2299161)>, "description"=>"sdkvjsdf sdkf sdkfj sdkf dsfj", "dtend"=>#<DateTime: 2012-12-30T12:00:00+00:00 (2456292/1,0/1,2299161)>, "dtstart"=>#<DateTime: 2012-12-29T10:00:00+00:00 (29475491/12,0/1,2299161)>, "summary"=>"12345", "uid"=>"b2c45e20-3575-0130-7d2e-109add70606c", "x-radicale_name"=>"b2c45e20-3575-0130-7d2e-109add70606c.ics"}>, #<Icalendar::Event:0x007f8ad10d7dd0 @name="VEVENT", @components={}, @properties={"sequence"=>0, "dtstamp"=>#<DateTime: 2012-12-31T13:44:10+00:00 (4244474429/1728,0/1,2299161)>, "uid"=>"b2c45e20-3575-0130-7d2e-109add70606c", "x-radicale_name"=>"b2c45e20-3575-0130-7d2e-109add70606c.ics"}>]
|
61
|
+
|
62
|
+
>> result.class
|
63
|
+
=> Array
|
64
|
+
|
65
|
+
>> result.count
|
66
|
+
=> 2
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
####Update Event
|
71
|
+
|
72
|
+
event = {:start => "2012-12-29 10:00", :end => "2012-12-30 12:00", :title => "12345", :description => "sdkvjsdf sdkf sdkfj sdkf dsfj"}
|
73
|
+
# set UUID
|
74
|
+
event[:uid] => "e795c480-34e0-0130-7d1d-109add70606c"
|
75
|
+
c = cal.update_event(event)
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
####Delete Event
|
80
|
+
|
81
|
+
cal.delete_event("e795c480-34e0-0130-7d1d-109add70606c")
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
##Usage ToDo
|
87
|
+
|
88
|
+
####not finished ATM
|
89
|
+
Have a look tomorrow...
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
##Work to be done ...
|
94
|
+
|
95
|
+
1. find and notify if overlapping events
|
96
|
+
2. code cleanup -> more ActiveRecord style
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
##Testing
|
102
|
+
|
103
|
+
agcaldav will use RSpec for its test coverage. Inside the gem
|
104
|
+
directory, you can run the specs for RoR 3.x with:
|
105
|
+
|
106
|
+
rake spec
|
107
|
+
(will be implemented in > v0.2.5)
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
##Licence
|
112
|
+
|
113
|
+
MIT
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
##Contributors
|
118
|
+
|
119
|
+
[Check all contributors][c]
|
120
|
+
|
121
|
+
|
122
|
+
1. Fork it.
|
123
|
+
2. Create a branch (`git checkout -b my_feature_branch`)
|
124
|
+
3. Commit your changes (`git commit -am "bugfixed abc..."`)
|
125
|
+
4. Push to the branch (`git push origin my_feature_branch`)
|
126
|
+
5. Open a [Pull Request][1]
|
127
|
+
6. Enjoy a refreshing Club Mate and wait
|
128
|
+
|
129
|
+
[c]: https://github.com/agilastic/agcaldav/contributors
|
130
|
+
[1]: https://github.com/agilastic/agcaldav/pulls/
|
131
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
module SabredavClient
|
2
|
+
|
3
|
+
class Calendar
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(data)
|
7
|
+
@client = SabredavClient::Client.new(data)
|
8
|
+
end
|
9
|
+
|
10
|
+
def events
|
11
|
+
@events ||= SabredavClient::Events.new(client)
|
12
|
+
end
|
13
|
+
|
14
|
+
def info
|
15
|
+
header = {content_type: "application/xml"}
|
16
|
+
body = SabredavClient::XmlRequestBuilder::PROPFINDCalendar.new(properties: [:displayname, :sync_token, :getctag]).to_xml
|
17
|
+
|
18
|
+
req = client.create_request(:propfind, header: header, body: body)
|
19
|
+
res = req.run
|
20
|
+
|
21
|
+
SabredavClient::Errors::errorhandling(res)
|
22
|
+
|
23
|
+
xml = REXML::Document.new(res.body)
|
24
|
+
{
|
25
|
+
displayname: REXML::XPath.first(xml, "//d:displayname").text,
|
26
|
+
ctag: REXML::XPath.first(xml, "//cs:getctag").text,
|
27
|
+
sync_token: REXML::XPath.first(xml, "//d:sync-token").text
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def create(displayname: "", description: "")
|
32
|
+
body = SabredavClient::XmlRequestBuilder::Mkcalendar.new(displayname, description).to_xml
|
33
|
+
header = {dav: "resource-must-be-null", content_type: "application/xml"}
|
34
|
+
|
35
|
+
req = client.create_request(:mkcalendar, header: header, body: body)
|
36
|
+
|
37
|
+
res = req.run
|
38
|
+
|
39
|
+
SabredavClient::Errors.errorhandling(res)
|
40
|
+
info
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete
|
44
|
+
req = client.create_request(:delete)
|
45
|
+
res = req.run
|
46
|
+
|
47
|
+
if res.code.to_i.between?(200,299)
|
48
|
+
true
|
49
|
+
else
|
50
|
+
SabredavClient::Errors::errorhandling(res)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def share(adds: [], removes: [], summary: nil, common_name: nil,
|
55
|
+
privilege: "write-read", type: nil)
|
56
|
+
|
57
|
+
header = {content_length: "xxxx", content_type: "application/xml"}
|
58
|
+
body = SabredavClient::XmlRequestBuilder::PostSharing.new(
|
59
|
+
adds, summary, common_name, privilege, removes).to_xml
|
60
|
+
|
61
|
+
req = client.create_request(:post, header: header, body: body)
|
62
|
+
|
63
|
+
res = req.run
|
64
|
+
|
65
|
+
raise SabredavClient::Errors::ShareeTypeNotSupportedError if type && type != :email
|
66
|
+
|
67
|
+
if res.code.to_i.between?(200,299)
|
68
|
+
true
|
69
|
+
else
|
70
|
+
SabredavClient::Errors::errorhandling(res)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def fetch_changes(sync_token)
|
75
|
+
|
76
|
+
body = SabredavClient::XmlRequestBuilder::ReportEventChanges.new(sync_token).to_xml
|
77
|
+
header = {content_type: "application/xml"}
|
78
|
+
|
79
|
+
req = client.create_request(:report, header: header, body: body)
|
80
|
+
|
81
|
+
res = req.run
|
82
|
+
|
83
|
+
SabredavClient::Errors::errorhandling(res)
|
84
|
+
|
85
|
+
changes = []
|
86
|
+
deletions = []
|
87
|
+
xml = REXML::Document.new(res.body)
|
88
|
+
|
89
|
+
#FIXME This is so damn ugly, but at least it`s working now
|
90
|
+
REXML::XPath.each(xml, "//d:response/", {"d"=> "DAV:"}) do |response|
|
91
|
+
entry = REXML::Document.new.add(response)
|
92
|
+
if (REXML::XPath.first(entry, "//d:status").text == "HTTP/1.1 404 Not Found")
|
93
|
+
deletions.push(
|
94
|
+
REXML::XPath.first(entry, "//d:href").text.to_s.split("/").last)
|
95
|
+
else
|
96
|
+
changes.push(
|
97
|
+
{
|
98
|
+
uri: REXML::XPath.first(entry, "//d:href").text.split("/").last,
|
99
|
+
etag: REXML::XPath.first(entry, "//d:getetag").text
|
100
|
+
})
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
{
|
105
|
+
changes: changes,
|
106
|
+
deletions: deletions,
|
107
|
+
sync_token: REXML::XPath.first(xml, "//d:sync-token").text
|
108
|
+
}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module SabredavClient
|
2
|
+
class Client
|
3
|
+
attr_reader :authtype, :host, :port, :base_path, :user, :password, :ssl,
|
4
|
+
:digest_auth, :duri, :proxy_host, :proxy_uri, :proxy_port, :base_path
|
5
|
+
|
6
|
+
def format=(fmt)
|
7
|
+
@format = fmt
|
8
|
+
end
|
9
|
+
|
10
|
+
def format
|
11
|
+
@format ||= Format::Debug.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(data)
|
15
|
+
unless data[:proxy_uri].nil?
|
16
|
+
proxy_uri = URI(data[:proxy_uri])
|
17
|
+
@proxy_host = proxy_uri.host
|
18
|
+
@proxy_port = proxy_uri.port.to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
uri = URI(data[:uri])
|
22
|
+
|
23
|
+
@host = uri.host
|
24
|
+
@port = uri.port.to_i
|
25
|
+
@base_path = uri.path
|
26
|
+
@user = data[:user]
|
27
|
+
@password = data[:password]
|
28
|
+
@ssl = uri.scheme == 'https'
|
29
|
+
|
30
|
+
unless data[:authtype].nil?
|
31
|
+
@authtype = data[:authtype]
|
32
|
+
|
33
|
+
if @authtype == 'digest'
|
34
|
+
|
35
|
+
@digest_auth = Net::HTTP::DigestAuth.new
|
36
|
+
@duri = URI.parse data[:uri]
|
37
|
+
@duri.user = @user
|
38
|
+
@duri.password = @password
|
39
|
+
|
40
|
+
elsif @authtype == 'basic'
|
41
|
+
#Don't Raise or do anything else
|
42
|
+
else
|
43
|
+
raise "Authentication Type Specified Is Not Valid. Please use basic or digest"
|
44
|
+
end
|
45
|
+
else
|
46
|
+
@authtype = 'basic'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_request(method, header: {}, body: "", path: "")
|
51
|
+
request = SabredavClient::Request.new(method, self, path)
|
52
|
+
request.add_header(header) unless header.empty?
|
53
|
+
request.add_body(body) unless body.empty?
|
54
|
+
request
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SabredavClient
|
2
|
+
module Errors
|
3
|
+
|
4
|
+
def self.errorhandling response
|
5
|
+
case response.code.to_i
|
6
|
+
when 401
|
7
|
+
raise SabredavClient::Errors::AuthenticationError
|
8
|
+
when 403
|
9
|
+
raise SabredavClient::Errors::ForbiddenError
|
10
|
+
when 404
|
11
|
+
raise SabredavClient::Errors::NotFoundError
|
12
|
+
when 405
|
13
|
+
raise SabredavClient::Errors::NotAllowedError
|
14
|
+
when 410
|
15
|
+
raise SabredavClient::Errors::NotExistError
|
16
|
+
when 412
|
17
|
+
raise SabredavClient::Errors::PreconditionFailed
|
18
|
+
when 500
|
19
|
+
raise SabredavClient::Errors::APIError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class SabredavClientError < StandardError; end
|
24
|
+
|
25
|
+
class PropertyNotSupportedError < SabredavClientError; end
|
26
|
+
class ShareeTypeNotSupportedError < SabredavClientError; end
|
27
|
+
|
28
|
+
class HTTPMethodNotSupportedError < SabredavClientError; end
|
29
|
+
|
30
|
+
class APIError < SabredavClientError; end
|
31
|
+
class ForbiddenError < APIError; end
|
32
|
+
class NotFoundError < APIError; end
|
33
|
+
class PreconditionFailed < APIError; end
|
34
|
+
class NotAllowedError < APIError; end
|
35
|
+
class AuthenticationError < APIError; end
|
36
|
+
class NotExistError < APIError; end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module SabredavClient
|
2
|
+
|
3
|
+
class Events
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def find(uri)
|
11
|
+
req = client.create_request(:get, path: uri)
|
12
|
+
res = req.run
|
13
|
+
|
14
|
+
SabredavClient::Errors::errorhandling(res)
|
15
|
+
res.body
|
16
|
+
end
|
17
|
+
|
18
|
+
def find_multiple(starts: "", ends: "")
|
19
|
+
events = []
|
20
|
+
header = {depth: "1", content_type: "application/xml"}
|
21
|
+
|
22
|
+
if starts.is_a? Integer
|
23
|
+
body = SabredavClient::XmlRequestBuilder::ReportVEVENT.new(Time.at(starts).utc.strftime("%Y%m%dT%H%M%S"),
|
24
|
+
Time.at(ends).utc.strftime("%Y%m%dT%H%M%S") ).to_xml
|
25
|
+
else
|
26
|
+
body = SabredavClient::XmlRequestBuilder::ReportVEVENT.new(Time.parse(starts).utc.strftime("%Y%m%dT%H%M%S"),
|
27
|
+
Time.parse(ends).utc.strftime("%Y%m%dT%H%M%S") ).to_xml
|
28
|
+
end
|
29
|
+
|
30
|
+
req = client.create_request(:report, header: header)
|
31
|
+
res = req.run
|
32
|
+
|
33
|
+
SabredavClient::Errors::errorhandling(res)
|
34
|
+
result = ""
|
35
|
+
|
36
|
+
xml = REXML::Document.new(res.body)
|
37
|
+
REXML::XPath.each( xml, '//c:calendar-data/', {"c"=>"urn:ietf:params:xml:ns:caldav"} ){|c| result << c.text}
|
38
|
+
|
39
|
+
calendar = Icalendar::Calendar.parse(result).first
|
40
|
+
if calendar
|
41
|
+
calendar.events
|
42
|
+
else
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def owner(uri)
|
48
|
+
header = {content_type: "application/xml"}
|
49
|
+
body = XmlRequestBuilder::PropfindOwner.new.to_xml
|
50
|
+
req = client.create_request(:propfind, path: uri, header: header, body: body)
|
51
|
+
res = req.run
|
52
|
+
|
53
|
+
SabredavClient::Errors::errorhandling(res)
|
54
|
+
xml = REXML::Document.new(res.body)
|
55
|
+
REXML::XPath.first(xml, "//d:objectOwner").text
|
56
|
+
end
|
57
|
+
|
58
|
+
def update_owner(uri, owner)
|
59
|
+
header = {content_type: "application/xml"}
|
60
|
+
body = XmlRequestBuilder::ProppatchOwner.new(owner).to_xml
|
61
|
+
req = client.create_request(:proppatch, path: uri, header: header, body: body)
|
62
|
+
res = req.run
|
63
|
+
|
64
|
+
if res.code.to_i.between?(200,299)
|
65
|
+
true
|
66
|
+
else
|
67
|
+
SabredavClient::Errors::errorhandling(res)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete(uri)
|
72
|
+
req = client.create_request(:delete, path: uri)
|
73
|
+
res = req.run
|
74
|
+
|
75
|
+
if res.code.to_i.between?(200,299)
|
76
|
+
true
|
77
|
+
else
|
78
|
+
SabredavClient::Errors::errorhandling(res)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_update(uri, event_ics, etag = nil)
|
83
|
+
header = {content_type: "text/calendar"}
|
84
|
+
body = event_ics
|
85
|
+
|
86
|
+
if etag
|
87
|
+
header[:if_match] = %Q/"#{etag.gsub(/\A['"]+|['"]+\Z/, "")}"/
|
88
|
+
end
|
89
|
+
|
90
|
+
req = client.create_request(:put,header: header, body: body, path: uri)
|
91
|
+
res = req.run
|
92
|
+
|
93
|
+
SabredavClient::Errors::errorhandling(res)
|
94
|
+
res['etag']
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module SabredavClient
|
2
|
+
module Format
|
3
|
+
class Raw
|
4
|
+
def method_missing(m, *args, &block)
|
5
|
+
return *args
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Debug < Raw
|
10
|
+
end
|
11
|
+
|
12
|
+
class Pretty < Raw
|
13
|
+
def parse_calendar(s)
|
14
|
+
result = ""
|
15
|
+
xml = REXML::Document.new(s)
|
16
|
+
|
17
|
+
REXML::XPath.each( xml, '//c:calendar-data/', {"c"=>"urn:ietf:params:xml:ns:caldav"} ){|c| result << c.text}
|
18
|
+
r = Icalendar.parse(result)
|
19
|
+
r
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_todo( body )
|
23
|
+
result = []
|
24
|
+
xml = REXML::Document.new( body )
|
25
|
+
REXML::XPath.each( xml, '//c:calendar-data/', { "c"=>"urn:ietf:params:xml:ns:caldav"} ){ |c|
|
26
|
+
p c.text
|
27
|
+
p parse_tasks( c.text )
|
28
|
+
result += parse_tasks( c.text )
|
29
|
+
}
|
30
|
+
return result
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_tasks( vcal )
|
34
|
+
return_tasks = Array.new
|
35
|
+
cals = Icalendar.parse(vcal)
|
36
|
+
cals.each { |tcal|
|
37
|
+
tcal.todos.each { |ttask| # FIXME
|
38
|
+
return_tasks << ttask
|
39
|
+
}
|
40
|
+
}
|
41
|
+
return return_tasks
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_events( vcal )
|
45
|
+
Icalendar.parse(vcal)
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_single( body )
|
49
|
+
# FIXME: parse event/todo/vcard
|
50
|
+
parse_events( body )
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Net
|
2
|
+
class HTTP
|
3
|
+
class Report < HTTPRequest
|
4
|
+
METHOD = 'REPORT'
|
5
|
+
REQUEST_HAS_BODY = true
|
6
|
+
RESPONSE_HAS_BODY = true
|
7
|
+
end
|
8
|
+
|
9
|
+
class Mkcalendar < HTTPRequest
|
10
|
+
METHOD = 'MKCALENDAR'
|
11
|
+
REQUEST_HAS_BODY = true
|
12
|
+
RESPONSE_HAS_BODY = true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module SabredavClient
|
2
|
+
|
3
|
+
class Principal
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(data)
|
7
|
+
@client = SabredavClient::Client.new(data)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create(email, displayname = nil)
|
11
|
+
header = {content_type: "text/xml", depth: "1"}
|
12
|
+
body = SabredavClient::XmlRequestBuilder::MkcolPrincipal.new(email, displayname).to_xml
|
13
|
+
req = client.create_request(:mkcol, header: header, body: body)
|
14
|
+
|
15
|
+
res = req.run
|
16
|
+
if res.code.to_i.between?(200,299)
|
17
|
+
true
|
18
|
+
else
|
19
|
+
SabredavClient::Errors::errorhandling(res)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete
|
24
|
+
#FIXME seems like deleting a principal is forbidden by sabredav
|
25
|
+
req = client.create_request(:delete)
|
26
|
+
res = req.run
|
27
|
+
|
28
|
+
if res.code.to_i.between?(200,299)
|
29
|
+
true
|
30
|
+
else
|
31
|
+
SabredavClient::Errors::errorhandling(res)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|