ibg 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c7a42ae549580fa53bc5595d620cf05438673e5c
4
+ data.tar.gz: 2bf79c3f8e52b2ccd3f53ccf09b67a2a40ca6baa
5
+ SHA512:
6
+ metadata.gz: 220bb544b16e09be77167e755ec70ea2c41157fa13982058b52ed92f93e4773849cd2bbd257a22698ac8ffa21f8370da5b9303eda97d337d61e79f0f3771aa05
7
+ data.tar.gz: 4a91f1bd881076a67a1e21a6c0669d32b399589e5a6c552f92028a38308f8c393d7f27657c79e36d12ea2298e488ec5e0403d226307ab3123381360de9bf0116
data/Dockerfile CHANGED
@@ -9,6 +9,7 @@ RUN gem install sinatra
9
9
  RUN gem install haml
10
10
  RUN apt-get install -y make ruby-dev g++
11
11
  RUN gem install aws-sdk thin
12
+ RUN gem install bundler rake
12
13
  RUN git clone https://github.com/ohac/iceberg.git
13
14
  RUN \
14
15
  mkdir -p /iceberg/public/css && \
@@ -24,7 +25,7 @@ RUN \
24
25
  curl -sO https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/fonts/glyphicons-halflings-regular.ttf
25
26
  EXPOSE 4567
26
27
  WORKDIR /iceberg
27
- CMD rackup -p 4567 -o 0.0.0.0
28
+ CMD bundle exec rackup -p 4567 -o 0.0.0.0
28
29
 
29
30
  # Build:
30
31
  # docker build -t ohac/iceberg .
data/bin/iceberg-sync CHANGED
@@ -16,14 +16,14 @@ class MultiReader
16
16
  @readers << reader
17
17
  end
18
18
 
19
- def read(size = nil)
19
+ def read(size = nil, outbuf = '')
20
20
  rv = ''
21
21
  loop do
22
22
  reader = @readers[@cur]
23
23
  break unless reader
24
- s = reader.read(size) # TODO S3
24
+ s = reader.read(size, outbuf) # TODO S3
25
25
  if s
26
- rv += s
26
+ rv << s
27
27
  if size
28
28
  size -= s.size
29
29
  break if size <= 0
@@ -32,6 +32,8 @@ class MultiReader
32
32
  @cur += 1
33
33
  end
34
34
  end
35
+ outbuf.clear
36
+ outbuf << rv
35
37
  rv.size > 0 ? rv : nil
36
38
  end
37
39
 
data/ibg.gemspec CHANGED
@@ -21,7 +21,9 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.7"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_dependency 'sinatra'
24
+ spec.add_dependency 'thin'
24
25
  spec.add_dependency 'haml'
25
26
  spec.add_dependency 'redis'
26
27
  spec.add_dependency 'aws-sdk'
28
+ spec.add_dependency 'i18n'
27
29
  end
data/lib/ibg.rb CHANGED
@@ -43,6 +43,7 @@ module Iceberg
43
43
  IBDB_TRIPCODE_FUND = 'iceberg:tripcode:fund:'
44
44
  IBDB_RECENT_PEERS = 'iceberg:recentpeers'
45
45
  IBDB_PEERS = 'iceberg:peers'
46
+ IBDB_SHORT_URL = 'iceberg:shorturl:'
46
47
 
47
48
  ALGORITHM = 'AES-128-CBC'
48
49
  REDIS = if ENV['DB_PORT_6379_TCP_PORT']
@@ -143,13 +144,15 @@ module Iceberg
143
144
  end
144
145
 
145
146
  def self.download(name, filename, hexdigest)
146
- ctype, disp = case filename
147
+ ctype, disp = case filename ? filename.downcase : nil
147
148
  when /\.jpg$/ ; ['image/jpeg', 'inline']
148
149
  when /\.png$/ ; ['image/png', 'inline']
149
150
  when /\.gif$/ ; ['image/gif', 'inline']
150
151
  when /\.mp3$/ ; ['audio/mpeg', 'inline']
152
+ when /\.m4a$/ ; ['audio/mpeg', 'inline']
151
153
  when /\.ogg$/ ; ['audio/ogg', 'inline']
152
- when /\.flac$/ ; ['audio/flac', 'inline']
154
+ when /\.flac$/ ; ['audio/x-flac', 'inline']
155
+ when /\.alac$/ ; ['audio/alac', 'inline']
153
156
  when /\.webm$/ ; ['video/webm', 'inline']
154
157
  when /\.txt$/ ; ['text/plain', 'inline']
155
158
  else ['application/octet-stream', 'attachment']
@@ -182,4 +185,19 @@ module Iceberg
182
185
  end
183
186
  end
184
187
 
188
+ def self.url2key(url, seconds)
189
+ key = "%010d" % rand(10000000000)
190
+ dbkey = IBDB_SHORT_URL + key
191
+ unless REDIS.exists(dbkey) # TODO retry
192
+ REDIS.set(dbkey, url)
193
+ REDIS.expire(dbkey, seconds)
194
+ key
195
+ end
196
+ end
197
+
198
+ def self.key2url(key)
199
+ dbkey = IBDB_SHORT_URL + key
200
+ REDIS.get(dbkey)
201
+ end
202
+
185
203
  end
data/lib/ibg/storage.rb CHANGED
@@ -65,7 +65,7 @@ module Iceberg
65
65
  end
66
66
 
67
67
  # TODO S3 bin/icebergsync.rb
68
- def read(size = nil)
68
+ def read(size = nil, outbuf = '')
69
69
  if block_given?
