tilia-vobject 4.0.0.pre.alpha5 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.sabre.md +59 -2
  3. data/Gemfile +1 -8
  4. data/Gemfile.lock +18 -12
  5. data/LICENSE +1 -1
  6. data/LICENSE.sabre +1 -1
  7. data/lib/tilia/v_object.rb +1 -0
  8. data/lib/tilia/v_object/birthday_calendar_generator.rb +11 -11
  9. data/lib/tilia/v_object/cli.rb +39 -38
  10. data/lib/tilia/v_object/component.rb +47 -50
  11. data/lib/tilia/v_object/component/available.rb +4 -37
  12. data/lib/tilia/v_object/component/v_alarm.rb +6 -18
  13. data/lib/tilia/v_object/component/v_availability.rb +6 -39
  14. data/lib/tilia/v_object/component/v_calendar.rb +66 -98
  15. data/lib/tilia/v_object/component/v_card.rb +42 -69
  16. data/lib/tilia/v_object/component/v_event.rb +5 -17
  17. data/lib/tilia/v_object/component/v_free_busy.rb +4 -16
  18. data/lib/tilia/v_object/component/v_journal.rb +16 -16
  19. data/lib/tilia/v_object/component/v_time_zone.rb +2 -14
  20. data/lib/tilia/v_object/component/v_todo.rb +17 -36
  21. data/lib/tilia/v_object/date_time_parser.rb +24 -24
  22. data/lib/tilia/v_object/document.rb +25 -25
  23. data/lib/tilia/v_object/free_busy_data.rb +7 -7
  24. data/lib/tilia/v_object/free_busy_generator.rb +73 -75
  25. data/lib/tilia/v_object/i_tip.rb +1 -0
  26. data/lib/tilia/v_object/i_tip/broker.rb +134 -116
  27. data/lib/tilia/v_object/i_tip/i_tip_exception.rb +1 -1
  28. data/lib/tilia/v_object/i_tip/message.rb +13 -13
  29. data/lib/tilia/v_object/invalid_data_exception.rb +8 -0
  30. data/lib/tilia/v_object/node.rb +22 -27
  31. data/lib/tilia/v_object/parameter.rb +22 -22
  32. data/lib/tilia/v_object/parse_exception.rb +1 -1
  33. data/lib/tilia/v_object/parser.rb +1 -0
  34. data/lib/tilia/v_object/parser/json.rb +9 -19
  35. data/lib/tilia/v_object/parser/mime_dir.rb +73 -39
  36. data/lib/tilia/v_object/parser/parser.rb +9 -14
  37. data/lib/tilia/v_object/parser/xml.rb +33 -50
  38. data/lib/tilia/v_object/parser/xml/element.rb +1 -0
  39. data/lib/tilia/v_object/parser/xml/element/key_value.rb +2 -2
  40. data/lib/tilia/v_object/property.rb +52 -52
  41. data/lib/tilia/v_object/property/binary.rb +10 -10
  42. data/lib/tilia/v_object/property/boolean.rb +6 -6
  43. data/lib/tilia/v_object/property/flat_text.rb +3 -3
  44. data/lib/tilia/v_object/property/float_value.rb +10 -10
  45. data/lib/tilia/v_object/property/i_calendar.rb +1 -0
  46. data/lib/tilia/v_object/property/i_calendar/cal_address.rb +3 -3
  47. data/lib/tilia/v_object/property/i_calendar/date_time.rb +29 -57
  48. data/lib/tilia/v_object/property/i_calendar/duration.rb +6 -6
  49. data/lib/tilia/v_object/property/i_calendar/period.rb +10 -10
  50. data/lib/tilia/v_object/property/i_calendar/recur.rb +16 -24
  51. data/lib/tilia/v_object/property/integer_value.rb +8 -8
  52. data/lib/tilia/v_object/property/text.rb +21 -36
  53. data/lib/tilia/v_object/property/time.rb +29 -6
  54. data/lib/tilia/v_object/property/unknown.rb +2 -2
  55. data/lib/tilia/v_object/property/uri.rb +24 -5
  56. data/lib/tilia/v_object/property/utc_offset.rb +5 -5
  57. data/lib/tilia/v_object/property/v_card.rb +1 -0
  58. data/lib/tilia/v_object/property/v_card/date.rb +3 -3
  59. data/lib/tilia/v_object/property/v_card/date_and_or_time.rb +30 -42
  60. data/lib/tilia/v_object/property/v_card/date_time.rb +1 -1
  61. data/lib/tilia/v_object/property/v_card/language_tag.rb +4 -4
  62. data/lib/tilia/v_object/property/v_card/time_stamp.rb +5 -5
  63. data/lib/tilia/v_object/reader.rb +12 -11
  64. data/lib/tilia/v_object/recur.rb +2 -0
  65. data/lib/tilia/v_object/recur/event_iterator.rb +30 -27
  66. data/lib/tilia/v_object/recur/max_instances_exceeded_exception.rb +10 -0
  67. data/lib/tilia/v_object/recur/no_instances_exception.rb +1 -1
  68. data/lib/tilia/v_object/recur/r_date_iterator.rb +15 -41
  69. data/lib/tilia/v_object/recur/r_rule_iterator.rb +23 -156
  70. data/lib/tilia/v_object/settings.rb +16 -0
  71. data/lib/tilia/v_object/splitter.rb +1 -0
  72. data/lib/tilia/v_object/splitter/i_calendar.rb +5 -5
  73. data/lib/tilia/v_object/splitter/splitter_interface.rb +2 -2
  74. data/lib/tilia/v_object/splitter/v_card.rb +5 -5
  75. data/lib/tilia/v_object/string_util.rb +25 -9
  76. data/lib/tilia/v_object/time_zone_data.rb +1 -0
  77. data/lib/tilia/v_object/time_zone_util.rb +6 -6
  78. data/lib/tilia/v_object/uuid_util.rb +3 -3
  79. data/lib/tilia/v_object/v_card_converter.rb +24 -21
  80. data/lib/tilia/v_object/version.rb +1 -1
  81. data/lib/tilia/v_object/writer.rb +7 -7
  82. data/test/test_helper.rb +3 -3
  83. data/test/v_object/birthday_calendar_generator_test.rb +22 -0
  84. data/test/v_object/component/v_alarm_test.rb +3 -1
  85. data/test/v_object/component/v_calendar_test.rb +40 -4
  86. data/test/v_object/component/v_card_test.rb +1 -1
  87. data/test/v_object/component_test.rb +5 -3
  88. data/test/v_object/date_time_parser_test.rb +15 -5
  89. data/test/v_object/free_busy_generator_test.rb +5 -5
  90. data/test/v_object/i_tip/broker_attendee_reply_test.rb +19 -0
  91. data/test/v_object/i_tip/broker_delete_event_test.rb +146 -2
  92. data/test/v_object/i_tip/broker_new_event_test.rb +21 -0
  93. data/test/v_object/i_tip/broker_process_reply_test.rb +10 -0
  94. data/test/v_object/i_tip/broker_tester.rb +1 -1
  95. data/test/v_object/i_tip/broker_update_event_test.rb +36 -0
  96. data/test/v_object/issue259_test.rb +24 -0
  97. data/test/v_object/issue40_test.rb +3 -1
  98. data/test/v_object/j_cal_test.rb +15 -12
  99. data/test/v_object/parser/json_test.rb +5 -5
  100. data/test/v_object/parser/mime_dir_test.rb +109 -0
  101. data/test/v_object/property/binary_test.rb +4 -2
  102. data/test/v_object/property/i_calendar/date_time_test.rb +3 -1
  103. data/test/v_object/property/uri_test.rb +23 -0
  104. data/test/v_object/recur/event_iterator/by_month_in_daily_test.rb +1 -1
  105. data/test/v_object/recur/event_iterator/by_set_pos_hang_test.rb +1 -1
  106. data/test/v_object/recur/event_iterator/expand_floating_times_test.rb +9 -9
  107. data/test/v_object/recur/event_iterator/handle_r_date_expand_test.rb +51 -0
  108. data/test/v_object/recur/event_iterator/incorrect_expand_test.rb +3 -5
  109. data/test/v_object/recur/event_iterator/infinite_loop_problem_test.rb +3 -1
  110. data/test/v_object/{issue26_test.rb → recur/event_iterator/issue26_test.rb} +3 -1
  111. data/test/v_object/recur/event_iterator/main_test.rb +9 -3
  112. data/test/v_object/recur/event_iterator/max_instances_test.rb +38 -0
  113. data/test/v_object/recur/event_iterator/missing_overridden_test.rb +3 -5
  114. data/test/v_object/recur/event_iterator/no_instances_test.rb +5 -3
  115. data/test/v_object/recur/event_iterator/override_first_event_test.rb +9 -9
  116. data/test/v_object/recur/r_date_iterator_test.rb +18 -0
  117. data/test/v_object/recur/r_rule_iterator_test.rb +4 -4
  118. data/test/v_object/splitter/i_calendar_test.rb +27 -7
  119. data/test/v_object/splitter/v_card_test.rb +5 -3
  120. data/test/v_object/test_case.rb +14 -4
  121. data/tilia-vobject.gemspec +2 -2
  122. metadata +17 -11
