sonar_rexchange 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/RAKEFILE +50 -0
- data/README +89 -0
- data/REXCHANGE-CHANGELOG +52 -0
- data/REXCHANGE-MIT-LICENSE +22 -0
- data/VERSION +1 -0
- data/lib/r_exchange.rb +2 -0
- data/lib/rexchange.rb +33 -0
- data/lib/rexchange/appointment.rb +38 -0
- data/lib/rexchange/contact.rb +29 -0
- data/lib/rexchange/credentials.rb +38 -0
- data/lib/rexchange/dav_delete_request.rb +30 -0
- data/lib/rexchange/dav_get_request.rb +28 -0
- data/lib/rexchange/dav_mkcol_request.rb +27 -0
- data/lib/rexchange/dav_move_request.rb +30 -0
- data/lib/rexchange/dav_proppatch_request.rb +49 -0
- data/lib/rexchange/dav_search_request.rb +8 -0
- data/lib/rexchange/exchange_request.rb +86 -0
- data/lib/rexchange/folder.rb +108 -0
- data/lib/rexchange/generic_item.rb +124 -0
- data/lib/rexchange/message.rb +88 -0
- data/lib/rexchange/message_href.rb +107 -0
- data/lib/rexchange/note.rb +16 -0
- data/lib/rexchange/r_exception.rb +25 -0
- data/lib/rexchange/session.rb +28 -0
- data/lib/rexchange/task.rb +26 -0
- data/test/functional.rb +23 -0
- metadata +92 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Trampoline Systems Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/RAKEFILE
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "sonar_rexchange"
|
8
|
+
gem.summary = %Q{Modified rexchange gem}
|
9
|
+
gem.description = %Q{The sonar_rexchange gem imports and fixes bugs in the rexchange gem.}
|
10
|
+
gem.email = "hello@empire42.com"
|
11
|
+
gem.homepage = "http://github.com/trampoline/sonar-rexchange"
|
12
|
+
gem.authors = ["Peter MacRobert", "Daniel Kwiecinski", "Craig McMillan"]
|
13
|
+
end
|
14
|
+
Jeweler::GemcutterTasks.new
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
Rake::TestTask.new(:test) do |test|
|
21
|
+
test.libs << 'lib' << 'test'
|
22
|
+
test.pattern = 'test/**/test_*.rb'
|
23
|
+
test.verbose = true
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'rcov/rcovtask'
|
28
|
+
Rcov::RcovTask.new do |test|
|
29
|
+
test.libs << 'test'
|
30
|
+
test.pattern = 'test/**/test_*.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
rescue LoadError
|
34
|
+
task :rcov do
|
35
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
task :test => :check_dependencies
|
40
|
+
task :default => :test
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "sonar_rexchange #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/README
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
= RExchange
|
2
|
+
|
3
|
+
== Please note
|
4
|
+
sonar-rexchange is a modified version of the rexchange gem.
|
5
|
+
|
6
|
+
RExchange is a pure ruby wrapper for the Microsoft Exchange Server WebDAV API
|
7
|
+
|
8
|
+
== Things you should know
|
9
|
+
|
10
|
+
* Requires Ruby 1.8.4 (or later, for the extended WebDAV support in the net/http library)
|
11
|
+
* RExchange is cross-platform compatible, being written in pure Ruby
|
12
|
+
* Kiwi fruits are packed with vitamins
|
13
|
+
|
14
|
+
== Why should you use RExchange
|
15
|
+
|
16
|
+
* It makes interacting with Exchange simple
|
17
|
+
* It was written for a real application, and does real work reliably day in and day out
|
18
|
+
|
19
|
+
== Example
|
20
|
+
|
21
|
+
# We pass our uri (pointing directly to a mailbox), a username, and a password to RExchange::open
|
22
|
+
# to create a RExchange::Session. Notice that we escape the "\" in our username.
|
23
|
+
RExchange::open('https://example.com/exchange/admin/', 'mydomain\\admin', 'secret') do |mailbox|
|
24
|
+
|
25
|
+
# The block parameter ("mailbox" in this case) is actually the Session itself.
|
26
|
+
# You can refer to folders by chaining them as method calls. "inbox" in this case
|
27
|
+
# isn't a defined method for Session, but part of the DSL to refer to folder names.
|
28
|
+
# Each folder name returns a RExchange::Folder. The folder is Enumerable, allowing
|
29
|
+
# iteration over the items in the folder, depending on the DAV:content-class of
|
30
|
+
# the folder.
|
31
|
+
mailbox.inbox.each do |message|
|
32
|
+
|
33
|
+
# The "message" block parameter is a RExchange::Message object. You have access to
|
34
|
+
# several attributes of the message, including: href, from, to, message_id, date,
|
35
|
+
# importance, has_attachment? and body.
|
36
|
+
p message.subject
|
37
|
+
|
38
|
+
# The RExchange::Message#move_to method moves the message to another folder, in this
|
39
|
+
# case, an "archive" folder off of the inbox.
|
40
|
+
message.move_to mailbox.inbox.archive
|
41
|
+
end
|
42
|
+
|
43
|
+
# Folder names are "normalized", replacing dashes and spaces with underscores,
|
44
|
+
# squeezing out multiple underscores in a row, and downcasing the whole thing.
|
45
|
+
# So a folder name such as "My Very-long Folder Name" would look like:
|
46
|
+
mailbox.my_very_long_folder_name
|
47
|
+
|
48
|
+
# The Enumerable mixin gives us an Folder#entries method in case we just want to
|
49
|
+
# return an array.
|
50
|
+
messages = mailbox.inbox.entries
|
51
|
+
|
52
|
+
# Other methods, like Enumerable#map and Enumerable#sort_by let us manipulate
|
53
|
+
# the Folder in fun ways:
|
54
|
+
puts mailbox.contacts.sort_by { |contact| contact.first_name }.map do |contact|
|
55
|
+
<<-CONTACT
|
56
|
+
Name: #{contact.first_name} #{contact.last_name}
|
57
|
+
Email: #{contact.email}
|
58
|
+
Phone: #{contact.phone}
|
59
|
+
CONTACT
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# We can access the Global Address Book by accessing the "/public" folder:
|
65
|
+
RExchange::open('https://example.com/public', 'mydomain\\somebody', 'secret') do |mailbox|
|
66
|
+
|
67
|
+
puts mailbox.company_contacts.each do |contact|
|
68
|
+
<<-CONTACT
|
69
|
+
Company: #{contact.company}
|
70
|
+
Name: #{contact.first_name} #{contact.last_name}
|
71
|
+
Email: #{contact.email}
|
72
|
+
Phone: #{contact.phone}
|
73
|
+
CONTACT
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
== Caveats
|
79
|
+
|
80
|
+
There are several features missing (simply because we didn't need them yet). Among them:
|
81
|
+
|
82
|
+
* The ability to delete messages or folders
|
83
|
+
* The ability to create folders
|
84
|
+
* There's no mechanism for sending new messages, or replying or forwarding existing ones
|
85
|
+
* There are a lot more message attributes we're not retrieving since they weren't useful to us, but they might be to you
|
86
|
+
* Exporting an email or entire folder tree to offline storage
|
87
|
+
* And much much more!
|
88
|
+
|
89
|
+
If you'd like to see any of these features, or have some ideas of your own you'd like to see implemented don't hesitate to let us know, and if it strikes our fancy maybe you'll get some free programming!
|
data/REXCHANGE-CHANGELOG
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
-- 0.3.4:
|
2
|
+
* Updated the README so it jives with the current version
|
3
|
+
* Removed Folder::join since it's only used by Folder#to_s, and just used a simpler
|
4
|
+
solution in Folder#to_s instead
|
5
|
+
|
6
|
+
-- 0.3.3:
|
7
|
+
* Folder objects now default to using the Message class for enumeration
|
8
|
+
if no class is associated with the content_type of the Folder.
|
9
|
+
|
10
|
+
-- 0.3.2:
|
11
|
+
* Quick hack to make Message#move_to work
|
12
|
+
|
13
|
+
-- 0.3.1:
|
14
|
+
* Disabled a warning about overwriting GenericItem::CONTENT_CLASS
|
15
|
+
* Added a "rescue" for Time::parse failures that reverts to the original element text
|
16
|
+
|
17
|
+
-- 0.3.0:
|
18
|
+
* Added support for Appointments
|
19
|
+
* Options hash for Session creation is gone. The new form is: "RExchange::Session.new(url, username, password)"
|
20
|
+
* Removed GenericItem#[], GenericItem#method_missing (attributes are explicit now)
|
21
|
+
* Removed Folder#get_messages, #get_contacts and #messages_in. Folders are now Enumerables using Enumerable#entries, #each, etc
|
22
|
+
to retrieve entries according to the folder's content-class. So a 'mailfolder' will retrieve Message instances,
|
23
|
+
a 'calendarfolder' will retrieve Appointment instances, and so on.
|
24
|
+
|
25
|
+
-- 0.2.0:
|
26
|
+
* Fixed a bug in Message#move_to when passing folders
|
27
|
+
* Added support for Contact browsing
|
28
|
+
* Added GenericItem to abstract Contacts and Messages
|
29
|
+
* Renamed Folder#messages to Folder#get_messages to avoid naming collisions
|
30
|
+
* Modified attributes in GenericItem that end with "date" to be Time::parse'd
|
31
|
+
* Added "r_exchange.rb" for Rails auto-require compatibility
|
32
|
+
* Now calling String#normalize on attribute names instead of just String#tr('-', '_')
|
33
|
+
|
34
|
+
-- 0.1.4:
|
35
|
+
* Moved Folder::normalize_folder_name to String#normalize, and added support for MixedCase sources.
|
36
|
+
* Fixed a bug where the normalized folder name was being used for the Folder#to_s result.
|
37
|
+
* Moved the meat of Folder#messages to Message::find
|
38
|
+
* Added Message#to_s
|
39
|
+
* Modified Folder#get_folders to return a hash instead of an array, providing both the original, and normalized names.
|
40
|
+
|
41
|
+
-- 0.1.3: Bugfixes
|
42
|
+
* Fixed several nasty bugs.
|
43
|
+
|
44
|
+
-- 0.1.2: Minor documentation/cleanup
|
45
|
+
* Removed a double-dash in the README that was apparently causing some viewing errors
|
46
|
+
* Changed Session initialize to a ternary condition
|
47
|
+
* Added RExchange::Message#has_attachments?
|
48
|
+
* Added documentation for most methods in RExchange::Message and RExchange::Folder
|
49
|
+
|
50
|
+
-- 0.1.1
|
51
|
+
* Fleshed out the README
|
52
|
+
* Copied the RAKEFILE from the Rools project
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2006 Samuel Smoot
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.7
|
data/lib/r_exchange.rb
ADDED
data/lib/rexchange.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rexchange/session'
|
2
|
+
require 'rexchange/r_exception'
|
3
|
+
|
4
|
+
class String
|
5
|
+
def ends_with?(partial)
|
6
|
+
self[self.size - partial.size..self.size] == partial
|
7
|
+
end
|
8
|
+
|
9
|
+
def ensure_ends_with(partial)
|
10
|
+
self.ends_with?(partial) ? self : self + partial
|
11
|
+
end
|
12
|
+
|
13
|
+
def normalize
|
14
|
+
self.split(/(?=[A-Z][a-z]*)/).join('_').tr('- ', '_').squeeze('_').downcase
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module RExchange
|
19
|
+
# Use STDOUT or another stream if you'd like to capture the HTTP debug output
|
20
|
+
DEBUG_STREAM = $log
|
21
|
+
|
22
|
+
PR_HTTPMAIL_READ = 'read'
|
23
|
+
NS_HTTPMAIL = 'urn:schemas:httpmail'
|
24
|
+
|
25
|
+
# A shortcut to RExchange::Session#new
|
26
|
+
def self.open(dav_uri, owa_uri, username = nil, password = nil)
|
27
|
+
session = RExchange::Session.new(dav_uri, owa_uri, username, password)
|
28
|
+
|
29
|
+
yield session if block_given?
|
30
|
+
return session
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rexchange/generic_item'
|
2
|
+
|
3
|
+
module RExchange
|
4
|
+
class Appointment < GenericItem
|
5
|
+
|
6
|
+
set_folder_type 'calendar'
|
7
|
+
|
8
|
+
attribute_mappings :all_day_event => 'urn:schemas:calendar:alldayevent',
|
9
|
+
:busy_status => 'urn:schemas:calendar:busystatus',
|
10
|
+
:contact => 'urn:schemas:calendar:contact',
|
11
|
+
:contact_url => 'urn:schemas:calendar:contacturl',
|
12
|
+
:created_on => 'urn:schemas:calendar:created',
|
13
|
+
:description_url => 'urn:schemas:calendar:descriptionurl',
|
14
|
+
:end_at => 'urn:schemas:calendar:dtend',
|
15
|
+
:created_at => 'urn:schemas:calendar:dtstamp',
|
16
|
+
:start_at => 'urn:schemas:calendar:dtstart',
|
17
|
+
:duration => 'urn:schemas:calendar:duration',
|
18
|
+
:expires_on => 'urn:schemas:calendar:exdate',
|
19
|
+
:expiry_rule => 'urn:schemas:calendar:exrule',
|
20
|
+
:has_attachment? => 'urn:schemas:httpmail:hasattachment',
|
21
|
+
:html => 'urn:schemas:httpmail:htmldescription',
|
22
|
+
:modified_on => 'urn:schemas:calendar:lastmodified',
|
23
|
+
:location => 'urn:schemas:calendar:location',
|
24
|
+
:location_url => 'urn:schemas:calendar:locationurl',
|
25
|
+
:meeting_status => 'urn:schemas:calendar:meetingstatus',
|
26
|
+
:normalized_subject => 'urn:schemas:httpmail:normalizedsubject',
|
27
|
+
:priority => 'urn:schemas:httpmail:priority',
|
28
|
+
:recurres_on => 'urn:schemas:calendar:rdate',
|
29
|
+
:reminder_offset => 'urn:schemas:calendar:reminderoffset',
|
30
|
+
:reply_time => 'urn:schemas:calendar:replytime',
|
31
|
+
:sequence => 'urn:schemas:calendar:sequence',
|
32
|
+
:subject => 'urn:schemas:httpmail:subject',
|
33
|
+
:body => 'urn:schemas:httpmail:textdescription',
|
34
|
+
:timezone => 'urn:schemas:calendar:timezone',
|
35
|
+
:uid => 'urn:schemas:calendar:uid'
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rexchange/generic_item'
|
2
|
+
|
3
|
+
module RExchange
|
4
|
+
class Contact < GenericItem
|
5
|
+
|
6
|
+
set_folder_type 'contact'
|
7
|
+
set_content_class 'person'
|
8
|
+
|
9
|
+
attribute_mappings :first_name => 'urn:schemas:contacts:givenName',
|
10
|
+
:middle_name => 'urn:schemas:contacts:middlename',
|
11
|
+
:last_name => 'urn:schemas:contacts:sn',
|
12
|
+
:title => 'urn:schemas:contacts:title',
|
13
|
+
:created_at => 'DAV:creationdate',
|
14
|
+
:address => 'urn:schemas:contacts:mailingstreet',
|
15
|
+
:city => 'urn:schemas:contacts:mailingcity',
|
16
|
+
:state => 'urn:schemas:contacts:st',
|
17
|
+
:zip_code => 'urn:schemas:contacts:mailingpostalcode',
|
18
|
+
:country => 'urn:schemas:contacts:co',
|
19
|
+
:phone => 'urn:schemas:contacts:homePhone',
|
20
|
+
:business_phone => 'urn:schemas:contacts:telephoneNumber',
|
21
|
+
:fax => 'urn:schemas:contacts:facsimiletelephonenumber',
|
22
|
+
:mobile => 'urn:schemas:contacts:mobile',
|
23
|
+
:email => 'urn:schemas:contacts:email1',
|
24
|
+
:website => 'urn:schemas:contacts:businesshomepage',
|
25
|
+
:company => 'urn:schemas:contacts:o',
|
26
|
+
:notes => 'urn:schemas:httpmail:textdescription'
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module RExchange
|
4
|
+
|
5
|
+
# Credentials are passed around between Folders to emulate a stateful
|
6
|
+
# connection with the RExchange::Session
|
7
|
+
class Credentials
|
8
|
+
attr_reader :user, :password, :dav_uri, :owa_uri
|
9
|
+
attr_accessor :auth_cookie
|
10
|
+
|
11
|
+
# You must pass a dav_uri, owa_uri, a username and a password
|
12
|
+
def initialize(dav_uri = nil, owa_uri = nil, username = nil, password = nil)
|
13
|
+
owa_uri = nil if owa_uri && owa_uri.blank?
|
14
|
+
@dav_uri = URI.parse(dav_uri) if dav_uri
|
15
|
+
@owa_uri = URI.parse(owa_uri) if owa_uri
|
16
|
+
@dav_use_ssl = @dav_uri.scheme ? (@dav_uri.scheme.downcase == 'https') : false
|
17
|
+
@user = username || (@dav_uri && @dav_uri.userinfo ? @dav_uri.userinfo.split(':')[0] : nil) || (@owa_uri && @owa_uri.userinfo ? @owa_uri.userinfo.split(':')[0] : nil)
|
18
|
+
@password = password || (@dav_uri && @dav_uri.userinfo ? @dav_uri.userinfo.split(':')[1] : nil) || (@owa_uri && @owa_uri.userinfo ? @owa_uri.userinfo.split(':')[1] : nil)
|
19
|
+
@dav_port = (@dav_uri.port || @dav_uri.default_port) if @dav_uri
|
20
|
+
@owa_port = (@owa_uri.port || @owa_uri.default_port) if @owa_uri
|
21
|
+
if block_given?
|
22
|
+
yield self
|
23
|
+
else
|
24
|
+
return self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def dav_use_ssl?
|
29
|
+
@dav_use_ssl
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_owa?
|
33
|
+
@owa_uri && @owa_uri.scheme && @owa_uri.host
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rexchange/exchange_request'
|
2
|
+
|
3
|
+
module RExchange
|
4
|
+
# Used to move entities to different locations in the accessable mailbox.
|
5
|
+
class DavDeleteRequest < ExchangeRequest
|
6
|
+
METHOD = 'DELETE'
|
7
|
+
REQUEST_HAS_BODY = false
|
8
|
+
RESPONSE_HAS_BODY = false
|
9
|
+
|
10
|
+
def self.execute(credentials, source, &b)
|
11
|
+
begin
|
12
|
+
options = {
|
13
|
+
:path => source
|
14
|
+
}
|
15
|
+
|
16
|
+
response = super credentials, options
|
17
|
+
yield response if b
|
18
|
+
response
|
19
|
+
rescue RException => e
|
20
|
+
raise e
|
21
|
+
rescue Exception => e
|
22
|
+
raise RException.new(options[:request], response, e)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|