vpim2 0.0.1

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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +504 -0
  3. data/COPYING +58 -0
  4. data/README +182 -0
  5. data/lib/atom.rb +728 -0
  6. data/lib/plist.rb +22 -0
  7. data/lib/vpim.rb +13 -0
  8. data/lib/vpim/address.rb +219 -0
  9. data/lib/vpim/attachment.rb +102 -0
  10. data/lib/vpim/date.rb +222 -0
  11. data/lib/vpim/dirinfo.rb +277 -0
  12. data/lib/vpim/duration.rb +119 -0
  13. data/lib/vpim/enumerator.rb +32 -0
  14. data/lib/vpim/field.rb +614 -0
  15. data/lib/vpim/icalendar.rb +381 -0
  16. data/lib/vpim/maker/vcard.rb +16 -0
  17. data/lib/vpim/property/base.rb +193 -0
  18. data/lib/vpim/property/common.rb +315 -0
  19. data/lib/vpim/property/location.rb +38 -0
  20. data/lib/vpim/property/priority.rb +43 -0
  21. data/lib/vpim/property/recurrence.rb +69 -0
  22. data/lib/vpim/property/resources.rb +24 -0
  23. data/lib/vpim/repo.rb +181 -0
  24. data/lib/vpim/rfc2425.rb +367 -0
  25. data/lib/vpim/rrule.rb +591 -0
  26. data/lib/vpim/vcard.rb +1430 -0
  27. data/lib/vpim/version.rb +18 -0
  28. data/lib/vpim/vevent.rb +187 -0
  29. data/lib/vpim/view.rb +90 -0
  30. data/lib/vpim/vjournal.rb +58 -0
  31. data/lib/vpim/vpim.rb +65 -0
  32. data/lib/vpim/vtodo.rb +103 -0
  33. data/samples/README.mutt +93 -0
  34. data/samples/ab-query.rb +57 -0
  35. data/samples/cmd-itip.rb +156 -0
  36. data/samples/ex_cpvcard.rb +55 -0
  37. data/samples/ex_get_vcard_photo.rb +22 -0
  38. data/samples/ex_mkv21vcard.rb +34 -0
  39. data/samples/ex_mkvcard.rb +64 -0
  40. data/samples/ex_mkyourown.rb +29 -0
  41. data/samples/ics-dump.rb +210 -0
  42. data/samples/ics-to-rss.rb +84 -0
  43. data/samples/mutt-aliases-to-vcf.rb +45 -0
  44. data/samples/osx-wrappers.rb +86 -0
  45. data/samples/reminder.rb +203 -0
  46. data/samples/rrule.rb +71 -0
  47. data/samples/tabbed-file-to-vcf.rb +390 -0
  48. data/samples/vcf-dump.rb +86 -0
  49. data/samples/vcf-lines.rb +61 -0
  50. data/samples/vcf-to-ics.rb +22 -0
  51. data/samples/vcf-to-mutt.rb +121 -0
  52. data/test/test_all.rb +17 -0
  53. data/test/test_date.rb +120 -0
  54. data/test/test_dur.rb +41 -0
  55. data/test/test_field.rb +156 -0
  56. data/test/test_ical.rb +415 -0
  57. data/test/test_repo.rb +158 -0
  58. data/test/test_rrule.rb +1030 -0
  59. data/test/test_vcard.rb +973 -0
  60. data/test/test_view.rb +79 -0
  61. metadata +117 -0
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $-w = true
4
+ $:.unshift File.dirname($0) + '/../lib'
5
+
6
+ require 'pp'
7
+ require 'getoptlong'
8
+ require 'vpim/vcard'
9
+
10
+ HELP =<<EOF
11
+ Usage: #{$0} <vcard>...
12
+
13
+ Options
14
+ -h,--help Print this helpful message.
15
+ -n,--name Print the vCard name.
16
+ -d,--debug Print debug information.
17
+
18
+ Examples:
19
+ EOF
20
+
21
+ opt_name = nil
22
+ opt_debug = nil
23
+
24
+ opts = GetoptLong.new(
25
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
26
+ [ "--name", "-n", GetoptLong::NO_ARGUMENT ],
27
+ [ "--debug", "-d", GetoptLong::NO_ARGUMENT ]
28
+ )
29
+
30
+ opts.each do |opt, arg|
31
+ case opt
32
+ when "--help" then
33
+ puts HELP
34
+ exit 0
35
+
36
+ when "--name" then
37
+ opt_name = true
38
+
39
+ when "--debug" then
40
+ opt_debug = true
41
+ end
42
+ end
43
+
44
+ if ARGV.length < 1
45
+ puts "no vcard files specified, try -h!"
46
+ exit 1
47
+ end
48
+
49
+ ARGV.each do |file|
50
+
51
+ cards = Vpim::Vcard.decode(open(file))
52
+
53
+ cards.each do |card|
54
+ card.each do |field|
55
+ puts "..#{field.name.capitalize}=#{field.value.inspect}"
56
+
57
+ if field.group
58
+ puts " group=#{field.group}"
59
+ end
60
+
61
+ field.each_param do |param, values|
62
+ puts " #{param}=[#{values.join(", ")}]"
63
+ end
64
+ end
65
+
66
+ if opt_name
67
+ begin
68
+ puts "#name=#{card.name.formatted}"
69
+ rescue
70
+ puts "! failed to decode name!"
71
+ end
72
+ end
73
+
74
+
75
+ if opt_debug
76
+ card.groups.sort.each do |group|
77
+ card.enum_by_group(group).each do |field|
78
+ puts "#{group} -> #{field.inspect}"
79
+ end
80
+ end
81
+ end
82
+
83
+ puts ""
84
+ end
85
+ end
86
+
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $-w = true
4
+ $:.unshift File.dirname($0) + '/../lib'
5
+
6
+ require 'pp'
7
+ require 'getoptlong'
8
+ require 'vpim/vcard'
9
+
10
+ HELP =<<EOF
11
+ Usage: #{$0} <vcard>...
12
+
13
+ Options
14
+ -h,--help Print this helpful message.
15
+
16
+ Examples:
17
+ EOF
18
+
19
+ opt_name = nil
20
+ opt_debug = nil
21
+
22
+ opts = GetoptLong.new(
23
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
24
+ [ "--name", "-n", GetoptLong::NO_ARGUMENT ],
25
+ [ "--debug", "-d", GetoptLong::NO_ARGUMENT ]
26
+ )
27
+
28
+ opts.each do |opt, arg|
29
+ case opt
30
+ when "--help" then
31
+ puts HELP
32
+ exit 0
33
+
34
+ when "--name" then
35
+ opt_name = true
36
+
37
+ when "--debug" then
38
+ opt_debug = true
39
+ end
40
+ end
41
+
42
+ if ARGV.length < 1
43
+ puts "no vcard files specified, try -h!"
44
+ exit 1
45
+ end
46
+
47
+ ARGV.each do |file|
48
+
49
+ cards = Vpim::Vcard.decode(open(file))
50
+
51
+ cards.each do |card|
52
+ card.lines.each_with_index do |line, i|
53
+ print line.name
54
+ if line.group.length > 0
55
+ print " (", line.group, ")"
56
+ end
57
+ print ": ", line.value.inspect, "\n"
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'vpim/vcard'
4
+ require 'vpim/icalendar'
5
+
6
+ $in = ARGV.first ? File.open(ARGV.shift) : $stdin
7
+ $out = ARGV.first ? File.open(ARGV.shift, 'w') : $stdout
8
+
9
+ cal = Vpim::Icalendar.create
10
+
11
+ Vpim::Vcard.decode($in).each do |card|
12
+ if card.birthday
13
+ cal.push Vpim::Icalendar::Vevent.create_yearly(
14
+ card.birthday,
15
+ "Birthday for #{card['fn'].strip}"
16
+ )
17
+ $stderr.puts "#{card['fn']} -> bday #{cal.events.last.dtstart}"
18
+ end
19
+ end
20
+
21
+ puts cal.encode
22
+
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # For a query command, mutt expects output of the form:
4
+ #
5
+ # informational line
6
+ # <email>TAB<name>[TAB<other info>]
7
+ # ...
8
+ #
9
+ # For an alias command, mutt expects output of the form:
10
+ # alias NICKNAME EMAIL
11
+ #
12
+ # NICKNAME shouldn't have spaces, and EMAIL can be either "user@example.com",
13
+ # "<user@example.com>", or "User <user@example.com>".
14
+
15
+ $-w = true
16
+ $:.unshift File.dirname($0) + '/../lib'
17
+
18
+
19
+ require 'getoptlong'
20
+ require 'vpim/vcard'
21
+
22
+ HELP =<<EOF
23
+ Usage: vcf-to-mutt.rb [--aliases] [query]
24
+
25
+ Queries a vCard file and prints the results in Mutt's query result format, or
26
+ as a Mutt alias file. No query matches all vCards.
27
+
28
+ The query is matched against all fields, so you can use 'climbers' to match all
29
+ vCards that has that string in the Notes field if you want to email all the
30
+ rock climbers you know. Or you can query all vCards with addresses in a
31
+ particular city, you get the idea.
32
+
33
+ Options
34
+ -h,--help Print this helpful message.
35
+ -a,--aliases Output an alias file, otherwise output a query response.
36
+
37
+ Examples:
38
+
39
+ Put in your muttrc file (either ~/.muttrc or ~/.mutt/muttrc) a line such as:
40
+
41
+ set query_command = "vcf-to-mutt.rb '%s' < ~/mycards.vcf"
42
+
43
+ Bugs:
44
+
45
+ The aliases output file bases the alias name on the nickname, or the full
46
+ name, but either way, they aren't guaranteed to be unique if you have more than
47
+ email address in a vCard, or more than one vCard for the same nickname or full
48
+ name.
49
+ EOF
50
+
51
+ opt_query = ''
52
+ opt_aliases = false
53
+
54
+ opts = GetoptLong.new(
55
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
56
+ [ "--aliases", "-a", GetoptLong::NO_ARGUMENT ]
57
+ )
58
+
59
+ opts.each do |opt, arg|
60
+ case opt
61
+ when "--help" then
62
+ puts HELP
63
+ exit 0
64
+
65
+ when "--aliases" then
66
+ opt_aliases = true
67
+ end
68
+ end
69
+
70
+ opt_query = ARGV.first
71
+
72
+ module Mutt
73
+ def Mutt.vcard_query(cards, query)
74
+ query = query.downcase if query
75
+ cards.find_all do |card|
76
+ card.detect do |f|
77
+ !query || f.value.downcase.include?(query)
78
+ end
79
+ end
80
+ end
81
+
82
+ def Mutt.query_print(cards, caption)
83
+ puts caption
84
+
85
+ cards.each do
86
+ |vcard|
87
+ # find the email addresses
88
+ vcard.enum_by_name("email").each do |f|
89
+ nn = vcard.nickname
90
+ nn = nn ? "\t#{nn}" : ""
91
+ puts "#{f.value}\t#{vcard['fn']}#{nn}"
92
+ end
93
+ end
94
+ end
95
+
96
+ def Mutt.alias_print(cards)
97
+ cards.each do
98
+ |vcard|
99
+ # find the email addresses
100
+ vcard.enum_by_name("email").each do |f|
101
+ em = f.value
102
+ fn = vcard['fn']
103
+ nn = vcard.nickname || fn.gsub(/\s+/,'')
104
+ puts "alias #{nn} #{fn} <#{em}>"
105
+ end
106
+ end
107
+ end
108
+
109
+ end
110
+
111
+ cards = Vpim::Vcard.decode($stdin)
112
+
113
+ matches = Mutt::vcard_query(cards, opt_query)
114
+
115
+ if opt_aliases
116
+ Mutt::alias_print(matches)
117
+ else
118
+ qstr = opt_query == '' ? '<all records>' : opt_query;
119
+ Mutt::query_print(matches, "Query #{qstr} against #{cards.size} vCards:")
120
+ end
121
+
data/test/test_all.rb ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pp'
4
+
5
+ $-w = true
6
+
7
+ $:.unshift File.dirname(__FILE__) + "/../lib"
8
+
9
+
10
+ pp [__LINE__, $:, $"]
11
+
12
+ require 'test/unit'
13
+
14
+ Dir[File.dirname(__FILE__) + "/test_*.rb"].each do |test|
15
+ require test unless test =~ /test_all/
16
+ end
17
+
data/test/test_date.rb ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'vpim/date'
4
+ require 'vpim/time'
5
+ require 'test/unit'
6
+
7
+ class TestVpimDate < Test::Unit::TestCase
8
+
9
+ def test_to_time
10
+ # Need to test with DateTime, but I don't have that with ruby 1.6.
11
+ assert_equal(Time.at(0), Date.new(1970, 1, 1).vpim_to_time)
12
+ assert_equal(Time.at(24 * 60 * 60), Date.new(1970, 1, 2).vpim_to_time)
13
+ end
14
+
15
+ def test_date_weekstart
16
+ assert_equal(Date.weekstart(2004, 01, 12, 'tu').to_s, Date.new(2004, 01, 6).to_s)
17
+ assert_equal(Date.weekstart(2004, 01, 12, 'we').to_s, Date.new(2004, 01, 7).to_s)
18
+ assert_equal(Date.weekstart(2004, 01, 12, 'th').to_s, Date.new(2004, 01, 8).to_s)
19
+ assert_equal(Date.weekstart(2004, 01, 12, 'fr').to_s, Date.new(2004, 01, 9).to_s)
20
+ assert_equal(Date.weekstart(2004, 01, 12, 'sa').to_s, Date.new(2004, 01, 10).to_s)
21
+ assert_equal(Date.weekstart(2004, 01, 12, 'su').to_s, Date.new(2004, 01, 11).to_s)
22
+ assert_equal(Date.weekstart(2004, 01, 12, 'mo').to_s, Date.new(2004, 01, 12).to_s)
23
+ end
24
+
25
+ def do_bywday(args, expect)
26
+ # Rewrite 'string' weekday specifications.
27
+ args = [ args[0], args[1], Date.str2wday(args[2]), args[3] ]
28
+ date = Date.bywday(*args)
29
+ dates = DateGen.bywday(*args)
30
+ need = Date.new(*expect)
31
+
32
+ assert_equal(date, need)
33
+
34
+ # Date.bywday always produces a single date, so should the generator, in
35
+ # this case.
36
+ assert_equal(dates[0], need)
37
+ end
38
+
39
+ def test_bywday
40
+
41
+ # 2004
42
+ #
43
+ # January February March
44
+ # S M Tu W Th F S S M Tu W Th F S S M Tu W Th F S
45
+ # 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6
46
+ # 4 5 6 7 8 9 10 8 9 10 11 12 13 14 7 8 9 10 11 12 13
47
+ # 11 12 13 14 15 16 17 15 16 17 18 19 20 21 14 15 16 17 18 19 20
48
+ # 18 19 20 21 22 23 24 22 23 24 25 26 27 28 21 22 23 24 25 26 27
49
+ # 25 26 27 28 29 30 31 29 28 29 30 31
50
+ #
51
+ do_bywday([2004, 1, 4, 1], [2004, 1, 1])
52
+ do_bywday([2004, 1, 4, 2], [2004, 1, 8])
53
+ do_bywday([2004, 1, 4, -1], [2004, 1, 29])
54
+ do_bywday([2004, 1, 4, -2], [2004, 1, 22])
55
+ do_bywday([2004, 1, 4, -5], [2004, 1, 1])
56
+ do_bywday([2004,nil, 4, 1], [2004, 1, 1])
57
+ do_bywday([2004,nil, 4, 2], [2004, 1, 8])
58
+ do_bywday([2004,-12, 4, 1], [2004, 1, 1])
59
+ do_bywday([2004,-12, 4, 2], [2004, 1, 8])
60
+ do_bywday([2004,-12, 4, -1], [2004, 1, 29])
61
+ do_bywday([2004,-12, 4, -2], [2004, 1, 22])
62
+ do_bywday([2004,-12, 4, -5], [2004, 1, 1])
63
+
64
+ do_bywday([2004, 1, "th", 1], [2004, 1, 1])
65
+ do_bywday([2004, 1, "th", 2], [2004, 1, 8])
66
+ do_bywday([2004, 1, "th", -1], [2004, 1, 29])
67
+ do_bywday([2004, 1, "th", -2], [2004, 1, 22])
68
+ do_bywday([2004, 1, "th", -5], [2004, 1, 1])
69
+ do_bywday([2004,nil, "th", 1], [2004, 1, 1])
70
+ do_bywday([2004,nil, "th", 2], [2004, 1, 8])
71
+ do_bywday([2004,-12, "th", 1], [2004, 1, 1])
72
+ do_bywday([2004,-12, "th", 2], [2004, 1, 8])
73
+ do_bywday([2004,-12, "th", -1], [2004, 1, 29])
74
+ do_bywday([2004,-12, "th", -2], [2004, 1, 22])
75
+ do_bywday([2004,-12, "th", -5], [2004, 1, 1])
76
+
77
+ # October November December
78
+ # S M Tu W Th F S S M Tu W Th F S S M Tu W Th F S
79
+ # 1 2 1 2 3 4 5 6 1 2 3 4
80
+ # 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11
81
+ # 10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18
82
+ # 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25
83
+ # 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31
84
+ # 31
85
+
86
+ do_bywday([2004, -1, 4, 1], [2004, 12, 2])
87
+ do_bywday([2004, -1, 4, -1], [2004, 12, 30])
88
+ do_bywday([2004, -1, 4, -2], [2004, 12, 23])
89
+ do_bywday([2004, -1, 4, -5], [2004, 12, 2])
90
+ do_bywday([2004,nil, 4, -1], [2004, 12, 30])
91
+ do_bywday([2004,nil, 4, -2], [2004, 12, 23])
92
+ do_bywday([2004,nil, 4, -5], [2004, 12, 2])
93
+ do_bywday([2004,nil, 4, -7], [2004, 11, 18])
94
+
95
+ end
96
+
97
+ def do_gen(args)
98
+ assert_nothing_thrown do
99
+ dates = DateGen.bywday(*args)
100
+ dates.each do |d|
101
+ assert_equal(args[0], d.year)
102
+ if(args[1])
103
+ mon = args[1]
104
+ if mon < 0
105
+ mon = 13 + args[1]
106
+ end
107
+ assert_equal(mon, d.mon)
108
+ end
109
+ assert_equal(args[2], d.wday)
110
+ end
111
+ end
112
+ end
113
+
114
+ def test_gen
115
+ do_gen([2004, 12, 1])
116
+ do_gen([2004, -1, 1])
117
+ do_gen([2004, nil, 1])
118
+ end
119
+ end
120
+
data/test/test_dur.rb ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'vpim/duration'
4
+ require 'test/unit'
5
+
6
+ include Vpim
7
+
8
+ class TestVpimDate < Test::Unit::TestCase
9
+
10
+ def duration(d0, h0, m0, s0)
11
+ # 3 hours, 2 mins, 39 secs
12
+ d = Duration.secs(d0 * 24 * 60 * 60 + h0 * 60 * 60 + m0 * 60 + s0)
13
+
14
+ assert_equal(d.secs, d0 * 24 * 60 * 60 + h0 * 60 * 60 + m0 * 60 + s0)
15
+ assert_equal(d.mins, d0 * 24 * 60 + h0 * 60 + m0)
16
+ assert_equal(d.hours, d0 * 24 + h0)
17
+ assert_equal(d.days, d0)
18
+ assert_equal(d.by_hours, [d0*24 + h0, m0, s0])
19
+ assert_equal(d.by_days, [d0, h0, m0, s0])
20
+
21
+ h, m, s = d.by_hours
22
+
23
+ assert_equal(h, h0 + d0*24)
24
+ assert_equal(m, m0)
25
+ assert_equal(s, s0)
26
+
27
+ d, h, m, s = d.by_days
28
+
29
+ assert_equal(d, d0)
30
+ assert_equal(h, h0)
31
+ assert_equal(m, m0)
32
+ assert_equal(s, s0)
33
+ end
34
+
35
+ def test_1
36
+ duration(0, 3, 2, 39)
37
+ duration(5, 23, 39, 1)
38
+ end
39
+
40
+ end
41
+