@@ -11,8 +11,8 @@ module Tilia
11
11
  class RRuleIterator
12
12
  # Creates the Iterator.
13
13
  #
14
- # @param string|array rrule
15
- # @param DateTimeInterface start
14
+ # @param [String|array] rrule
15
+ # @param [Time] start
16
16
  def initialize(rrule, start)
17
17
  @week_start = 'MO'
18
18
  @counter = 0
@@ -48,7 +48,7 @@ module Tilia
48
48
 
49
49
  # Returns the current item number.
50
50
  #
51
- # @return int
51
+ # @return [Fixnum]
52
52
  def key
53
53
  @counter
54
54
  end
@@ -57,7 +57,7 @@ module Tilia
57
57
  # iterator. This will return false if we've gone beyond the UNTIL or COUNT
58
58
  # statements.
59
59
  #
60
- # @return bool
60
+ # @return [Boolean]
61
61
  def valid
62
62
  return @counter < @count if @count
63
63
  @until.nil? || @current_date <= @until
@@ -65,7 +65,7 @@ module Tilia
65
65
 
66
66
  # Resets the iterator.
67
67
  #
68
- # @return void
68
+ # @return [void]
69
69
  def rewind
70
70
  @current_date = @start_date.clone
71
71
  @counter = 0
@@ -73,7 +73,7 @@ module Tilia
73
73
 
