icalendar 0.95

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/COPYING +56 -0
  2. data/GPL +340 -0
  3. data/README +121 -0
  4. data/Rakefile +101 -0
  5. data/docs/api/classes/Array.html +146 -0
  6. data/docs/api/classes/Date.html +157 -0
  7. data/docs/api/classes/DateTime.html +178 -0
  8. data/docs/api/classes/Fixnum.html +146 -0
  9. data/docs/api/classes/Float.html +146 -0
  10. data/docs/api/classes/Icalendar/Alarm.html +184 -0
  11. data/docs/api/classes/Icalendar/Base.html +118 -0
  12. data/docs/api/classes/Icalendar/Calendar.html +411 -0
  13. data/docs/api/classes/Icalendar/Component.html +306 -0
  14. data/docs/api/classes/Icalendar/DateProp.html +187 -0
  15. data/docs/api/classes/Icalendar/DateProp/ClassMethods.html +195 -0
  16. data/docs/api/classes/Icalendar/Event.html +202 -0
  17. data/docs/api/classes/Icalendar/Freebusy.html +157 -0
  18. data/docs/api/classes/Icalendar/InvalidComponentClass.html +117 -0
  19. data/docs/api/classes/Icalendar/InvalidPropertyValue.html +117 -0
  20. data/docs/api/classes/Icalendar/Journal.html +190 -0
  21. data/docs/api/classes/Icalendar/Parameter.html +166 -0
  22. data/docs/api/classes/Icalendar/Parser.html +447 -0
  23. data/docs/api/classes/Icalendar/Timezone.html +197 -0
  24. data/docs/api/classes/Icalendar/Todo.html +199 -0
  25. data/docs/api/classes/String.html +160 -0
  26. data/docs/api/classes/Time.html +161 -0
  27. data/docs/api/created.rid +1 -0
  28. data/docs/api/files/COPYING.html +163 -0
  29. data/docs/api/files/GPL.html +531 -0
  30. data/docs/api/files/README.html +241 -0
  31. data/docs/api/files/lib/icalendar/base_rb.html +108 -0
  32. data/docs/api/files/lib/icalendar/calendar_rb.html +101 -0
  33. data/docs/api/files/lib/icalendar/component/alarm_rb.html +101 -0
  34. data/docs/api/files/lib/icalendar/component/event_rb.html +101 -0
  35. data/docs/api/files/lib/icalendar/component/freebusy_rb.html +101 -0
  36. data/docs/api/files/lib/icalendar/component/journal_rb.html +101 -0
  37. data/docs/api/files/lib/icalendar/component/timezone_rb.html +101 -0
  38. data/docs/api/files/lib/icalendar/component/todo_rb.html +101 -0
  39. data/docs/api/files/lib/icalendar/component_rb.html +101 -0
  40. data/docs/api/files/lib/icalendar/conversions_rb.html +108 -0
  41. data/docs/api/files/lib/icalendar/helpers_rb.html +101 -0
  42. data/docs/api/files/lib/icalendar/parameter_rb.html +101 -0
  43. data/docs/api/files/lib/icalendar/parser_rb.html +109 -0
  44. data/docs/api/files/lib/icalendar_rb.html +118 -0
  45. data/docs/api/fr_class_index.html +48 -0
  46. data/docs/api/fr_file_index.html +43 -0
  47. data/docs/api/fr_method_index.html +63 -0
  48. data/docs/api/index.html +24 -0
  49. data/docs/api/rdoc-style.css +208 -0
  50. data/docs/examples/create_cal.rb +40 -0
  51. data/docs/examples/parse_cal.rb +19 -0
  52. data/docs/examples/single_event.ics +18 -0
  53. data/docs/rfcs/rfc2425.pdf +0 -0
  54. data/docs/rfcs/rfc2426.pdf +0 -0
  55. data/docs/rfcs/rfc2445.pdf +0 -0
  56. data/docs/rfcs/rfc2446.pdf +0 -0
  57. data/docs/rfcs/rfc2447.pdf +0 -0
  58. data/docs/rfcs/rfc3283.txt +738 -0
  59. data/lib/icalendar.rb +27 -0
  60. data/lib/icalendar/#helpers.rb# +92 -0
  61. data/lib/icalendar/base.rb +31 -0
  62. data/lib/icalendar/calendar.rb +112 -0
  63. data/lib/icalendar/component.rb +253 -0
  64. data/lib/icalendar/component/alarm.rb +35 -0
  65. data/lib/icalendar/component/event.rb +68 -0
  66. data/lib/icalendar/component/freebusy.rb +35 -0
  67. data/lib/icalendar/component/journal.rb +61 -0
  68. data/lib/icalendar/component/timezone.rb +43 -0
  69. data/lib/icalendar/component/todo.rb +65 -0
  70. data/lib/icalendar/conversions.rb +115 -0
  71. data/lib/icalendar/helpers.rb +109 -0
  72. data/lib/icalendar/parameter.rb +33 -0
  73. data/lib/icalendar/parser.rb +395 -0
  74. data/test/calendar_test.rb +46 -0
  75. data/test/component/event_test.rb +47 -0
  76. data/test/component_test.rb +74 -0
  77. data/test/parser_test.rb +83 -0
  78. data/test/property_helpers.rb +35 -0
  79. data/test/simplecal.ics +119 -0
  80. data/test/single_event.ics +23 -0
  81. metadata +135 -0
