mumboe-vpim 0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/CHANGES +510 -0
  2. data/COPYING +58 -0
  3. data/README +185 -0
  4. data/lib/vpim/address.rb +219 -0
  5. data/lib/vpim/agent/atomize.rb +104 -0
  6. data/lib/vpim/agent/base.rb +73 -0
  7. data/lib/vpim/agent/calendars.rb +173 -0
  8. data/lib/vpim/agent/handler.rb +26 -0
  9. data/lib/vpim/agent/ics.rb +161 -0
  10. data/lib/vpim/attachment.rb +102 -0
  11. data/lib/vpim/date.rb +222 -0
  12. data/lib/vpim/dirinfo.rb +277 -0
  13. data/lib/vpim/duration.rb +119 -0
  14. data/lib/vpim/enumerator.rb +32 -0
  15. data/lib/vpim/field.rb +614 -0
  16. data/lib/vpim/icalendar.rb +384 -0
  17. data/lib/vpim/maker/vcard.rb +16 -0
  18. data/lib/vpim/property/base.rb +193 -0
  19. data/lib/vpim/property/common.rb +315 -0
  20. data/lib/vpim/property/location.rb +38 -0
  21. data/lib/vpim/property/priority.rb +43 -0
  22. data/lib/vpim/property/recurrence.rb +69 -0
  23. data/lib/vpim/property/resources.rb +24 -0
  24. data/lib/vpim/repo.rb +261 -0
  25. data/lib/vpim/rfc2425.rb +367 -0
  26. data/lib/vpim/rrule.rb +591 -0
  27. data/lib/vpim/time.rb +40 -0
  28. data/lib/vpim/vcard.rb +1456 -0
  29. data/lib/vpim/version.rb +18 -0
  30. data/lib/vpim/vevent.rb +187 -0
  31. data/lib/vpim/view.rb +90 -0
  32. data/lib/vpim/vjournal.rb +58 -0
  33. data/lib/vpim/vpim.rb +65 -0
  34. data/lib/vpim/vtodo.rb +103 -0
  35. data/lib/vpim.rb +13 -0
  36. data/samples/README.mutt +93 -0
  37. data/samples/ab-query.rb +57 -0
  38. data/samples/agent.ru +10 -0
  39. data/samples/cmd-itip.rb +156 -0
  40. data/samples/ex_cpvcard.rb +55 -0
  41. data/samples/ex_get_vcard_photo.rb +22 -0
  42. data/samples/ex_mkv21vcard.rb +34 -0
  43. data/samples/ex_mkvcard.rb +64 -0
  44. data/samples/ex_mkyourown.rb +29 -0
  45. data/samples/ics-dump.rb +210 -0
  46. data/samples/ics-to-rss.rb +84 -0
  47. data/samples/mutt-aliases-to-vcf.rb +45 -0
  48. data/samples/osx-wrappers.rb +86 -0
  49. data/samples/reminder.rb +209 -0
  50. data/samples/rrule.rb +71 -0
  51. data/samples/tabbed-file-to-vcf.rb +390 -0
  52. data/samples/vcf-dump.rb +86 -0
  53. data/samples/vcf-lines.rb +61 -0
  54. data/samples/vcf-to-ics.rb +22 -0
  55. data/samples/vcf-to-mutt.rb +121 -0
  56. data/test/test_agent_atomize.rb +84 -0
  57. data/test/test_agent_calendars.rb +128 -0
  58. data/test/test_agent_ics.rb +96 -0
  59. data/test/test_all.rb +17 -0
  60. data/test/test_date.rb +120 -0
  61. data/test/test_dur.rb +41 -0
  62. data/test/test_field.rb +156 -0
  63. data/test/test_ical.rb +437 -0
  64. data/test/test_misc.rb +13 -0
  65. data/test/test_repo.rb +129 -0
  66. data/test/test_rrule.rb +1030 -0
  67. data/test/test_vcard.rb +973 -0
  68. data/test/test_view.rb +79 -0
  69. metadata +140 -0
