sme_storage 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +9 -0
- data/README +12 -0
- data/Rakefile +13 -0
- data/lib/sme_storage/api.rb +67 -0
- data/lib/sme_storage/mime_boundary.rb +15 -0
- data/lib/sme_storage/uploader.rb +38 -0
- data/lib/sme_storage.rb +79 -0
- metadata +61 -0
data/LICENSE
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Copyright (c) 2010, Vehera LTD
All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
4
|
+
|
5
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
6
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
7
|
+
* Neither the name of Vehera nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
8
|
+
|
9
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
A small ruby library for uploading files to SMEStorage (http://www.smestorage.com/). It does not implement all of SMEStorage's API, just the file upload part.
|
2
|
+
|
3
|
+
Basic usage:
|
4
|
+
|
5
|
+
require "rubygems"
|
6
|
+
require "sme_storage"
|
7
|
+
|
8
|
+
storage = SmeStorage.new("user", "password")
|
9
|
+
storage.authenticate
|
10
|
+
storage.upload("/Users/augustl/Desktop/testfile.txt")
|
11
|
+
|
12
|
+
Author: August Lilleaas, august.lilleaas@gmail.com
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
require "base64"
|
4
|
+
require "rexml/document"
|
5
|
+
|
6
|
+
class SmeStorage
|
7
|
+
# The interface to the REST api. You need a token to interact with it.
|
8
|
+
#
|
9
|
+
# @token = SmeStorage::Api.get_token(username, password)
|
10
|
+
#
|
11
|
+
# When you have the token, you can call any action you want in the API.
|
12
|
+
#
|
13
|
+
# SmeStorage::Api.get(@token, "doInitUpload", "arbitary", "parameters", "here")
|
14
|
+
class Api
|
15
|
+
HTTP = Net::HTTP.new("www.smestorage.com", 80)
|
16
|
+
API_URI = "/api"
|
17
|
+
USER_AGENT = "SMEStorage Automator Upload Workflow"
|
18
|
+
|
19
|
+
attr_reader :root
|
20
|
+
|
21
|
+
# Similar to +new+, but also fetches and parses XML in one pass.
|
22
|
+
def self.get(*args)
|
23
|
+
instance = new(*args)
|
24
|
+
instance.fetch
|
25
|
+
instance.parse
|
26
|
+
return instance
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the token if successful, false if not.
|
30
|
+
def self.get_token(username, password)
|
31
|
+
response = get(nil, "gettoken", username, password)
|
32
|
+
response.ok? && response.root.elements["token"].text
|
33
|
+
end
|
34
|
+
|
35
|
+
# The token can be nil, for authentication operations. The action matches
|
36
|
+
# the action names in the SMEStorage API. The arguments are the base64
|
37
|
+
# encoded comma separated arguments, also matching the SMEStorage API.
|
38
|
+
def initialize(token, action, *arguments)
|
39
|
+
@token = token || "*"
|
40
|
+
@action = action
|
41
|
+
@arguments = encode_arguments(arguments)
|
42
|
+
@uri = [API_URI, @token, @action, @arguments].join("/")
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch
|
46
|
+
request = Net::HTTP::Get.new(@uri)
|
47
|
+
request["User-Agent"] = USER_AGENT
|
48
|
+
@xml = HTTP.request(request).body
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse
|
52
|
+
@doc = REXML::Document.new(@xml)
|
53
|
+
@root = @doc.root
|
54
|
+
@status = @root.elements["status"].text
|
55
|
+
end
|
56
|
+
|
57
|
+
def ok?
|
58
|
+
@status == "ok"
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def encode_arguments(arguments)
|
64
|
+
arguments.map {|arg| Base64.encode64(arg).chomp }.join(",")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class SmeStorage
|
2
|
+
# Inspired by TMail.new_boundary. Generates a unique boundary for the
|
3
|
+
# multipart file uploads in +Uploader+.
|
4
|
+
class MimeBoundary
|
5
|
+
def initialize
|
6
|
+
t = Time.now
|
7
|
+
random_tag = sprintf("%x%x_%x%x", t.to_i, t.tv_usec, Thread.current.object_id, rand(255))
|
8
|
+
@boundary = "mimepart_" + random_tag
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
@boundary
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
|
4
|
+
class SmeStorage
|
5
|
+
# The actual uploading of a file is not done with the regular API. It
|
6
|
+
# emulates a HTML form type multipart upload.
|
7
|
+
class Uploader
|
8
|
+
UPLOADER_SCRIPT = "http://www.smetube.com/cgi-bin/uploader/uploader1.cgi"
|
9
|
+
|
10
|
+
def initialize(upload_code, path_to_file)
|
11
|
+
@upload_code = upload_code
|
12
|
+
@path_to_file = path_to_file
|
13
|
+
@boundary = MimeBoundary.new.to_s
|
14
|
+
@uri = URI.parse("#{UPLOADER_SCRIPT}?#{@upload_code}")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Mimics a HTML form type multipart upload.
|
18
|
+
def upload
|
19
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
20
|
+
request = Net::HTTP::Post.new(@uri.request_uri)
|
21
|
+
request.body = request_body(File.basename(@path_to_file), File.read(@path_to_file))
|
22
|
+
request["Content-Type"] = "multipart/form-data, boundary=#{@boundary}"
|
23
|
+
http.request(request)
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_body(filename, file)
|
27
|
+
post_body = []
|
28
|
+
post_body << "--#{@boundary}\r\n"
|
29
|
+
post_body << "Content-Disposition: form-data; name=\"datafile\"; filename=\"#{filename}\"\r\n"
|
30
|
+
post_body << "Content-Type: text/plain\r\n"
|
31
|
+
post_body << "\r\n"
|
32
|
+
post_body << file
|
33
|
+
post_body << "\r\n--#{@boundary}--\r\n"
|
34
|
+
|
35
|
+
post_body.join
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/sme_storage.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require "sme_storage/api"
|
2
|
+
require "sme_storage/mime_boundary"
|
3
|
+
require "sme_storage/uploader"
|
4
|
+
|
5
|
+
# The wrapper class for the uploading operation.
|
6
|
+
#
|
7
|
+
# storage = SmeStorage.new("username", "password")
|
8
|
+
# storage.authenticate
|
9
|
+
# storage.upload("/path/to/file")
|
10
|
+
class SmeStorage
|
11
|
+
class NotAuthenticated < RuntimeError; end
|
12
|
+
def initialize(username, password)
|
13
|
+
@username, @password = username, password
|
14
|
+
end
|
15
|
+
|
16
|
+
# Performs the authentication. Has to be called before upload.
|
17
|
+
def authenticate
|
18
|
+
@token = Api.get_token(@username, @password)
|
19
|
+
@authenticated = (@token != nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
# The actual upload. Takes a File instance, or a Pathname, or a
|
23
|
+
# String (path to the file, not file contents).
|
24
|
+
def upload(file_thing)
|
25
|
+
raise NotAuthenticated unless authenticated?
|
26
|
+
|
27
|
+
case file_thing.class.name.to_sym # so that we don't have to require pathname
|
28
|
+
when :File
|
29
|
+
perform_upload(file_thing.path)
|
30
|
+
when :Pathname
|
31
|
+
perform_upload(file_thing.to_s)
|
32
|
+
when :String
|
33
|
+
perform_upload(file_thing)
|
34
|
+
else
|
35
|
+
raise ArgumentError, "Needs a File, String or Pathname"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def authenticated?
|
40
|
+
@authenticated == true
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def perform_upload(path)
|
46
|
+
if !File.file?(path)
|
47
|
+
raise ArgumentError, "The file `#{path}' does not exist."
|
48
|
+
end
|
49
|
+
|
50
|
+
# Tell the API we're going to upload
|
51
|
+
init_call = Api.get(@token, "doInitUpload",
|
52
|
+
File.basename(path), # File label
|
53
|
+
"", # Description
|
54
|
+
"", # Tags
|
55
|
+
"", # ID of parent folder
|
56
|
+
File.basename(path), # Filename
|
57
|
+
"xml", # Response type
|
58
|
+
"", # Response data, when response type is javascript
|
59
|
+
"", # Encryption phrase. Blank means unencrypted
|
60
|
+
"", # File ID, for overwrites
|
61
|
+
"n" # Chuck the file (y or n)
|
62
|
+
)
|
63
|
+
|
64
|
+
# Perform the upload
|
65
|
+
upload_code = init_call.root.elements["uploadcode"].text
|
66
|
+
Uploader.new(upload_code, path).upload
|
67
|
+
|
68
|
+
# Tell the API that we have uploaded
|
69
|
+
response = Api.get(@token, "doCompleteUpload", upload_code)
|
70
|
+
|
71
|
+
if response.ok?
|
72
|
+
file_id = response.root.elements["file"].elements["fi_id"].text
|
73
|
+
tiny_url = Api.get(@token, "getFileTinyURL", file_id)
|
74
|
+
tiny_url.root.elements["tinyurl"].text
|
75
|
+
else
|
76
|
+
false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sme_storage
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- August Lilleaas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-29 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: " Uploads files to SMEStorage with theri API.\n"
|
17
|
+
email: august.lilleaas@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- LICENSE
|
27
|
+
- Rakefile
|
28
|
+
- lib/sme_storage/api.rb
|
29
|
+
- lib/sme_storage/mime_boundary.rb
|
30
|
+
- lib/sme_storage/uploader.rb
|
31
|
+
- lib/sme_storage.rb
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://gitorious.org/smestorage
|
34
|
+
licenses: []
|
35
|
+
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.3.5
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: SMEStorage file upload library.
|
60
|
+
test_files: []
|
61
|
+
|