70
70
  close
71
71
  File.open(@path, 'rb') do |fd|
@@ -77,7 +77,7 @@ module Iceberg
77
77
  end
78
78
  else
79
79
  @fd = File.open(@path, 'rb') unless @fd
80
- @fd.read(size)
80
+ @fd.read(size, outbuf)
81
81
  end
82
82
  end
83
83
 
data/lib/ibg/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Iceberg
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/ibg/web.rb CHANGED
@@ -6,6 +6,8 @@ require 'nkf'
6
6
  require 'fileutils'
7
7
  require 'base64'
8
8
  require 'json'
9
+ require 'i18n'
10
+ require 'i18n/backend/fallbacks'
9
11
 
10
12
  module Iceberg
11
13
 
@@ -19,6 +21,14 @@ module Iceberg
19
21
  FORBIDDEN_CHARS = " #<>:\\/*?\"|&',;`"
20
22
 
21
23
  enable :sessions
24
+ enable :logging
25
+
26
+ configure do
27
+ I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
28
+ locales = Dir[File.join(ICEBERG_HOME, 'locales', '*.yml')]
29
+ I18n.load_path = locales
30
+ I18n.backend.load_translations
31
+ end
22
32
 
23
33
  helpers do
24
34
 
@@ -29,6 +39,10 @@ module Iceberg
29
39
  haml(template, options)
30
40
  end
31
41
 
42
+ def t(text)
43
+ I18n.t(text)
44
+ end
45
+
32
46
  end
33
47
 
34
48
  CONTENT_TYPES = {
@@ -47,9 +61,15 @@ module Iceberg
47
61
  end
48
62
  content_type CONTENT_TYPES[request_uri], :charset => 'utf-8'
49
63
  response.headers['Cache-Control'] = 'no-cache'
64
+ I18n.locale = session[:locale] || 'ja'
50
65
  end
51
66
 
52
67
  get '/' do
68
+ locale = params[:locale]
69
+ if locale
70
+ I18n.locale = locale
71
+ session[:locale] = locale
72
+ end
53
73
  filemax = SETTING['local']['filemax']
54
74
  recentfiles = REDIS.lrange(IBDB_RECENT, 0, filemax)
55
75
  tripcodelist = REDIS.smembers(IBDB_TRIPCODE_SET)
@@ -95,7 +115,7 @@ module Iceberg
95
115
  rv[:name] = origname
96
116
  session[:uploaded] = rv
97
117
  rescue => x
98
- p x
118
+ p x
99
119
  end
100
120
  redirect '/'
101
121
  end
@@ -162,15 +182,37 @@ p x
162
182
  :exists => o.exists?}
163
183
  end
164
184
 
185
+ post '/shorten' do
186
+ name = params[:name]
187
+ filename = params[:filename]
188
+ hexdigest = params[:digest]
189
+ seconds = params[:seconds]
190
+ params = hexdigest ? "?digest=#{hexdigest}&filename=#{filename}" : ''
191
+ url = "/show/#{name}#{params}"
192
+ key = Iceberg.url2key(url, seconds)
193
+ haml :shorten, :locals => {:key => key}
194
+ end
195
+
196
+ get '/s/:key' do
197
+ key = params[:key]
198
+ url = Iceberg.key2url(key)
199
+ redirect url if url
200
+ sleep 1 # TODO bruteforce attack
201
+ raise
202
+ end
203
+
165
204
  get '/container/:name' do
166
205
  name = params[:name]
167
206
  hexdigest = params[:digest]
168
- haml :container, :locals => { :name => name, :hexdigest => hexdigest }
207
+ filename = params[:filename]
208
+ haml :container, :locals => { :name => name, :hexdigest => hexdigest,
209
+ :filename => filename }
169
210
  end
170
211
 
171
212
  ['/download/:name', '/api/v1/download/:name'].each do |path|
172
213
  get path do
173
214
  name = params[:name]
215
+ name = name.split('.')[0] if name.index('.')
174
216
  filename = params[:filename]
175
217
  hexdigest = params[:digest]
176
218
  ctype, disp, file, cipher = Iceberg.download(name, filename, hexdigest)
@@ -184,18 +226,87 @@ p x
184
226
  response.headers['Content-Disposition'] =
185
227
  "#{disp}; filename=\"#{filename}\""
186
228
  end
187
- stream do |out|
229
+ range = request.env['HTTP_RANGE']
230
+ skip = 0
231
+ size = nil
232
+ if range
233
+ range = range.split('=')[1].split('-').map(&:to_i)
234
+ size = range[1]
235
+ if size
236
+ skip = range[0]
237
+ size = size + 1 - skip
238
+ status 206
239
+ end
240
+ end
241
+ if size && size < 4 * 1024 * 1024 # TODO under 4 MiB
242
+ out = ''
188
243
  begin
189
244
  file.read do |data|
190
245
  data = cipher.update(data) if cipher
191
246
  out << data
192
- sleep 0.1 # TODO
193
247
  end
194
- out << cipher.final if cipher
248
+ if cipher
249
+ data = cipher.final
250
+ out << data
251
+ end
195
252
  rescue => x
196
253
  p x
197
254
  end
198
255
  Iceberg.recordip(request.ip)
