agcaldav 0.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,49 @@
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
+ ##Usage
5
+
6
+ First, you've to install the gem
7
+
8
+ gem install agcaldav
9
+
10
+ and require it
11
+
12
+ require "agcaldav"
13
+
14
+ 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.
15
+
16
+
17
+ Now you can e.g. create a new AgCalDAV-Client:
18
+
19
+ cal = AgCalDAV::Client.new(:uri => "http://localhost:5232/user/calendar", :user => "user" , :password => "")
20
+
21
+ Alternatively, the proxy parameters can be specified:
22
+
23
+ cal = AgCalDAV::Client.new(:uri => "http://localhost:5232/user/calendar",:user => "user" , :password => "password, :proxy_uri => "http://my-proxy.com:8080")
24
+
25
+
26
+ ####Create an Event and save it
27
+
28
+ result = cal.create_event(:start => "2012-12-29 10:00", :end => "2012-12-30 12:00", :title => "12345", :description => "sdkvjsdf sdkf sdkfj sdkf dsfj")
29
+
30
+ Determine Event UID:
31
+
32
+ result[:uid]
33
+
34
+
35
+ Find Event:
36
+
37
+ r = cal.find_event(result[:uid])
38
+
39
+
40
+ Find Events within time interval:
41
+
42
+ result = cal.find_events(:start => "2012-10-01 08:00", :end => "2013-01-01")
43
+ #TODO.... (no XML -> Icalendar with multiple events....)
44
+
45
+
46
+
47
+ ... next tomorrow ...
48
+
49
+
data/agcaldav.gemspec CHANGED
@@ -1,11 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/caldav/version', __FILE__)
2
+ require File.expand_path('../lib/agcaldav/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "agcaldav"
6
- s.version = CalDAV::VERSION
7
- s.summary = "new Ruby CalDAV client"
8
- s.description = "yet another new Ruby client for CalDAV calendar and tasks."
6
+ s.version = AgCalDAV::VERSION
7
+ s.summary = "Ruby CalDAV client"
8
+ s.description = "yet another great Ruby client for CalDAV calendar and tasks."
9
9
 
10
10
  s.required_ruby_version = '>= 1.9.2'
11
11
 
@@ -22,7 +22,8 @@ Gem::Specification.new do |s|
22
22
  s.add_runtime_dependency 'uuid'
23
23
  s.add_runtime_dependency 'builder'
24
24
  #s.add_dependency "json"
25
- #s.add_development_dependency "rspec"
25
+ s.add_development_dependency "rspec"
26
+ # sorry for no tests atm :-/
26
27
 
27
28
  s.files = `git ls-files`.split("\n")
28
29
  s.require_paths = ["lib"]
@@ -0,0 +1,154 @@
1
+ module AgCalDAV
2
+ class Client
3
+ include Icalendar
4
+ attr_accessor :host, :port, :url, :user, :password, :ssl
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
+ uri = URI(data[:uri])
21
+ @host = uri.host
22
+ @port = uri.port.to_i
23
+ @url = uri.path
24
+ @user = data[:user]
25
+ @password = data[:password]
26
+ @ssl = uri.scheme == 'https'
27
+ end
28
+
29
+ def __create_http
30
+ if @proxy_uri.nil?
31
+ http = Net::HTTP.new(@host, @port)
32
+ else
33
+ http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port)
34
+ end
35
+ if @ssl
36
+ http.use_ssl = @ssl
37
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
38
+ end
39
+ http
40
+ end
41
+
42
+ def find_events data
43
+ datetime_start = data[:start]
44
+ datetime_stop = data[:end]
45
+ res = nil
46
+ __create_http.start {|http|
47
+ req = Net::HTTP::Report.new(@url, initheader = {'Content-Type'=>'application/xml'} )
48
+ req.basic_auth @user, @password
49
+ req.body = AgCalDAV::Request::ReportVEVENT.new(DateTime.parse(datetime_start).strftime("%Y%m%dT%H%M"),
50
+ DateTime.parse(datetime_stop).strftime("%Y%m%dT%H%M") ).to_xml
51
+ res = http.request( req )
52
+ }
53
+ format.parse_calendar( res.body ) #TODO
54
+ #result = Icalendar.parse(res.body)
55
+ end
56
+
57
+ def find_event uuid
58
+ res = nil
59
+ __create_http.start {|http|
60
+ req = Net::HTTP::Get.new("#{@url}/#{uuid}.ics")
61
+ req.basic_auth @user, @password
62
+ res = http.request( req )
63
+ }
64
+ #raise AuthenticationError if res.code.to_i == 401
65
+ #raise APIError if res.code.to_i >= 500
66
+ result = Icalendar.parse(res.body)
67
+ result
68
+ end
69
+
70
+ def delete_event uuid
71
+ __create_http.start {|http|
72
+ req = Net::HTTP::Delete.new("#{@url}/#{uuid}.ics")
73
+ req.basic_auth @user, @password
74
+ res = http.request( req )
75
+ }
76
+ end
77
+
78
+ def create_event event
79
+ c = Calendar.new
80
+ uuid = UUID.new.generate
81
+ c.event do
82
+ uid uuid # still a BUG
83
+ dtstart DateTime.parse(event[:start])
84
+ dtend DateTime.parse(event[:end])
85
+ duration event[:duration]
86
+ summary event[:title]
87
+ description event[:description]
88
+ klass event[:accessibility] #PUBLIC, PRIVATE, CONFIDENTIAL
89
+ location event[:location]
90
+ geo_location event[:geo_location]
91
+ status event[:status]
92
+ end
93
+ c.publish
94
+ c.event.uid = uuid
95
+ cstring = c.to_ical
96
+ res = nil
97
+ http = Net::HTTP.new(@host, @port)
98
+ __create_http.start { |http|
99
+ req = Net::HTTP::Put.new("#{@url}/#{uuid}.ics")
100
+ req['Content-Type'] = 'text/calendar'
101
+ req.basic_auth @user, @password
102
+ req.body = cstring
103
+ res = http.request( req )
104
+ }
105
+ raise AuthenticationError if res.code.to_i == 401
106
+ raise APIError if res.code.to_i >= 500
107
+ {:uid => uuid, :cal => c, :cal_string => cstring, :response_code => res.code} #TODO
108
+ end
109
+
110
+ def add_alarm tevent, altCal="Calendar"
111
+ # FIXME create icalendar event -> cal.event.new (tevent)
112
+
113
+ # TODO
114
+
115
+
116
+
117
+
118
+ end
119
+
120
+ def update event
121
+ # FIXME old one not neat
122
+
123
+ # TODO
124
+ end
125
+
126
+ def todo
127
+ res = nil
128
+ __create_http.start {|http|
129
+ req = Net::HTTP::Report.new(@url, initheader = {'Content-Type'=>'application/xml'} )
130
+ req.basic_auth @user, @password
131
+ req.body = AgCalDAV::Request::ReportVTODO.new.to_xml
132
+ res = http.request( req )
133
+ }
134
+ # FIXME: process HTTP code
135
+ format.parse_todo( res.body )
136
+ end
137
+
138
+ def filterTimezone( vcal )
139
+ data = ""
140
+ inTZ = false
141
+ vcal.split("\n").each{ |l|
142
+ inTZ = true if l.index("BEGIN:VTIMEZONE")
143
+ data << l+"\n" unless inTZ
144
+ inTZ = false if l.index("END:VTIMEZONE")
145
+ }
146
+ return data
147
+ end
148
+ end
149
+
150
+ class AgCalDAVError < StandardError
151
+ end
152
+ class AuthenticationError < AgCalDAVError; end
153
+ class APIError < AgCalDAVError; end
154
+ end
@@ -1,4 +1,4 @@
1
- module CalDAV
1
+ module AgCalDAV
2
2
  module Filter
3
3
  class Base
4
4
  attr_accessor :parent, :child
@@ -1,4 +1,4 @@
1
- module CalDAV
1
+ module AgCalDAV
2
2
  module Format
3
3
  class Raw
4
4
  def method_missing(m, *args, &block)
@@ -1,11 +1,11 @@
1
- module CalDAV
1
+ module AgCalDAV
2
2
  class Query
3
3
  attr_accessor :child
4
4
 
5
5
  #TODO: raise error if to_xml is called before child is assigned
6
6
  def to_xml(xml = Builder::XmlMarkup.new(:indent => 2))
7
7
  xml.instruct!
8
- xml.tag! "cal:calendar-query", CalDAV::NAMESPACES do
8
+ xml.tag! "cal:calendar-query", AgCalDAV::NAMESPACES do
9
9
  xml.tag! "dav:prop" do
10
10
  xml.tag! "dav:getetag"
11
11
  xml.tag! "cal:calendar-data"
@@ -1,6 +1,6 @@
1
1
  require 'builder'
2
2
 
3
- module CalDAV
3
+ module AgCalDAV
4
4
  NAMESPACES = { "xmlns:d" => 'DAV:', "xmlns:c" => "urn:ietf:params:xml:ns:caldav" }
5
5
  module Request
6
6
  class Base
@@ -0,0 +1,3 @@
1
+ module AgCalDAV
2
+ VERSION="0.2.1"
3
+ end
@@ -2,18 +2,18 @@ require 'net/https'
2
2
  require 'uuid'
3
3
  require 'rexml/document'
4
4
  require 'rexml/xpath'
5
- require 'date'
6
5
  require 'icalendar'
7
6
  require 'time'
7
+ require 'date'
8
8
 
9
9
  ['client.rb', 'request.rb', 'net.rb', 'query.rb', 'filter.rb', 'format.rb'].each do |f|
10
- require File.join( File.dirname(__FILE__), 'caldav', f )
10
+ require File.join( File.dirname(__FILE__), 'agcaldav', f )
11
11
  end
12
12
 
13
13
  class Event
14
- attr_accessor :uid, :created, :dtstart, :dtend, :lastmodified, :summary, :description, :name, :action
14
+ attr_accessor :uid, :created, :dtstart, :dtend, :lastmodified, :summary, :description, :name, :action, :to_ical
15
15
  end
16
16
 
17
17
  class Todo
18
18
  attr_accessor :uid, :created, :summary, :dtstart, :status, :completed
19
- end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: agcaldav
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-28 00:00:00.000000000 Z
12
+ date: 2012-12-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: icalendar
@@ -59,23 +59,39 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- description: yet another new Ruby client for CalDAV calendar and tasks.
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: yet another great Ruby client for CalDAV calendar and tasks.
63
79
  email: ebeling-hoppe@agilastic.de
64
80
  executables: []
65
81
  extensions: []
66
82
  extra_rdoc_files: []
67
83
  files:
68
84
  - .gitignore
69
- - README.rdoc
85
+ - README.md
70
86
  - agcaldav.gemspec
71
- - lib/caldav.rb
72
- - lib/caldav/client.rb
73
- - lib/caldav/filter.rb
74
- - lib/caldav/format.rb
75
- - lib/caldav/net.rb
76
- - lib/caldav/query.rb
77
- - lib/caldav/request.rb
78
- - lib/caldav/version.rb
87
+ - lib/agcaldav.rb
88
+ - lib/agcaldav/client.rb
89
+ - lib/agcaldav/filter.rb
90
+ - lib/agcaldav/format.rb
91
+ - lib/agcaldav/net.rb
92
+ - lib/agcaldav/query.rb
93
+ - lib/agcaldav/request.rb
94
+ - lib/agcaldav/version.rb
79
95
  homepage: https://github.com/agilastic/agcaldav
80
96
  licenses:
81
97
  - MIT
@@ -100,5 +116,5 @@ rubyforge_project:
100
116
  rubygems_version: 1.8.24
101
117
  signing_key:
102
118
  specification_version: 3
103
- summary: new Ruby CalDAV client
119
+ summary: Ruby CalDAV client
104
120
  test_files: []
data/README.rdoc DELETED
@@ -1,3 +0,0 @@
1
- CalDAV library
2
-
3
- based on 4fthawaiian/ruby-caldav and collectiveidea/caldav and martinpovolny/ruby-caldav
data/lib/caldav/client.rb DELETED
@@ -1,214 +0,0 @@
1
- module CalDAV
2
- class Client
3
- include Icalendar
4
- attr_accessor :host, :port, :url, :user, :password, :ssl
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( *args )
15
- case args.length
16
- when 3
17
- __init_from_uri( *args )
18
- when 5
19
- __init_from_host_port( *args )
20
- else
21
- raise "#{self.class.to_s}: invalid number of arguments: #{args.length}"
22
- end
23
- end
24
-
25
- def __init_from_uri( suri, user, password )
26
- uri = URI( suri )
27
- @host = uri.host
28
- @port = uri.port
29
- @url = [ uri.scheme, '://', uri.host, uri.path ].join('') # FIXME: port?
30
- @user = user
31
- @password = password
32
- @ssl = uri.scheme == 'https'
33
- end
34
-
35
- def __init_from_host_port( host, port, url, user, password )
36
- @host = host
37
- @port = port
38
- @url = url
39
- @user = user
40
- @password = password
41
- @ssl = port == 443
42
- end
43
-
44
- def __create_http
45
- http = Net::HTTP.new(@host, @port)
46
- http.use_ssl = @ssl
47
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
48
- #http.set_debug_output $stderr
49
- http
50
- end
51
-
52
- def report datetime_start, datetime_stop
53
- res = nil
54
- __create_http.start {|http|
55
- req = Net::HTTP::Report.new(@url, initheader = {'Content-Type'=>'application/xml'} )
56
- req.basic_auth @user, @password
57
- req.body = CalDAV::Request::ReportVEVENT.new(DateTime.parse(datetime_start).strftime("%Y%m%dT%H%M"),
58
- DateTime.parse(datetime_stop).strftime("%Y%m%dT%H%M") ).to_xml
59
- res = http.request( req )
60
- }
61
- format.parse_calendar( res.body )
62
- end
63
-
64
- def get uuid
65
- res = nil
66
- __create_http.start {|http|
67
- req = Net::HTTP::Get.new("#{@url}/#{uuid}.ics")
68
- req.basic_auth @user, @password
69
- res = http.request( req )
70
- }
71
-
72
- # FIXME: process HTTP code
73
- format.parse_single( res.body )
74
- end
75
-
76
- def delete uuid
77
- __create_http.start {|http|
78
- req = Net::HTTP::Delete.new("#{@url}/#{uuid}.ics")
79
- req.basic_auth @user, @password
80
- res = http.request( req )
81
- }
82
- end
83
-
84
- def create event
85
- event.uid = UUID.generate
86
- event.dtstamp = DateTime.now.strftime "%Y%m%dT%H%M%SZ"
87
- event.dtstart = event.dtstart.strftime("%Y%m%dT%H%M%S")
88
- event.dtend = event.dtend.strftime("%Y%m%dT%H%M%S")
89
- cal = Calendar.new
90
- cal.event = Event.new(event)
91
- c = cal.to_ical
92
- res = nil
93
- http = Net::HTTP.new(@host, @port)
94
- __create_http.start { |http|
95
- req = Net::HTTP::Put.new("#{@url}/#{event.uid}.ics")
96
- req['Content-Type'] = 'text/calendar'
97
- req.basic_auth @user, @password
98
- req.body = dings
99
- res = http.request( req )
100
- }
101
- return event.uid, res
102
- end
103
-
104
- def add_alarm tevent, altCal="Calendar"
105
- #[#<Icalendar::Alarm:0x10b9d1b90 @name=\"VALARM\", @components={}, @properties={\"trigger\"=>\"-PT5M\", \"action\"=>\"DISPLAY\", \"description\"=>\"\"}>]
106
- dtstart_string = ( Time.parse(tevent.dtstart.to_s) + Time.now.utc_offset.to_i.abs ).strftime "%Y%m%dT%H%M%S"
107
- dtend_string = ( Time.parse(tevent.dtend.to_s) + Time.now.utc_offset.to_i.abs ).strftime "%Y%m%dT%H%M%S"
108
- alarmText = <<EOL
109
- BEGIN:VCALENDAR
110
- VERSION:2.0
111
- PRODID:Ruby iCalendar
112
- BEGIN:VEVENT
113
- UID:#{tevent.uid}
114
- SUMMARY:#{tevent.summary}
115
- DESCRIPTION:#{tevent.description}
116
- DTSTART:#{dtstart_string}
117
- DTEND:#{dtend_string}
118
- BEGIN:VALARM
119
- ACTION:DISPLAY
120
- TRIGGER;RELATED=START:-PT5M
121
- DESCRIPTION:Reminder
122
- END:VALARM
123
- BEGIN:VALARM
124
- TRIGGER:-PT5M
125
- ACTION:EMAIL
126
- ATTENDEE:#{tevent.organizer}
127
- SUMMARY:#{tevent.summary}
128
- DESCRIPTION:#{tevent.description}
129
- TRIGGER:-PT5M
130
- END:VALARM
131
- END:VEVENT
132
- END:VCALENDAR
133
- EOL
134
- p alarmText
135
- res = nil
136
- puts "#{@url}/#{tevent.uid}.ics"
137
- thttp = __create_http.start
138
- #thttp.set_debug_output $stderr
139
- req = Net::HTTP::Put.new("#{@url}/#{tevent.uid}.ics", initheader = {'Content-Type'=>'text/calendar'} )
140
- req.basic_auth @user, @password
141
- req.body = alarmText
142
- res = thttp.request( req )
143
- p res.inspect
144
-
145
- return tevent.uid
146
- end
147
-
148
- def update event
149
- dings = """BEGIN:VCALENDAR
150
- PRODID:Caldav.rb
151
- VERSION:2.0
152
-
153
- BEGIN:VTIMEZONE
154
- TZID:/Europe/Vienna
155
- X-LIC-LOCATION:Europe/Vienna
156
- BEGIN:DAYLIGHT
157
- TZOFFSETFROM:+0100
158
- TZOFFSETTO:+0200
159
- TZNAME:CEST
160
- DTSTART:19700329T020000
161
- RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
162
- END:DAYLIGHT
163
- BEGIN:STANDARD
164
- TZOFFSETFROM:+0200
165
- TZOFFSETTO:+0100
166
- TZNAME:CET
167
- DTSTART:19701025T030000
168
- RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
169
- END:STANDARD
170
- END:VTIMEZONE
171
-
172
- BEGIN:VEVENT
173
- CREATED:#{event.created}
174
- UID:#{event.uid}
175
- SUMMARY:#{event.summary}
176
- DTSTART;TZID=Europe/Vienna:#{event.dtstart}
177
- DTEND;TZID=Europe/Vienna:#{event.dtend.rfc3339}
178
- END:VEVENT
179
- END:VCALENDAR"""
180
-
181
- res = nil
182
- __create_http.start {|http|
183
- req = Net::HTTP::Put.new("#{@url}/#{event.uid}.ics", initheader = {'Content-Type'=>'text/calendar'} )
184
- req.basic_auth @user, @password
185
- req.body = dings
186
- res = http.request( req )
187
- }
188
- return event.uid
189
- end
190
-
191
- def todo
192
- res = nil
193
- __create_http.start {|http|
194
- req = Net::HTTP::Report.new(@url, initheader = {'Content-Type'=>'application/xml'} )
195
- req.basic_auth @user, @password
196
- req.body = CalDAV::Request::ReportVTODO.new.to_xml
197
- res = http.request( req )
198
- }
199
- # FIXME: process HTTP code
200
- format.parse_todo( res.body )
201
- end
202
-
203
- def filterTimezone( vcal )
204
- data = ""
205
- inTZ = false
206
- vcal.split("\n").each{ |l|
207
- inTZ = true if l.index("BEGIN:VTIMEZONE")
208
- data << l+"\n" unless inTZ
209
- inTZ = false if l.index("END:VTIMEZONE")
210
- }
211
- return data
212
- end
213
- end
214
- end
@@ -1,3 +0,0 @@
1
- module CalDAV
2
- VERSION=0.2
3
- end
File without changes