scashin133-vpim 9.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/CHANGES +510 -0
  4. data/COPYING +58 -0
  5. data/LICENSE +20 -0
  6. data/Makefile +135 -0
  7. data/README +182 -0
  8. data/README.rdoc +17 -0
  9. data/Rakefile +54 -0
  10. data/THANKS +2 -0
  11. data/VERSION +1 -0
  12. data/ex_fmt_convert.rb +25 -0
  13. data/ex_ics_api.rb +54 -0
  14. data/lib/vpim/address.rb +219 -0
  15. data/lib/vpim/agent/atomize.rb +104 -0
  16. data/lib/vpim/agent/base.rb +73 -0
  17. data/lib/vpim/agent/calendars.rb +173 -0
  18. data/lib/vpim/agent/handler.rb +26 -0
  19. data/lib/vpim/agent/ics.rb +161 -0
  20. data/lib/vpim/attachment.rb +102 -0
  21. data/lib/vpim/date.rb +222 -0
  22. data/lib/vpim/dirinfo.rb +277 -0
  23. data/lib/vpim/duration.rb +119 -0
  24. data/lib/vpim/enumerator.rb +32 -0
  25. data/lib/vpim/field.rb +618 -0
  26. data/lib/vpim/icalendar.rb +384 -0
  27. data/lib/vpim/maker/vcard.rb +16 -0
  28. data/lib/vpim/property/base.rb +193 -0
  29. data/lib/vpim/property/common.rb +315 -0
  30. data/lib/vpim/property/location.rb +38 -0
  31. data/lib/vpim/property/priority.rb +43 -0
  32. data/lib/vpim/property/recurrence.rb +69 -0
  33. data/lib/vpim/property/resources.rb +24 -0
  34. data/lib/vpim/repo.rb +261 -0
  35. data/lib/vpim/rfc2425.rb +371 -0
  36. data/lib/vpim/rrule.rb +591 -0
  37. data/lib/vpim/time.rb +40 -0
  38. data/lib/vpim/vcard.rb +1426 -0
  39. data/lib/vpim/version.rb +19 -0
  40. data/lib/vpim/vevent.rb +187 -0
  41. data/lib/vpim/view.rb +90 -0
  42. data/lib/vpim/vjournal.rb +58 -0
  43. data/lib/vpim/vpim.rb +65 -0
  44. data/lib/vpim/vtodo.rb +103 -0
  45. data/lib/vpim.rb +13 -0
  46. data/mbox2vcard.rb +89 -0
  47. data/outline.sh +4 -0
  48. data/profile.rb +6 -0
  49. data/profile.txt +276 -0
  50. data/samples/README.mutt +93 -0
  51. data/samples/ab-query.rb +57 -0
  52. data/samples/agent.ru +10 -0
  53. data/samples/cmd-itip.rb +156 -0
  54. data/samples/ex_cpvcard.rb +55 -0
  55. data/samples/ex_get_vcard_photo.rb +22 -0
  56. data/samples/ex_mkv21vcard.rb +34 -0
  57. data/samples/ex_mkvcard.rb +64 -0
  58. data/samples/ex_mkyourown.rb +29 -0
  59. data/samples/ics-dump.rb +210 -0
  60. data/samples/ics-to-rss.rb +84 -0
  61. data/samples/mutt-aliases-to-vcf.rb +45 -0
  62. data/samples/osx-wrappers.rb +86 -0
  63. data/samples/reminder.rb +209 -0
  64. data/samples/rrule.rb +71 -0
  65. data/samples/tabbed-file-to-vcf.rb +390 -0
  66. data/samples/vcf-dump.rb +86 -0
  67. data/samples/vcf-lines.rb +61 -0
  68. data/samples/vcf-to-ics.rb +22 -0
  69. data/samples/vcf-to-mutt.rb +121 -0
  70. data/setup.rb +1585 -0
  71. data/stamp.rb +29 -0
  72. data/test/calendars/weather.calendar/Events/1205042405-0-0.ics +17 -0
  73. data/test/calendars/weather.calendar/Events/1205128857-1-1205128857.ics +21 -0
  74. data/test/calendars/weather.calendar/Events/1205215257-2--1884536782.ics +22 -0
  75. data/test/calendars/weather.calendar/Events/1205301657-3--679062325.ics +21 -0
  76. data/test/calendars/weather.calendar/Events/1205388057-4-526584932.ics +20 -0
  77. data/test/calendars/weather.calendar/Events/1205474457-5-1732404989.ics +21 -0
  78. data/test/calendars/weather.calendar/Events/1205560857-6--1356569450.ics +21 -0
  79. data/test/calendars/weather.calendar/Events/1205647257-7--150403793.ics +22 -0
  80. data/test/calendars/weather.calendar/Events/1205712057-8-1055761864.ics +20 -0
  81. data/test/calendars/weather.calendar/Info.plist +20 -0
  82. data/test/common.rb +51 -0
  83. data/test/test_agent_atomize.rb +84 -0
  84. data/test/test_agent_calendars.rb +128 -0
  85. data/test/test_agent_ics.rb +96 -0
  86. data/test/test_all.rb +14 -0
  87. data/test/test_date.rb +120 -0
  88. data/test/test_dur.rb +41 -0
  89. data/test/test_field.rb +156 -0
  90. data/test/test_ical.rb +437 -0
  91. data/test/test_misc.rb +13 -0
  92. data/test/test_repo.rb +129 -0
  93. data/test/test_rrule.rb +1030 -0
  94. data/test/test_vcard.rb +1017 -0
  95. data/test/test_view.rb +79 -0
  96. data/test/weekly.ics +40 -0
  97. data/vpim.gemspec +157 -0
  98. metadata +206 -0