256
+ response.headers['Content-Range'] = "bytes #{range.join('-')}/#{out.size}"
257
+ out[skip, size]
258
+ else
259
+ stream do |out|
260
+ begin
261
+ file.read do |data|
262
+ data = cipher.update(data) if cipher
263
+ if skip <= 0
264
+ if size
265
+ if size > 0
266
+ out << data[0, size]
267
+ size -= data.size
268
+ end
269
+ else
270
+ out << data
271
+ end
272
+ else
273
+ if skip >= data.size
274
+ skip -= data.size
275
+ else
276
+ if size
277
+ out << data[skip, size]
278
+ size -= data.size - skip
279
+ else
280
+ out << data[(skip)..-1]
281
+ end
282
+ skip = 0
283
+ end
284
+ end
285
+ sleep 0.1 # TODO
286
+ end
287
+ if cipher
288
+ data = cipher.final
289
+ if skip <= 0
290
+ if size
291
+ if size > 0
292
+ out << data[0, size]
293
+ end
294
+ else
295
+ out << data
296
+ end
297
+ else
298
+ if size
299
+ out << data[skip, size]
300
+ else
301
+ out << data[(skip)..-1]
302
+ end
303
+ end
304
+ end
305
+ rescue => x
306
+ p x
307
+ end
308
+ Iceberg.recordip(request.ip)
309
+ end
199
310
  end
200
311
  end
201
312
  end
data/locales/en.yml ADDED
@@ -0,0 +1,40 @@
1
+ en:
2
+ online_storage: Oneline Storage - Iceberg
3
+ home: Home
4
+ source: Source
5
+ roadmap: Roadmap
6
+ upload: Upload
7
+ download: Download
8
+ recent_peers: Recent Peers
9
+ cryptographic_keys: Cryptographic Keys
10
+ cryptographic_keys_note1: "All keys are stored on your browser's storage."
11
+ cryptographic_keys_note2: "It is important to backup keys."
12
+ file: File
13
+ text: Text
14
+ step1: STEP 1
15
+ step2: STEP 2
16
+ tripcode_tag: Tripcode Tag (Option)aaa
17
+ tripcode: 'Tripcode:'
18
+ up_to_size: 'Up to %s MiB.'
19
+ trip_key: Trip Key
20
+ files: Files
21
+ tags: Tags
22
+ show_keys: Show Keys
23
+ import_keys: Import Keys
24
+ forget_all_keys: Forget All Keys
25
+ files_in_fifo: '%s / %s files in FIFO.'
26
+ carousel11: 'Your stuff, anywhere'
27
+ carousel12: 'You can share pictures, recordings, videos – anything.'
28
+ carousel13: 'You can quickly share URL to view, download, and collaborate on all the files you want - no email attachment needed.'
29
+ demo: Demo
30
+ carousel21: 'Safe and secure'
31
+ carousel22: 'Full SSL communication. Use Amazon S3.'
32
+ carousel23: "Everything's automatically private, so you control who sees what."
33
+ carousel24: 'Server does not store your AES encryption key.'
34
+ carousel25: "Storing it into your browser's local storage."
35
+ carousel31: 'Open source'
36
+ carousel32: 'Iceberg is open source software.'
37
+ carousel33: 'You can improve this software. Run anywhere.'
38
+ carousel41: 'Decentralized'
39
+ carousel42: 'It is possible to download and upload encrypted files via API.'
40
+ carousel43: 'Anybody can duplicate and re-upload files.'
data/locales/ja.yml ADDED
@@ -0,0 +1,40 @@
1
+ ja:
2
+ online_storage: オンラインストレージ - Iceberg
3
+ home: ホーム
4
+ source: ソースコード
5
+ roadmap: ロードマップ
6
+ upload: アップロード
7
+ download: ダウンロード
8
+ recent_peers: 最近のピア
9
+ cryptographic_keys: 暗号化鍵
10
+ cryptographic_keys_note1: すべての鍵はあなたのブラウザに保存されています。
11
+ cryptographic_keys_note2: 鍵をバックアップしておくことをおすすめします。
12
+ file: ファイル
13
+ text: テキスト
14
+ step1: ステップ1
15
+ step2: ステップ2
16
+ tripcode_tag: トリップタグ(オプション)
17
+ tripcode: 'トリップ:'
18
+ up_to_size: '最大 %s MiBまで'
19
+ trip_key: トリップ鍵
20
+ files: ファイル
21
+ tags: タグ
22
+ show_keys: 鍵を見る
23
+ import_keys: 鍵を取り込む
24
+ forget_all_keys: すべての鍵を削除
25
+ files_in_fifo: '%s / %s ファイルがFIFOに存在'
26
+ carousel11: 'すべてのファイルをどこからでも'
27
+ carousel12: '写真、音楽、動画など、何でも保管しておけます。'
28
+ carousel13: 'メール添付不要。アドレス共有で閲覧やダウンロードが可能に。'
29
+ demo: サンプルファイル
30
+ carousel21: '安全で安心'
31
+ carousel22: '通信経路はSSLで暗号化。ファイルはAmazon S3に冗長保存。'
32
+ carousel23: "ファイルは共有なしで保存され、後で選択できます。"
33
+ carousel24: 'AES暗号化鍵はサーバには保存しません。'
34
+ carousel25: "ブラウザの内部ストレージに保存されます。"
35
+ carousel31: 'オープンソース'
36
+ carousel32: 'Icebergはオープンソースソフトウェアです。'
37
+ carousel33: '誰でもこのソフトを改良することができ、どこでも動かせます。'
38
+ carousel41: '分散システム'
39
+ carousel42: '暗号化ファイルはAPIでダウンロード・アップロードが可能です。'
40
+ carousel43: '誰でもファイルの冗長化に参加することができます。'
data/public/show.js CHANGED
@@ -6,4 +6,24 @@ $(function(){
6
6
  localStorage.setItem(encdigest + ':name', name);
7
7
  localStorage.setItem(encdigest + ':digest', digest);
8
8
  }
9
+ $('#apply').click(function () {
10
+ var textdata = $('#textdata');
11
+ if (textdata) {
12
+ //var metadata = textdata.contents()[0].body.innerHTML;
13
+ var metadata = $('pre', textdata.contents()).text(); // TODO Chrome only?
14
+ $(metadata.split('\n')).each(function (i, x) {
15
+ var kv = x.split('=');
16
+ var k = kv[0];
17
+ var v = kv[1];
18
+ if (v) {
19
+ if (v.length == 0) {
20
+ localStorage.removeItem(k);
21
+ }
22
+ else {
23
+ localStorage.setItem(k, v);
24
+ }
25
+ }
26
+ });
27
+ }
28
+ });
9
29
  });
