sras 2.1.1.pre.10
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/.gitignore +3 -0
- data/.travis.yml +10 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +64 -0
- data/LICENSE +23 -0
- data/README.rst +59 -0
- data/Rakefile +19 -0
- data/bin/sras +117 -0
- data/config/config.yml.example +43 -0
- data/config.ru +3 -0
- data/lib/sras/helpers/asset.rb +107 -0
- data/lib/sras/helpers/init.rb +4 -0
- data/lib/sras/helpers/setup.rb +12 -0
- data/lib/sras/models/asset.rb +35 -0
- data/lib/sras/models/init.rb +20 -0
- data/lib/sras/views/create.erb +2 -0
- data/lib/sras/views/data.erb +1 -0
- data/lib/sras/views/index.erb +1 -0
- data/lib/sras/views/metadata.erb +13 -0
- data/lib/sras/views/show.erb +13 -0
- data/lib/sras.rb +97 -0
- data/sras.gemspec +23 -0
- data/test/test.asset +14 -0
- metadata +158 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sras (2.1.1.pre.9)
|
5
|
+
dm-migrations (= 1.1.0)
|
6
|
+
dm-mysql-adapter (= 1.1.0)
|
7
|
+
dm-timestamps (= 1.1.0)
|
8
|
+
dm-types (= 1.1.0)
|
9
|
+
hpricot (= 0.8.4)
|
10
|
+
rake (= 0.9.2.2)
|
11
|
+
sinatra (= 1.2.6)
|
12
|
+
thin (= 1.2.11)
|
13
|
+
|
14
|
+
GEM
|
15
|
+
remote: http://rubygems.org/
|
16
|
+
specs:
|
17
|
+
addressable (2.2.6)
|
18
|
+
bcrypt-ruby (2.1.4)
|
19
|
+
daemons (1.1.4)
|
20
|
+
data_objects (0.10.6)
|
21
|
+
addressable (~> 2.1)
|
22
|
+
dm-core (1.1.0)
|
23
|
+
addressable (~> 2.2.4)
|
24
|
+
dm-do-adapter (1.1.0)
|
25
|
+
data_objects (~> 0.10.2)
|
26
|
+
dm-core (~> 1.1.0)
|
27
|
+
dm-migrations (1.1.0)
|
28
|
+
dm-core (~> 1.1.0)
|
29
|
+
dm-mysql-adapter (1.1.0)
|
30
|
+
dm-do-adapter (~> 1.1.0)
|
31
|
+
do_mysql (~> 0.10.2)
|
32
|
+
dm-timestamps (1.1.0)
|
33
|
+
dm-core (~> 1.1.0)
|
34
|
+
dm-types (1.1.0)
|
35
|
+
bcrypt-ruby (~> 2.1.4)
|
36
|
+
dm-core (~> 1.1.0)
|
37
|
+
fastercsv (~> 1.5.4)
|
38
|
+
json (~> 1.4.6)
|
39
|
+
stringex (~> 1.2.0)
|
40
|
+
uuidtools (~> 2.1.2)
|
41
|
+
do_mysql (0.10.6)
|
42
|
+
data_objects (= 0.10.6)
|
43
|
+
eventmachine (0.12.10)
|
44
|
+
fastercsv (1.5.4)
|
45
|
+
hpricot (0.8.4)
|
46
|
+
json (1.4.6)
|
47
|
+
rack (1.3.3)
|
48
|
+
rake (0.9.2.2)
|
49
|
+
sinatra (1.2.6)
|
50
|
+
rack (~> 1.1)
|
51
|
+
tilt (>= 1.2.2, < 2.0)
|
52
|
+
stringex (1.2.2)
|
53
|
+
thin (1.2.11)
|
54
|
+
daemons (>= 1.0.9)
|
55
|
+
eventmachine (>= 0.12.6)
|
56
|
+
rack (>= 1.0.0)
|
57
|
+
tilt (1.3.3)
|
58
|
+
uuidtools (2.1.2)
|
59
|
+
|
60
|
+
PLATFORMS
|
61
|
+
ruby
|
62
|
+
|
63
|
+
DEPENDENCIES
|
64
|
+
sras!
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2010-2011 Dave Coyle <http://coyled.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/README.rst
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
SRAS -- An Asset Server for OpenSimulator
|
2
|
+
=========================================
|
3
|
+
|
4
|
+
Features
|
5
|
+
--------
|
6
|
+
|
7
|
+
* Asset de-duplication
|
8
|
+
* Compressed asset storage on disk
|
9
|
+
* Ability to disable serving of specific assets without deleting
|
10
|
+
|
11
|
+
|
12
|
+
Install
|
13
|
+
-------
|
14
|
+
|
15
|
+
The packages of Ruby shipping with Ubuntu don't include built-in zlib
|
16
|
+
support. I prefer using RVM [ http://rvm.beginrescueend.com/ ]
|
17
|
+
anyway.
|
18
|
+
|
19
|
+
Built & testing with Ruby v1.9.2. Tested with Thin, but should also
|
20
|
+
work with Passenger.
|
21
|
+
|
22
|
+
Install via: ::
|
23
|
+
|
24
|
+
$ gem install sras
|
25
|
+
|
26
|
+
then copy the following text into ``/etc/sras/sras.conf`` or
|
27
|
+
``~/.srasrc`` and edit as appropriate: ::
|
28
|
+
|
29
|
+
sras:
|
30
|
+
production:
|
31
|
+
default_asset_dir: /srv/sras
|
32
|
+
port: 8003
|
33
|
+
log_file: /var/log/sras.log
|
34
|
+
pid_file: /tmp/sras.pid
|
35
|
+
|
36
|
+
mysql:
|
37
|
+
production:
|
38
|
+
adapter: mysql
|
39
|
+
host: localhost
|
40
|
+
username: sras
|
41
|
+
password: sras
|
42
|
+
database: sras
|
43
|
+
|
44
|
+
|
45
|
+
Running
|
46
|
+
-------
|
47
|
+
|
48
|
+
Then just: ::
|
49
|
+
|
50
|
+
$ sras start
|
51
|
+
|
52
|
+
to start a single instance. In a production environment you would
|
53
|
+
likely want to run several instances behind a reverse proxy like
|
54
|
+
Nginx.
|
55
|
+
|
56
|
+
To see additional options: ::
|
57
|
+
|
58
|
+
$ sras --help
|
59
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'yaml'
|
3
|
+
require 'dm-core'
|
4
|
+
require 'dm-migrations'
|
5
|
+
|
6
|
+
#Rake::TestTask.new(:test) do |t|
|
7
|
+
# t.test_files = FileList['test/test_*.rb']
|
8
|
+
# t.verbose = true
|
9
|
+
#end
|
10
|
+
|
11
|
+
require ::File.dirname(__FILE__) + '/lib/sras/helpers/init'
|
12
|
+
|
13
|
+
namespace 'db' do
|
14
|
+
require ::File.dirname(__FILE__) + '/lib/sras/models/init'
|
15
|
+
|
16
|
+
task :create do
|
17
|
+
DataMapper.auto_upgrade!
|
18
|
+
end
|
19
|
+
end
|
data/bin/sras
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'yaml'
|
5
|
+
require 'thin'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
ROOT = ::File.dirname(::File.realdirpath(__FILE__))
|
9
|
+
|
10
|
+
# defaults...
|
11
|
+
options[:environment] = 'production'
|
12
|
+
options[:config_file] = '/etc/sras/sras.conf'
|
13
|
+
|
14
|
+
# look for more appropriate SRAS config file...
|
15
|
+
if File.exists?("#{ROOT}/config/config.yml")
|
16
|
+
options[:config_file] = "#{ROOT}/config/config.yml"
|
17
|
+
elsif File.exists?(File.expand_path('~/.srasrc'))
|
18
|
+
options[:config_file] = File.expand_path('~/.srasrc')
|
19
|
+
end
|
20
|
+
|
21
|
+
OptionParser.new do |opts|
|
22
|
+
opts.banner = 'Usage: sras [options] <start|stop>'
|
23
|
+
|
24
|
+
opts.on('-c', '--config <file>', 'SRAS config file') do |c|
|
25
|
+
options[:config_file] = c
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on('-e', '--environment <production|development|test>',
|
29
|
+
'Environment in which to run') do |e|
|
30
|
+
options[:environment] = e
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on('-h', '--host <hostname|ip_addy>', 'Address to which to bind') do |h|
|
34
|
+
options[:host] = h
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on('-p', '--port <N>', Integer, 'TCP port to which to bind') do |p|
|
38
|
+
options[:port] = p
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on('-l', '--log <file>', 'Log file') do |l|
|
42
|
+
options[:log_file] = l
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on('-P', '--pid <file>', 'PID file') do |p|
|
46
|
+
options[:pid_file] = p
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
50
|
+
puts opts
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
if ARGV.last
|
55
|
+
command = ARGV.last.chomp
|
56
|
+
if command == 'start' || command == 'stop'
|
57
|
+
options[:command] = command
|
58
|
+
else
|
59
|
+
puts opts
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
else
|
63
|
+
puts opts
|
64
|
+
exit
|
65
|
+
end
|
66
|
+
end.parse!
|
67
|
+
|
68
|
+
# load SRAS config file...
|
69
|
+
if File.exists?(options[:config_file])
|
70
|
+
@config = YAML.load_file(options[:config_file])
|
71
|
+
else
|
72
|
+
warn "Couldn't find SRAS config file. Exiting."
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
|
76
|
+
# base thin options...
|
77
|
+
#-d -R #{::File.dirname(__FILE__)}/../config.ru"
|
78
|
+
#thin_opts << " -e #{options[:environment]}"
|
79
|
+
|
80
|
+
if ! options[:host]
|
81
|
+
if @config['sras'][options[:environment]]['host']
|
82
|
+
options[:host] = @config['sras'][options[:environment]]['host']
|
83
|
+
else
|
84
|
+
options[:host] = '0.0.0.0'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
if ! options[:port]
|
89
|
+
if @config['sras'][options[:environment]]['port']
|
90
|
+
options[:port] = @config['sras'][options[:environment]]['port']
|
91
|
+
else
|
92
|
+
options[:port] = '8003'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
if ! options[:log_file]
|
97
|
+
if @config['sras'][options[:environment]]['log_file']
|
98
|
+
options[:log_file] = @config['sras'][options[:environment]]['log_file']
|
99
|
+
else
|
100
|
+
options[:log_file] = "log/sras_#{options[:environment]}.log"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if ! options[:pid_file]
|
105
|
+
if @config['sras'][options[:environment]]['pid_file']
|
106
|
+
options[:pid_file] = @config['sras'][options[:environment]]['pid_file']
|
107
|
+
else
|
108
|
+
options[:pid_file] = "/tmp/sras_#{options[:environment]}.pid"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
require "#{ROOT}/../lib/sras.rb"
|
113
|
+
server = Thin::Server.new(options[:host], options[:port], SRAS.new)
|
114
|
+
server.log_file = options[:log_file]
|
115
|
+
server.pid_file = options[:pid_file]
|
116
|
+
server.tag = 'sras'
|
117
|
+
server.start
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# copy or rename this config.yml.example file to config.yml and
|
3
|
+
# edit below...
|
4
|
+
#
|
5
|
+
|
6
|
+
sras:
|
7
|
+
production:
|
8
|
+
default_asset_dir: /srv/sras
|
9
|
+
|
10
|
+
#test:
|
11
|
+
# default_asset_dir: /var/tmp/sras
|
12
|
+
|
13
|
+
#development:
|
14
|
+
# default_asset_dir: /var/tmp/sras
|
15
|
+
|
16
|
+
|
17
|
+
mysql:
|
18
|
+
# the below 'production' settings are the only ones you need to
|
19
|
+
# update unless you plan on making changes to SRAS code...
|
20
|
+
production:
|
21
|
+
adapter: mysql
|
22
|
+
host: localhost
|
23
|
+
username: sras
|
24
|
+
password: sras
|
25
|
+
database: sras
|
26
|
+
|
27
|
+
# the below 'test' settings will be used only if you run tests.
|
28
|
+
# you can ignore, delete, or change these...
|
29
|
+
#test:
|
30
|
+
# adapter: mysql
|
31
|
+
# host: localhost
|
32
|
+
# username: sras_test
|
33
|
+
# password: sras_test
|
34
|
+
# database: sras_test
|
35
|
+
|
36
|
+
# the 'development' settings below are used only by the Travis CI
|
37
|
+
# service which is triggered when SRAS code changes are committed
|
38
|
+
# to GitHub. you can ignore, delete, or change these...
|
39
|
+
#development:
|
40
|
+
# adapter: mysql2
|
41
|
+
# database: sras_test
|
42
|
+
# username:
|
43
|
+
# encoding: ascii
|
data/config.ru
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module AssetHelper
|
5
|
+
|
6
|
+
def get_asset_data(asset_id)
|
7
|
+
@asset = Asset.get(asset_id)
|
8
|
+
|
9
|
+
if @asset.enabled == false
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
@asset_file = @asset.base_dir + '/' + @asset.sha256[0..2] + '/' + @asset.sha256[3..5] + '/' + @asset.sha256
|
14
|
+
|
15
|
+
if File.exists?(@asset_file + '.gz')
|
16
|
+
Zlib::GzipReader.open(@asset_file + '.gz') do |file|
|
17
|
+
@asset_data = file.read
|
18
|
+
end
|
19
|
+
elsif File.exists?(@asset_file)
|
20
|
+
File.open(@asset_file) do |file|
|
21
|
+
@asset_data = file.read
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
return @asset_data
|
26
|
+
end
|
27
|
+
|
28
|
+
def write_asset_data()
|
29
|
+
@asset_file_dir = @asset.base_dir + '/' + @asset.sha256[0..2] + '/' + @asset.sha256[3..5]
|
30
|
+
@asset_file = @asset_file_dir + '/' + @asset.sha256
|
31
|
+
|
32
|
+
# see if asset file with this hash already exists. if it
|
33
|
+
# does, then we don't need to overwrite it with identical
|
34
|
+
# data...
|
35
|
+
if File.exists?(@asset_file + '.gz') || File.exists?(@asset_file)
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
# mkdirs if necessary...
|
40
|
+
FileUtils.mkpath @asset_file_dir
|
41
|
+
|
42
|
+
# write the data to a file, gzip'd...
|
43
|
+
Zlib::GzipWriter.open(@asset_file + '.gz') do |file|
|
44
|
+
file.write @asset_data
|
45
|
+
file.close
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Flags added to opensim in 9b22393. Current values (from
|
50
|
+
# OpenSim/Framework/AssetBase.cs):
|
51
|
+
#
|
52
|
+
# [Flags]
|
53
|
+
# public enum AssetFlags : int
|
54
|
+
# {
|
55
|
+
# Normal = 0,
|
56
|
+
# Maptile = 1,
|
57
|
+
# Rewritable = 2,
|
58
|
+
# Collectable = 4
|
59
|
+
# }
|
60
|
+
@flags = {
|
61
|
+
'Normal' => 0,
|
62
|
+
'Maptile' => 1,
|
63
|
+
'Rewritable' => 2,
|
64
|
+
'Collectable' => 4
|
65
|
+
}
|
66
|
+
|
67
|
+
# usage:
|
68
|
+
# asset_type = get_asset_type('image/tga')
|
69
|
+
# asset_type = get_asset_type(12)
|
70
|
+
def get_asset_type(request)
|
71
|
+
|
72
|
+
# default 'application/octet-stream'
|
73
|
+
asset_type = {
|
74
|
+
'image/jp2' => 0,
|
75
|
+
'application/ogg' => 1,
|
76
|
+
'application/x-metaverse-callingcard' => 2,
|
77
|
+
'application/x-metaverse-landmark' => 3,
|
78
|
+
'application/x-metaverse-clothing' => 5,
|
79
|
+
'application/x-metaverse-primitive' => 6,
|
80
|
+
'application/x-metaverse-notecard' => 7,
|
81
|
+
'application/x-metaverse-folder' => 8,
|
82
|
+
'application/x-metaverse-lsl' => 10,
|
83
|
+
'application/x-metaverse-lso' => 11,
|
84
|
+
'image/tga' => 12,
|
85
|
+
'application/x-metaverse-bodypart' => 13,
|
86
|
+
'audio/x-wav' => 17,
|
87
|
+
'image/jpeg' => 19,
|
88
|
+
'application/x-metaverse-animation' => 20,
|
89
|
+
'application/x-metaverse-gesture' => 21,
|
90
|
+
'application/x-metaverse-simstate' => 22
|
91
|
+
}
|
92
|
+
|
93
|
+
if asset_type[request]
|
94
|
+
response = asset_type[request]
|
95
|
+
elsif asset_type.invert[request]
|
96
|
+
response = asset_type.invert[request]
|
97
|
+
end
|
98
|
+
|
99
|
+
return response
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
helpers AssetHelper
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
RACK_ENV = ENV['RACK_ENV'] || 'production'
|
2
|
+
@dbms = ENV['DBMS'] || 'mysql'
|
3
|
+
|
4
|
+
if File.exists?("#{ROOT}/config/config.yml")
|
5
|
+
config_file = "#{ROOT}/config/config.yml"
|
6
|
+
elsif File.exists?(File.expand_path('~/.srasrc'))
|
7
|
+
config_file = File.expand_path('~/.srasrc')
|
8
|
+
else
|
9
|
+
config_file = '/etc/sras/sras.conf'
|
10
|
+
end
|
11
|
+
|
12
|
+
@config = YAML.load_file(config_file)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#CREATE TABLE `assets` (
|
2
|
+
# `id` char(36) NOT NULL,
|
3
|
+
# `asset_type` tinyint(4) NOT NULL,
|
4
|
+
# `sha256` char(64) NOT NULL,
|
5
|
+
# `name` varchar(64) DEFAULT NULL,
|
6
|
+
# `description` varchar(64) DEFAULT NULL,
|
7
|
+
# `local` tinyint(1) DEFAULT NULL,
|
8
|
+
# `temporary` tinyint(1) DEFAULT NULL,
|
9
|
+
# `base_dir` varchar(64) NOT NULL,
|
10
|
+
# `created_at` int(11) DEFAULT NULL,
|
11
|
+
# `updated_at` int(11) DEFAULT NULL,
|
12
|
+
# `enabled` tinyint(1) NOT NULL DEFAULT '1',
|
13
|
+
# PRIMARY KEY (`id`),
|
14
|
+
# KEY `assets_id_sha256` (`id`,`sha256`),
|
15
|
+
# KEY `assets_sha256` (`sha256`)
|
16
|
+
#) ENGINE=MyISAM DEFAULT CHARSET=ascii;
|
17
|
+
|
18
|
+
class Asset
|
19
|
+
include DataMapper::Resource
|
20
|
+
property :id, String, :length => 36, :required => true,
|
21
|
+
:key => true, :index => :id_sha256
|
22
|
+
property :asset_type, Integer, :required => true,
|
23
|
+
:min => 0, :max => 99
|
24
|
+
property :sha256, String, :length => 64, :required => true,
|
25
|
+
:index => [ :sha256, :id_sha256 ]
|
26
|
+
property :name, String, :length => 64
|
27
|
+
property :description, String, :length => 64
|
28
|
+
property :local, Boolean
|
29
|
+
property :temporary, Boolean
|
30
|
+
property :base_dir, String, :length => 64, :required => true,
|
31
|
+
:default => $default_asset_dir
|
32
|
+
property :created_at, EpochTime
|
33
|
+
property :updated_at, EpochTime
|
34
|
+
property :enabled, Boolean, :required => true, :default => true
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'dm-core'
|
3
|
+
require 'dm-types'
|
4
|
+
require 'dm-timestamps'
|
5
|
+
|
6
|
+
configure :development do
|
7
|
+
DataMapper::Logger.new(STDOUT, :debug)
|
8
|
+
end
|
9
|
+
|
10
|
+
$default_asset_dir = @config['sras'][RACK_ENV]['default_asset_dir']
|
11
|
+
|
12
|
+
DataMapper.setup(:default, {
|
13
|
+
:adapter => @config[@dbms][RACK_ENV]['adapter'],
|
14
|
+
:host => @config[@dbms][RACK_ENV]['host'],
|
15
|
+
:username => @config[@dbms][RACK_ENV]['username'],
|
16
|
+
:password => @config[@dbms][RACK_ENV]['password'],
|
17
|
+
:database => @config[@dbms][RACK_ENV]['database']
|
18
|
+
})
|
19
|
+
|
20
|
+
require ::File.dirname(__FILE__) + '/asset'
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @asset_data %>
|
@@ -0,0 +1 @@
|
|
1
|
+
SRAS
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<AssetMetadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
3
|
+
<FullID>
|
4
|
+
<Guid><%= @asset.id %></Guid>
|
5
|
+
</FullID>
|
6
|
+
<ID><%= @asset.id %></ID>
|
7
|
+
<Name><%= @asset.name %></Name>
|
8
|
+
<Description><%= @asset.description %></Description>
|
9
|
+
<CreationDate><%= @asset.created_at.to_time.iso8601 %></CreationDate>
|
10
|
+
<Type><%= @asset.asset_type %></Type>
|
11
|
+
<Local><%= @asset.local %></Local>
|
12
|
+
<Temporary><%= @asset.temporary %></Temporary>
|
13
|
+
</AssetMetadata>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<AssetBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
3
|
+
<Data><%= Base64.encode64(@asset_data) %></Data>
|
4
|
+
<FullID>
|
5
|
+
<Guid><%= @asset.id %></Guid>
|
6
|
+
</FullID>
|
7
|
+
<ID><%= @asset.id %></ID>
|
8
|
+
<Name><%= @asset.name %></Name>
|
9
|
+
<Description><%= @asset.description %></Description>
|
10
|
+
<Type><%= @asset.asset_type %></Type>
|
11
|
+
<Local><%= @asset.local %></Local>
|
12
|
+
<Temporary><%= @asset.temporary %></Temporary>
|
13
|
+
</AssetBase>
|
data/lib/sras.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#require 'bundler'
|
2
|
+
#Bundler.setup
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
|
6
|
+
require 'sinatra'
|
7
|
+
require 'erb'
|
8
|
+
require 'base64'
|
9
|
+
require 'digest/sha2'
|
10
|
+
require 'hpricot'
|
11
|
+
|
12
|
+
class SRAS < Sinatra::Application
|
13
|
+
set :views, Proc.new { File.join(root, "sras/views") }
|
14
|
+
|
15
|
+
get '/' do
|
16
|
+
erb :index
|
17
|
+
end
|
18
|
+
|
19
|
+
get '/assets/?' do
|
20
|
+
erb :index
|
21
|
+
end
|
22
|
+
|
23
|
+
post '/assets/?' do
|
24
|
+
content_type 'application/xml'
|
25
|
+
|
26
|
+
doc = Hpricot.XML(request.body.read)
|
27
|
+
|
28
|
+
# 404 if the ID already exists. need to revisit this.
|
29
|
+
if Asset.get((doc/:ID).text)
|
30
|
+
not_found
|
31
|
+
end
|
32
|
+
|
33
|
+
@asset_data = Base64.decode64((doc/:Data).text.chomp)
|
34
|
+
@asset_hash = Digest::SHA256.digest(@asset_data).unpack('H*')[0].upcase
|
35
|
+
@asset = Asset.new(
|
36
|
+
:id => (doc/:ID).text,
|
37
|
+
:asset_type => (doc/:Type).text,
|
38
|
+
:sha256 => @asset_hash,
|
39
|
+
:name => (doc/:Name).text,
|
40
|
+
:description => (doc/:Description).text,
|
41
|
+
:local => (doc/:Local).text,
|
42
|
+
:temporary => (doc/:Temporary).text
|
43
|
+
)
|
44
|
+
write_asset_data
|
45
|
+
@asset.save
|
46
|
+
erb :create
|
47
|
+
end
|
48
|
+
|
49
|
+
get '/assets/:asset_id' do
|
50
|
+
if @asset = Asset.get(params[:asset_id])
|
51
|
+
if @asset_data = get_asset_data(params[:asset_id])
|
52
|
+
content_type get_asset_type(@asset.asset_type)
|
53
|
+
erb :show
|
54
|
+
else
|
55
|
+
not_found
|
56
|
+
end
|
57
|
+
else
|
58
|
+
not_found
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
get '/assets/:asset_id/data' do
|
63
|
+
if @asset = Asset.get(params[:asset_id])
|
64
|
+
if @asset_data = get_asset_data(params[:asset_id])
|
65
|
+
content_type 'application/octet-stream'
|
66
|
+
erb :data
|
67
|
+
else
|
68
|
+
not_found
|
69
|
+
end
|
70
|
+
else
|
71
|
+
not_found
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
get '/assets/:asset_id/metadata' do
|
76
|
+
if @asset = Asset.get(params[:asset_id])
|
77
|
+
if @asset_data = get_asset_data(params[:asset_id])
|
78
|
+
content_type get_asset_type(@asset.asset_type)
|
79
|
+
erb :metadata
|
80
|
+
else
|
81
|
+
not_found
|
82
|
+
end
|
83
|
+
else
|
84
|
+
not_found
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
delete '/*' do
|
89
|
+
# we don't trust anyone to delete assets. opensim complains if it
|
90
|
+
# gets 403s, so return a 404 instead...
|
91
|
+
not_found
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
require ::File.dirname(__FILE__) + '/sras/helpers/init'
|
97
|
+
require ::File.dirname(__FILE__) + '/sras/models/init'
|
data/sras.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'sras'
|
3
|
+
s.version = '2.1.1.pre.10'
|
4
|
+
s.summary = 'Simple Ruby Asset Server'
|
5
|
+
s.description = 'Asset server for use with OpenSimulator'
|
6
|
+
s.authors = 'Dave Coyle'
|
7
|
+
s.email = 'hello@coyled.com'
|
8
|
+
s.homepage = 'http://coyled.com/sras'
|
9
|
+
s.license = 'MIT'
|
10
|
+
|
11
|
+
s.files = `git ls-files`.split("\n")
|
12
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
13
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
14
|
+
|
15
|
+
s.add_runtime_dependency 'dm-migrations', '1.1.0'
|
16
|
+
s.add_runtime_dependency 'dm-mysql-adapter', '1.1.0'
|
17
|
+
s.add_runtime_dependency 'dm-timestamps', '1.1.0'
|
18
|
+
s.add_runtime_dependency 'dm-types', '1.1.0'
|
19
|
+
s.add_runtime_dependency 'hpricot', '0.8.4'
|
20
|
+
s.add_runtime_dependency 'sinatra', '1.2.6'
|
21
|
+
s.add_runtime_dependency 'thin', '1.2.11'
|
22
|
+
s.add_runtime_dependency 'rake', '0.9.2.2'
|
23
|
+
end
|
data/test/test.asset
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<AssetBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
3
|
+
<Data>SGkuICBJJ20gYSBzdWJtaXR0ZWQgYXNzZXQhCg==
|
4
|
+
</Data>
|
5
|
+
<FullID>
|
6
|
+
<Guid>0193663d-44e4-4e6e-9a1c-8dd2febc5fc5</Guid>
|
7
|
+
</FullID>
|
8
|
+
<ID>0193663d-44e4-4e6e-9a1c-8dd2febc5fc5</ID>
|
9
|
+
<Name>test1</Name>
|
10
|
+
<Description>test submitted asset</Description>
|
11
|
+
<Type>10</Type>
|
12
|
+
<Local>true</Local>
|
13
|
+
<Temporary>false</Temporary>
|
14
|
+
</AssetBase>
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sras
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.1.1.pre.10
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dave Coyle
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-16 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: dm-migrations
|
16
|
+
requirement: &73169400 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - =
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *73169400
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: dm-mysql-adapter
|
27
|
+
requirement: &73169150 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - =
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.1.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *73169150
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: dm-timestamps
|
38
|
+
requirement: &73168920 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - =
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.1.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *73168920
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: dm-types
|
49
|
+
requirement: &73168690 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - =
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *73168690
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: hpricot
|
60
|
+
requirement: &73168460 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - =
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.8.4
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *73168460
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sinatra
|
71
|
+
requirement: &73168230 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - =
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.2.6
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *73168230
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: thin
|
82
|
+
requirement: &73168000 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - =
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 1.2.11
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *73168000
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rake
|
93
|
+
requirement: &73167770 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - =
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 0.9.2.2
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *73167770
|
102
|
+
description: Asset server for use with OpenSimulator
|
103
|
+
email: hello@coyled.com
|
104
|
+
executables:
|
105
|
+
- sras
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files: []
|
108
|
+
files:
|
109
|
+
- .gitignore
|
110
|
+
- .travis.yml
|
111
|
+
- Gemfile
|
112
|
+
- Gemfile.lock
|
113
|
+
- LICENSE
|
114
|
+
- README.rst
|
115
|
+
- Rakefile
|
116
|
+
- bin/sras
|
117
|
+
- config.ru
|
118
|
+
- config/config.yml.example
|
119
|
+
- lib/sras.rb
|
120
|
+
- lib/sras/helpers/asset.rb
|
121
|
+
- lib/sras/helpers/init.rb
|
122
|
+
- lib/sras/helpers/setup.rb
|
123
|
+
- lib/sras/models/asset.rb
|
124
|
+
- lib/sras/models/init.rb
|
125
|
+
- lib/sras/views/create.erb
|
126
|
+
- lib/sras/views/data.erb
|
127
|
+
- lib/sras/views/index.erb
|
128
|
+
- lib/sras/views/metadata.erb
|
129
|
+
- lib/sras/views/show.erb
|
130
|
+
- sras.gemspec
|
131
|
+
- test/test.asset
|
132
|
+
homepage: http://coyled.com/sras
|
133
|
+
licenses:
|
134
|
+
- MIT
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
141
|
+
requirements:
|
142
|
+
- - ! '>='
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ! '>'
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: 1.3.1
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 1.8.15
|
154
|
+
signing_key:
|
155
|
+
specification_version: 3
|
156
|
+
summary: Simple Ruby Asset Server
|
157
|
+
test_files:
|
158
|
+
- test/test.asset
|