sabredav_client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|