data/views/_navbar.haml CHANGED
@@ -1,9 +1,18 @@
1
1
  %li.active
2
- %a{:href => "#"} Home
2
+ %a{:href => "#"}= t 'home'
3
3
  %li
4
4
  - demourl = Iceberg::SETTING['local']['demourl'] || '#'
5
- %a{:href => demourl} Demo
5
+ %a{:href => demourl}= t 'demo'
6
6
  %li
7
- %a{:href => 'https://github.com/ohac/iceberg'} Source
7
+ %a{:href => 'https://github.com/ohac/iceberg'}= t 'source'
8
8
  %li
9
- %a{:href => 'https://github.com/ohac/iceberg/wiki'} Roadmap
9
+ %a{:href => 'https://github.com/ohac/iceberg/wiki'}= t 'roadmap'
10
+ %li{:class => 'dropdown'}
11
+ %a{:href => '#', :class => 'dropdown-toggle', 'data-toggle' => 'dropdown', :role => 'button', 'aria-expanded' => false}
12
+ Locale
13
+ %span{:class => 'caret'}
14
+ %ul{:class => 'dropdown-menu', :role => 'menu', 'aria-labelledby' => 'dropdownMenu1'}
15
+ %li{:role => 'presentation'}
16
+ %a{:role => 'menuitem', :tabindex => -1, :href => '/?locale=en'} English
17
+ %li{:role => 'presentation'}
18
+ %a{:role => 'menuitem', :tabindex => -1, :href => '/?locale=ja'} 日本語
data/views/container.haml CHANGED
@@ -1,8 +1,11 @@
1
+ !!! 5
1
2
  %html
2
3
  %body
4
+ %br
3
5
  - params = "?digest=#{hexdigest}"
6
+ - name += ".#{filename}" if filename
4
7
  - url = "#{name}#{params}"
5
8
  - dllink = "/download/#{url}"
6
9
  %audio{:controls => :controls}
7
- %source{:src => dllink, :type => 'audio/mp3'}
10
+ %source{:src => dllink, :type => 'audio/mpeg'}
8
11
  Your browser does not support audio
data/views/index.haml CHANGED
@@ -1,7 +1,8 @@
1
1
  !!! 5
2
+ - title = Time.now.strftime('%Y-%m-%d %H:%M ')
2
3
  %html
3
4
  %head
4
- %title Online Storage - Iceberg
5
+ %title= t 'online_storage'
5
6
  %meta{:property => 'twitter:card', :content => 'summary'}
6
7
  %meta{:name => 'twitter:title', :content => 'Online Storage - Iceberg'}
