waz-storage 1.0.6 → 1.1.0

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.
@@ -120,6 +120,22 @@ module WAZ
120
120
  :url => self.class.service_instance.generate_request_uri("#{self.name}/#{blob_name}"),
121
121
  :content_type => content_type)
122
122
  end
123
+
124
+ # Uploads the contents of a stream to the specified blob within this container, using
125
+ # the required <em>content_type</em>. The stream will be uploaded in blocks of size
126
+ # <em>block_size</em> bytes, which defaults to four megabytes. <strong>The <em>options</em>
127
+ # parameter, if provided, will set the default metadata properties for the blob</strong>.
128
+ def upload(blob_name, stream, content_type, options = {}, block_size = 4 * 2**20)
129
+ blob_name.gsub!(%r{^/}, '')
130
+ path = "#{self.name}/#{blob_name}"
131
+ n = 0
132
+ until stream.eof?
133
+ self.class.service_instance.put_block path, Base64.encode64('%064d' % n), stream.read(block_size)
134
+ n += 1
135
+ end
136
+ self.class.service_instance.put_block_list path, (0...n).map{|id| Base64.encode64('%064d' % id)}, content_type, options
137
+ return BlobObject.new(:name => blob_name, :url => self.class.service_instance.generate_request_uri("#{self.name}/#{blob_name}"), :content_type => content_type)
138
+ end
123
139
 
124
140
  # Retrieves the blob by the given name. If the blob isn't found on the current container
125
141
  # it will return nil instead of throwing an exception.
@@ -136,4 +152,4 @@ module WAZ
136
152
  end
137
153
  end
138
154
  end
139
- end
155
+ end
@@ -83,7 +83,19 @@ module WAZ
83
83
  default_headers = {"Content-Type" => content_type, :x_ms_version => "2009-09-19", :x_ms_blob_type => "BlockBlob"}
84
84
  execute :put, path, nil, metadata.merge(default_headers), payload
85
85
  end
86
-
86
+
87
+ # Commits a list of blocks to the given blob.
88
+ #
89
+ # blockids is a list of valid, already-uploaded block IDs (base64-encoded)
90
+ #
91
+ # content_type is required by the blobs api, but on this method is defaulted to "application/octect-stream"
92
+ #
93
+ # metadata is a hash that stores all the properties that you want to add to the blob when creating it.
94
+ def put_block_list(path, blockids, content_type = "application/octet-stream", metadata = {})
95
+ default_headers = {"Content-Type" => content_type, :x_ms_version => "2009-09-19"}
96
+ execute :put, path, { :comp => 'blocklist' }, metadata.merge(default_headers), '<?xml version="1.0" encoding="utf-8"?><BlockList>' + blockids.map {|id| "<Latest>#{id.rstrip}</Latest>"}.join + '</BlockList>'
97
+ end
98
+
87
99
  # Retrieves a blob (content + headers) from the current path.
88
100
  def get_blob(path, options = {})
89
101
  execute :get, path, options, {:x_ms_version => "2009-09-19"}
@@ -58,7 +58,7 @@ module WAZ
58
58
  # Creates a canonical representation of the message by combining account_name/resource_path.
59
59
  def canonicalize_message(url)
