slothbear-redcap 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,70 @@
1
+ = redcap
2
+
3
+ redcap is a library for uploading images
4
+ to Second Life. It costs L$10 per image uploaded.
5
+ You can save some money during testing by using the
6
+ Preview Grid (if available).
7
+
8
+ == installation
9
+
10
+ To install redcap as a gem:
11
+ gem install slothbear-redcap --source http://gems.github.com
12
+
13
+ If you'd rather grab a couple files and give it a try, download
14
+ the following files from http://github.com/slothbear/redcap/tree/master
15
+ bin/redcap
16
+ lib/redcap/uploader.rb
17
+
18
+ Amend this line in redcap to fit your installation and give it a try.
19
+ require "redcap/uploader"
20
+
21
+ == usage
22
+
23
+ Upload a JPG:
24
+ redcap your_image.jpg first_name last_name SL_password
25
+
26
+ Upload a PNG to the preview grid:
27
+ redcap -g preview picture.png first_name last_name SL_password
28
+
29
+ Note you can upload any image format that your installation of ImageMagick
30
+ can read.
31
+
32
+ == release notes
33
+ All images are uploaded into the top level of your Inventory. [to be
34
+ fixed for release 1.0.0]
35
+
36
+ Second Life requires the uploaded image dimensions to be powers of 2. If you'd
37
+ like to re-size your image to its original aspect ratio, make use of
38
+ Uploader::aspect_ratio. (see forthcoming LSL example)
39
+
40
+ installing ImageMagick and RMagick: http://rmagick.rubyforge.org/install-osx.html
41
+
42
+ When you install ImageMagick, make sure you include the jpeg2 variant:
43
+ sudo port install tiff -macosx imagemagick +q8 +gs +wmf +jpeg2
44
+
45
+ To make sure your ImageMagick can produce SL-compatible JPEG-2000 files,
46
+ issue the following command:
47
+ identify -list format | grep JPC
48
+ The JPC line should include "rw-" indicating it can write files, like:
49
+ JPC* JPC rw- JPEG-2000 Code Stream Syntax
50
+
51
+ The /tests were developed for a previous release and do not run at this time.
52
+
53
+
54
+ == copyright
55
+
56
+ redcap -- library for uploading files to Second Life
57
+ Copyright 2009 Paul Morganthall
58
+
59
+ redcap is free software: you can redistribute it and/or modify
60
+ it under the terms of the GNU General Public License as published by
61
+ the Free Software Foundation, either version 3 of the License, or
62
+ any later version.
63
+
64
+ This program is distributed in the hope that it will be useful,
65
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
66
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67
+ GNU General Public License for more details.
68
+
69
+ You should have received a copy of the GNU General Public License
70
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/Rakefile ADDED
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "redcap"
8
+ gem.summary = %Q{Utilities for uploading files to Second Life}
9
+ gem.email = "slothbear@constella.org"
10
+ gem.homepage = "http://adammarker.org/redcap"
11
+ gem.authors = ["Paul Morganthall"]
12
+ # gem.platform = Gem::Platform::Ruby
13
+ gem.has_rdoc = false
14
+ gem.required_ruby_version = '>=1.8'
15
+
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.pattern = 'test/**/*_test.rb'
27
+ test.verbose = true
28
+ end
29
+
30
+ begin
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/*_test.rb'
35
+ test.verbose = true
36
+ end
37
+ rescue LoadError
38
+ task :rcov do
39
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
+ end
41
+ end
42
+
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ if File.exist?('VERSION.yml')
49
+ config = YAML.load(File.read('VERSION.yml'))
50
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
51
+ else
52
+ version = ""
53
+ end
54
+
55
+ rdoc.rdoc_dir = 'rdoc'
56
+ rdoc.title = "redcap #{version}"
57
+ rdoc.rdoc_files.include('README*')
58
+ rdoc.rdoc_files.include('lib/**/*.rb')
59
+ end
60
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 7
3
+ :patch: 1
4
+ :major: 0
data/bin/redcap ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # redcap -- library for uploading files to Second Life
4
+ # Copyright 2009 Paul Morganthall
5
+ #
6
+ # redcap is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'redcap/uploader'
20
+ require 'getoptlong'
21
+
22
+ synopsis = %{# == Synopsis
23
+ #
24
+ # redcap: upload image to Second Life
25
+ # using the specified AV credentials.
26
+ #
27
+ # == Usage
28
+ #
29
+ # redcap [OPTIONS] [first_name last_name password] image_file
30
+ #
31
+ # --help, -h:
32
+ # show help
33
+ #
34
+ # --grid grid, -g grid:
35
+ # upload image to the specified grid, default = main
36
+ # other legal value: preview
37
+ #
38
+ # first_name, last_name, password:
39
+ # Second Life credentials used to login.
40
+ #
41
+ # image_file: path to the image file to be uploaded
42
+ }
43
+
44
+ grid = 'main'
45
+
46
+ opts = GetoptLong.new(
47
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
48
+ [ '--grid', '-g', GetoptLong::REQUIRED_ARGUMENT ]
49
+ )
50
+
51
+ opts.each do |opt, arg|
52
+ case opt
53
+ when '--help'
54
+ puts synopsis
55
+ exit
56
+ when '--grid'
57
+ grid = arg
58
+ end
59
+ end
60
+
61
+ case ARGV.size
62
+ when 4
63
+ first_name, last_name, password, image_file = ARGV
64
+ else
65
+ puts "missing arguments (try --help)"
66
+ exit
67
+ end
68
+
69
+ unless image_file =~ /^http/ or File.exists?(image_file)
70
+ puts "file not found: #{image_file}"
71
+ exit
72
+ end
73
+
74
+ uploader = Redcap::Uploader.new(first_name, last_name, password, image_file, grid)
75
+
76
+
77
+ # on successful upload, prepend the original image aspect ratio.
78
+ if uploader.success
79
+ puts "file successfully uploaded, UUID=#{uploader.new_asset_id}"
80
+ puts "original aspect ratio: #{sprintf("%.4f", uploader.aspect_ratio)}"
81
+ else
82
+ puts "error encountered while uploading:\n#{uploader.msg}"
83
+ end
data/doc/placeholder ADDED
File without changes
@@ -0,0 +1,208 @@
1
+ # redcap -- library for uploading files to Second Life
2
+ # Copyright 2009 Paul Morganthall
3
+ #
4
+ # redcap is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'rubygems'
18
+ require 'builder'
19
+ require 'digest/md5'
20
+ require 'logger'
21
+ require 'net/https'
22
+ require 'rexml/document'
23
+ require 'RMagick' # Requires ImageMagick with JPEG2000 (.JPC) installed
24
+ require 'tempfile'
25
+ require 'xmlrpc/client'
26
+ require 'yaml'
27
+
28
+ # Uploader: support for uploading files to Second Life
29
+ # The standard upload fee (L$10) is charged upon successful upload.
30
+ # This program was inspired and informed by the work of Katherine Berry, author
31
+ # of phpsimcaps, AjaxLife, and other cool stuff:
32
+ # http://blog.katharineberry.co.uk/
33
+
34
+ module Redcap
35
+ GRIDS = {"main" => "https://login.agni.lindenlab.com/cgi-bin/login.cgi",
36
+ "preview" => "https://login.aditi.lindenlab.com/cgi-bin/login.cgi"}
37
+
38
+ class Uploader
39
+ attr_reader :success, :new_asset_id, :msg, :aspect_ratio
40
+
41
+ def initialize(first_name, last_name, password, filename, grid="main")
42
+ @debug = false
43
+ @log = Logger.new('redcap.log')
44
+ @log.level = Logger::DEBUG # DEBUG, WARN,
45
+ @trace = Array.new # global trace stored here for now
46
+ # ? seperate from log, so it can be glommed to log in one piece
47
+ @trace << [first_name, last_name, filename, grid, Time.now].join("/")
48
+
49
+ #1: invoke [begin block has rescue at end]
50
+ begin
51
+ #2: login
52
+ login_data = login(first_name, last_name, password, GRIDS[grid])
53
+ login_data["seed_capability"] or raise "seed_capability not found"
54
+ login_data["inventory-root"] or raise "inventory-root not found"
55
+
56
+ #3: request the upload capability
57
+ cap_request = send_request(login_data["seed_capability"],
58
+ %{<llsd><array><string>NewFileAgentInventory</string></array></llsd>})
59
+ cap_request["NewFileAgentInventory"] or raise "no image upload capability found"
60
+
61
+ #4: request an upload ticket
62
+ ticket_request = send_request(cap_request["NewFileAgentInventory"],
63
+ encode_ticket(login_data["inventory-root"], filename))
64
+ ticket_request["state"] == "upload" or raise "state not upload"
65
+ ticket_request["uploader"] or raise "no uploader found"
66
+
67
+ #5: upload image
68
+ upload_status = send_request(ticket_request["uploader"], make_slimage(filename))
69
+ upload_status["state"] = "complete" or raise "upload failed: #{upload_status["state"]}"
70
+
71
+ #7: retrieve the UUID of the newly uploaded image
72
+ @success = true
73
+ @new_asset_id = upload_status["new_asset"]
74
+ # upon success, log the original request and the final result.
75
+ @log.info(@trace[0].to_yaml + @trace[-1].to_yaml)
76
+
77
+ rescue
78
+ @success = false
79
+ @msg = "#{$!}"
80
+ @log.fatal @trace.to_yaml # on failure, log everything
81
+ if @debug
82
+ @msg += "\ntrace: #{@trace[0]}"
83
+ end
84
+ end
85
+
86
+ end # initialize
87
+
88
+ private
89
+
90
+ def login(first_name, last_name, password, login_url, method="login_to_simulator")
91
+
92
+ login_params = {
93
+ :first => first_name,
94
+ :last => last_name,
95
+ :passwd => "$1$" + Digest::MD5.hexdigest(password),
96
+ :options => %w{inventory-root},
97
+ :start => "last",
98
+ :channel => "redcap.rb", # w/channel, no need for build id.
99
+ :mac => "00:D0:4D:28:A1:F1", # required.
100
+ :read_critical => "true", # skip...
101
+ :agree_to_tos => "true", # potential...
102
+ :skipoptional => "true", # dialogs...
103
+ }
104
+
105
+ login_url or raise "unrecognized grid name"
106
+ @trace << [login_url, method] << login_params
107
+ @log.debug "#{login_url} / #{method} / #{login_params}"
108
+ server = XMLRPC::Client.new2(login_url)
109
+ server.http_header_extra = {"Content-Type" => "text/xml"}
110
+ server.timeout = 120
111
+ result = server.call(method, login_params)
112
+ @trace << result
113
+ @log.debug "raw login response: #{result.to_yaml}"
114
+ # unearth some parameters
115
+ if result.has_key?("inventory-root") then
116
+ result["inventory-root"] = result["inventory-root"][0]["folder_id"]
117
+ end
118
+
119
+ # If the login server says "indeterminate", follow the path given.
120
+ if "indeterminate" == result["login"] then
121
+ @log.info "indeterminate login:\n#{result.to_yaml}"
122
+ next_url = result["next_url"]
123
+ next_method = result["next_method"]
124
+ message = result["message"]
125
+ @log.warn "Login redirected:\n#{next_url}, method: #{next_method}, message: #{message}"
126
+ result = login(first_name, last_name, password, next_url, next_method)
127
+ elsif "false" == result["login"] or "true" != result["login"] then
128
+ raise "error during login: #{result["message"]}"
129
+ end
130
+
131
+ result
132
+ end # login
133
+
134
+ # Examine URL and return the base url (server), port number, and parameter path
135
+ def parse_capability(cap)
136
+ match = %r{https://(.+):(\d+)(.+)}.match(cap)
137
+ match or raise "capability format not understood: #{cap}"
138
+ match.captures
139
+ end
140
+
141
+ # Convert LLSD ( Linden Lab Structured Data) into a simple hash.
142
+ def decode_llsd(body)
143
+ doc = REXML::Document.new(body)
144
+ pairs = Hash[*doc.elements.to_a("/llsd/map/*")]
145
+ result = Hash.new
146
+ pairs.each { |key,value| result[key.text.strip] = value.text.strip }
147
+ result
148
+ end
149
+
150
+ def send_request(capability, data)
151
+ @log.debug "send_request / #{capability} #{data if data[0,1] == '<'}"
152
+
153
+ server, port, path = parse_capability(capability)
154
+ site = Net::HTTP.new(server, port)
155
+ # site.set_debug_output($stderr)
156
+ site.use_ssl = true
157
+ site.verify_mode = OpenSSL::SSL::VERIFY_NONE
158
+
159
+ response = site.request_post(path, data, {"Content-Type" => "text/xml"})
160
+ result = decode_llsd(response.body)
161
+ @log.debug "response\n#{result.to_yaml}"
162
+ @trace << result
163
+ result
164
+ end
165
+
166
+ def encode_ticket(folder, filename)
167
+ request = {
168
+ "asset_type" => "texture",
169
+ "description" => "uploaded by http://adammarker.org/redcap/",
170
+ "folder_id" => folder,
171
+ "inventory_type" => "texture",
172
+ "name" => File.basename(filename)
173
+ }
174
+
175
+ xml = Builder::XmlMarkup.new(:indent => 2)
176
+ xml.llsd {
177
+ xml.map {
178
+ request.each do |key, value|
179
+ xml.key(key)
180
+ xml.string(value)
181
+ end
182
+ }
183
+ }
184
+ xml.target!
185
+ end
186
+
187
+ # adapted from function by Simon Kröger posted in comp.lang.ruby
188
+ # maximum dimension of an SL image is 1024.
189
+ def nextpow2(n)
190
+ throw 'eeek' if n < 0 # Simon's. perhaps there is another way?
191
+ return 1 if n < 2
192
+ [1 << (n-1).to_s(2).size, 1024].min
193
+ end
194
+
195
+ # Convert image to SL standards:
196
+ # 1. JPEG-2000 Code Stream Syntax (JPC)
197
+ # 2. width and height must be a power of 2
198
+ def make_slimage(filename)
199
+ image = Magick::Image.read(filename).first
200
+ @aspect_ratio = image.columns.to_f / image.rows.to_f
201
+ new_image = image.resize(nextpow2(image.columns), nextpow2(image.rows))
202
+ slimage = Tempfile.new('redcap').path
203
+ new_image.write("jpc:#{slimage}") or raise "Unable to write JPC image."
204
+ open(slimage, 'rb') { |f| f.read }
205
+ end
206
+
207
+ end # class
208
+ end # module
data/redcap.gemspec ADDED
@@ -0,0 +1,61 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{redcap}
5
+ s.version = "0.7.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Paul Morganthall"]
9
+ s.date = %q{2009-07-24}
10
+ s.default_executable = %q{redcap}
11
+ s.email = %q{slothbear@constella.org}
12
+ s.executables = ["redcap"]
13
+ s.extra_rdoc_files = [
14
+ "LICENSE",
15
+ "README.rdoc"
16
+ ]
17
+ s.files = [
18
+ ".document",
19
+ ".gitignore",
20
+ "LICENSE",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION.yml",
24
+ "bin/redcap",
25
+ "doc/placeholder",
26
+ "lib/redcap/uploader.rb",
27
+ "redcap.gemspec",
28
+ "test/redcap_image.jpc",
29
+ "test/redcap_test.rb",
30
+ "test/synapse.jpg",
31
+ "test/test_helper.rb",
32
+ "test/test_llsd.rb",
33
+ "test/test_nextpowerof2.rb",
34
+ "test/test_parsecap.rb",
35
+ "test/test_ticket.rb"
36
+ ]
37
+ s.homepage = %q{http://adammarker.org/redcap}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8")
41
+ s.rubygems_version = %q{1.3.1}
42
+ s.summary = %q{Utilities for uploading files to Second Life}
43
+ s.test_files = [
44
+ "test/redcap_test.rb",
45
+ "test/test_helper.rb",
46
+ "test/test_llsd.rb",
47
+ "test/test_nextpowerof2.rb",
48
+ "test/test_parsecap.rb",
49
+ "test/test_ticket.rb"
50
+ ]
51
+
52
+ if s.respond_to? :specification_version then
53
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
+ s.specification_version = 2
55
+
56
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
+ else
58
+ end
59
+ else
60
+ end
61
+ end
Binary file
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class RedcapTest < Test::Unit::TestCase
4
+ def test_something_for_real
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
data/test/synapse.jpg ADDED
Binary file
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'redcap'
7
+
8
+ class Test::Unit::TestCase
9
+ end
data/test/test_llsd.rb ADDED
@@ -0,0 +1,62 @@
1
+ # LLSD (The Linden Lab Structured Data system) is the XML protocol
2
+ # used for redcap's communication with Second Life. All current
3
+ # structures are simple maps (hashes) with pairs of key/values.
4
+
5
+ # For more information regarding The LLSD flexible data system
6
+ # see http://wiki.secondlife.com/wiki/LLSD
7
+
8
+ require 'test/unit'
9
+ require 'redcap'
10
+
11
+ $llsd = %{
12
+ <llsd>
13
+ <map>
14
+ <key>name</key>
15
+ <string>/Users/orion/Desktop/textures/rose bases are red.jpeg</string>
16
+ <key>folder_id</key>
17
+ <string>98359cef-1609-4317-be54-f044cc784b0a</string>
18
+ <key>description</key>
19
+ <string>uploaded by redcap</string>
20
+ <key>inventory_type</key>
21
+ <string>texture</string>
22
+ <key>asset_type</key>
23
+ <string>texture</string>
24
+ </map>
25
+ </llsd>
26
+ }
27
+
28
+ $llsd_odd = %{
29
+ <llsd>
30
+ <map>
31
+ <key>name</key>
32
+ </map>
33
+ </llsd>
34
+ }
35
+
36
+ class TestLLSD < Test::Unit::TestCase
37
+
38
+ def testTypicalDecode
39
+ result = decode_llsd($llsd)
40
+ assert_equal("/Users/orion/Desktop/textures/rose bases are red.jpeg", result["name"])
41
+ assert_equal("98359cef-1609-4317-be54-f044cc784b0a", result["folder_id"])
42
+ assert_equal("uploaded by redcap", result["description"])
43
+ assert_equal("texture", result["inventory_type"])
44
+ assert_equal("texture", result["asset_type"])
45
+ end
46
+
47
+ def testDecodeBadXML
48
+ assert_raise(REXML::ParseException) { decode_llsd("<badxml>") }
49
+ end
50
+
51
+ # The LLSD should contain an even number of elements (key, value, key, value)
52
+ # Well formed LLSD shouldn't have an odd number, but if it does...
53
+ def testDecodeOddPair
54
+ assert_raise(ArgumentError) { decode_llsd($llsd_odd) }
55
+ end
56
+
57
+ def testDecodeRandomText
58
+ result = decode_llsd("gibberish")
59
+ assert_equal({}, result)
60
+ end
61
+
62
+ end
@@ -0,0 +1,39 @@
1
+ # nextpow2 is adapted from function by Simon Kröger posted in comp.lang.ruby
2
+ # original post: http://www.ruby-forum.com/topic/76261
3
+
4
+ # The adaptation made for Second Life constrain the maximum value returned
5
+ # to 1024, the maximum dimention of an SL texture.
6
+
7
+ require 'test/unit'
8
+ require '../redcap'
9
+
10
+ class TestNextPowerOf2 < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @check_array = [[1, 1], [2,2]]
14
+ (2..9).each do | i |
15
+ @check_array << [ 2**i - 1, 2**i] << [2**i, 2**i] << [2**i + 1, 2**(i+1)]
16
+ end
17
+ end
18
+
19
+ # test copied from Rick Denatale's post to the thread mentioned above.
20
+ def test_normal
21
+ @check_array.each do | input, output |
22
+ assert_equal(output, nextpow2(input))
23
+ end
24
+ end
25
+
26
+ def test_over
27
+ assert_equal(1024, nextpow2(1023))
28
+ assert_equal(1024, nextpow2(1025))
29
+ assert_equal(1024, nextpow2(10240))
30
+ end
31
+
32
+ def test_under
33
+ assert_equal(2, nextpow2(2))
34
+ assert_equal(1, nextpow2(1))
35
+ assert_equal(1, nextpow2(0))
36
+ assert_raise(NameError) { nextpow2(-1) }
37
+ end
38
+
39
+ end
@@ -0,0 +1,31 @@
1
+ # Second Life hands us complete URLs, but Net::HTTP requires
2
+ # separate values for protocol, server, port, and path.
3
+
4
+ # HTTPS protocol is always used, so that part of the URL is ignored.
5
+
6
+
7
+ require 'test/unit'
8
+ # can I use require relative??
9
+ require '../lib/redcap/uploader'
10
+
11
+ class TestParseCap < Test::Unit::TestCase
12
+
13
+ def test_typical
14
+ result = parse_capability("https://sim4.aditi.lindenlab.com:12043/cap/f692b7fc-3074-a277-c08c-74363e5248cb")
15
+ assert_equal(3,result.size)
16
+ server, port, path = result
17
+ assert_equal("sim4.aditi.lindenlab.com", server)
18
+ assert_equal("12043", port)
19
+ assert_equal("/cap/f692b7fc-3074-a277-c08c-74363e5248cb", path)
20
+ end
21
+
22
+ def test_abnormal
23
+ assert_raise(RuntimeError) { parse_capability("") }
24
+ assert_raise(RuntimeError) { parse_capability("ftp://www.secondlife.com:12045/cap/xxx") }
25
+ assert_raise(RuntimeError) { parse_capability("https://test.server.com:/app/path") }
26
+ end
27
+
28
+
29
+ end
30
+
31
+ # squeak
@@ -0,0 +1,26 @@
1
+ # A more general routine to encode to LLSD is probably in the future,
2
+ # but the structure is so simple a custom routine is sufficient for now.
3
+
4
+ # encode_ticket wraps a hash around the asset upload parameters, then uses
5
+ # Builder to create the required LLSD structure.
6
+
7
+ # The required structure is a series of <key> <string> elements, wrapped
8
+ # in the top level <llsd><map>. For example:
9
+ # <llsd><map>
10
+ # <key>asset_type</key>
11
+ # <string>texture</string>
12
+ # </map></llsd>
13
+
14
+ # TODO: this test is lame and fragile; perhaps a mock object would help?
15
+
16
+ require "test/unit"
17
+ require "../redcap.rb"
18
+
19
+ $answer = %{<llsd>\n <map>\n <key>name</key>\n <string>file.jpg</string>\n <key>folder_id</key>\n <string>000-ffff-f0lde4</string>\n <key>description</key>\n <string>uploaded by redcap</string>\n <key>inventory_type</key>\n <string>texture</string>\n <key>asset_type</key>\n <string>texture</string>\n </map>\n</llsd>\n}
20
+
21
+ class TestTicket < Test::Unit::TestCase
22
+ def test_typical
23
+ result = encode_ticket("000-ffff-f0lde4", "file.jpg")
24
+ assert_equal($answer, result)
25
+ end
26
+ end