icalendar 0.95

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.
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