74
74
  # Goes on to the next iteration.
75
75
  #
76
- # @return void
76
+ # @return [void]
77
77
  def next
78
78
  # Otherwise, we find the next event in the normal RRULE
79
79
  # sequence.
@@ -95,7 +95,7 @@ module Tilia
95
95
 
96
96
  # Returns true if this recurring event never ends.
97
97
  #
98
- # @return bool
98
+ # @return [Boolean]
99
99
  def infinite?
100
100
  !@count && !@until
101
101
  end
@@ -103,153 +103,25 @@ module Tilia
103
103
  # This method allows you to quickly go to the next occurrence after the
104
104
  # specified date.
105
105
  #
106
- # @param DateTimeInterface dt
106
+ # @param [Time] dt
107
107
  #
108
- # @return void
108
+ # @return [void]
109
109
  def fast_forward(dt)
110
110
  self.next while valid && @current_date < dt
111
111
  end
112
112
 
113
113
  protected
114
114
 
115
- # The reference start date/time for the rrule.
116
- #
117
- # All calculations are based on this initial date.
118
- #
119
- # @var DateTimeInterface
120
- # RUBY attr_accessor :start_date
121
-
122
- # The date of the current iteration. You can get this by calling
123
- # .current.
124
- #
125
- # @var DateTimeInterface
126
- # RUBY attr_accessor :current_date
127
-
128
- # Frequency is one of: secondly, minutely, hourly, daily, weekly, monthly,
129
- # yearly.
130
- #
131
- # @var string
132
- # RUBY attr_accessor :frequency
133
-
134
- # The number of recurrences, or 'null' if infinitely recurring.
135
- #
136
- # @var int
137
- # RUBY attr_accessor :count
138
-
139
- # The interval.
140
- #
141
- # If for example frequency is set to daily, interval = 2 would mean every
142
- # 2 days.
143
- #
144
- # @var int
145
- # RUBY attr_accessor :interval
146
-
147
- # The last instance of this recurrence, inclusively.
148
- #
149
- # @var DateTimeInterface|null
150
- # RUBY attr_accessor :until
151
-
152
- # Which seconds to recur.
153
- #
154
- # This is an array of integers (between 0 and 60)
155
- #
156
- # @var array
157
- # RUBY attr_accessor :by_second
158
-
159
- # Which minutes to recur.
160
- #
161
- # This is an array of integers (between 0 and 59)
162
- #
163
- # @var array
164
- # RUBY attr_accessor :by_minute
165
-
166
- # Which hours to recur.
167
- #
168
- # This is an array of integers (between 0 and 23)
169
- #
170
- # @var array
171
- # RUBY attr_accessor :by_hour
172
-
173
- # The current item in the list.
174
- #
175
- # You can get this number with the key method.
176
- #
177
- # @var int
178
- # RUBY attr_accessor :counter
179
-
180
- # Which weekdays to recur.
181
- #
182
- # This is an array of weekdays
183
- #
184
- # This may also be preceeded by a positive or negative integer. If present,
185
- # this indicates the nth occurrence of a specific day within the monthly or
186
- # yearly rrule. For instance, -2TU indicates the second-last tuesday of
187
- # the month, or year.
188
- #
189
- # @var array
190
- # RUBY attr_accessor :by_day
191
-
192
- # Which days of the month to recur.
193
- #
194
- # This is an array of days of the months (1-31). The value can also be
195
- # negative. -5 for instance means the 5th last day of the month.
196
- #
197
- # @var array
198
- # RUBY attr_accessor :by_month_day
199
-
200
- # Which days of the year to recur.
201
- #
202
- # This is an array with days of the year (1 to 366). The values can also
203
- # be negative. For instance, -1 will always represent the last day of the
204
- # year. (December 31st).
205
- #
206
- # @var array
207
- # RUBY attr_accessor :by_year_day
208
-
209
- # Which week numbers to recur.
210
- #
211
- # This is an array of integers from 1 to 53. The values can also be
212
- # negative. -1 will always refer to the last week of the year.
213
- #
214
- # @var array
215
- # RUBY attr_accessor :by_week_no
216
-
217
- # Which months to recur.
218
- #
219
- # This is an array of integers from 1 to 12.
220
- #
221
- # @var array
222
- # RUBY attr_accessor :by_month
223
-
224
- # Which items in an existing st to recur.
225
- #
226
- # These numbers work together with an existing by* rule. It specifies
227
- # exactly which items of the existing by-rule to filter.
228
- #
229
- # Valid values are 1 to 366 and -1 to -366. As an example, this can be
230
- # used to recur the last workday of the month.
231
- #
232
- # This would be done by setting frequency to 'monthly', byDay to
233
- # 'MO,TU,WE,TH,FR' and bySetPos to -1.
234
- #
235
- # @var array
236
- # RUBY attr_accessor :by_set_pos
237
-
238
- # When the week starts.
239
- #
240
- # @var string
241
- # RUBY attr_accessor :week_start
242
-
243
115
  # Does the processing for advancing the iterator for hourly frequency.
