Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d982058
Update to Savon 0.9.2 and add preliminary support for GSSNEGOTIATE
calamitas Jun 8, 2011
2bd789c
Fix for empty params
calamitas Jun 10, 2011
fdca918
Also use the new authentication stuff for fetch and head
calamitas Jun 10, 2011
c70e697
Add support for ThreadIndex
calamitas Jun 10, 2011
93b7ca7
Normalize the keys of lists (sometimes returned in lowercase)
calamitas Jun 15, 2011
c8341ea
Use a specific error when an item is not found
calamitas Jun 16, 2011
b682b92
A number of fixes
calamitas Jun 17, 2011
e05259b
Add support for fetching the list of templates
calamitas Jun 22, 2011
2461880
Add some administrative stuff
calamitas Jun 24, 2011
32f1dd1
Support for empty Lookup fields
calamitas Jul 25, 2011
08346d5
Allow specifying an absolute URL when fetching content an doing head …
calamitas Jul 27, 2011
1e3249c
Remove debug output
calamitas Sep 21, 2011
2943596
A few optimizations
calamitas Sep 22, 2011
99134f3
Add relative_url
calamitas Sep 22, 2011
4c7a11d
Fix to relative_url
calamitas Sep 23, 2011
4c5b5bd
Fix when a subfolder is created and it already exists
calamitas Sep 23, 2011
f71ce55
Escape urls for attachments
calamitas Sep 26, 2011
3ba997d
Allow higher versions of Savon than exactly 0.9.2
joerixaop Jan 10, 2012
7352f47
Apparently we need 1.0
joerixaop Jan 10, 2012
b633bb1
Version 0.9.8 contains the necessary patch
joerixaop Feb 15, 2012
6acb4d0
Add row_limit option to GetListItems and GetListChangesSinceToken que…
Mar 6, 2012
e9e2601
Don't use 'try' method which come from rails. Sorry.
Mar 6, 2012
8b59ded
:row_limit => nil give errors when the token is present. (Apparenty n…
Mar 6, 2012
144e355
row_limit instead of 'ro w_limit' (stange that I didn't catch this …
Apr 11, 2012
1176ae4
with wasabi authentication. We can now get the wsdl document when the…
Nov 15, 2012
2a43192
RowLimit Bux fixed.
Nov 19, 2012
32ed5a2
Merge branch 'row_limit_on_get_list_items' into with_wasabi_authentic…
Nov 19, 2012
e579f41
Will be much faster to retreive the attributes of type User. + some o…
Nov 20, 2012
82171fe
Fix for TaxonomyFieldTypeMulti
joerixaop Feb 1, 2013
b95b556
Add support for https
joerixaop Apr 2, 2013
5e02bd6
Fix for TaxonomyType
Feb 20, 2014
73cc178
Other fix for TaxonomyField
Feb 20, 2014
461324f
Syntax seems to have changed slightly in ruby 2.2
joerixaop Sep 4, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions activesp.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ Gem::Specification.new do |s|
s.files += Dir['lib/**/*.rb']
# s.bindir = "bin"
# s.executables.push(*(Dir['bin/*.rb']))
s.add_dependency('savon-xaop', '= 0.7.2.7')
s.add_dependency('nokogiri')
s.add_dependency('savon', '>= 0.9.8')
s.add_dependency('curb')
s.add_dependency('httpi', '= 0.9.4')
# s.rdoc_options << '--exclude' << 'ext' << '--main' << 'README'
# s.extra_rdoc_files = ["README"]
s.has_rdoc = false
Expand Down
3 changes: 3 additions & 0 deletions lib/activesp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ module ActiveSP
require 'activesp/ghost_field'
require 'activesp/user'
require 'activesp/group'
require 'activesp/user_group_proxy'
require 'activesp/role'
require 'activesp/permission_set'
require 'activesp/file'
require 'activesp/site_template'
require 'activesp/list_template'
28 changes: 25 additions & 3 deletions lib/activesp/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ class Base
extend Caching
extend Associations

# @private
def relative_url(site_or_list = @list ? @list.site.connection.root : connection.root)
reference_url = site_or_list.url
reference_url += "/" unless reference_url[-1, 1] == "/"
url = self.url
reference_url = reference_url.sub(/\Ahttps?:\/\/[^\/]+/, "")
url = url.sub(/\Ahttps?:\/\/[^\/]+/, "")
url[reference_url.length..-1]
end

# Returns a key that can be used to retrieve this object later on using {Connection#find_by_key}
# @return [String]
def key
Expand Down Expand Up @@ -85,9 +95,11 @@ def attribute_type(name)
# @return [Integer, Float, String, Time, Boolean, Base] The assigned value
# @raise [ArgumentError] Raised when this object does not have an attribute by the given name or if the attribute by the given name is read-only
def set_attribute(name, value)
has_attribute?(name) and field = attribute_type(name) and internal_attribute_types[name] or raise ArgumentError, "#{self} has no field by the name #{name}"
!field.ReadOnly or raise ArgumentError, "field #{name} of #{self} is read-only"
current_attributes[name] = type_check_attribute(field, value)
set_attribute_internal(name, value, false)
end

def set_attribute!(name, value)
set_attribute_internal(name, value, true)
end

# Provides convenient getters and setters for attributes. Note that no name mangling
Expand Down Expand Up @@ -134,6 +146,16 @@ def changed_attributes
changes
end

def set_attribute_internal(name, value, override_restrictions)
has_attribute?(name) and field = attribute_type_internal(name, override_restrictions) or raise ArgumentError, "#{self} has no field by the name #{name}"
override_restrictions or !field.ReadOnly or raise ArgumentError, "field #{name} of #{self} is read-only"
current_attributes[name] = type_check_attribute(field, value, override_restrictions)
end

def attribute_type_internal(name, override_restrictions)
attribute_type(name)
end

end

end
157 changes: 114 additions & 43 deletions lib/activesp/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,71 @@
# OTHER DEALINGS IN THE SOFTWARE.

require 'savon'
require 'activesp/wasabi_authentication'
require 'net/ntlm_http'

Savon::Request.logger.level = Logger::ERROR
Savon.configure do |config|
config.log = false
end

HTTPI.log = false

HTTPI.adapter = :curb

class Savon::SOAP::Fault

def error_code
Integer(((to_hash[:fault] || {})[:detail] || {})[:errorcode] || 0)
end

def error_string
((to_hash[:fault] || {})[:detail] || {})[:errorstring]
end

end

Savon::Response.error_handler do |soap_fault|
soap_fault[:detail][:errorstring]
class HTTPI::Auth::Config

# Accessor for the GSSNEGOTIATE auth credentials.
def gssnegotiate(*args)
return @gssnegotiate if args.empty?

self.type = :gssnegotiate
@gssnegotiate = args.flatten.compact
end

# Returns whether to use GSSNEGOTIATE auth.
def gssnegotiate?
type == :gssnegotiate
end

end

class HTTPI::Adapter::Curb

def setup_client(request)
basic_setup request
setup_http_auth request if request.auth.http?
setup_ssl_auth request.auth.ssl if request.auth.ssl?
setup_ntlm_auth request if request.auth.ntlm?
setup_gssnegotiate_auth request if request.auth.gssnegotiate?
end

def setup_gssnegotiate_auth(request)
client.username, client.password = *request.auth.credentials
client.http_auth_types = request.auth.type
end

end

# This is because setting the cookie causes problems on SP 2011
class Savon::Client

private

def set_cookie(headers)
end

end

module ActiveSP
Expand All @@ -43,7 +102,7 @@ class Connection

# @private
# TODO: create profile
attr_reader :login, :password, :auth_type, :root_url, :trace
attr_reader :login, :password, :auth_type, :root_url, :trace, :user_group_proxy

# @param [Hash] options The connection options
# @option options [String] :root The URL of the root site
Expand All @@ -57,6 +116,7 @@ def initialize(options = {})
@password = options.delete(:password)
@auth_type = options.delete(:auth_type) || :ntlm
@trace = options.delete(:trace)
@user_group_proxy = options.delete(:user_group_proxy)
options.empty? or raise ArgumentError, "unknown options #{options.keys.map { |k| k.inspect }.join(", ")}"
cache = nil
configure_persistent_cache { |c| cache ||= c }
Expand Down Expand Up @@ -95,6 +155,15 @@ def find_by_key(key)
else
ActiveSP::ContentType.new(parent, nil, trail[1])
end
when ?M
case type[1]
when ?S
site_template(trail[0])
when ?L
list_template(trail[0].to_i)
else
raise "not yet #{key.inspect}"
end
else
raise "not yet #{key.inspect}"
end
Expand All @@ -107,54 +176,56 @@ def find_by_key(key)
# @param [String] url The URL to fetch
# @return [String] The content fetched from the URL
def fetch(url)
# TODO: support HTTPS too
@open_params ||= begin
u = URL(@root_url)
[u.host, u.port]
end
Net::HTTP.start(*@open_params) do |http|
request = Net::HTTP::Get.new(URL(url).full_path.gsub(/ /, "%20"))
if @login
case auth_type
when :ntlm
request.ntlm_auth(@login, @password)
when :basic
request.basic_auth(@login, @password)
else
raise ArgumentError, "Unknown authentication type #{auth_type.inspect}"
end
url = "#{protocol}://#{open_params.join(':')}#{url.gsub(/ /, "%20")}" unless /\Ahttp:\/\// === url
request = HTTPI::Request.new(url)
if login
case auth_type
when :ntlm
request.auth.ntlm(login, password)
when :basic
request.auth.basic(login, password)
when :digest
request.auth.digest(login, password)
when :gss_negotiate
request.auth.gssnegotiate(login, password)
else
raise ArgumentError, "Unknown authentication type #{auth_type.inspect}"
end
response = http.request(request)
# if Net::HTTPFound === response
# response = fetch(response["location"])
# end
# response
end
HTTPI.get(request)
end

def head(url)
# TODO: support HTTPS too
url = "#{protocol}://#{open_params.join(':')}#{url.gsub(/ /, "%20")}" unless /\Ahttp:\/\// === url
request = HTTPI::Request.new(url)
if login
case auth_type
when :ntlm
request.auth.ntlm(login, password)
when :basic
request.auth.basic(login, password)
when :digest
request.auth.digest(login, password)
when :gss_negotiate
request.auth.gssnegotiate(login, password)
else
raise ArgumentError, "Unknown authentication type #{auth_type.inspect}"
end
end
HTTPI.head(request).headers
end

def open_params
@open_params ||= begin
u = URL(@root_url)
[u.host, u.port]
end
Net::HTTP.start(*@open_params) do |http|
request = Net::HTTP::Head.new(URL(url).full_path.gsub(/ /, "%20"))
if @login
case auth_type
when :ntlm
request.ntlm_auth(@login, @password)
when :basic
request.basic_auth(@login, @password)
else
raise ArgumentError, "Unknown authentication type #{auth_type.inspect}"
end
end
response = http.request(request)
# if Net::HTTPFound === response
# response = fetch(response["location"])
# end
# response
end

def protocol
@protocol ||= begin
u = URL(@root_url)
u.protocol
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/activesp/content_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def fields_by_name
# See {Base#save}
# @return [void]
def save
p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes)
p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes, false)
end

# @private
Expand All @@ -121,9 +121,9 @@ def to_s

def data
if @list
call("Lists", "get_list_content_type", "listName" => @list.id, "contentTypeId" => @id).xpath("//sp:ContentType", NS).first
call("Lists", "GetListContentType", "listName" => @list.id, "contentTypeId" => @id).xpath("//sp:ContentType", NS).first
else
call("Webs", "get_content_type", "contentTypeId" => @id).xpath("//sp:ContentType", NS).first
call("Webs", "GetContentType", "contentTypeId" => @id).xpath("//sp:ContentType", NS).first
end
end
cache :data
Expand Down
6 changes: 6 additions & 0 deletions lib/activesp/errors.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
module ActiveSP

class NotFound < Exception
end

class AccessDenied < Exception
end

class PermissionDenied < Exception
end

class AlreadyExists < Exception

def initialize(msg, &object_blk)
Expand Down
Loading