stupeflixclient 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,123 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+ module Stupeflixclient
5
+
6
+ class Connection
7
+ def initialize(server, base_url)
8
+ @server = server
9
+ @base_url = base_url
10
+ @MAX_NETWORK_RETRY = 1
11
+ @debuglevel = 0
12
+ end
13
+
14
+ def request_get( resource, args = nil, headers={})
15
+ return request(resource, "get", args, body = nil, filename = nil, headers=headers)
16
+ end
17
+
18
+ def request_delete( resource, args = nil, headers={})
19
+ return request(resource, "delete", args, headers=headers)
20
+ end
21
+
22
+ def request_head( resource, args = nil, headers={})
23
+ return request(resource, "head", args, headers=headers)
24
+ end
25
+
26
+ def request_post( resource, args = nil, body = nil, filename=nil, headers={})
27
+ return request(resource, "post", args , body = body, filename=filename, headers=headers)
28
+ end
29
+
30
+ def request_put(resource, args = nil, body = nil, filename=nil, headers={}, sendcallback = nil)
31
+ dump("In request_put in connection", resource, "PUT")
32
+ resp = request(resource, "put", args , body = body, filename=filename, headers=headers, sendcallback = sendcallback)
33
+ return resp
34
+ end
35
+
36
+ def dump( message, request_uri, method)
37
+ if @debuglevel > 0
38
+ print message, " " , time.asctime, " " , request_uri, "\n"
39
+ end
40
+ end
41
+
42
+ def request_method(verb)
43
+ Net::HTTP.const_get(verb.to_s.capitalize)
44
+ end
45
+
46
+ def fetch(uri_str, limit = 10)
47
+ # You should choose better exception.
48
+ raise ArgumentError, 'HTTP redirect too deep' if limit == 0
49
+
50
+ response = Net::HTTP.get_response(URI.parse(uri_str))
51
+ case response
52
+ when Net::HTTPSuccess then response
53
+ when Net::HTTPRedirection then fetch(response['location'], limit - 1)
54
+ else
55
+ response.error!
56
+ end
57
+
58
+ end
59
+
60
+ def request( resource, method = "get", args = nil, body = nil, filename=nil, headers={}, sendcallback = nil)
61
+ params = nil
62
+ path = resource
63
+
64
+ if headers == nil
65
+ headers = {}
66
+ end
67
+
68
+ headers['User-Agent'] = 'Basic Agent'
69
+
70
+ # TEMPORARY : add support for streaming
71
+ if method != "get"
72
+ if not body and filename
73
+ bodystream = File.open(filename, 'r')
74
+ end
75
+ end
76
+
77
+ if args
78
+ path += "?" + urllib.urlencode(args)
79
+ end
80
+
81
+ url = 'http://' + @server + @base_url + path
82
+
83
+ dump("Connection Request starting", path, method.upcase)
84
+
85
+ for i in 0..@MAX_NETWORK_RETRY
86
+ begin
87
+ # http.set_debug_output $stdout
88
+ # headers['Expect'] = '100-Continue'
89
+
90
+ response = nil
91
+ while true
92
+ url = URI.parse(url)
93
+ request = request_method(method).new(url.path + "?" + url.query, headers)
94
+ if bodystream
95
+ request.body_stream = bodystream
96
+ elsif body
97
+ request.body = body
98
+ end
99
+ http = Net::HTTP.new(url.host, url.port)
100
+ result = http.start {|http|
101
+ response = http.request(request)
102
+ }
103
+ case response
104
+ when Net::HTTPRedirection
105
+ then
106
+ url = response['location']
107
+ else
108
+ break
109
+ end
110
+ end
111
+ break
112
+ rescue StandardError => e
113
+ if i == (@MAX_NETWORK_RETRY - 1)
114
+ raise
115
+ end
116
+ end
117
+ end
118
+ response["status"] = response.code.to_s
119
+ return {'headers' => response, 'body' => response.body}
120
+ end
121
+
122
+ end
123
+ end
@@ -0,0 +1,4 @@
1
+ module Stupeflixclient::Constants
2
+ SERVER_NAME = "http://services.stupeflix.com"
3
+ BASE_ENDPOINT = 'stupeflix-1.0'
4
+ end
@@ -0,0 +1,4 @@
1
+ module Stupeflixclient::Settings
2
+ ACCESS_KEY = ENV['stupeflix_access_key']
3
+ ACCESS_SECRET = ENV['stupeflix_access_secret']
4
+ end
@@ -0,0 +1,273 @@
1
+ require 'openssl'
2
+ require 'digest'
3
+ require 'base64'
4
+ require 'stupeflixclient/connection'
5
+ require 'digest/md5'
6
+ module Stupeflixclient
7
+ class StupeflixBase
8
+ def initialize( accessKey, privateKey, host = "http://services.stupeflix.com", service = 'stupeflix-1.0', debug = false)
9
+ @accessKey = accessKey
10
+ @privateKey = privateKey
11
+ len = host.length - 7
12
+ if host[host.length - 1, 1] == "/"
13
+ host = host[0, host.length - 1]
14
+ end
15
+
16
+ @host = host[7,len]
17
+ @base_url = service
18
+ @debug = debug
19
+ @service = service
20
+ @TEXT_XML_CONTENT_TYPE = "text/xml"
21
+ @APPLICATION_ZIP_CONTENT_TYPE = "application/zip"
22
+ @APPLICATION_JSON_CONTENT_TYPE = "application/json"
23
+ @APPLICATION_URLENCODED_CONTENT_TYPE = "application/x-www-form-urlencoded"
24
+ @PROFILES_PARAMETER = "Profiles"
25
+ @XML_PARAMETER = "ProfilesXML"
26
+ @MARKER_PARAMETER = "Marker"
27
+ @MAXKEYS_PARAMETER = "MaxKeys"
28
+ # Currently there is only the Marker parameter (used for partial enumeration)
29
+ @parametersToAdd = [@MARKER_PARAMETER, @MAXKEYS_PARAMETER]
30
+ @sleepTime = 1.0
31
+ @maxRetry = 4
32
+ @base = true
33
+ end
34
+
35
+ def connectionGet
36
+ return Connection.new(@host, "/" + @base_url)
37
+ end
38
+
39
+ def paramString( parameters)
40
+ paramStr = ""
41
+ if parameters != nil
42
+ for p in @parametersToAdd
43
+ if parameters.include?(p)
44
+ paramStr += sprintf( "%s\n%s\n", p, parameters[p])
45
+ end
46
+ end
47
+ end
48
+ return paramStr
49
+ end
50
+
51
+ def strToSign( method, resource, md5, mime, datestr, parameters)
52
+ paramStr = paramString(parameters)
53
+ stringToSign = sprintf( "%s\n%s\n%s\n%s\n%s\n%s", method, md5, mime, datestr, '/' + @service + resource, paramStr)
54
+ return stringToSign
55
+ end
56
+
57
+ def sign( strToSign, secretKey)
58
+ digest = OpenSSL::Digest::Digest.new('sha1')
59
+ return OpenSSL::HMAC.hexdigest(digest, secretKey, strToSign)
60
+ end
61
+
62
+ def signUrl( url, method, md5, mime, parameters = {})
63
+ now =Time.now.to_i
64
+ strToSign = strToSign(method, url, md5, mime, now, parameters)
65
+ signature = sign(strToSign, @privateKey)
66
+ url += sprintf( "?Date=%s&AccessKey=%s&Signature=%s", now, @accessKey,signature)
67
+ if parameters
68
+ parameters.each_pair do |k,v|
69
+ url += sprintf("&%s=%s", k,v)
70
+ end
71
+ end
72
+ return url
73
+ end
74
+
75
+ def md5FileOrBody( filename, body = nil)
76
+ md5 = Digest::MD5.new()
77
+
78
+ if body != nil
79
+ md5.update(body)
80
+ else
81
+ chunksize=1024
82
+ f = File.open(filename, 'r')
83
+
84
+ while true
85
+ chunk = f.read(chunksize)
86
+ if not chunk
87
+ break
88
+ end
89
+ md5.update(chunk)
90
+ end
91
+ f.close
92
+ end
93
+
94
+ digest = md5.digest
95
+
96
+ return [digest, md5.hexdigest, Base64.encode64(digest).strip]
97
+ end
98
+
99
+ def isZip( filename)
100
+ f = File.open(filename, 'r')
101
+ header = f.read(4)
102
+ return header == 'PK'+3.chr+4.chr
103
+ end
104
+
105
+ def logdebug( s)
106
+ if @debug
107
+ print s.to_s
108
+ end
109
+ end
110
+
111
+ def error( message)
112
+ logdebug(message)
113
+ raise StandardError, message
114
+ end
115
+
116
+ def answer_error( answer, message)
117
+ raise StandardError, sprintf( "%s\n%s", message, answer['body'])
118
+ end
119
+
120
+ # sendcallback is an object with
121
+ # - a 'sendCallBack' member function that accept a unique int argument (=number of bytes written so far)
122
+ # - a 'sendBlockSize' member function with no argument which return the size of block to be sent
123
+ def sendContent( method, url, contentType, filename = nil, body = nil, parameters = nil, sendcallback = nil)
124
+
125
+ # SEND DATA
126
+ conn = connectionGet()
127
+
128
+ md5, md5hex, md5base64 = md5FileOrBody(filename, body)
129
+
130
+ if filename
131
+ size = File.stat(filename).size
132
+ else
133
+ size = body.length
134
+ end
135
+
136
+ headers = {'Content-MD5' => md5base64.to_s,
137
+ 'Content-Length' => size.to_s,
138
+ 'Content-Type' => contentType}
139
+
140
+ url = signUrl(url, method, md5base64, contentType, parameters)
141
+
142
+ # LAUNCH THE REQUEST : TODO : pass filename instead of body
143
+ if method == "PUT"
144
+ answer = conn.request_put(url, args = nil, body = body, filename = filename, headers = headers, sendcallback = sendcallback)
145
+ elsif method == "POST"
146
+ answer = conn.request_post(url, args = nil, body = body, filename = filename, headers = headers)
147
+ elsif method == "DELETE"
148
+ answer = conn.request_delete(url, headers = headers)
149
+ end
150
+
151
+ headers = answer['headers']
152
+
153
+ logdebug(headers)
154
+ logdebug(answer['body'])
155
+
156
+ # NOW CHECK THAT EVERYTHING IS OK
157
+ status = headers['status']
158
+ if status != '200'
159
+ msg = sprintf( "sendContent : bad STATUS %s", status )
160
+ answer_error(answer, msg)
161
+ end
162
+
163
+ if headers['etag'] == nil
164
+ msg = "corrupted answer: no etag in headers. Response body is " + answer['body']
165
+ error(msg)
166
+ end
167
+
168
+ obtainedMD5 = headers['etag']
169
+
170
+ if obtainedMD5 != md5hex
171
+ msg = sprintf( "sendContent : bad returned etags %s =! %s (ref)", obtainedMD5, md5hex)
172
+ error(msg)
173
+ end
174
+
175
+ return answer
176
+ end
177
+
178
+ def getContentUrl( url, method, parameters)
179
+ return signUrl(url, method, "", "", parameters)
180
+ end
181
+
182
+ def getContent( url, filename = nil, parameters = nil)
183
+ sleepTime = @sleepTime
184
+
185
+ for i in 0..@maxRetry
186
+ raiseExceptionOn404 = (i + 1) == @maxRetry
187
+ ret = getContent_(url, filename, parameters, raiseExceptionOn404)
188
+ if ret["status"] != 404
189
+ return ret
190
+ end
191
+ # Wait for amazon S3 ...
192
+ sleep(1)
193
+ end
194
+ end
195
+
196
+ def getContent_( url, filename = nil, parameters = nil, raiseExceptionOn404 = true)
197
+ method = "GET"
198
+ url = getContentUrl(url, method, parameters)
199
+
200
+ # GET DATA
201
+ conn = connectionGet()
202
+ answer = conn.request_get(url)
203
+ body = answer['body']
204
+
205
+ headers = answer['headers']
206
+ status = headers['status'].to_i
207
+
208
+ if status == 204
209
+ # there was no content
210
+ obtainedSize = 0
211
+ if body.length != 0
212
+ error("204 status with non empty body.")
213
+ end
214
+ elsif status == 200
215
+ obtainedSize =headers['content-length'].to_i
216
+ elsif status == 404 and not raiseExceptionOn404
217
+ return {"url" => headers['content-location'], "status" => 404}
218
+ else
219
+ msg = sprintf( "getContent : bad STATUS %s", status )
220
+ answer_error(answer, msg)
221
+ end
222
+
223
+ if body.length != obtainedSize
224
+ error("Non matching body length and content-length")
225
+ end
226
+
227
+ if filename != nil
228
+ f = File.open(filename, 'w')
229
+ f.write(body)
230
+ f.close
231
+
232
+ if obtainedSize == 0
233
+ File.unlink(filename)
234
+ else
235
+ filesize = File.stat(filename).size
236
+ if obtainedSize != filesize
237
+ File.unlink(filename)
238
+ error(sprintf( "file size is incorrect : file size = %d, body size = %d", filesize, obtainedSize))
239
+ end
240
+ end
241
+ end
242
+
243
+ # NOW CHECK EVERYTHING IS OK
244
+ md5, md5hex, md5base64 = md5FileOrBody(filename, body)
245
+
246
+ if status != 204
247
+ obtainedMD5 = headers['etag'].gsub(/"/,"")
248
+ if obtainedMD5 != md5hex
249
+ if filename
250
+ File.unlink(filename)
251
+ end
252
+ error(sprintf( "getDefinition : bad returned etag %s =! %s (ref)", md5hex, obtainedMD5))
253
+ end
254
+ end
255
+
256
+ if status == 200
257
+ logdebug(sprintf( "headers = %s", headers) )
258
+ url = headers['content-location']
259
+ ret = {'size' => obtainedSize, 'url' => url, 'headers' => headers}
260
+ else
261
+ ret = {'size' => obtainedSize, 'url' => url}
262
+ end
263
+
264
+ if not filename
265
+ ret['body'] = body
266
+ end
267
+
268
+ ret["status"] = status
269
+
270
+ return ret
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,354 @@
1
+ require 'stupeflixclient/stupeflix_base'
2
+ require 'stupeflixclient/connection'
3
+ require 'cgi'
4
+ require 'json.rb'
5
+ module Stupeflixclient
6
+ class StupeflixClient < StupeflixBase
7
+ def initialize(accessKey, privateKey, host = "http://services.stupeflix.com", service = 'stupeflix-1.0', debug = false)
8
+ super(accessKey, privateKey, host, service, debug)
9
+ @batch = false
10
+ @batchData = ""
11
+ end
12
+
13
+ # Start a batch, used for speeduping video definition upload
14
+ # Operation that can be batched : sendDefinition and createProfiles
15
+ # Operation
16
+ # Only works for xml definition, not zip, and xml must be in UTF8
17
+ def batchStart( maxSize = 1000000)
18
+ @batch = true
19
+ @batchData = "<batch>"
20
+ @batchMaxSize = maxSize
21
+ end
22
+
23
+ # End a batch: actually send data
24
+ def batchEnd
25
+ @batchData += "</batch>"
26
+ sendDefinitionBatch(body = @batchData)
27
+ @batchData = ""
28
+ @batch = false
29
+ end
30
+
31
+ # Send a definition file to the API
32
+ def sendDefinition( user, resource, filename = nil, body = nil)
33
+ url = definitionUrl(user, resource)
34
+ if body
35
+ contentType = @TEXT_XML_CONTENT_TYPE;
36
+ elsif isZip(filename)
37
+ contentType = @APPLICATION_ZIP_CONTENT_TYPE
38
+ else
39
+ contentType = @TEXT_XML_CONTENT_TYPE
40
+ end
41
+ if @batch and contentType == @TEXT_XML_CONTENT_TYPE
42
+ @batchData += sprintf("<task user=\"%s\" resource=\"%s\">", user, resource)
43
+ if body
44
+ @batchData += body
45
+ else
46
+ @batchData += File.open(filename).read
47
+ end
48
+ else
49
+
50
+ return sendContent("PUT", url, contentType, filename, body)
51
+ end
52
+ end
53
+
54
+ # Send a definition file to the API
55
+ def sendDefinitionBatch( filename = nil, body = nil)
56
+ url = @definitionBatchUrl
57
+ contentType = @TEXT_XML_CONTENT_TYPE;
58
+ return sendContent("PUT", url, contentType, filename, body)
59
+ end
60
+
61
+ def getDefinition( user, resource, filename)
62
+ url = definitionUrl(user, resource)
63
+ return getContent(url, filename)['size']
64
+ end
65
+
66
+ def _getAbsoluteUrl( url, followRedirect = false)
67
+ urlPart = getContentUrl(url, 'GET', nil)
68
+ if followRedirect
69
+ conn = connection.Connection(@base_url, followRedirect = false)
70
+ response = conn.request_get(urlPart)
71
+ return response["headers"]["location"]
72
+ else
73
+ return @base_url + urlPart
74
+ end
75
+ end
76
+
77
+ def getProfileUrl( user, resource, profile, followRedirect = false)
78
+ url = profileUrl(user, resource, profile)
79
+ return _getAbsoluteUrl(url, followRedirect)
80
+ end
81
+
82
+ def getProfile( user, resource, profile, filename)
83
+ url = profileUrl(user, resource, profile)
84
+ getContent(url, filename)
85
+ end
86
+
87
+ def getProfileThumbUrl( user, resource, profile, followRedirect = false)
88
+ url = profileThumbUrl(user, resource, profile, "thumb.jpg")
89
+ return _getAbsoluteUrl(url, followRedirect)
90
+ end
91
+
92
+ def getProfileThumb( user, resource, profile, filename)
93
+ url = profileThumbUrl(user, resource, profile, "thumb.jpg")
94
+ getContent(url, filename)
95
+ end
96
+
97
+ def getProfileReportUrl( user, resource, profile, followRedirect = false)
98
+ url = profileReportUrl(user, resource, profile)
99
+ return _getAbsoluteUrl(url, followRedirect)
100
+ end
101
+
102
+ def getProfileReport( user, resource, profile, filename)
103
+ url = profileReportUrl(user, resource, profile)
104
+ getContent(url, filename)
105
+ end
106
+
107
+ def createProfiles( user, resource, profiles)
108
+ profileData = profiles.xmlGet
109
+ if @batch
110
+ @batchData += profileData
111
+ @batchData += "</task>"
112
+ if @batchData.length >= @batchMaxSize
113
+ begin
114
+ @batchEnd
115
+ finally
116
+ batchStart(@batchMaxSize)
117
+ end
118
+ end
119
+ else
120
+ url, parameters = profileCreateUrl(user, resource, profileData)
121
+ contentType = @APPLICATION_URLENCODED_CONTENT_TYPE
122
+ body = ""
123
+ parameters.each_pair do |k,v|
124
+ body += CGI::escape(k) + "=" + CGI::escape(v)
125
+ end
126
+ return sendContent("POST", url, contentType, filename = nil, body = body)
127
+ end
128
+ end
129
+
130
+ def getStatus( user = nil, resource = nil, profile = nil, marker = nil, maxKeys = nil)
131
+ url, parameters = statusUrl(user, resource, profile, marker, maxKeys)
132
+ ret = getContent(url, filename = nil, parameters = parameters)
133
+ status = JSON.parse(ret['body'])
134
+ return status
135
+ end
136
+
137
+ def getMarker( status)
138
+ if status.length == 0
139
+ return nil
140
+ end
141
+ lastStatus = status[-1]
142
+ #return map(lambda x: lastStatus[x], ["user", "resource", "profile"])
143
+ return []
144
+ end
145
+
146
+ # helper functions : build non signed urls for each kind of action
147
+ def definitionUrl( user, resource)
148
+ return sprintf( "/%s/%s/definition/", user, resource)
149
+ end
150
+
151
+ # helper functions : build non signed urls for each kind of action
152
+ def definitionBatchUrl
153
+ return "/batch/"
154
+ end
155
+
156
+ def profileUrl( user, resource, profile)
157
+ return sprintf( "/%s/%s/%s/", user, resource, profile)
158
+ end
159
+
160
+ def profileThumbUrl( user, resource, profile, thumbname)
161
+ return sprintf( "/%s/%s/%s/%s/", user, resource, profile, thumbname)
162
+ end
163
+
164
+ def profileReportUrl( user, resource, profile)
165
+ return sprintf( "/%s/%s/%s/%s/", user, resource, profile, "report.xml")
166
+ end
167
+
168
+ def profileCreateUrl( user, resource, profiles)
169
+ s = sprintf( "/%s/%s/", user, resource)
170
+ parameters = {@XML_PARAMETER => profiles}
171
+ return s, parameters
172
+ end
173
+
174
+ def actionUrl( user, resource, profile, action)
175
+ path = [user, resource, profile]
176
+ s = ""
177
+ path.each do |p|
178
+ if p == nil
179
+ break
180
+ end
181
+ s += sprintf( "/%s", p )
182
+ end
183
+ s += sprintf( "/%s/", action )
184
+ return s
185
+ end
186
+
187
+ def statusUrl( user, resource, profile, marker = nil, maxKeys = nil)
188
+ params = {}
189
+ if marker != nil
190
+ params[@MARKER_PARAMETER] = marker.join('/')
191
+ end
192
+ if maxKeys != nil
193
+ params[@MAXKEYS_PARAMETER] = maxKeys
194
+ end
195
+
196
+ return [actionUrl(user, resource, profile, "status"), params]
197
+ end
198
+ end
199
+
200
+ class StupeflixXMLNode
201
+ def initialize( nodeName, attributes = nil, children = nil, text = nil)
202
+ @children = children
203
+ @attributes = attributes
204
+ @nodeName = nodeName
205
+ @text = text
206
+ end
207
+
208
+ def xmlGet
209
+ docXML = '<' + @nodeName
210
+ if @attributes and @attributes.length != 0
211
+
212
+ @attributes.each_pair do |k, v|
213
+ docXML += " "
214
+ if v == nil
215
+ v = ""
216
+ end
217
+ k = k.to_s
218
+ v = v.to_s
219
+ docXML += k + '="' + CGI.escapeHTML(v) + '"'
220
+ end
221
+ end
222
+ docXML += '>'
223
+ if @children
224
+ for c in @children
225
+ docXML += c.xmlGet
226
+ end
227
+ end
228
+ if @text
229
+ docXML += @text
230
+ end
231
+ docXML += '</' + @nodeName + '>'
232
+
233
+ return docXML
234
+ end
235
+
236
+ def metaChildrenAppend( meta = nil, notify = nil, children = nil)
237
+ childrenArray = []
238
+ if meta
239
+ childrenArray += [meta]
240
+ end
241
+ if notify
242
+ childrenArray += [notify]
243
+ end
244
+ if children
245
+ childrenArray += children
246
+ end
247
+ return childrenArray
248
+ end
249
+ end
250
+
251
+ class StupeflixMeta < StupeflixXMLNode
252
+ def initialize(dict)
253
+ children = []
254
+
255
+ dict.all? {|k, v|
256
+ children += [StupeflixXMLNode.new(k, nil, nil, v)]
257
+ }
258
+ super("meta", {}, children)
259
+ end
260
+ end
261
+
262
+ class StupeflixProfileSet < StupeflixXMLNode
263
+ def initialize( profiles, meta = nil, notify = nil)
264
+ children = metaChildrenAppend(meta, notify, profiles)
265
+ super("profiles", {}, children)
266
+ end
267
+
268
+ def deflt(profiles)
269
+ profSet = []
270
+ for p in profiles
271
+ upload = StupeflixDefaultUpload
272
+ profSet += [StupeflixProfile(p, [upload])]
273
+ end
274
+
275
+ return StupeflixProfileSet.new(profSet)
276
+ end
277
+ end
278
+
279
+ class StupeflixProfile < StupeflixXMLNode
280
+ def initialize( profileName, uploads = nil, meta = nil, notify = nil)
281
+ children = metaChildrenAppend(meta, notify, uploads)
282
+ super("profile", {"name" => profileName}, children)
283
+ end
284
+ end
285
+
286
+ class StupeflixNotify < StupeflixXMLNode
287
+ def initialize( url, statusRegexp)
288
+ super("notify", {"url" => url, "statusRegexp" => statusRegexp})
289
+ end
290
+ end
291
+
292
+ class StupeflixHttpHeader < StupeflixXMLNode
293
+ def initialize(key, value)
294
+ super("header", {"key" => key, "value" => value})
295
+ end
296
+ end
297
+
298
+ class StupeflixUpload < StupeflixXMLNode
299
+ def initialize( name, parameters, meta = nil, notify = nil, children = nil)
300
+ children = metaChildrenAppend(meta, notify, children)
301
+ super(name, parameters, children)
302
+ end
303
+ end
304
+
305
+ class StupeflixHttpPOSTUpload < StupeflixUpload
306
+ def initialize( url, meta = nil, notify = nil)
307
+ super("httpPOST", {"url" => url}, meta, notify)
308
+ end
309
+ end
310
+
311
+ class StupeflixHttpPUTUpload < StupeflixUpload
312
+ def initialize( url, meta = nil, notify = nil, headers = nil)
313
+ super("httpPUT", {"url" => url}, meta, notify, headers)
314
+ end
315
+ end
316
+
317
+ class StupeflixYoutubeUpload < StupeflixUpload
318
+ def initialize(login, password, meta = nil, notify = nil)
319
+ super("youtube", {"login" => login, "password" => password}, meta, notify)
320
+ end
321
+ end
322
+
323
+ class StupeflixBrightcoveUpload < StupeflixUpload
324
+ def initialize(token, reference_id = nil, meta = nil, notify = nil)
325
+ parameters = {"sid" => token}
326
+ if reference_id != nil
327
+ parameters["reference_id"] = reference_id
328
+ end
329
+ super("brightcove", parameters, meta, notify)
330
+ end
331
+ end
332
+
333
+ class StupeflixDefaultUpload < StupeflixUpload
334
+ def initialize( meta = nil, notify = nil)
335
+ children = metaChildrenAppend(meta)
336
+ super("stupeflixStore", {}, meta, notify)
337
+ end
338
+ end
339
+
340
+ class StupeflixS3Upload < StupeflixUpload
341
+ def initialize(bucket, resourcePrefix, accesskey = nil, secretkey = nil, meta = nil, notify = nil)
342
+ children = metaChildrenAppend(meta)
343
+ parameters = {"bucket" => bucket, "resourcePrefix" => resourcePrefix}
344
+ if accesskey != nil
345
+ parameters["accesskey"] = accesskey
346
+ end
347
+ if secretkey != nil
348
+ parameters["secretkey"] = secretkey
349
+ end
350
+ super("s3", parameters, meta, notify)
351
+ end
352
+ end
353
+
354
+ end