244
116
  #
245
- # @return void
117
+ # @return [void]
246
118
  def next_hourly
247
119
  @current_date += @interval.hours
248
120
  end
249
121
 
250
122
  # Does the processing for advancing the iterator for daily frequency.
251
123
  #
252
- # @return void
124
+ # @return [void]
253
125
  def next_daily
254
126
  unless @by_hour || @by_day
255
127
  @current_date += @interval.days
@@ -290,7 +162,7 @@ module Tilia
290
162
 
291
163
  # Does the processing for advancing the iterator for weekly frequency.
292
164
  #
293
- # @return void
165
+ # @return [void]
294
166
  def next_weekly
295
167
  if !@by_hour && !@by_day
296
168
  @current_date += @interval.weeks
@@ -334,7 +206,7 @@ module Tilia
334
206
 
335
207
  # Does the processing for advancing the iterator for monthly frequency.
336
208
  #
337
- # @return void
209
+ # @return [void]
338
210
  def next_monthly
339
211
  current_day_of_month = @current_date.day
340
212
  unless @by_month_day || @by_day
@@ -376,7 +248,7 @@ module Tilia
376
248
  # If we made it all the way here, it means there were no
377
249
  # valid occurrences, and we need to advance to the next
378
250
  # month.
379
- @current_date - (@current_date.day - 1).days
251
+ @current_date -= (@current_date.day - 1).days
380
252
  @current_date += @interval.months
381
253
 
382
254
  # This goes to 0 because we need to start counting at the
@@ -389,7 +261,7 @@ module Tilia
389
261
 
390
262
  # Does the processing for advancing the iterator for yearly frequency.
391
263
  #
392
- # @return void
264
+ # @return [void]
393
265
  def next_yearly
394
266
  current_month = @current_date.month
395
267
  current_year = @current_date.year
@@ -502,9 +374,9 @@ module Tilia
502
374
  # This method receives a string from an RRULE property, and populates this
503
375
  # class with all the values.
504
376
  #
505
- # @param string|array rrule
377
+ # @param [String|array] rrule
506
378
  #
507
- # @return void
379
+ # @return [void]
508
380
  def parse_r_rule(rrule)
509
381
  if rrule.is_a?(String)
510
382
  rrule = Property::ICalendar::Recur.string_to_array(rrule)
@@ -516,7 +388,7 @@ module Tilia
516
388
  when 'FREQ'
517
389
  value = value.downcase
518
390
  unless ['secondly', 'minutely', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'].include?(value)
519
- fail ArgumentError, "Unknown value for FREQ=#{value.upcase}"
391
+ fail InvalidDataException, "Unknown value for FREQ=#{value.upcase}"
520
392
  end
521
393
  @frequency = value
522
394
  when 'UNTIL'
@@ -534,7 +406,7 @@ module Tilia
534
406
  when 'INTERVAL', 'COUNT'
535
407
  val = value.to_i
536
408
  if val < 1
537
- fail ArgumentError, "#{key.upcase} in RRULE must be a positive integer!"
409
+ fail InvalidDataException, "#{key.upcase} in RRULE must be a positive integer!"
538
410
  end
539
411
  key = key.downcase
540
412
  key == 'interval' ? @interval = val : @count = val
@@ -548,7 +420,7 @@ module Tilia
548
420
  value = value.is_a?(Array) ? value : [value]
549
421
  value.each do |part|
550
422
  unless part =~ /^ (-|\+)? ([1-5])? (MO|TU|WE|TH|FR|SA|SU) $/xi
551
- fail ArgumentError, "Invalid part in BYDAY clause: #{part}"
423
+ fail InvalidDataException, "Invalid part in BYDAY clause: #{part}"
552
424
  end
553
425
  end
554
426
  @by_day = value
@@ -565,22 +437,17 @@ module Tilia
565
437
  when 'WKST'
566
438
  @week_start = value.upcase
567
439
  else
568
- fail ArgumentError, "Not supported: #{key.upcase}"
440
+ fail InvalidDataException, "Not supported: #{key.upcase}"
569
441
  end
570
442
  end
571
443
  end
572
444
 
573
- # Mappings between the day number and english day name.
574
- #
575
- # @var array
576
- # RUBY: attr_accessor :day_names
577
-
578
445
  # Returns all the occurrences for a monthly frequency with a 'byDay' or
579
446
  # 'byMonthDay' expansion for the current month.
580
447
  #
581
448
  # The returned list is an array of integers with the day of month (1-31).
582
449
  #
583
- # @return array
450
+ # @return [array]
584
451
  def monthly_occurrences
585
452
  start_date = @current_date.clone
586
453
 
@@ -682,7 +549,7 @@ module Tilia
682
549
 
683
550
  # Simple mapping from iCalendar day names to day numbers.
684
551
  #
685
- # @var array
552
+ # @return [array]
686
553
  # RUBY: attr_accessor :day_map
687
554
 
688
555
  def hours
@@ -23,9 +23,25 @@ module Tilia
23
23
  # appointments made for many years to come.
24
24
  @max_date = '2100-01-01'
25
25
 
26
+ # The maximum number of recurrences that will be generated.
27
+ #
28
+ # This setting limits the maximum of recurring events that this library
29
+ # generates in its recurrence iterators.
30
+ #
31
+ # This is a security measure. Without this, it would be possible to craft
32
+ # specific events that recur many, many times, potentially DDOSing the
33
+ # server.
34
+ #
35
+ # The default (3500) allows creation of a dialy event that goes on for 10
36
+ # years, which is hopefully long enough for most.
37
+ #
38
+ # Set this value to -1 to disable this control altogether.
39
+ @max_recurrences = 3500
40
+
26
41
  class << self
27
42
  attr_accessor :min_date
28
43
  attr_accessor :max_date
44
+ attr_accessor :max_recurrences
29
45
  end
30
46
  end
31
47
  end
@@ -1,5 +1,6 @@
1
1
  module Tilia
2
2
  module VObject
3
+ # Splitts VObject files that contain several VObjects
3
4
  module Splitter
4
5
  require 'tilia/v_object/splitter/splitter_interface'
5
6
  require 'tilia/v_object/splitter/i_calendar'
@@ -14,20 +14,20 @@ module Tilia
14
14
 
15
15
  # Timezones.
16
16
  #
17
- # @var array
17
+ # @return [array]
18
18
  # RUBY: attr_accessor :vtimezones
19
19
 
20
20
  # iCalendar objects.
21
21
  #
22
- # @var array
22
+ # @return [array]
23
23
  # RUBY: attr_accessor :objects
24
24
 
25
25
  # Constructor.
26
26
  #
27
27
  # The splitter should receive an readable file stream as it's input.
28
28
  #
29
- # @param resource input
30
- # @param int options Parser options, see the OPTIONS constants.
29
+ # @param [resource] input
30
+ # @param [Fixnum] options Parser options, see the OPTIONS constants.
31
31
  def initialize(input, options = 0)
32
32
  @vtimezones = {}
33
33
  @objects = {}
@@ -65,7 +65,7 @@ module Tilia
65
65
  #
66
66
  # When the end is reached, null will be returned.
67
67
  #
68
- # @return Sabre\VObject\Component|null
68
+ # @return [Sabre\VObject\Component, nil]
69
69
  def next
70
70
  key = @objects.keys.first
71
71
 
@@ -13,7 +13,7 @@ module Tilia
13
13
  #
14
14
  # The splitter should receive an readable file stream as it's input.
15
15
  #
16
- # @param resource input
16
+ # @param [resource] input
17
17
  def initialize(_input)
18
18
  end
19
19
 
@@ -22,7 +22,7 @@ module Tilia
22
22
  #
23
23
  # When the end is reached, null will be returned.
24
24
  #
25
- # @return Sabre\VObject\Component|null
25
+ # @return [Sabre\VObject\Component, nil]
26
26
  def next
27
27
  end
28
28
  end
@@ -12,20 +12,20 @@ module Tilia
12
12
  include SplitterInterface
13
13
  # File handle.
14
14
  #
15
- # @var resource
15
+ # @return [resource]
16
16
  # RUBY: attr_accessor :input
17
17
 
18
18
  # Persistent parser.
19
19
  #
20
- # @var MimeDir
20
+ # @return [MimeDir]
21
21
  # RUBY: attr_accessor :parser
22
22
 
23
23
  # Constructor.
24
24
  #
25
25
  # The splitter should receive an readable file stream as it's input.
26
26
  #
27
- # @param resource input
28
- # @param int options Parser options, see the OPTIONS constants.
27
+ # @param [resource] input
28
+ # @param [Fixnum] options Parser options, see the OPTIONS constants.
29
29
  def initialize(input, options = 0)
30
30
  @input = input
31
31
  @parser = Parser::MimeDir.new(input, options)
@@ -36,7 +36,7 @@ module Tilia
36
36
  #
37
37
  # When the end is reached, null will be returned.
38
38
  #
39
- # @return Sabre\VObject\Component|null
39
+ # @return [Sabre\VObject\Component, nil]
40
40
  def next
41
41
  begin
42
42
  object = @parser.parse
@@ -4,9 +4,9 @@ module Tilia
4
4
  class StringUtil
5
5
  # Returns true or false depending on if a string is valid UTF-8.
6
6
  #
7
- # @param string str
7
+ # @param [String] str
8
8
  #
9
- # @return bool
9
+ # @return [Boolean]
10
10
  def self.utf8?(str)
11
11
  fail ArgumentError, 'str needs to be a String' unless str.is_a?(String)
12
12
  # Control characters
@@ -20,22 +20,38 @@ module Tilia
20
20
  # Currently only ISO-5991-1 input and UTF-8 input is supported, but this
21
21
  # may be expanded upon if we receive other examples.
22
22
  #
23
- # @param string str
23
+ # @param [String] str
24
24
  #
25
- # @return string
25
+ # @return [String]
26
26
  def self.convert_to_utf8(str)
27
+ str = str.encode('UTF-8', guess_encoding(str))
28
+
29
+ # Removing any control characters
30
+ str.gsub(/(?:[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F])/, '')
31
+ end
32
+
33
+ # Detects the encoding of a string
34
+ #
35
+ # Currently only supports 'UTF-8', 'ISO-5991-1' and 'Windows-1252'.
36
+ #
37
+ # @param [String] str
38
+ # @return [String] encoding
39
+ def self.guess_encoding(str)
27
40
  cd = CharDet.detect(str)
28
41
 
29
42
  # Best solution I could find ...
30
43
  if cd['confidence'] > 0.4 && cd['encoding'] =~ /(?:windows|iso)/i
31
- str = str.encode('UTF-8', cd['encoding'])
44
+ cd['encoding']
45
+ else
46
+ 'UTF-8'
32
47
  end
33
-
34
- # Removing any control characters
35
- str.gsub(/(?:[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F])/, '')
36
48
  end
37
49
 
38
- # TODO: document
50
+ # Cuts the string after a certain bytelength
51
+ #
52
+ # @param [String] string
53
+ # @param [Fixnum] length
54
+ # @return [String] cut string
39
55
  def self.mb_strcut(string, length)
40
56
  return '' if string == ''
41
57