@@ -0,0 +1,18 @@
1
+ =begin
2
+ Copyright (C) 2008 Sam Roberts
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 Vpim
10
+ PRODID = '-//Octet Cloud//vPim 9.3.15//EN'
11
+
12
+ VERSION = '9.3.15'
13
+
14
+ # Return the API version as a string.
15
+ def Vpim.version
16
+ VERSION
17
+ end
18
+ end
@@ -0,0 +1,187 @@
1
+ =begin
2
+ Copyright (C) 2008 Sam Roberts
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
+ require 'vpim/dirinfo'
10
+ require 'vpim/field'
11
+ require 'vpim/rfc2425'
12
+ require 'vpim/rrule'
13
+ require 'vpim/vpim'
14
+ require 'vpim/property/base'
15
+ require 'vpim/property/common'
16
+ require 'vpim/property/priority'
17
+ require 'vpim/property/location'
18
+ require 'vpim/property/resources'
19
+ require 'vpim/property/recurrence'
20
+
21
+ module Vpim
22
+ class Icalendar
23
+ class Vevent
24
+
25
+ include Vpim::Icalendar::Property::Base
26
+ include Vpim::Icalendar::Property::Common
27
+ include Vpim::Icalendar::Property::Priority
28
+ include Vpim::Icalendar::Property::Location
29
+ include Vpim::Icalendar::Property::Resources
30
+ include Vpim::Icalendar::Property::Recurrence
31
+
32
+ def initialize(fields) #:nodoc:
33
+ outer, inner = Vpim.outer_inner(fields)
34
+
35
+ @properties = Vpim::DirectoryInfo.create(outer)
36
+
37
+ @elements = inner
38
+
39
+ # See "TODO - fields" in dirinfo.rb
40
+ end
41
+
42
+ # TODO - derive everything from Icalendar::Component to get rid of this kind of stuff?
43
+ def fields #:nodoc:
44
+ f = @properties.to_a
45
+ last = f.pop
46
+ f.push @elements
47
+ f.push last
48
+ end
49
+
50
+ def properties #:nodoc:
51
+ @properties
52
+ end
53
+
54
+ # Create a new Vevent object. All events must have a DTSTART field,
55
+ # specify it as either a Time or a Date in +start+, it defaults to "now"
56
+ #
57
+ # If specified, +fields+ must be either an array of Field objects to
58
+ # add, or a Hash of String names to values that will be used to build
59
+ # Field objects. The latter is a convenient short-cut allowing the Field
60
+ # objects to be created for you when called like:
61
+ #
62
+ # Vevent.create(Date.today, 'SUMMARY' => "today's event")
63
+ #
64
+ def Vevent.create(start = Time.now, fields=[])
65
+ # TODO
66
+ # - maybe events are usually created in a particular way? With a
67
+ # start/duration or a start/end? Maybe I can make it easier. Ideally, I
68
+ # would like to make it hard to encode an invalid Event.
69
+ # - I don't think its useful to have a default dtstart for events
70
+ # - also, I don't think dstart is mandatory
71
+ dtstart = DirectoryInfo::Field.create('DTSTART', start)
72
+ di = DirectoryInfo.create([ dtstart ], 'VEVENT')
73
+
74
+ Vpim::DirectoryInfo::Field.create_array(fields).each { |f| di.push_unique f }
75
+
76
+ new(di.to_a)
77
+ end
78
+
79
+ # Creates a yearly repeating event, such as for a birthday.
80
+ def Vevent.create_yearly(date, summary)
81
+ create(
82
+ date,
83
+ 'SUMMARY' => summary.to_str,
84
+ 'RRULE' => 'FREQ=YEARLY'
85
+ )
86
+ end
87
+
88
+ # Accept an event invitation. The +invitee+ is the Address that wishes
89
+ # to accept the event invitation as confirmed.
90
+ #
91
+ # The event created is identical to this one, but
92
+ # - without the attendees
93
+ # - with the invitee added with a PARTSTAT of ACCEPTED
94
+ def accept(invitee)
95
+ # FIXME - move to Vpim::Itip.
96
+ invitee = invitee.copy
97
+ invitee.partstat = 'ACCEPTED'
98
+
99
+ fields = []
100
+
101
+ @properties.each_with_index do
102
+ |f,i|
103
+
104
+ # put invitee in as field[1]
105
+ fields << invitee.encode('ATTENDEE') if i == 1
106
+
107
+ fields << f unless f.name? 'ATTENDEE'
108
+ end
109
+
110
+ Vevent.new(fields)
111
+ end
112
+
113
+ # In iTIP, whether this event is OPAQUE or TRANSPARENT to scheduling. If
114
+ # transparency is not explicitly set, it defaults to OPAQUE.
115
+ def transparency
116
+ proptoken 'TRANSP', ["OPAQUE", "TRANSPARENT"], "OPAQUE"
117
+ end
118
+
119
+ # The duration in seconds of an Event, or nil if unspecified. If the
120
+ # DURATION field is not present, but the DTEND field is, the duration is
121
+ # calculated from DTSTART and DTEND. Durations of zero seconds are
122
+ # possible.
123
+ def duration
124
+ propduration 'DTEND'
125
+ end
126
+
127
+ # The end time for this Event. If the DTEND field is not present, but the
128
+ # DURATION field is, the end will be calculated from DTSTART and
129
+ # DURATION.
130
+ def dtend
131
+ propend 'DTEND'
132
+ end
133
+
134
+ # Make a new Vevent, or make changes to an existing Vevent.
135
+ class Maker
136
+ include Vpim::Icalendar::Set::Util #:nodoc:
137
+ include Vpim::Icalendar::Set::Common
138
+
139
+ # The event that changes are being made to.
140
+ attr_reader :event
141
+
142
+ def initialize(event) #:nodoc:
143
+ @event = event
144
+ @comp = event
145
+ end
146
+
147
+ # Make changes to +event+. If +event+ is not specified, creates a new
148
+ # event. Yields a Vevent::Maker, and returns +event+.
149
+ def self.make(event = Vpim::Icalendar::Vevent.create) #:yield:maker
150
+ m = self.new(event)
151
+ yield m
152
+ m.event
153
+ end
154
+
155
+ # Set transparency to "OPAQUE" or "TRANSPARENT", see Vpim::Vevent#transparency.
156
+ def transparency(token)
157
+ set_token 'TRANSP', ["OPAQUE", "TRANSPARENT"], "OPAQUE", token
158
+ end
159
+
160
+ # Set end for events with fixed durations. +end+ can be a Date or Time
161
+ def dtend(dtend)
162
+ set_date_or_datetime 'DTEND', 'DATE-TIME', dtend
163
+ end
164
+
165
+ # Add a RRULE to this event. The rule can be provided as a pre-build
166
+ # RRULE value, or the RRULE maker can be used.
167
+ def add_rrule(rule = nil, &block) #:yield: Rrule::Maker
168
+ # TODO - should be in Property::Reccurrence::Set
169
+ unless rule
170
+ rule = Rrule::Maker.new(&block).encode
171
+ end
172
+ @comp.properties.push(Vpim::DirectoryInfo::Field.create("RRULE", rule))
173
+ self
174
+ end
175
+
176
+ # Set the RRULE for this event. See #add_rrule
177
+ def set_rrule(rule = nil, &block) #:yield: Rrule::Maker
178
+ rm_all("RRULE")
179
+ add_rrule(rule, &block)
180
+ end
181
+
182
+ end
183
+
184
+ end
185
+ end
186
+ end
187
+
data/lib/vpim/view.rb ADDED
@@ -0,0 +1,90 @@
1
+ =begin
2
+ Copyright (C) 2008 Sam Roberts
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
+ require "enumerator"
10
+
11
+ module Vpim
12
+ module View
13
+
14
+ SECSPERDAY = 24 * 60 * 60
15
+
16
+ # View only events occuring in the next week.
17
+ module Week
18
+ def each(klass = nil) #:nodoc:
19
+ unless block_given?
20
+ return Enumerable::Enumerator.new(self, :each, klass)
21
+ end
22
+
23
+ t0 = Time.new.to_a
24
+ t0[0] = t0[1] = t0[2] = 0 # sec,min,hour = 0
25
+ t0 = Time.local(*t0)
26
+ t1 = t0 + 7 * SECSPERDAY
27
+
28
+ # Need to filter occurrences, too. Create modules for this on the fly.
29
+ occurrences = Module.new
30
+ # I'm passing state into the module's instance methods by doing string
31
+ # evaluation... which sucks, but I don't think I can get this closure in
32
+ # there.
33
+ occurrences.module_eval(<<"__", __FILE__, __LINE__+1)
34
+ def occurrences(dountil=nil)
35
+ unless block_given?
36
+ return Enumerable::Enumerator.new(self, :occurrences, dountil)
37
+ end
38
+ super(dountil) do |t|
39
+ t0 = Time.at(#{t0.to_i})
40
+ t1 = Time.at(#{t1.to_i})
41
+ break if t >= t1
42
+ tend = t
43
+ if respond_to? :duration
44
+ tend += duration || 0
45
+ end
46
+ if tend >= t0
47
+ yield t
48
+ end
49
+ end
50
+ end
51
+ __
52
+ =begin
53
+ block = lambda do |dountil|
54
+ unless block_given?
55
+ return Enumerable::Enumerator.new(self, :occurrences, dountil)
56
+ end
57
+ super(dountil) do |t|
58
+ break if t >= t1
59
+ yield t
60
+ end
61
+ end
62
+ occurrences.send(:define_method, :occurrences, block)
63
+ =end
64
+ super do |ve|
65
+ if ve.occurs_in?(t0, t1)
66
+ if ve.respond_to? :occurrences
67
+ ve.extend occurrences
68
+ end
69
+ yield ve
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ # Return a calendar view for the next week.
76
+ def self.week(cal)
77
+ cal.clone.extend Week.dup
78
+ end
79
+
80
+ module Todo
81
+ end
82
+
83
+ # Return a calendar view of only todos (optionally, include todos that
84
+ # are done).
85
+ def self.todos(cal, withdone=false)
86
+ end
87
+
88
+ end
89
+ end
90
+
@@ -0,0 +1,58 @@
1
+ =begin
2
+ Copyright (C) 2008 Sam Roberts
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
+ require 'vpim/dirinfo'
10
+ require 'vpim/field'
11
+ require 'vpim/rfc2425'
12
+ require 'vpim/vpim'
13
+ require 'vpim/property/base'
14
+ require 'vpim/property/common'
15
+ require 'vpim/property/recurrence'
16
+
17
+ module Vpim
18
+ class Icalendar
19
+
20
+ class Vjournal
21
+ include Vpim::Icalendar::Property::Base
22
+ include Vpim::Icalendar::Property::Common
23
+ include Vpim::Icalendar::Property::Recurrence
24
+
25
+ def initialize(fields) #:nodoc:
26
+ outer, inner = Vpim.outer_inner(fields)
27
+
28
+ @properties = Vpim::DirectoryInfo.create(outer)
29
+
30
+ @elements = inner
31
+ end
32
+
33
+ # TODO - derive everything from Icalendar::Component to get rid of this kind of stuff?
34
+ def fields #:nodoc:
35
+ f = properties.to_a
36
+ last = f.pop
37
+ f.push @elements
38
+ f.push last
39
+ end
40
+
41
+ def properties #:nodoc:
42
+ @properties
43
+ end
44
+
45
+ # Create a Vjournal component.
46
+ def self.create(fields=[])
47
+ di = DirectoryInfo.create([], 'VJOURNAL')
48
+
49
+ Vpim::DirectoryInfo::Field.create_array(fields).each { |f| di.push_unique f }
50
+
51
+ new(di.to_a)
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+
data/lib/vpim/vpim.rb ADDED
@@ -0,0 +1,65 @@
1
+ =begin
2
+ Copyright (C) 2008 Sam Roberts
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
+ require 'vpim/version'
10
+
11
+ #:main:README
12
+ #:title:vPim - vCard and iCalendar support for Ruby
13
+ module Vpim
14
+ # Exception used to indicate that data being decoded is invalid, the message
15
+ # should describe what is invalid.
16
+ class InvalidEncodingError < StandardError; end
17
+
18
+ # Exception used to indicate that data being decoded is unsupported, the message
19
+ # should describe what is unsupported.
20
+ #
21
+ # If its unsupported, its likely because I didn't anticipate it being useful
22
+ # to support this, and it likely it could be supported on request.
23
+ class UnsupportedError < StandardError; end
24
+
25
+ # Exception used to indicate that encoding failed, probably because the
26
+ # object would not result in validly encoded data. The message should
27
+ # describe what is unsupported.
28
+ class Unencodeable < StandardError; end
29
+ end
30
+
31
+ module Vpim::Methods #:nodoc:
32
+ module_function
33
+
34
+ # Case-insensitive comparison of +str0+ to +str1+, returns true or false.
35
+ # Either argument can be nil, where nil compares not equal to anything other
36
+ # than nil.
37
+ #
38
+ # This is available both as a module function:
39
+ # Vpim::Methods.casecmp?("yes", "YES")
40
+ # and an instance method:
41
+ # include Vpim::Methods
42
+ # casecmp?("yes", "YES")
43
+ #
44
+ # Will work with ruby1.6 and ruby 1.8.
45
+ #
46
+ # TODO - could make this be more efficient, but I'm supporting 1.6, not
47
+ # optimizing for it.
48
+ def casecmp?(str0, str1)
49
+ if str0 == nil
50
+ if str1 == nil
51
+ return true
52
+ else
53
+ return false
54
+ end
55
+ end
56
+
57
+ begin
58
+ str0.casecmp(str1) == 0
59
+ rescue NoMethodError
60
+ str0.downcase == str1.downcase
61
+ end
62
+ end
63
+
64
+ end
65
+
data/lib/vpim/vtodo.rb ADDED
@@ -0,0 +1,103 @@
1
+ =begin
2
+ Copyright (C) 2008 Sam Roberts
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
+ require 'vpim/dirinfo'
10
+ require 'vpim/field'
11
+ require 'vpim/rfc2425'
12
+ require 'vpim/vpim'
13
+ require 'vpim/property/base'
14
+ require 'vpim/property/common'
15
+ require 'vpim/property/priority'
16
+ require 'vpim/property/location'
17
+ require 'vpim/property/resources'
18
+ require 'vpim/property/recurrence'
19
+
20
+ module Vpim
21
+ class Icalendar
22
+
23
+ class Vtodo
24
+ include Vpim::Icalendar::Property::Base
25
+ include Vpim::Icalendar::Property::Common
26
+ include Vpim::Icalendar::Property::Priority
27
+ include Vpim::Icalendar::Property::Location
28
+ include Vpim::Icalendar::Property::Resources
29
+ include Vpim::Icalendar::Property::Recurrence
30
+
31
+ def initialize(fields) #:nodoc:
32
+ outer, inner = Vpim.outer_inner(fields)
33
+
34
+ @properties = Vpim::DirectoryInfo.create(outer)
35
+
36
+ @elements = inner
37
+ end
38
+
39
+ # TODO - derive everything from Icalendar::Component to get this kind of stuff?
40
+ def fields #:nodoc:
41
+ f = @properties.to_a
42
+ last = f.pop
43
+ f.push @elements
44
+ f.push last
45
+ end
46
+
47
+ def properties #:nodoc:
48
+ @properties
49
+ end
50
+
51
+ # Create a new Vtodo object.
52
+ #
53
+ # If specified, +fields+ must be either an array of Field objects to
54
+ # add, or a Hash of String names to values that will be used to build
55
+ # Field objects. The latter is a convenient short-cut allowing the Field
56
+ # objects to be created for you when called like:
57
+ #
58
+ # Vtodo.create('SUMMARY' => "buy mangos")
59
+ #
60
+ # TODO - maybe todos are usually created in a particular way? I can
61
+ # make it easier. Ideally, I would like to make it hard to encode an invalid
62
+ # Event.
63
+ def Vtodo.create(fields=[])
64
+ di = DirectoryInfo.create([], 'VTODO')
65
+
66
+ Vpim::DirectoryInfo::Field.create_array(fields).each { |f| di.push_unique f }
67
+
68
+ new(di.to_a)
69
+ end
70
+
71
+ # The duration in seconds of a Todo, or nil if unspecified. If the
72
+ # DURATION field is not present, but the DUE field is, the duration is
73
+ # calculated from DTSTART and DUE. Durations of zero seconds are
74
+ # possible.
75
+ def duration
76
+ propduration 'DUE'
77
+ end
78
+
79
+ # The time at which this Todo is due to be completed. If the DUE field is not present,
80
+ # but the DURATION field is, due will be calculated from DTSTART and DURATION.
81
+ def due
82
+ propend 'DUE'
83
+ end
84
+
85
+ # The date and time that a to-do was actually completed, a Time.
86
+ def completed
87
+ proptime 'COMPLETED'
88
+ end
89
+
90
+ # The percentage completetion of the to-do, between 0 and 100. 0 means it hasn't
91
+ # started, 100 that it has been completed.
92
+ #
93
+ # TODO - the handling of this property isn't tied to either COMPLETED: or
94
+ # STATUS:, but perhaps it should be?
95
+ def percent_complete
96
+ propinteger 'PERCENT-COMPLETE'
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+ end
103
+
data/lib/vpim.rb ADDED
@@ -0,0 +1,13 @@
1
+ =begin
2
+ Copyright (C) 2008 Sam Roberts
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
+ # the existence of this file is a hack to support users or rubygems
10
+
11
+ require 'vpim/icalendar'
12
+ require 'vpim/vcard'
13
+
@@ -0,0 +1,93 @@
1
+
2
+ ** cmd-itip.rb
3
+
4
+ This script pretty-prints iTIP calendar invitations, often sent by email using iMIP
5
+ as text/calendar objects.
6
+
7
+ Download the latest vPim from:
8
+
9
+ http://rubyforge.org/projects/vpim/
10
+
11
+ It requires Ruby to be installed.
12
+
13
+ Install vpim:
14
+
15
+ tar -xzf vpim-XX.tgz
16
+ cd vpim-XX
17
+ ruby install.rb config
18
+ ruby install.rb setup
19
+ sudo ruby install.rb install
20
+
21
+ Install cmd-itip.rb into your path, perhaps without the extension.
22
+
23
+ cp samples/cmd-itip.rb ~/bin/cmd-itip
24
+ chmod +x ~/bin/cmd-itip
25
+
26
+ Modify your ~/.mailcap or /etc/mailcap files to call cmd-itip, add a line like:
27
+
28
+ text/calendar; cmd-itip --myaddr "sroberts@" %s; copiousoutput
29
+
30
+ If you give a REGEX to --myaddr to tell cmd-itip your email addresses, cmd-itip
31
+ will avoid printing some information on the attendees to an invitation.
32
+
33
+ Modify muttrc to autoview calendars with a command like:
34
+
35
+ auto_view text/calendar
36
+
37
+ Notes on Notes;
38
+
39
+ Because Domino sends a close-to-unreadable text/plain attachment along with the
40
+ text/calendar in a multipart/alternative, and the text/plain is first in the
41
+ alternatives, the garbage will be at the top, and the nicely printed calendar
42
+ at the bottom. Because of this, I reorder the view preference so the calendar
43
+ invitation is clearly printed at the top of the message with a muttrc command
44
+ like:
45
+
46
+ alternative_order text/calendar text/plain
47
+
48
+ Domino also includes the calendar twice in the mail message, so you'll see it
49
+ twice, I don't know what to do about that.
50
+
51
+ Notes on application/octet-stream:
52
+
53
+ Some calendar programs, such as Apple's Mail.app, wrongly send iCalendar attachments
54
+ with a content-type of application/octet-stream. In order to be processed correctly, use
55
+ the mutt 1.5 or later capability to lookup the correct MIME content-type based on the
56
+ file extension. Put this in your muttrc file:
57
+
58
+ mime_lookup application/octet-stream
59
+
60
+ and ensure /etc/mime.types or ~/.mime.types contains:
61
+
62
+ text/calendar ics
63
+
64
+
65
+
66
+ ** vcf-to-mutt.rb
67
+
68
+ This script searches a set of vCards can output the results as a Mutt query response,
69
+ or a Mutt aliases file.
70
+
71
+ It used to support querying the OS X Address Book, but that is better done with lbdb, see
72
+ http://www.spinnaker.de/lbdb/.
73
+
74
+ To install, you must:
75
+
76
+ 1 - install vPim (see README)
77
+
78
+ 3 - copy vcf-to-mutt into a directory in your path, such
79
+ as ~/bin, and chmod +x vcf-to-mutt.rb to make it executable.
80
+
81
+ 4 - Put in your muttrc file (either ~/.muttrc or ~/.mutt/muttrc) a line such as:
82
+
83
+ set query_command = "vcf-to-mutt.rb '%s'"
84
+
85
+ 5 - The query command ("Q") will query the address book, control-t will give you auto-completion
86
+ of email addresses, see the Mutt manual page.
87
+
88
+
89
+ ** mutt-aliases-to-vcf.rb
90
+
91
+ This script converts a mutt aliases file into a vCard file.
92
+
93
+
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $-w = true
4
+ $:.unshift File.dirname($0) + '/../lib'
5
+
6
+ require 'osx-wrappers'
7
+
8
+ require 'getoptlong'
9
+ require 'vpim/vcard'
10
+ require 'osx-wrappers'
11
+
12
+ HELP =<<EOF
13
+ Usage: ab-query.rb [--me] [--all]
14
+
15
+ Queries the OS X Address Book for vCards.
16
+
17
+ -h, --help print this helpful message
18
+ -m, --me list my vCard
19
+ -a, --all list all vCards
20
+ EOF
21
+
22
+ opts = GetoptLong.new(
23
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
24
+ [ "--me", "-m", GetoptLong::NO_ARGUMENT ],
25
+ [ "--all", "-a", GetoptLong::NO_ARGUMENT ]
26
+ )
27
+
28
+ abook = nil
29
+
30
+ opts.each do |opt, arg|
31
+ case opt
32
+ when "--help" then
33
+ puts HELP
34
+ exit 0
35
+
36
+ when "--all" then
37
+ abook = OSX::ABAddressBook.sharedAddressBook unless abook
38
+
39
+ abook.people.to_a.each {
40
+ |person|
41
+
42
+ puts person.vCard
43
+ }
44
+
45
+ when "--me" then
46
+ abook = OSX::ABAddressBook.sharedAddressBook unless abook
47
+
48
+ puts abook.me.vCard
49
+ end
50
+ end
51
+
52
+
53
+ unless abook
54
+ puts HELP
55
+ exit 1
56
+ end
57
+
data/samples/agent.ru ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # Run as "rackup agent.ru", default rackup arguments follow:
3
+ #\ -p 4567
4
+
5
+ require "vpim/agent/ics"
6
+
7
+ use Rack::Reloader, 0
8
+
9
+ run Vpim::Agent::Ics
10
+