data/Makefile ADDED
@@ -0,0 +1,135 @@
1
+ # Makefile
2
+
3
+ SHELL:=/bin/sh
4
+
5
+ RUBY=/usr/bin/ruby
6
+
7
+ .PHONY: default doc test other
8
+
9
+ do: release
10
+
11
+ reminder:
12
+ ruby -I lib samples/reminder.rb
13
+
14
+ default: test
15
+
16
+ bday:
17
+ @ruby18 -I . vcf-to-ics.rb < _all.vcf | tee _bday.ics
18
+
19
+ doc-upload:
20
+ cd doc; scp -r . sam@rubyforge.org:/var/www/gforge-projects/vpim/
21
+
22
+ agent-upload:
23
+ rsync -v --archive --compress --cvs-exclude --exclude=.svn/ --del lib octet:webapps/agent/
24
+
25
+ RDFLAGS = -w2
26
+
27
+ #--diagram
28
+ # --main doc/foo.html
29
+
30
+ TEST=test/test_all.rb
31
+
32
+ dcal:
33
+ sh -c "./ics-dump.rb ~/Library/Calendars/Play.ics"
34
+ sh -c "./ics-dump.rb ~/Library/Calendars/Events.ics"
35
+
36
+ test:
37
+ $(RUBY) $(TEST)
38
+ for e in ex_*.rb; do $(RUBY) -w -I lib $$e; done >/dev/null
39
+ #/usr/bin/ruby -w -I lib $(TEST)
40
+ #/opt/local/bin/ruby -w -I lib $(TEST)
41
+
42
+ test_new:
43
+ for r in /opt/local/bin/ruby /usr/local/bin/ruby18; do $$r -w $(TEST); done
44
+
45
+ test_old:
46
+ for r in /usr/bin/ruby; do $$r -w $(TEST); done
47
+
48
+ .PHONY: coverage
49
+ coverage:
50
+ rcov -Ilib -x "^/" test/test_all.rb
51
+ open coverage/index.html
52
+
53
+ outline:
54
+ zsh ./outline.sh > outline.txt
55
+
56
+ .PHONY: tags
57
+ tags:
58
+ /sw/bin/ctags -R --extra=+f lib test
59
+ #RUBYLIB=/Users/sam/p/ruby/ruby/lib /usr/local/bin/rdoc18 -f tags lib
60
+ #mv tags tags.ctags
61
+ #sort tags.ctags tags.rdoc > tags
62
+
63
+ ri:
64
+ rdoc18 -f ri lib
65
+
66
+ open:
67
+ open doc/index.html
68
+
69
+ SAMPLES := \
70
+ samples/ab-query.rb \
71
+ samples/cmd-itip.rb \
72
+ samples/ex_get_vcard_photo.rb \
73
+ samples/ex_cpvcard.rb \
74
+ samples/ex_mkvcard.rb \
75
+ samples/ex_mkv21vcard.rb \
76
+ samples/ex_mkyourown.rb \
77
+ samples/ics-dump.rb \
78
+ samples/ics-to-rss.rb \
79
+ samples/mutt-aliases-to-vcf.rb \
80
+ samples/reminder.rb \
81
+ samples/rrule.rb \
82
+ samples/tabbed-file-to-vcf.rb \
83
+ samples/vcf-dump.rb \
84
+ samples/vcf-lines.rb \
85
+ samples/vcf-to-mutt.rb \
86
+ samples/vcf-to-ics.rb \
87
+
88
+ .PHONY: doc
89
+ doc:
90
+ rm -rf doc/
91
+ rdoc $(RDFLAGS) lib/vpim CHANGES COPYING README samples/README.mutt
92
+ for s in $(SAMPLES); do cp $$s doc/`basename $$s .rb`.txt; done
93
+ chmod u=rw doc/*.txt
94
+ chmod go=r doc/*.txt
95
+ mkdir -p $(HOME)/Sites/vpim
96
+ cp -r doc/* $(HOME)/Sites/vpim/
97
+ open doc/index.html
98
+ ruby -I lib -w -rpp ex_ics_api.rb > ex_ics_api.out
99
+
100
+ V:=$(shell ruby stamp.rb)
101
+ P:=vpim-$V
102
+ R:=../releases/$P
103
+
104
+ release: stamp doc pkg gem
105
+
106
+ install:
107
+ for r in /usr/bin/ruby /opt/local/bin/ruby ruby18; do (cd $R; $$r install.rb config; sudo $$r install.rb install); done
108
+
109
+ stamp:
110
+ ruby stamp.rb $V > lib/vpim/version.rb
111
+
112
+ gem:
113
+ mkdir -p ../releases
114
+ mkdir -p bin
115
+ cp -v samples/reminder.rb bin/reminder
116
+ cp -v samples/rrule.rb bin/rrule
117
+ chmod +x bin/*
118
+ ruby vpim.gemspec
119
+ mv vpim*.gem ../releases/
120
+
121
+ pkg:
122
+ rm -rf $R/*
123
+ mkdir -p $R/lib
124
+ mkdir -p $R/samples
125
+ mkdir -p $R/test
126
+ cp COPYING README CHANGES setup.rb $R/
127
+ cp -vr lib/vpim $R/lib/
128
+ cp samples/README.mutt $R/samples
129
+ cp $(SAMPLES) $R/samples
130
+ cp samples/osx-wrappers.rb $R/samples
131
+ cp test/test_*.rb $R/test
132
+ # no docs: cp -r doc $R/
133
+ cd ../releases && tar -zcf $P.tgz $P
134
+
135
+ # vim:noexpandtab:tabstop=2:sw=2:
data/README ADDED
@@ -0,0 +1,182 @@
1
+ Author:: Sam Roberts <vieuxtech@gmail.com>
2
+ Copyright:: Copyright (C) 2008 Sam Roberts
3
+ License:: May be distributed under the same terms as Ruby
4
+ Homepage:: http://vpim.rubyforge.org
5
+ Download:: http://rubyforge.org/projects/vpim
6
+ Install:: sudo gem install vpim
7
+
8
+ vPim provides calendaring, scheduling, and contact support for Ruby through the
9
+ standard iCalendar and vCard data formats for "personal information" exchange.
10
+
11
+ = Thanks
12
+
13
+ - http://ZipDX.com: for sponsoring development of FREQ=weekly and BYSETPOS in
14
+ recurrence rules.
15
+ - http://RubyForge.org: for their generous hosting of this project.
16
+
17
+ = Installation
18
+
19
+ There is a vPim package installable using ruby-gems:
20
+
21
+ # sudo gem install vpim (may require root privilege)
22
+
23
+ It is also installable in the standard way. Untar the package, and do:
24
+
25
+ $ ruby setup.rb --help
26
+
27
+ or do:
28
+
29
+ $ ruby setup.rb config
30
+ $ ruby setup.rb setup
31
+ # ruby setup.rb install (may require root privilege)
32
+
33
+ = Overview
34
+
35
+ vCard (RFC 2426) is a format for personal information, see Vpim::Vcard and
36
+ Vpim::Maker::Vcard.
37
+
38
+ iCalendar (RFC 2445) is a format for calendar related information, see
39
+ Vpim::Icalendar.
40
+
41
+ vCard and iCalendar support is built on top of an implementation of the MIME
42
+ Content-Type for Directory Information (RFC 2425). The basic RFC 2425 format is
43
+ implemented by Vpim::DirectoryInfo and Vpim::DirectoryInfo::Field.
44
+
45
+ The libary is quite useful, but improvements are ongoing. If you find
46
+ something missing or have suggestions, please contact me. I can't promise
47
+ instantaneous turnaround, but I might be able to suggest another approach, and
48
+ features requested by users of vPim go to the top of the todo list. If you need
49
+ a feature for a commercial project, consider sponsoring development.
50
+
51
+ = Examples
52
+
53
+ Here's an example to give a sense for how iCalendars are encoded and decoded:
54
+
55
+ require 'vpim/icalendar'
56
+
57
+ cal = Vpim::Icalendar.create2
58
+
59
+ cal.add_event do |e|
60
+ e.dtstart Date.new(2005, 04, 28)
61
+ e.dtend Date.new(2005, 04, 29)
62
+ e.summary "Monthly meet-the-CEO day"
63
+ e.description <<'---'
64
+ Unlike last one, this meeting will change your life because
65
+ we are going to discuss your likely demotion if your work isn't
66
+ done soon.
67
+ ---
68
+ e.categories [ 'APPOINTMENT' ]
69
+ e.categories do |c| c.push 'EDUCATION' end
70
+ e.url 'http://www.example.com'
71
+ e.sequence 0
72
+ e.access_class "PRIVATE"
73
+ e.transparency 'OPAQUE'
74
+
75
+ now = Time.now
76
+ e.created now
77
+ e.lastmod now
78
+
79
+
80
+ e.organizer do |o|
81
+ o.cn = "Example Organizer, Mr."
82
+ o.uri = "mailto:organizer@example.com"
83
+ end
84
+
85
+ attendee = Vpim::Icalendar::Address.create("mailto:attendee@example.com")
86
+ attendee.rsvp = true
87
+ e.add_attendee attendee
88
+ end
89
+
90
+ icsfile = cal.encode
91
+
92
+ puts '--- Encode:'
93
+
94
+ puts icsfile
95
+
96
+ puts '--- Decode:'
97
+
98
+ cal = Vpim::Icalendar.decode(icsfile).first
99
+
100
+ cal.components do |e|
101
+ puts e.summary
102
+ puts e.description
103
+ puts e.dtstart.to_s
104
+ puts e.dtend.to_s
105
+ end
106
+
107
+ This produces:
108
+
109
+ --- Encode:
110
+ BEGIN:VCALENDAR
111
+ VERSION:2.0
112
+ PRODID:-//Ensemble Independent//vPim 0.357//EN
113
+ CALSCALE:Gregorian
114
+ BEGIN:VEVENT
115
+ DTSTART;VALUE=DATE:20050428
116
+ DTEND;VALUE=DATE:20050429
117
+ SUMMARY:Monthly meet-the-CEO day
118
+ DESCRIPTION:Unlike last one, this meeting will change your life because\nwe
119
+ are going to discuss your likely demotion if your work isn't\ndone soon.\n
120
+ CATEGORIES:APPOINTMENT,EDUCATION
121
+ URL:http://www.example.com
122
+ SEQUENCE:0
123
+ CLASS:PRIVATE
124
+ CREATED:20060402T231755
125
+ LAST-MODIFIED:20060402T231755
126
+ ORGANIZER;CN="Example Organizer, Mr.":mailto:organizer@example.com
127
+ ATTENDEE;RSVP=true:mailto:attendee@example.com
128
+ END:VEVENT
129
+ END:VCALENDAR
130
+ --- Decode:
131
+ Monthly meet-the-CEO day
132
+ Unlike last one, this meeting will change your life because
133
+ we are going to discuss your likely demotion if your work isn't
134
+ done soon.
135
+ Thu Apr 28 00:00:00 UTC 2005
136
+ Fri Apr 29 00:00:00 UTC 2005
137
+
138
+
139
+ More examples of using vPim are provided in samples/.
140
+
141
+ vCard examples are:
142
+ - link:ex_mkvcard.txt: example of creating a vCard
143
+ - link:ex_cpvcard.txt: example of copying and them modifying a vCard
144
+ - link:ex_mkv21vcard.txt: example of creating version 2.1 vCard
145
+ - link:mutt-aliases-to-vcf.txt: convert a mutt aliases file to vCards
146
+ - link:ex_get_vcard_photo.txt: pull photo data from a vCard
147
+ - link:ab-query.txt: query the OS X Address Book to find vCards
148
+ - link:vcf-to-mutt.txt: query vCards for matches, output in formats useful
149
+ with Mutt (see link:README.mutt for details)
150
+ - link:tabbed-file-to-vcf.txt: convert a tab-delimited file to vCards, a
151
+ (small but) complete application contributed by Dane G. Avilla, thanks!
152
+ - link:vcf-to-ics.txt: example of how to create calendars of birthdays from vCards
153
+ - link:vcf-dump.txt: utility for dumping contents of .vcf files
154
+
155
+ iCalendar examples are:
156
+ - link:ics-to-rss.txt: prints todos as RSS, or starts a WEBrick servlet
157
+ that publishes todos as a RSS feed. Thanks to Dave Thomas for this idea,
158
+ from http://pragprog.com/pragdave/Tech/Blog/ToDos.rdoc.
159
+ - link:cmd-itip.txt: prints emailed iCalendar invitations in human-readable
160
+ form, and see link:README.mutt for instruction on mutt integration. I get
161
+ a lot of meeting invitations from Lotus Notes/Domino users at work, and
162
+ this is pretty useful in figuring out where and when I am supposed to be.
163
+ - link:reminder.txt: prints upcoming events and todos, by default from
164
+ Apple's iCal calendars
165
+ - link:rrule.txt: utility for printing recurrence rules
166
+ - link:ics-dump.txt: utility for dumping contents of .ics files
167
+
168
+ = Project Information
169
+
170
+ vPim can be downloaded from the Ruby Forge project page:
171
+
172
+ - http://rubyforge.org/projects/vpim
173
+
174
+ or installed as a gem:
175
+
176
+ - sudo gem install vpim
177
+
178
+ For notifications about new releases, or to ask questions about vPim, please
179
+ subscribe to "vpim-talk":
180
+
181
+ - http://rubyforge.org/mailman/listinfo/vpim-talk
182
+
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = vpim
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Sean Cashin. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "scashin133-vpim"
8
+ gem.summary = %Q{iCalendar and vCard support for ruby}
9
+ gem.description = %Q{This is a pure-ruby library for decoding and encoding vCard and iCalendar data ("personal information") called vPim.}
10
+ gem.email = "vieuxtech@gmail.com; scashin133@gmail.com"
11
+ gem.homepage = "http://github.com/scashin133/vpim"
12
+ gem.authors = ["Sam Roberts", "Sean Cashin"]
13
+ gem.add_development_dependency "shoulda", ">= 0"
14
+ gem.add_development_dependency "sinatra", ">= 0"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "vpim #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/THANKS ADDED
@@ -0,0 +1,2 @@
1
+ Jade Meskill
2
+ Ryan King
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 9.4.0
data/ex_fmt_convert.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'vpim/icalendar'
2
+ require 'open-uri'
3
+
4
+ class Convert
5
+ def initialize(io)
6
+ @io = io
7
+ end
8
+
9
+ def each
10
+ @io.each do |line|
11
+ line.gsub!("\r", "\\n")
12
+ yield line
13
+ end
14
+ end
15
+ end
16
+
17
+ io = open("http://upcoming.org/calendar/metro/45")
18
+ cvt = Convert.new(io)
19
+ cal = Vpim::Icalendar.decode(cvt).first
20
+
21
+ cal.components do |c|
22
+ puts "-------------------------------------------------"
23
+ puts c.description
24
+ end
25
+
data/ex_ics_api.rb ADDED
@@ -0,0 +1,54 @@
1
+ require 'vpim/icalendar'
2
+
3
+ cal = Vpim::Icalendar.create2
4
+
5
+ cal.add_event do |e|
6
+ e.dtstart Date.new(2005, 04, 28)
7
+ e.dtend Date.new(2005, 04, 29)
8
+ e.summary "Monthly meet-the-CEO day"
9
+ e.description <<'---'
10
+ Unlike last one, this meeting will change your life because
11
+ we are going to discuss your likely demotion if your work isn't
12
+ done soon.
13
+ ---
14
+ e.categories [ 'APPOINTMENT' ]
15
+ e.categories do |c| c.push 'EDUCATION' end
16
+ e.url 'http://www.example.com'
17
+ e.sequence 0
18
+ e.access_class "PRIVATE"
19
+ e.transparency 'OPAQUE'
20
+ e.set_text('LOCATION', 'my location')
21
+
22
+ now = Time.now
23
+ e.created now
24
+ e.lastmod now
25
+
26
+
27
+ e.organizer do |o|
28
+ o.cn = "Example Organizer, Mr."
29
+ o.uri = "mailto:organizer@example.com"
30
+ end
31
+
32
+ attendee = Vpim::Icalendar::Address.create("mailto:attendee@example.com")
33
+ attendee.rsvp = true
34
+ e.add_attendee attendee
35
+ end
36
+
37
+ icsfile = cal.encode
38
+
39
+ puts '--- Encode:'
40
+
41
+ puts icsfile
42
+
43
+ puts '--- Decode:'
44
+
45
+ cal = Vpim::Icalendar.decode(icsfile).first
46
+
47
+ cal.components do |e|
48
+ puts e.summary
49
+ puts e.description
50
+ puts e.dtstart.to_s
51
+ puts e.dtend.to_s
52
+ end
53
+
54
+
@@ -0,0 +1,219 @@
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
+ =begin
10
+
11
+ Notes on a CAL-ADDRESS
12
+
13
+ When used with ATTENDEE, the parameters are:
14
+ CN
15
+ CUTYPE
16
+ DELEGATED-FROM
17
+ DELEGATED-TO
18
+ DIR
19
+ LANGUAGE
20
+ MEMBER
21
+ PARTSTAT
22
+ ROLE
23
+ RSVP
24
+ SENT-BY
25
+
26
+ When used with ORGANIZER, the parameters are:
27
+ CN
28
+ DIR
29
+ LANGUAGE
30
+ SENT-BY
31
+
32
+
33
+ What I've seen in Notes invitations, and iCal responses:
34
+ ROLE
35
+ PARTSTAT
36
+ RSVP
37
+ CN
38
+
39
+ Support these last 4, for now.
40
+
41
+ =end
42
+
43
+ module Vpim
44
+ class Icalendar
45
+ # Used to represent calendar fields containing CAL-ADDRESS values.
46
+ # The organizer or the attendees of a calendar event are examples of such
47
+ # a field.
48
+ #
49
+ # Example:
50
+ #
51
+ # ORGANIZER;CN="A. Person":mailto:a_person@example.com
52
+ #
53
+ # ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION
54
+ # ;CN="Sam Roberts";RSVP=TRUE:mailto:SRoberts@example.com
55
+ #
56
+ class Address
57
+
58
+ # Create a copy of Address. If the original Address was frozen, this one
59
+ # won't be.
60
+ def copy
61
+ #Marshal.load(Marshal.dump(self))
62
+ self.dup.dirty
63
+ end
64
+
65
+ def dirty #:nodoc:
66
+ @field = nil
67
+ self
68
+ end
69
+
70
+ # Addresses in a CAL-ADDRESS are represented as a URI, usually a mailto URI.
71
+ attr_accessor :uri
72
+ # The common or displayable name associated with the calendar address, or
73
+ # nil if there is none.
74
+ attr_accessor :cn
75
+ # The participation role for the calendar user specified by the address.
76
+ #
77
+ # The standard roles are:
78
+ # - CHAIR Indicates chair of the calendar entity
79
+ # - REQ-PARTICIPANT Indicates a participant whose participation is required
80
+ # - OPT-PARTICIPANT Indicates a participant whose participation is optional
81
+ # - NON-PARTICIPANT Indicates a participant who is copied for information purposes only
82
+ #
83
+ # The default role is REQ-PARTICIPANT, returned if no ROLE parameter was
84
+ # specified.
85
+ attr_accessor :role
86
+ # The participation status for the calendar user specified by the
87
+ # property PARTSTAT, a String.
88
+ #
89
+ # These are the participation statuses for an Event:
90
+ # - NEEDS-ACTION Event needs action
91
+ # - ACCEPTED Event accepted
92
+ # - DECLINED Event declined
93
+ # - TENTATIVE Event tentatively accepted
94
+ # - DELEGATED Event delegated
95
+ #
96
+ # Default is NEEDS-ACTION.
97
+ #
98
+ # FIXME - make the default depend on the component type.
99
+ attr_accessor :partstat
100
+ # The value of the RSVP field, either +true+ or +false+. It is used to
101
+ # specify whether there is an expectation of a reply from the calendar
102
+ # user specified by the property value.
103
+ attr_accessor :rsvp
104
+
105
+ def initialize(field=nil) #:nodoc:
106
+ @field = field
107
+ @uri = ''
108
+ @cn = ''
109
+ @role = "REQ-PARTICIPANT"
110
+ @partstat = "NEEDS-ACTION"
111
+ @rsvp = false
112
+ end
113
+
114
+ # Create a new Address. It will encode as a +name+ property.
115
+ def self.create(uri='')
116
+ adr = new
117
+ adr.uri = uri.to_str
118
+ adr
119
+ end
120
+
121
+ def self.decode(field)
122
+ adr = new(field)
123
+ adr.uri = field.value
124
+
125
+ cn = field.param('CN')
126
+
127
+ if cn
128
+ adr.cn = cn.first
129
+ end
130
+
131
+ role = field.param('ROLE')
132
+
133
+ if role
134
+ adr.role = role.first.strip.upcase
135
+ end
136
+
137
+ partstat = field.param('PARTSTAT')
138
+
139
+ if partstat
140
+ adr.partstat = partstat.first.strip.upcase
141
+ end
142
+
143
+ rsvp = field.param('RSVP')
144
+
145
+ if rsvp
146
+ adr.rsvp = case rsvp.first
147
+ when /TRUE/i then true
148
+ when /FALSE/i then false
149
+ else raise InvalidEncodingError, "RSVP param value not TRUE/FALSE: #{rsvp}"
150
+ end
151
+ end
152
+
153
+ adr.freeze
154
+ end
155
+
156
+ # Return a representation of this Address as a DirectoryInfo::Field.
157
+ def encode(name) #:nodoc:
158
+ if @field
159
+ # FIXME - set the field name, it could be different from cached
160
+ return @field
161
+ end
162
+
163
+ value = uri.to_str.strip
164
+
165
+ if value.empty?
166
+ raise Uencodeable, "Address#uri is zero-length"
167
+ end
168
+
169
+ params = {}
170
+
171
+ if cn.length > 0
172
+ params['CN'] = Vpim::encode_paramvalue(cn)
173
+ end
174
+
175
+ # FIXME - default value is different for non-vEvent
176
+ if role.length > 0 && role != 'REQ-PARTICIPANT'
177
+ params['ROLE'] = Vpim::encode_paramtext(role)
178
+ end
179
+
180
+ # FIXME - default value is different for non-vEvent
181
+ if partstat.length > 0 && partstat != 'NEEDS-ACTION'
182
+ params['PARTSTAT'] = Vpim::encode_paramtext(partstat)
183
+ end
184
+
185
+ if rsvp
186
+ params['RSVP'] = 'true'
187
+ end
188
+
189
+ Vpim::DirectoryInfo::Field.create(name, value, params)
190
+ end
191
+
192
+ # Return true if the +uri+ is == to this address' URI. The comparison
193
+ # is case-insensitive (because email addresses and domain names are).
194
+ def ==(uri)
195
+ # TODO - could I use a URI library?
196
+ Vpim::Methods.casecmp?(self.uri.to_str, uri.to_str)
197
+ end
198
+
199
+ # A string representation of an address, using the common name, and the
200
+ # URI. The URI protocol is stripped if it's "mailto:".
201
+ def to_s
202
+ u = uri
203
+ u = u.gsub(/^mailto: */i, '')
204
+
205
+ if cn.length > 0
206
+ "#{cn.inspect} <#{uri}>"
207
+ else
208
+ uri
209
+ end
210
+ end
211
+
212
+ def inspect #:nodoc:
213
+ "#<Vpim::Icalendar::Address:cn=#{cn.inspect} status=#{partstat} rsvp=#{rsvp} #{uri.inspect}>"
214
+ end
215
+
216
+ end
217
+ end
218
+ end
219
+