7
8
  %meta{:name => 'twitter:description',
@@ -24,7 +25,7 @@
24
25
  %span.icon-bar
25
26
  %span.icon-bar
26
27
  %span.icon-bar
27
- %a.navbar-brand{:href => "#"} Online Storage - Iceberg
28
+ %a.navbar-brand{:href => "#"}= t 'online_storage'
28
29
  %div#navbar{:class => "collapse navbar-collapse"}
29
30
  %ul{:class => "nav navbar-nav"}= partial :navbar
30
31
  %div.container
@@ -50,7 +51,7 @@
50
51
  = name
51
52
  - if tripcode
52
53
  %br
53
- Tripcode:
54
+ = t 'tripcode'
54
55
  %a{:href => "/tripcode/#{tripcode}"}= tripcode
55
56
  %input#tripcode{:type => :hidden, :value => tripcode}
56
57
 
@@ -65,37 +66,37 @@
65
66
  %img{:src => "data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==", :alt => "First slide"}
66
67
  %div{:class => "container"}
67
68
  %div{:class => "carousel-caption"}
68
- %h1 Your stuff, anywhere
69
- %p You can share pictures, recordings, videos – anything.
70
- %p You can quickly share URL to view, download, and collaborate on all the files you want - no email attachment needed.
69
+ %h1= t 'carousel11'
70
+ %p= t 'carousel12'
71
+ %p= t 'carousel13'
71
72
  %p
72
73
  - demourl = Iceberg::SETTING['local']['demourl'] || '#'
73
- %a{:class => "btn btn-lg btn-primary", :href => demourl} Demo
74
+ %a{:class => "btn btn-lg btn-primary", :href => demourl}= t 'demo'
74
75
  %div{:class => "item"}
75
76
  %img{:src => "data:image/gif;base64,R0lGODlhAQABAIAAAGZmZgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==", :alt => "Second slide"}
76
77
  %div{:class => "container"}
77
78
  %div{:class => "carousel-caption"}
78
- %h1 Safe and secure
79
- %p Full SSL communication. Use Amazon S3.
80
- %p Everything's automatically private, so you control who sees what.
81
- %p Server does not store your AES encryption key.
82
- %p Storing it into your browser's local storage.
79
+ %h1= t 'carousel21'
80
+ %p= t 'carousel22'
81
+ %p= t 'carousel23'
82
+ %p= t 'carousel24'
83
+ %p= t 'carousel25'
83
84
  %div{:class => "item"}
84
85
  %img{:src => "data:image/gif;base64,R0lGODlhAQABAIAAAFVVVQAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==", :alt => "Third slide"}
85
86
  %div{:class => "container"}
86
87
  %div{:class => "carousel-caption"}
87
- %h1 Open source
88
- %p Iceberg is open source software.
89
- %p You can improve this software. Run anywhere.
88
+ %h1= t 'carousel31'
89
+ %p= t 'carousel32'
90
+ %p= t 'carousel33'
90
91
  %p
91
92
  %a{:class => "btn btn-lg btn-primary", :href => 'https://github.com/ohac/iceberg'} GitHub
92
93
  %div{:class => "item"}
93
94
  %img{:src => "data:image/gif;base64,R0lGODlhAQABAIAAAFVVVQAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==", :alt => "slide 4"}
94
95
  %div{:class => "container"}
95
96
  %div{:class => "carousel-caption"}
96
- %h1 Decentralized
97
- %p It is possible to download and upload encrypted files via API.
98
- %p Anybody can duplicate and re-upload files.
97
+ %h1= t 'carousel41'
98
+ %p= t 'carousel42'
99
+ %p= t 'carousel43'
99
100
  %p
100
101
  %a{:class => "btn btn-lg btn-primary", :href => 'https://github.com/ohac/iceberg'} GitHub
101
102
  %a{:class => "left carousel-control", :href => "#myCarousel", :role => "button", 'data-slide' => "prev"}
@@ -105,42 +106,42 @@
105
106
  %span{:class => "glyphicon glyphicon-chevron-right", 'aria-hidden' => true}
106
107
  %span{:class => "sr-only"} Next
107
108
 
108
- %h1 Upload
109
+ %h1= t 'upload'
109
110
  %ul#uploadtabs{:class => 'nav nav-tabs'}
110
111
  %li.active{:role => 'presentation'}
111
112
  %a{:href => '#filetab', 'aria-controls' => 'filetab', :role => :tab,
112
113
  'data-toggle' => 'tab'}
113
114
  %span{:class => 'glyphicon glyphicon-paperclip',
114
115
  'aria-hidden' => true}
115
- File
116
+ = t 'file'
116
117
  %li{:role => 'presentation'}
117
118
  %a{:href => '#texttab', 'aria-controls' => 'texttab', :role => :tab,
118
119
  'data-toggle' => 'tab'}
119
120
  %span{:class => 'glyphicon glyphicon-pencil',
120
121
  'aria-hidden' => true}
121
- Text
122
+ = t 'text'
122
123
  %div{:class => 'tab-content'}
123
124
  %div#filetab{:role => :tabpanel, :class => 'tab-pane active'}
124
125
 
125
126
  %form{:action => '/upload', :method => 'post',
126
127
  :enctype => 'multipart/form-data'}
127
128
  %br
128
- %label STEP 1
129
+ %label= t 'step1'
129
130
  %br
130
131
  %input{:type => 'file', :name => 'file'}
131
- Up to #{maxfilesize / (1024 * 1024)} MiB.
132
+ = (t 'up_to_size') % (maxfilesize / (1024 * 1024))
132
133
  %br
133
134
  %br
134
- %label STEP 2
135
+ %label= t 'step2'
135
136
  %br
136
137
  %button{:type => 'submit',
137
138
  :class => 'btn btn-lg btn-default'}
138
139
  %span{:class => 'glyphicon glyphicon-cloud-upload',
139
140
  'aria-hidden' => true}
140
- Upload
141
+ = t 'upload'
141
142
  %br
142
143
  %br
143
- %label Tripcode Tag (Option)
144
+ %label= t 'tripcode_tag'
144
145
  %br
145
146
  %div{:class => 'input-group'}
146
147
  %span{:class => 'input-group-addon', :id => 'basic-addon1'}
@@ -148,32 +149,31 @@
148
149
  'aria-hidden' => true}
149
150
  \#
150
151
  %input{:type => :text, :class => 'form-control',
151
- :placeholder => 'Trip Key',
152
+ :placeholder => (t 'trip_key'),
152
153
  'aria-describedby' => 'basic-addon1', :name => 'tripkey'}
153
154
 
154
155
  %div#texttab{:role => :tabpanel, :class => 'tab-pane'}
155
156
  %form{:action => '/uploadtext', :method => 'post',
156
157
  :enctype => 'multipart/form-data'}
157
158
  %br
158
- %label STEP 1
159
+ %label= t 'step1'
159
160
  %br
160
- - title = Time.now.strftime('%Y-%m-%d %H:%M ')
161
161
  %input{:type => 'input', :name => 'title', :value => title,
162
162
  :class => 'form-control'}
163
163
  %br
164
164
  %textarea{:rows => 10, :cols => 40, :name => 'text',
165
165
  :class => 'form-control'}
166
166
  %br
167
- %label STEP 2
167
+ %label= t 'step2'
168
168
  %br
169
169
  %button{:type => 'submit',
170
170
  :class => 'btn btn-lg btn-default'}