@@ -0,0 +1,27 @@
1
+ =begin
2
+ Copyright (C) 2005 Jeff Rose
3
+
4
+ This library is free software; you can redistribute it and/or modify it
5
+ under the same terms as the ruby language itself, see the file COPYING for
6
+ details.
7
+ =end
8
+
9
+ $:.unshift(File.dirname(__FILE__))
10
+
11
+ # Base classes and mixin modules
12
+ require 'icalendar/conversions'
13
+ #require 'icalendar/helpers'
14
+ require 'icalendar/base'
15
+ require 'icalendar/component'
16
+
17
+ # Calendar and components
18
+ require 'icalendar/calendar'
19
+ require 'icalendar/component/event'
20
+ require 'icalendar/component/journal'
21
+ require 'icalendar/component/todo'
22
+ require 'icalendar/component/freebusy'
23
+ require 'icalendar/component/timezone'
24
+ require 'icalendar/component/alarm'
25
+
26
+ # Calendar parser
27
+ require 'icalendar/parser'
@@ -0,0 +1,92 @@
1
+ =begin
2
+ Copyright (C) 2005 Jeff Rose
3
+ Copyright (C) 2005 Sam Roberts
4
+
5
+ This library is free software; you can redistribute it and/or modify it
6
+ under the same terms as the ruby language itself, see the file COPYING for
7
+ details.
8
+ =end
9
+
10
+ module Icalendar
11
+ module DateProp
12
+ # You have to do this to mixin class methods rather than instance methods.
13
+ def self.append_features(base)
14
+ super
15
+ klass.extend(ClassMethods)
16
+ end
17
+
18
+ # This is made a sub-module just so it can be added as class
19
+ # methods rather than instance methods.
20
+ module ClassMethods
21
+ def ical_property(dp, alias_name = nil)
22
+ dp = "#{dp}".strip.downcase
23
+ getter = dp
24
+ setter = "#{dp}="
25
+ query = "#{dp}?"
26
+
27
+ unless instance_methods.include? getter
28
+ code = <<-code
29
+ def #{getter}(*a)
30
+ if a.empty?
31
+ @properties[#{dp.upcase}]
32
+ else
33
+ self.#{dp} = a.first
34
+ end
35
+ end
36
+ code
37
+
38
+ module_eval code
39
+ end
40
+
41
+ unless instance_methods.include? setter
42
+ code = <<-code
43
+ def #{setter} a
44
+ @properties[#{dp.upcase}] = a
45
+ end
46
+ code
47
+
48
+ module_eval code
49
+ end
50
+
51
+ unless instance_methods.include? query
52
+ code = <<-code
53
+ def #{query}
54
+ @properties.has_key?(#{dp.upcase})
55
+ end
56
+ code
57
+
58
+ module_eval code
59
+ end
60
+
61
+ # Define the getter
62
+ getter = "get#{property.to_s.capitalize}"
63
+ define_method(getter.to_sym) do
64
+ puts "inside getting..."
65
+ getDateProperty(property.to_s.upcase)
66
+ end
67
+
68
+ # Define the setter
69
+ setter = "set#{property.to_s.capitalize}"
70
+ define_method(setter.to_sym) do |*params|
71
+ date = params[0]
72
+ utc = params[1]
73
+ puts "inside setting..."
74
+ setDateProperty(property.to_s.upcase, date, utc)
75
+ end
76
+
77
+ # Create aliases if a name was specified
78
+ # if not aliasName.nil?
79
+ # gasym = "get#{aliasName.to_s.capitalize}".to_sym
80
+ # gsym = getter.to_sym
81
+ # alias gasym gsym
82
+
83
+ # sasym = "set#{aliasName.to_s.capitalize}".to_sym
84
+ # ssym = setter.to_sym
85
+ # alias sasym ssym
86
+ # end
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,31 @@
1
+ =begin
2
+ Copyright (C) 2005 Jeff Rose
3
+
4
+ This library is free software; you can redistribute it and/or modify it
5
+ under the same terms as the ruby language itself, see the file COPYING for
6
+ details.
7
+ =end
8
+ require 'logger'
9
+
10
+ module Icalendar #:nodoc:
11
+
12
+ # A simple error class to differentiate iCalendar library exceptions
13
+ # from ruby language exceptions or others.
14
+ class IcalendarError < StandardError #:nodoc:
15
+ end
16
+
17
+ # Exception used when the library encounters a bogus calendar component.
18
+ class InvalidComponentClass < IcalendarError
19
+ end
20
+
21
+ # Exception used when the library encounters a bogus property value.
22
+ class InvalidPropertyValue < IcalendarError
23
+ end
24
+
25
+ # This class serves as the base class for just about everything in
26
+ # the library so that the logging system can be configured in one place.
27
+ class Base
28
+ @@logger = Logger.new(STDERR)
29
+ @@logger.level = Logger::WARN
30
+ end
31
+ end
@@ -0,0 +1,112 @@
1
+ =begin
2
+ Copyright (C) 2005 Jeff Rose
3
+
4
+ This library is free software; you can redistribute it and/or modify it
5
+ under the same terms as the ruby language itself, see the file COPYING for
6
+ details.
7
+ =end
8
+
9
+ module Icalendar
10
+
11
+
12
+ class Calendar < Component
13
+ attr_accessor :events, :todos, :journals, :freebusys, :timezones
14
+
15
+ ical_property :calscale, :calendar_scale
16
+ ical_property :prodid, :product_id
17
+ ical_property :version
18
+ ical_property :method
19
+
20
+ def initialize()
21
+ super("VCALENDAR")
22
+ @properties = {}
23
+ @property_params = {}
24
+
25
+ @events = []
26
+ @todos = []
27
+ @journals = []
28
+ @freebusys = []
29
+ @timezones = []
30
+
31
+ # Set some defaults
32
+ self.calscale = "GREGORIAN" # Who knows, but this is the only one in the spec.
33
+ self.prodid = "iCalendar-Ruby" # Current product... Should be overwritten
34
+ self.version = "2.0" # Version of the specification
35
+
36
+ end
37
+
38
+ def event(&block)
39
+ e = Event.new
40
+ self.add e
41
+
42
+ e.instance_eval &block if block
43
+
44
+ e
45
+ end
46
+
47
+ def todo(&block)
48
+ e = Todo.new
49
+ self.add e
50
+
51
+ e.instance_eval &block if block
52
+
53
+ e
54
+ end
55
+
56
+ def journal(&block)
57
+ e = Journal.new
58
+ self.add e
59
+
60
+ e.instance_eval &block if block
61
+
62
+ e
63
+ end
64
+
65
+ def freebusy(&block)
66
+ e = Freebusy.new
67
+ self.add e
68
+
69
+ e.instance_eval &block if block
70
+
71
+ e
72
+ end
73
+
74
+ def timezone(&block)
75
+ e = Timezone.new
76
+ self.add e
77
+
78
+ e.instance_eval &block if block
79
+
80
+ e
81
+ end
82
+
83
+
84
+ #TODO: Implement the rest of these ^ methods for todo etc...
85
+
86
+ def add(component)
87
+ if component.is_a? Event
88
+ @events << component
89
+ elsif component.is_a? Todo
90
+ @todos << component
91
+ elsif component.is_a? Journal
92
+ @journals << component
93
+ elsif component.is_a? Freebusy
94
+ @freebusys << component
95
+ elsif component.is_a? Timezone
96
+ @timezones << component
97
+ else
98
+ raise InvalidComponentClass
99
+ end
100
+ end
101
+
102
+ def to_ical
103
+ print_string do |s|
104
+ @events.each { |event| s << event.to_ical }
105
+ @todos.each { |todo| s << todo.to_ical }
106
+ @journals.each { |journal| s << journal.to_ical }
107
+ @freebusys.each { |freebusy| s << freebusy.to_ical }
108
+ @timezones.each { |timezone| s << timezone.to_ical }
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,253 @@
1
+ =begin
2
+ Copyright (C) 2005 Jeff Rose
3
+
4
+ This library is free software; you can redistribute it and/or modify it
5
+ under the same terms as the ruby language itself, see the file COPYING for
6
+ details.
7
+ =end
8
+
9
+ module Icalendar
10
+ # The body of the iCalendar object consists of a sequence of calendar
11
+ # properties and one or more calendar components. The calendar
12
+ # properties are attributes that apply to the calendar as a whole. The
13
+ # calendar components are collections of properties that express a
14
+ # particular calendar semantic. For example, the calendar component can
15
+ # specify an Event, a Todo, a Journal entry, Timezone information, or
16
+ # Freebusy time information, or an Alarm.
17
+ class Component < Icalendar::Base
18
+ attr_reader :name
19
+ attr_accessor :properties, :property_params
20
+
21
+ @@multi_properties = {}
22
+
23
+ def initialize(name)
24
+ @name = name
25
+ @properties = {}
26
+ @property_params = {}
27
+
28
+ @@logger.info("New #{@name[1,@name.size].capitalize}...")
29
+ end
30
+
31
+ def print_string
32
+ s = ""
33
+
34
+ # Begin a new component
35
+ s << "BEGIN:#{@name.upcase}\r\n"
36
+
37
+ # Then print the properties, possible parameters and potentially
38
+ # multiple parameter values for each parameter.
39
+ @properties.each do |key,value|
40
+ # Property name
41
+ s << "#{key.upcase}"
42
+
43
+ # Possible parameters
44
+ if @property_params.has_key?(key)
45
+ params = @property_params[key]
46
+ params.each do |key,val|
47
+ s << ";#{key}"
48
+ val = [ val ] unless val.respond_to?(:to_ary)
49
+
50
+ # Possible parameter values
51
+ unless val.empty?
52
+ s << "="
53
+ sep = "" # First entry comes after = sign, but then we need commas
54
+ val.each do |pval|
55
+ if pval.respond_to? :to_ical
56
+ s << sep << pval.to_ical
57
+ sep = ","
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # Property value
65
+ s << ":#{value.to_ical}\r\n"
66
+ end
67
+
68
+ # Any custom body of the derived component
69
+ yield(s)
70
+
71
+ # End of this component
72
+ s << "END:#{@name.upcase}\r\n"
73
+ end
74
+
75
+ # TODO: Look into the x-property, x-param stuff...
76
+ def custom_property(name, value)
77
+ @properties[name] = value
78
+ end
79
+
80
+ def multi_property?(name)
81
+ @@multi_properties.has_key?(name)
82
+ end
83
+
84
+ # Make it protected so we can monitor usage...
85
+ protected
86
+
87
+ # Define a set of methods supporting a new property
88
+ def Component.ical_property(property, alias_name = nil, prop_name = nil)
89
+ property = "#{property}".strip.downcase
90
+ getter = "#{property}"
91
+ setter = "#{property}="
92
+ query = "#{property}?"
93
+ alias_name = "#{alias_name}".strip.downcase unless alias_name.nil?
94
+
95
+ # If a prop_name was given then we use that for the actual storage
96
+ property = "#{prop_name}".strip.upcase unless prop_name.nil?
97
+
98
+ # Change underscores in property name to a dash
99
+ property[/_/] = '-' if property =~ /_/
100
+
101
+ # All properties names are stored in caps...
102
+ property = property.upcase
103
+
104
+ unless instance_methods.include? getter
105
+ code = <<-code
106
+ def #{getter}(*a)
107
+ if a.empty?
108
+ @properties["#{property}"]
109
+ else
110
+ self.#{getter} = a.first
111
+ end
112
+ end
113
+ code
114
+
115
+ class_eval code, "component.rb", 124
116
+
117
+ alias_method("#{alias_name}", "#{getter}") unless alias_name.nil?
118
+ end
119
+
120
+ unless instance_methods.include? setter
121
+ code = <<-code
122
+ def #{setter} a
123
+ unless a.respond_to?(:to_ical)
124
+ raise(NotImplementedError, "Property value does not support to_ical method!")
125
+ end
126
+
127
+ @properties["#{property}"] = a
128
+ end
129
+ code
130
+
131
+ class_eval code, "component.rb", 134
132
+
133
+ alias_method("#{alias_name}=", "#{setter}") unless alias_name.nil?
134
+ end
135
+
136
+ unless instance_methods.include? query
137
+ code = <<-code
138
+ def #{query}
139
+ @properties.has_key?("#{property}")
140
+ end
141
+ code
142
+
143
+ class_eval code, "component.rb", 144
144
+
145
+ alias_method("#{alias_name}\?", "#{query}") unless alias_name.nil?
146
+ end
147
+ end
148
+
149
+ # Define a set of methods defining a new property, which
150
+ # supports multiple values for the same property name.
151
+ def Component.ical_multi_property(property, singular, plural)
152
+ property = "#{property}".strip.upcase
153
+ singular = "#{singular}".strip.downcase
154
+ plural = "#{plural}".strip.downcase
155
+
156
+ getter = "#{plural}"
157
+ setter = "#{plural}="
158
+ adder = "add_#{singular}"
159
+ remover = "remove_#{singular}"
160
+ query = "#{plural}?"
161
+
162
+ # Set this key so the parser knows to use an array for
163
+ # storing this property type.
164
+ @@multi_properties["#{property}"] = true
165
+
166
+ # Getter for whole array
167
+ unless instance_methods.include? getter
168
+ code = <<-code
169
+ def #{getter}(*a)
170
+ if a.empty?
171
+ if @properties.has_key?("#{property}")
172
+ @properties["#{property}"]
173
+ else
174
+ []
175
+ end
176
+ else
177
+ self.#{setter}(a.first)
178
+ end
179
+ end
180
+ code
181
+
182
+ class_eval code, "component.rb", 186
183
+ end
184
+
185
+ # Setter for whole array
186
+ unless instance_methods.include? setter
187
+ code = <<-code
188
+ def #{setter}(a)
189
+ if a.respond_to?(:to_ary)
190
+ a.to_ary.each do |val|
191
+ unless val.respond_to?(:to_ical)
192
+ raise(NotImplementedError, "Property values do not support to_ical method!")
193
+ end
194
+ end
195
+
196
+ @properties["#{property}"] = a.to_ary
197
+
198
+
199
+ else
200
+ raise ArgumentError, "#{getter} is a multi-property that must be an array! Use the #{adder} method to add single entries."
201
+ end
202
+ end
203
+ code
204
+
205
+ class_eval code, "component.rb", 198
206
+ end
207
+
208
+ # Query for any of these properties
209
+ unless instance_methods.include? query
210
+ code = <<-code
211
+ def #{query}
212
+ @properties.has_key?("#{property}")
213
+ end
214
+ code
215
+
216
+ class_eval code, "component.rb", 210
217
+ end
218
+
219
+ # Add another item to this properties array
220
+ unless instance_methods.include? adder
221
+ code = <<-code
222
+ def #{adder}(a)
223
+ unless a.respond_to?(:to_ical)
224
+ raise(NotImplementedError, "Property value object does not support to_ical method!")
225
+ end
226
+
227
+ if @properties.has_key?("#{property}")
228
+ @properties["#{property}"] << a
229
+ else
230
+ @properties["#{property}"] = [a]
231
+ end
232
+ end
233
+ code
234
+
235
+ class_eval code, "component.rb", 228
236
+ end
237
+
238
+ # Remove an item from this properties array
239
+ unless instance_methods.include? remover
240
+ code = <<-code
241
+ def #{remover}(a)
242
+ if @properties.has_key?("#{property}")
243
+ @properties["#{property}"].delete(a)
244
+ end
245
+ end
246
+ code
247
+
248
+ class_eval code, "component.rb", 241
249
+ end
250
+
251
+ end
252
+ end
253
+ end