60
60
  uri_component = url.gsub(/https?:\/\/[^\/]+\//i, '').gsub(/\?.*/i, '')
61
- comp_component = url.scan(/(comp=[^&]+)/i).first()
61
+ comp_component = url.scan(/comp=[^&]+/i).first()
62
62
  uri_component << "?#{comp_component}" if comp_component
63
63
  canonicalized_message = "/#{self.account_name}/#{uri_component}"
64
64
  return canonicalized_message
@@ -104,7 +104,7 @@ module WAZ
104
104
  def canonicalize_message20090919(url)
105
105
  uri_component = url.gsub(/https?:\/\/[^\/]+\//i, '').gsub(/\?.*/i, '')
106
106
  query_component = (url.scan(/\?(.*)/i).first() or []).first()
107
- query_component = query_component.split('&').sort{|a, b| a <=> b}.map{ |p| p.split('=').join(':') }.join("\n") if query_component
107
+ query_component = query_component.split('&').sort{|a, b| a <=> b}.map{ |p| CGI::unescape(p.split('=').join(':')) }.join("\n") if query_component
108
108
  canonicalized_message = "/#{self.account_name}/#{uri_component}"
109
109
  canonicalized_message << "\n#{query_component}" if query_component
110
110
  return canonicalized_message
@@ -2,8 +2,8 @@ module WAZ
2
2
  module Storage
3
3
  module VERSION #:nodoc:
4
4
  MAJOR = '1'
5
- MINOR = '0'
6
- TINY = '6'
5
+ MINOR = '1'
6
+ TINY = '0'
7
7
  end
8
8
 
9
9
  Version = [VERSION::MAJOR, VERSION::MINOR, VERSION::TINY].compact * '.'
@@ -139,17 +139,17 @@ module WAZ
139
139
  def generate_payload(table_name, entity)
140
140
  payload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" \
141
141
  "<entry xmlns:d=\"#{DATASERVICES_NAMESPACE}\" xmlns:m=\"#{DATASERVICES_METADATA_NAMESPACE}\" xmlns=\"http://www.w3.org/2005/Atom\">" \
142
- "<id>#{generate_request_uri "#{table_name}"}(PartitionKey='#{entity[:partition_key]}',RowKey='#{entity[:row_key]}')</id>" \
143
- "<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"#{table_name}\" href=\"#{table_name}(PartitionKey='#{entity[:partition_key]}',RowKey='#{entity[:row_key]}')\" />" \
142
+ "<id>#{generate_request_uri "#{table_name}"}(PartitionKey='#{REXML::Text.new(entity[:partition_key], false, nil, false).to_s}',RowKey='#{REXML::Text.new(entity[:row_key], false, nil, false).to_s}')</id>" \
143
+ "<title /><updated>#{Time.now.utc.iso8601}</updated><author><name /></author><link rel=\"edit\" title=\"#{table_name}\" href=\"#{table_name}(PartitionKey='#{REXML::Text.new(entity[:partition_key], false, nil, false).to_s}',RowKey='#{REXML::Text.new(entity[:row_key], false, nil, false).to_s}')\" />" \
144
144
  "<content type=\"application/xml\"><m:properties>"
145
145
 
146
146
  entity.sort_by { |k| k.to_s }.each do |k,v|
147
147
  value, type = EdmTypeHelper.parse_to(v)[0].to_s, EdmTypeHelper.parse_to(v)[1].to_s
148
- payload << (!v.nil? ? "<d:#{k.to_s} m:type=\"#{k.edm_type || type}\">#{value}</d:#{k.to_s}>" : "<d:#{k.to_s} m:type=\"#{k.edm_type || type}\" m:null=\"true\" />") unless k.eql?(:partition_key) or k.eql?(:row_key)
148
+ payload << (!v.nil? ? "<d:#{k.to_s} m:type=\"#{k.edm_type || type}\">#{REXML::Text.new(value, false, nil, false).to_s}</d:#{k.to_s}>" : "<d:#{k.to_s} m:type=\"#{k.edm_type || type}\" m:null=\"true\" />") unless k.eql?(:partition_key) or k.eql?(:row_key)
149
149
  end
150
150
 
151
- payload << "<d:PartitionKey>#{entity[:partition_key]}</d:PartitionKey>" \
152
- "<d:RowKey>#{entity[:row_key]}</d:RowKey>" \
151
+ payload << "<d:PartitionKey>#{REXML::Text.new(entity[:partition_key], false, nil, false).to_s}</d:PartitionKey>" \
152
+ "<d:RowKey>#{REXML::Text.new(entity[:row_key], false, nil, false).to_s}</d:RowKey>" \
153
153
  "</m:properties></content></entry>"
154
154
  return payload
155
155
  end
@@ -175,4 +175,4 @@ module WAZ
175
175
  end
176
176
  end
177
177
  end
178
- end
178
+ end
data/rakefile CHANGED
@@ -44,7 +44,7 @@ end
44
44
  namespace :docs do
45
45
  Rake::RDocTask.new do |t|
46
46
  t.rdoc_dir = 'rdoc'
47
- t.title = "Windows Azure Storage library simple gem for accessing WAZs Storage REST API"
47
+ t.title = "Windows Azure Storage library - simple gem for accessing WAZ's Storage REST API"
48
48
  t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
49
49
  t.options << '--charset' << 'utf-8'
50
50
  t.rdoc_files.include('README.rdoc')
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waz-storage
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
+ - 1
8
9
  - 0
9
- - 6
10
- version: 1.0.6
10
+ version: 1.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Johnny G. Halife
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-18 00:00:00 -04:00
18
+ date: 2011-06-29 00:00:00 -03:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency