slothbear-redcap 0.7.1

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.
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