dav4rack_ext 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ Gemfile.lock
5
+ coverage/
6
+ doc/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ bundler_args: --without development
2
+ rvm:
3
+ - 1.9.3
4
+
data/Gemfile ADDED
@@ -0,0 +1,27 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'dav4rack', git: 'git://github.com/schmurfy/dav4rack.git', branch: 'parent_collection'
7
+
8
+ group(:example) do
9
+ gem 'thin'
10
+ gem 'shotgun'
11
+ gem 'coderay'
12
+ gem 'ox'
13
+ end
14
+
15
+ group(:test) do
16
+ gem 'eetee', '= 0.0.1'
17
+ gem 'mocha', '~> 0.12.0'
18
+ gem 'factory_girl', '~> 4.0'
19
+ gem 'virtus'
20
+
21
+ gem 'simplecov'
22
+ gem 'guard', '~> 1.5.4'
23
+ gem 'rb-fsevent'
24
+ gem 'growl'
25
+
26
+ gem 'rack-test', '~> 0.6.2'
27
+ end
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+
2
+ guard 'eetee' do
3
+ watch(%r{^lib/dav4rack_ext/(.+)\.rb$}) { |m| "specs/unit/#{m[1]}_spec.rb" }
4
+ watch(%r{specs/.+_spec\.rb$})
5
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Julien Ammous
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+
2
+ # Continuous integration ([![Build Status](https://secure.travis-ci.org/schmurfy/dav4rack_ext.png)](http://travis-ci.org/schmurfy/dav4rack_ext))
3
+
4
+ This gem is tested against these ruby by travis-ci.org:
5
+
6
+ - mri 1.9.3
7
+
8
+ # What is this gem ?
9
+ This gem extends dav4rack to provide a CardDAV extension, CalDAV is not currently available but will eventually be available too.
10
+
11
+
12
+ # Usage
13
+
14
+ Have a look at the examle folder, this is a standard Rack application and should run with any compliant server.
15
+
16
+
17
+ # Setting up development environment
18
+
19
+ ```bash
20
+ # clone the repository and:
21
+ $ bundle
22
+ $ bundle exec guard
23
+ ```
24
+
25
+ the tests will run when a file changed, if only want to run all tests once:
26
+
27
+ ```bash
28
+ $ bundle exec rake
29
+ ```
30
+
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require "bundler/gem_tasks"
4
+
5
+ task :default => :test
6
+
7
+ task :test do
8
+
9
+ # do not generate coverage report under travis
10
+ unless ENV['TRAVIS']
11
+
12
+ require 'simplecov'
13
+ SimpleCov.command_name "E.T."
14
+ SimpleCov.start do
15
+ add_filter ".*_spec"
16
+ add_filter "/helpers/"
17
+ end
18
+ end
19
+
20
+ require 'eetee'
21
+
22
+ runner = EEtee::Runner.new
23
+ runner.run_pattern('specs/**/*_spec.rb')
24
+ runner.report_results()
25
+
26
+ end
27
+
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/dav4rack_ext/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Julien Ammous"]
6
+ gem.email = ["schmurfy@gmail.com"]
7
+ gem.description = %q{CardDAV / CalDAV implementation}
8
+ gem.summary = %q{CardDAV / CalDAV implementation.}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.name = "dav4rack_ext"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = Dav4rackExt::VERSION
16
+
17
+ gem.add_dependency 'dav4rack'
18
+ gem.add_dependency 'http_router'
19
+ gem.add_dependency 'vcard_parser', '0.0.3'
20
+ end
data/example/config.ru ADDED
@@ -0,0 +1,50 @@
1
+
2
+ require 'virtus'
3
+ require 'http_router'
4
+ require 'dav4rack_ext/carddav'
5
+ require 'coderay'
6
+ require File.expand_path('../rack_sniffer', __FILE__)
7
+ require File.expand_path('../../specs/support/models', __FILE__)
8
+
9
+
10
+ $contacts = [
11
+ Testing::Contact.new(uid: "777-999", fields: [
12
+ Testing::Field.new(name: "N", value: "Durand;Christophe;;;"),
13
+ Testing::Field.new(name: "FN", value: "Christophe Durand"),
14
+ Testing::Field.new(name: "TEL", value: "09 87 67 89 33", params: {'Type' => ["HOME", "pref"]}),
15
+ Testing::Field.new(name: "ADR", value: ";;3 rue du chat;Dris;;90880;FRANCE"),
16
+ Testing::Field.new(name: "BDAY", value: "1900-01-01"),
17
+ Testing::Field.new(name: "X-YAGO-ID", value: "un dromadaire")
18
+ ])
19
+ ]
20
+
21
+ $books = [
22
+ Testing::AddressBook.new(name: 'default', path: 'default', name: "test 1", contacts: $contacts),
23
+ Testing::AddressBook.new(name: 'Second', path: 'second_one', name: "test 2", contacts: []),
24
+ ]
25
+
26
+ use XMLSniffer
27
+
28
+ def create_user(env)
29
+ Testing::User.new(env, id: 1, username: 'ja', addressbooks: $books)
30
+ end
31
+
32
+
33
+ # app1 = DAV4Rack::Carddav.app('/cards/',
34
+ # logger: Logger.new($stdout, Logger::DEBUG),
35
+ # current_user: USER
36
+ # )
37
+
38
+ app2 = DAV4Rack::Carddav.app('/:prefix/cards/',
39
+ logger: Logger.new($stdout, Logger::DEBUG),
40
+ current_user: method(:create_user),
41
+ root_uri_path: lambda do |env|
42
+ path = env['REQUEST_PATH']
43
+ n = path.index("/cards/")
44
+ path[0...(n + 7)]
45
+ end
46
+ )
47
+
48
+ run Rack::Cascade.new([app2])
49
+
50
+
@@ -0,0 +1,71 @@
1
+ require 'ox'
2
+ require 'rack/request'
3
+ require 'coderay'
4
+
5
+ class XMLSniffer
6
+ PREFIX = " " * 4
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ ret = nil
14
+ ret = @app.call(env)
15
+
16
+ ensure
17
+ request = Rack::Request.new(env)
18
+ puts "\n*** REQUEST ( #{request.request_method} #{request.path} ) ***"
19
+ request.body.rewind
20
+ dump_headers(env)
21
+
22
+ body = request.body.read
23
+ request.body.rewind
24
+
25
+ unless body.empty?
26
+ dump_xml(body)
27
+ end
28
+
29
+ if ret
30
+ if ret[2].respond_to?(:body) && !ret[2].body.empty? && !ret[-1].body[0].empty?
31
+ puts "\n --- RESPONSE (#{ret[0]}) ---"
32
+ ret[1].each do |name, value|
33
+ puts "#{name} = #{value}"
34
+ end
35
+
36
+ dump_xml(ret[-1].body[0])
37
+ else
38
+ puts "\n --- EMPTY RESPONSE (#{ret[0]}) ---"
39
+ ret[1].each do |name, value|
40
+ puts "#{name} = #{value}"
41
+ end
42
+ end
43
+ end
44
+
45
+ ret
46
+ end
47
+
48
+ private
49
+ def dump_headers(env)
50
+ extract_headers(env).each do |name, value|
51
+ puts "#{name} = #{value}"
52
+ end
53
+ end
54
+
55
+ def dump_xml(str)
56
+ doc = Ox.parse(str)
57
+ source = Ox.dump(doc)
58
+ puts ""
59
+ puts CodeRay.scan(source, :xml).term
60
+ rescue SyntaxError
61
+ puts "\n#{str}"
62
+ end
63
+
64
+ def extract_headers(env)
65
+ headers = env.select {|k,v| k.start_with?('HTTP_') || (k[0].upcase == k[0])}
66
+ headers.map do |pair|
67
+ [pair[0].ljust(20), pair[1]]
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,151 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <dfxml xmloutputversion='1.0'>
3
+ <metadata
4
+ xmlns='http://afflib.org/tcpflow/'
5
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
6
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
7
+ <dc:type>Feature Extraction</dc:type>
8
+ </metadata>
9
+ <creator version='1.0'>
10
+ <program>TCPFLOW</program>
11
+ <version>1.3.0</version>
12
+ <build_environment>
13
+ <compiler>GCC 4.2</compiler>
14
+ </build_environment>
15
+ <execution_environment>
16
+ <os_sysname>Darwin</os_sysname>
17
+ <os_release>12.2.0</os_release>
18
+ <os_version>Darwin Kernel Version 12.2.0: Sat Aug 25 00:48:52 PDT 2012; root:xnu-2050.18.24~1/RELEASE_X86_64</os_version>
19
+ <host>pomme.home</host>
20
+ <arch>x86_64</arch>
21
+ <command_line>tcpflow -c -p -s -i en1 port 3000</command_line>
22
+ <uid>0</uid>
23
+ <start_time>2012-10-31T12:57:39Z</start_time>
24
+ </execution_environment>
25
+ </creator>
26
+ <configuration>
27
+ </configuration>
28
+ <fileobject>
29
+ <filename>010.011.020.004.03000-010.011.020.002.49870</filename>
30
+ <filesize>0</filesize>
31
+ <tcpflow startime='2012-10-31T13:57:49.884333Z' endtime='2012-10-31T13:57:50.308991Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='18' srcport='3000' dstport='49870' family='2' out_of_order_count='0' />
32
+ </fileobject>
33
+ <fileobject>
34
+ <filename>010.011.020.004.03000-010.011.020.002.49870</filename>
35
+ <filesize>0</filesize>
36
+ <tcpflow startime='2012-10-31T13:57:50.312534Z' endtime='2012-10-31T13:57:50.312534Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='1' srcport='3000' dstport='49870' family='2' out_of_order_count='0' />
37
+ </fileobject>
38
+ <fileobject>
39
+ <filename>010.011.020.002.49870-010.011.020.004.03000</filename>
40
+ <filesize>0</filesize>
41
+ <tcpflow startime='2012-10-31T13:57:49.884065Z' endtime='2012-10-31T13:57:50.356369Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='20' srcport='49870' dstport='3000' family='2' out_of_order_count='0' />
42
+ </fileobject>
43
+ <fileobject>
44
+ <filename>010.011.020.002.49873-010.011.020.004.03000</filename>
45
+ <filesize>0</filesize>
46
+ <tcpflow startime='2012-10-31T13:57:49.890537Z' endtime='2012-10-31T13:58:01.861868Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='9' srcport='49873' dstport='3000' family='2' out_of_order_count='0' />
47
+ </fileobject>
48
+ <fileobject>
49
+ <filename>010.011.020.004.03000-010.011.020.002.49873</filename>
50
+ <filesize>0</filesize>
51
+ <tcpflow startime='2012-10-31T13:57:49.890676Z' endtime='2012-10-31T13:58:01.862114Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='10' srcport='3000' dstport='49873' family='2' out_of_order_count='0' />
52
+ </fileobject>
53
+ <fileobject>
54
+ <filename>010.011.020.002.49872-010.011.020.004.03000</filename>
55
+ <filesize>0</filesize>
56
+ <tcpflow startime='2012-10-31T13:57:49.890355Z' endtime='2012-10-31T13:58:01.863328Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='9' srcport='49872' dstport='3000' family='2' out_of_order_count='0' />
57
+ </fileobject>
58
+ <fileobject>
59
+ <filename>010.011.020.002.49871-010.011.020.004.03000</filename>
60
+ <filesize>0</filesize>
61
+ <tcpflow startime='2012-10-31T13:57:49.887984Z' endtime='2012-10-31T13:58:01.863682Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='12' srcport='49871' dstport='3000' family='2' out_of_order_count='0' />
62
+ </fileobject>
63
+ <fileobject>
64
+ <filename>010.011.020.004.03000-010.011.020.002.49872</filename>
65
+ <filesize>0</filesize>
66
+ <tcpflow startime='2012-10-31T13:57:49.890565Z' endtime='2012-10-31T13:58:01.863711Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='10' srcport='3000' dstport='49872' family='2' out_of_order_count='0' />
67
+ </fileobject>
68
+ <fileobject>
69
+ <filename>010.011.020.004.03000-010.011.020.002.49871</filename>
70
+ <filesize>0</filesize>
71
+ <tcpflow startime='2012-10-31T13:57:49.888206Z' endtime='2012-10-31T13:58:01.863807Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='13' srcport='3000' dstport='49871' family='2' out_of_order_count='0' />
72
+ </fileobject>
73
+ <fileobject>
74
+ <filename>010.011.020.004.03000-010.011.020.002.49879</filename>
75
+ <filesize>0</filesize>
76
+ <tcpflow startime='2012-10-31T13:59:12.006066Z' endtime='2012-10-31T13:59:12.049650Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='5' srcport='3000' dstport='49879' family='2' out_of_order_count='0' />
77
+ </fileobject>
78
+ <fileobject>
79
+ <filename>010.011.020.004.03000-010.011.020.002.49879</filename>
80
+ <filesize>0</filesize>
81
+ <tcpflow startime='2012-10-31T13:59:12.053563Z' endtime='2012-10-31T13:59:12.053563Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='1' srcport='3000' dstport='49879' family='2' out_of_order_count='0' />
82
+ </fileobject>
83
+ <fileobject>
84
+ <filename>010.011.020.002.49879-010.011.020.004.03000</filename>
85
+ <filesize>0</filesize>
86
+ <tcpflow startime='2012-10-31T13:59:12.005687Z' endtime='2012-10-31T13:59:12.066345Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='7' srcport='49879' dstport='3000' family='2' out_of_order_count='0' />
87
+ </fileobject>
88
+ <fileobject>
89
+ <filename>010.011.020.002.49877-010.011.020.004.03000</filename>
90
+ <filesize>0</filesize>
91
+ <tcpflow startime='2012-10-31T13:59:05.771985Z' endtime='2012-10-31T13:59:17.741454Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='9' srcport='49877' dstport='3000' family='2' out_of_order_count='0' />
92
+ </fileobject>
93
+ <fileobject>
94
+ <filename>010.011.020.002.49876-010.011.020.004.03000</filename>
95
+ <filesize>0</filesize>
96
+ <tcpflow startime='2012-10-31T13:59:05.771414Z' endtime='2012-10-31T13:59:17.741812Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='9' srcport='49876' dstport='3000' family='2' out_of_order_count='0' />
97
+ </fileobject>
98
+ <fileobject>
99
+ <filename>010.011.020.004.03000-010.011.020.002.49877</filename>
100
+ <filesize>0</filesize>
101
+ <tcpflow startime='2012-10-31T13:59:05.772144Z' endtime='2012-10-31T13:59:17.741857Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='10' srcport='3000' dstport='49877' family='2' out_of_order_count='0' />
102
+ </fileobject>
103
+ <fileobject>
104
+ <filename>010.011.020.004.03000-010.011.020.002.49876</filename>
105
+ <filesize>0</filesize>
106
+ <tcpflow startime='2012-10-31T13:59:05.771639Z' endtime='2012-10-31T13:59:17.742001Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='10' srcport='3000' dstport='49876' family='2' out_of_order_count='0' />
107
+ </fileobject>
108
+ <fileobject>
109
+ <filename>010.011.020.002.49875-010.011.020.004.03000</filename>
110
+ <filesize>0</filesize>
111
+ <tcpflow startime='2012-10-31T13:59:05.769349Z' endtime='2012-10-31T13:59:17.744050Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='9' srcport='49875' dstport='3000' family='2' out_of_order_count='0' />
112
+ </fileobject>
113
+ <fileobject>
114
+ <filename>010.011.020.002.49874-010.011.020.004.03000</filename>
115
+ <filesize>0</filesize>
116
+ <tcpflow startime='2012-10-31T13:59:05.768668Z' endtime='2012-10-31T13:59:17.744099Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='15' srcport='49874' dstport='3000' family='2' out_of_order_count='0' />
117
+ </fileobject>
118
+ <fileobject>
119
+ <filename>010.011.020.004.03000-010.011.020.002.49875</filename>
120
+ <filesize>0</filesize>
121
+ <tcpflow startime='2012-10-31T13:59:05.769512Z' endtime='2012-10-31T13:59:17.744330Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='10' srcport='3000' dstport='49875' family='2' out_of_order_count='0' />
122
+ </fileobject>
123
+ <fileobject>
124
+ <filename>010.011.020.004.03000-010.011.020.002.49874</filename>
125
+ <filesize>0</filesize>
126
+ <tcpflow startime='2012-10-31T13:59:05.768939Z' endtime='2012-10-31T13:59:17.744331Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='16' srcport='3000' dstport='49874' family='2' out_of_order_count='0' />
127
+ </fileobject>
128
+ <fileobject>
129
+ <filename>010.011.020.002.49885-010.011.020.004.03000</filename>
130
+ <filesize>0</filesize>
131
+ <tcpflow startime='2012-10-31T13:59:12.108827Z' endtime='2012-10-31T13:59:24.190630Z' src_ipn='10.11.20.2' dst_ipn='10.11.20.4' packets='18' srcport='49885' dstport='3000' family='2' out_of_order_count='0' />
132
+ </fileobject>
133
+ <fileobject>
134
+ <filename>010.011.020.004.03000-010.011.020.002.49885</filename>
135
+ <filesize>0</filesize>
136
+ <tcpflow startime='2012-10-31T13:59:12.108971Z' endtime='2012-10-31T13:59:24.190941Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.2' packets='20' srcport='3000' dstport='49885' family='2' out_of_order_count='0' />
137
+ </fileobject>
138
+ <fileobject>
139
+ <filename>010.011.020.004.03000-010.011.020.003.64824</filename>
140
+ <filesize>0</filesize>
141
+ <tcpflow startime='2012-10-31T14:01:44.888858Z' endtime='2012-10-31T14:01:44.892576Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.3' packets='5' srcport='3000' dstport='64824' family='2' out_of_order_count='0' />
142
+ </fileobject>
143
+ <fileobject>
144
+ <filename>010.011.020.004.03000-010.011.020.003.64824</filename>
145
+ <filesize>0</filesize>
146
+ <tcpflow startime='2012-10-31T14:01:44.895365Z' endtime='2012-10-31T14:01:44.895365Z' src_ipn='10.11.20.4' dst_ipn='10.11.20.3' packets='1' srcport='3000' dstport='64824' family='2' out_of_order_count='0' />
147
+ </fileobject>
148
+ <fileobject>
149
+ <filename>010.011.020.003.64824-010.011.020.004.03000</filename>
150
+ <filesize>0</filesize>
151
+ <tcpflow startime='2012-10-31T14:01:44.888669Z' endtime='2012-10-31T14:01:44.899458Z' src_ipn='10.11.20.3' dst_ipn='10.11.20.4' packets='7' srcport='64824' dstport='3000' family='2' out_of_order_count='0' />
data/example/test.rb ADDED
@@ -0,0 +1,50 @@
1
+
2
+ require 'faraday'
3
+
4
+ c = Faraday.new(:url => 'http://127.0.0.1:3000/carddav') do |faraday|
5
+ faraday.adapter Faraday.default_adapter
6
+ # faraday.response :logger # log requests to STDOUT
7
+ end
8
+
9
+ Faraday::Connection::METHODS << :propfind
10
+ Faraday::Connection::METHODS << :report
11
+
12
+
13
+ # response = c.run_request(:propfind, nil, <<-EOS, nil, &nil)
14
+ # <?xml version="1.0" encoding="UTF-8"?>
15
+ # <A:propfind xmlns:A="DAV:">
16
+ # <A:prop>
17
+ # <A:current-user-principal/>
18
+ # <A:principal-URL/>
19
+ # <A:resourcetype/>
20
+ # </A:prop>
21
+ # </A:propfind>
22
+ # EOS
23
+
24
+ # response = c.run_request(:report, '/book/1', <<-EOS, nil)
25
+ # <?xml version="1.0" encoding="UTF-8"?>
26
+ # <G:addressbook-multiget xmlns:G="urn:ietf:params:xml:ns:carddav">
27
+ # <A:prop xmlns:A="DAV:">
28
+ # <A:getetag/>
29
+ # <G:address-data/>
30
+ # </A:prop>
31
+ # <A:href xmlns:A="DAV:">/book/1/11</A:href>
32
+ # </G:addressbook-multiget>
33
+ # EOS
34
+
35
+
36
+ response = c.run_request(:propfind, nil, <<-EOS, nil)
37
+ <?xml version="1.0" encoding="UTF-8"?>
38
+ <A:propfind xmlns:A="DAV:" xmlns:B="urn:ietf:params:xml:ns:carddav" xmlns:C="http://calendarserver.org/ns/">
39
+ <A:prop>
40
+ <B:addressbook-home-set/>
41
+ <B:directory-gateway/>
42
+ <A:displayname/>
43
+ <C:email-address-set/>
44
+ <A:principal-collection-set/>
45
+ <A:principal-URL/>
46
+ <A:resource-id/>
47
+ <A:supported-report-set/>
48
+ </A:prop>
49
+ </A:propfind>
50
+ EOS