171
171
  %span{:class => 'glyphicon glyphicon-cloud-upload',
172
172
  'aria-hidden' => true}
173
- Upload
173
+ = t 'upload'
174
174
  %br
175
175
  %br
176
- %label Tripcode Tag (Option)
176
+ %label= t 'tripcode_tag'
177
177
  %br
178
178
  %div{:class => 'input-group'}
179
179
  %span{:class => 'input-group-addon', :id => 'basic-addon2'}
@@ -181,24 +181,24 @@
181
181
  'aria-hidden' => true}
182
182
  \#
183
183
  %input{:type => :text, :class => 'form-control',
184
- :placeholder => 'Trip Key',
184
+ :placeholder => (t 'trip_key'),
185
185
  'aria-describedby' => 'basic-addon2', :name => 'tripkey'}
186
186
 
187
187
  %hr
188
- %h1 Download
188
+ %h1= t 'download'
189
189
  %ul#downloadtabs{:class => 'nav nav-tabs'}
190
190
  %li.active{:role => 'presentation'}
191
191
  %a{:href => '#dltab', 'aria-controls' => 'dltab', :role => :tab,
192
192
  'data-toggle' => 'tab'}
193
193
  %span{:class => 'glyphicon glyphicon-file',
194
194
  'aria-hidden' => true}
195
- Files
195
+ = t 'files'
196
196
  %li{:role => 'presentation'}
197
197
  %a{:href => '#tagtab', 'aria-controls' => 'tagtab', :role => :tab,
198
198
  'data-toggle' => 'tab'}
199
- %span{:class => 'glyphicon glyphicon-tag',
199
+ %span{:class => 'glyphicon glyphicon-tags',
200
200
  'aria-hidden' => true}
201
- Tags
201
+ = t 'tags'
202
202
  %br
203
203
  %div{:class => 'tab-content'}
204
204
  %div#dltab{:role => :tabpanel, :class => 'tab-pane active'}
@@ -207,39 +207,61 @@
207
207
  %div
208
208
  %a.files{:href => "/show/#{file}", :id => file}= filename
209
209
  %br
210
- #{recentfiles.size} / #{filemax} files in FIFO.
210
+ = (t 'files_in_fifo') % [recentfiles.size, filemax]
211
211
  %div#tagtab{:role => :tabpanel, :class => 'tab-pane'}
212
212
  - tripcodelist.each do |tripcode|
213
213
  %div
214
214
  %a.tripcodelist{:href => "/tripcode/#{tripcode}",
215
215
  :id => tripcode}= tripcode
216
216
  %hr
217
- %h1 Recent Peers
217
+ %h1= t 'recent_peers'
218
218
  - salt = Iceberg::SETTING['local']['salt'] || ''
219
219
  - recentpeers.each do |digest, info|
220
220
  %p #{digest} (#{info})
221
221
  %hr
222
- %h1 Cryptographic Keys
223
- All keys are stored on your browser's storage.
224
- %br
225
- It is important to backup keys.
222
+ %h1= t 'cryptographic_keys'
223
+ = t 'cryptographic_keys_note1'
226
224
  %br
227
- %textarea#metadata{:class => 'form-control', :rows => 10}
225
+ = t 'cryptographic_keys_note2'
228
226
  %br
229
- %button#showkeys{:type => 'button', :class => 'btn btn-lg btn-default'}
230
- %span{:class => 'glyphicon glyphicon-open',
231
- 'aria-hidden' => true}
232
- Show Keys
233
- %button#apply{:type => 'button', :class => 'btn btn-lg btn-default'}
234
- %span{:class => 'glyphicon glyphicon-save',
235
- 'aria-hidden' => true}
236
- Import Keys
227
+ %form{:action => '/uploadtext', :method => 'post',
228
+ :enctype => 'multipart/form-data'}
229
+ %textarea#metadata{:class => 'form-control', :rows => 10,
230
+ :name => 'text'}
231
+ %br
232
+ %button#showkeys{:type => 'button', :class => 'btn btn-lg btn-default'}
233
+ %span{:class => 'glyphicon glyphicon-open',
234
+ 'aria-hidden' => true}
235
+ = t 'show_keys'
236
+ %button#apply{:type => 'button', :class => 'btn btn-lg btn-default'}
237
+ %span{:class => 'glyphicon glyphicon-save',
238
+ 'aria-hidden' => true}
239
+ = t 'import_keys'
240
+ %input{:type => :hidden, :name => 'title', :value => "#{title}Keys",
241
+ :class => 'form-control'}
242
+ %button{:type => 'submit',
243
+ :class => 'btn btn-lg btn-default'}
244
+ %span{:class => 'glyphicon glyphicon-cloud-upload',
245
+ 'aria-hidden' => true}
246
+ = t 'upload'
247
+ %br
248
+ %br
249
+ %label= t 'tripcode_tag'
250
+ %br
251
+ %div{:class => 'input-group'}
252
+ %span{:class => 'input-group-addon', :id => 'basic-addon2'}
253
+ %span{:class => 'glyphicon glyphicon-tag',
254
+ 'aria-hidden' => true}
255
+ \#
256
+ %input{:type => :text, :class => 'form-control',
257
+ :placeholder => (t 'trip_key'),
258
+ 'aria-describedby' => 'basic-addon2', :name => 'tripkey'}
237
259
  %br
238
260
  %br
239
261
  %button#deleteall{:type => 'button',
240
262
  :class => 'btn btn-sm btn-default'}
241
263
  %span{:class => 'glyphicon glyphicon-trash', 'aria-hidden' => true}
242
- Forget All Keys
264
+ = t 'forget_all_keys'
243
265
  %script{:type => 'text/javascript', :src => '/jquery-2.1.3.min.js'}
244
266
  %script{:type => 'text/javascript', :src => "#{cdn}/js/bootstrap.min.js"}
245
267
  %script{:type => 'text/javascript', :src => '/bootstrap-filestyle.min.js'}
@@ -0,0 +1,35 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title #{key} - Online Storage - Iceberg
5
+ %link{:href => "/style.css", :rel => "stylesheet", :type => "text/css",
6
+ :media => "screen"}
7
+ - cdn = Iceberg::SETTING['local']['cdn'] || ''
8
+ %link{:href => "#{cdn}/css/bootstrap.min.css", :rel => "stylesheet"}
9
+ %link{:href => "#{cdn}/css/bootstrap-theme.min.css", :rel => "stylesheet"}
10
+ %link{:href => "/starter-template.css", :rel => "stylesheet"}
11
+ %body
12
+ %nav{:class => "navbar navbar-inverse navbar-fixed-top"}
13
+ %div.container
14
+ %div.navbar-header
15
+ %button{:type => "button", :class => "navbar-toggle collapsed",
16
+ "data-toggle" => "collapse", "data-target" => "#navbar",
17
+ "aria-expanded" => "false", "aria-controls" => "navbar"}
18
+ %span.sr-only Toggle navigation
19
+ %span.icon-bar
20
+ %span.icon-bar
21
+ %span.icon-bar
22
+ %a.navbar-brand{:href => "/"} Online Storage - Iceberg
23
+ %div#navbar{:class => "collapse navbar-collapse"}
24
+ %ul{:class => "nav navbar-nav"}= partial :navbar
25
+ %div.container
26
+ %div.starter-template
27
+ - hostport = 'https://' + request.host
28
+ - shortlink = "/s/#{key}"
29
+ - url = "#{hostport}#{shortlink}"
30
+ %div{:class => 'input-group input-group-lg'}
31
+ %input{:type => :text, :class => 'form-control', :value => url}
32
+ %span{:class => "input-group-btn"}
33
+ %a{:href => shortlink, :class => 'btn btn-default'} Go!
34
+ %script{:type => 'text/javascript', :src => '/jquery-2.1.3.min.js'}
35
+ %script{:type => 'text/javascript', :src => "#{cdn}/js/bootstrap.min.js"}
data/views/show.haml CHANGED
@@ -7,7 +7,10 @@
7
7
  -# hostport = request.scheme + '://' + request.host
8
8
  - hostport = 'https://' + request.host
9
9
  - params = hexdigest ? "?digest=#{hexdigest}&filename=#{filename}" : ''
10
- - url = "#{name}#{params}"
10
+ - url1 = "#{name}#{params}"
11
+ - dllink1 = "/download/#{url1}"
12
+ - name2 = filename ? name + ".#{filename}" : name
13
+ - url = "#{name2}#{params}"
11
14
  - dllink = "/download/#{url}"
12
15
  - ctlink = "/container/#{url}"
13
16
  %head
@@ -15,14 +18,14 @@
15
18
  - if exists
16
19
  %meta{:name => 'twitter:title', :content => filename}
17
20
  - summary = true
18
- - case filename
21
+ - case filename.downcase
19
22
  - when /\.jpg$/, /\.gif$/, /\.png$/
20
23
  - if filesize < 1024 * 1024
21
24
  %meta{:property => 'twitter:card', :content => 'photo'}
22
25
  %meta{:name => 'twitter:image', :content => "#{hostport}#{dllink}"}
23
26
  %meta{:name => 'twitter:url', :content => request.url}
24
27
  - summary = false
25
- - when /\.mp3$/
28
+ - when /\.mp3$/, /\.m4a$/
26
29
  %meta{:property => 'twitter:card', :content => 'player'}
27
30
  %meta{:name => 'twitter:player', :content => "#{hostport}#{ctlink}"}
28
31
  %meta{:name => 'twitter:player:width', :content => 300}
@@ -62,9 +65,9 @@
62
65
  %input#digest{:type => :hidden, :value => hexdigest}
63
66
  %input#encdigest{:type => :hidden, :value => encdigest}
64
67
  - if exists
65
- - case filename
68
+ - case filename.downcase
66
69
  - when /\.txt$/
67
- %iframe{:src => dllink}
70
+ %iframe#textdata{:src => dllink, :width => 1024, :height => 360}
68
71
  %hr
69
72
  - when /\.webm$/
70
73
  %video{:width => 640, :height => 360, :controls => :controls}
@@ -73,21 +76,37 @@
73
76
  - when /\.jpg$/, /\.gif$/, /\.png$/
74
77
  %img{:src => dllink}
75
78
  %hr
76
- - when /\.mp3$/, /\.ogg$/, /\.flac$/
77
- %audio{:src => dllink, :controls => :controls}
79
+ - when /\.mp3$/, /\.ogg$/, /\.flac$/, /\.m4a$/
80
+ %audio{:controls => :controls}
81
+ %source{:src => dllink, :type => 'audio/mpeg'}
78
82
  %hr
79
- %a{:href => dllink, :class => 'btn btn-default btn-lg'}
80
- %span{:class => 'glyphicon glyphicon-cloud-download'} Download
83
+ %form{:action => '/shorten', :method => 'post'}
84
+ %a{:href => dllink, :class => 'btn btn-default btn-lg'}
85
+ %span{:class => 'glyphicon glyphicon-cloud-download'} Download
86
+ %input{:type => :hidden, :name => :name, :value => name}
87
+ %input{:type => :hidden, :name => :filename, :value => filename}
88
+ %input{:type => :hidden, :name => :digest, :value => hexdigest}
89
+ %input{:type => :hidden, :name => :seconds, :value => 60}= # TODO
90
+ %button{:type => :submit, :class => 'btn btn-lg btn-default'}
91
+ %span{:class => 'glyphicon glyphicon-share',
92
+ 'aria-hidden' => true}
93
+ Shorten URL (60 seconds)
94
+ - if /_Keys\.txt$/ === filename
95
+ %button#apply{:type => 'button',
96
+ :class => 'btn btn-lg btn-default'}
97
+ %span{:class => 'glyphicon glyphicon-save',
98
+ 'aria-hidden' => true}
99
+ Import Keys
81
100
  - else
82
101
  %p File not found
83
102
  %hr
84
103
  %label Share URL:
85
104
  %textarea{:rows => 2, :class => 'form-control'}
86
- #{hostport}/show/#{url}
105
+ #{hostport}/show/#{url1}
87
106
  %br
88
107
  %label Direct URL:
89
108
  %textarea{:rows => 2, :class => 'form-control'}
90
- #{hostport}#{dllink}
109
+ #{hostport}#{dllink1}
91
110
  %script{:type => 'text/javascript', :src => '/jquery-2.1.3.min.js'}
92
111
  %script{:type => 'text/javascript', :src => "#{cdn}/js/bootstrap.min.js"}
93
112
  %script{:type => 'text/javascript', :src => '/show.js'}
metadata CHANGED
@@ -1,110 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ibg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.0.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - OHASHI Hideya
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-01-18 00:00:00.000000000 Z
11
+ date: 2015-04-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.7'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.7'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
33
  version: '10.0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
40
  version: '10.0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: sinatra
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thin
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
60
67
  - !ruby/object:Gem::Version
61
68
  version: '0'
62
69
  - !ruby/object:Gem::Dependency
63
70
  name: haml
64
71
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
72
  requirements:
67
- - - ! '>='
73
+ - - ">="
68
74
  - !ruby/object:Gem::Version
69
75
  version: '0'
70
76
  type: :runtime
71
77
  prerelease: false
72
78
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
79
  requirements:
75
- - - ! '>='
80
+ - - ">="
76
81
  - !ruby/object:Gem::Version
77
82
  version: '0'
78
83
  - !ruby/object:Gem::Dependency
79
84
  name: redis
80
85
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
86
  requirements:
83
- - - ! '>='
87
+ - - ">="
84
88
  - !ruby/object:Gem::Version
85
89
  version: '0'
86
90
  type: :runtime
87
91
  prerelease: false
88
92
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
93
  requirements:
91
- - - ! '>='
94
+ - - ">="
92
95
  - !ruby/object:Gem::Version
93
96
  version: '0'
94
97
  - !ruby/object:Gem::Dependency
95
98
  name: aws-sdk
96
99
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
100
  requirements:
99
- - - ! '>='
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: i18n
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
100
116
  - !ruby/object:Gem::Version
101
117
  version: '0'
102
118
  type: :runtime
103
119
  prerelease: false
104
120
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
121
  requirements:
107
- - - ! '>='
122
+ - - ">="
108
123
  - !ruby/object:Gem::Version
109
124
  version: '0'
110
125
  description: Decenterized file storage
@@ -116,8 +131,8 @@ executables:
116
131
  extensions: []
117
132
  extra_rdoc_files: []
118
133
  files:
119
- - .gitignore
120
- - .travis.yml
134
+ - ".gitignore"
135
+ - ".travis.yml"
121
136
  - Dockerfile
122
137
  - Gemfile
123
138
  - LICENSE.txt
@@ -133,6 +148,8 @@ files:
133
148
  - lib/ibg/storage.rb
134
149
  - lib/ibg/version.rb
135
150
  - lib/ibg/web.rb
151
+ - locales/en.yml
152
+ - locales/ja.yml
136
153
  - public/bootstrap-filestyle.min.js
137
154
  - public/carousel.css
138
155
  - public/favicon.ico
@@ -149,32 +166,32 @@ files:
149
166
  - views/_navbar.haml
150
167
  - views/container.haml
151
168
  - views/index.haml
169
+ - views/shorten.haml
152
170
  - views/show.haml
153
171
  - views/tripcode.haml
154
172
  homepage: https://box.sighash.info/
155
173
  licenses:
156
174
  - MIT
175
+ metadata: {}
157
176
  post_install_message:
158
177
  rdoc_options: []
159
178
  require_paths:
160
179
  - lib
161
180
  required_ruby_version: !ruby/object:Gem::Requirement
162
- none: false
163
181
  requirements:
164
- - - ! '>='
182
+ - - ">="
165
183
  - !ruby/object:Gem::Version
166
184
  version: '0'
167
185
  required_rubygems_version: !ruby/object:Gem::Requirement
168
- none: false
169
186
  requirements:
170
- - - ! '>='
187
+ - - ">="
171
188
  - !ruby/object:Gem::Version
172
189
  version: '0'
173
190
  requirements: []
174
191
  rubyforge_project:
175
- rubygems_version: 1.8.23
192
+ rubygems_version: 2.2.2
176
193
  signing_key:
177
- specification_version: 3
194
+ specification_version: 4
178
195
  summary: Decenterized file storage
179
196
  test_files:
180
197
  - test/test_entry.rb