ass 0.0.11 → 0.0.15

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.md CHANGED
@@ -63,6 +63,7 @@ under the current directory, provide single pem file combined with certificate a
63
63
  * start ass server, default port is 4567 (sinatra's default port)
64
64
 
65
65
  ![ass usage](https://raw.github.com/eiffelqiu/ass/master/doc/capture1.png)
66
+ ![ass usage](https://raw.github.com/eiffelqiu/ass/master/doc/capture2.png)
66
67
 
67
68
  Configuration (ass.yml)
68
69
  =======
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.11
1
+ 0.0.15
data/ass.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  port: 4567
2
2
  mode: development
3
+ log: off
3
4
  cron: cron
4
5
  timer: 0
5
6
  apps:
data/cron CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
+ require 'rubygems'
4
5
  require 'yaml'
5
6
  require 'cgi'
6
7
  require 'digest/sha2'
@@ -25,7 +26,7 @@ $apps = config['apps'] || []
25
26
  ## Using curl command to send push notification message
26
27
  ############################################################
27
28
 
28
- @message = CGI::escape("今天你搓一男家的狗怎么样了?".to_uri)
29
+ @message = CGI::escape("This is an push notification message sent by ASS".to_uri)
29
30
 
30
31
  #@pid = Digest::SHA2.hexdigest("#{Time.now.to_i}")
31
32
  @pid = "#{Time.now.to_i}"
data/lib/ass.rb CHANGED
@@ -44,12 +44,14 @@ $port = config['port'] || 4567
44
44
  $mode = config['mode'] || env
45
45
  $VERSION = File.open("#{ROOTDIR}/VERSION", "rb").read
46
46
  $apps = config['apps'] || []
47
+ $log = config['log'] || 'off'
47
48
 
48
49
  ############################################################
49
50
  ## Certificate Key Setup
50
51
  ############################################################
51
52
 
52
53
  $certkey = {}
54
+
53
55
  def check_cert
54
56
  $apps.each { |app|
55
57
  unless File.exist?("#{Dir.pwd}/#{app}_#{$mode}.pem") then
@@ -60,31 +62,41 @@ def check_cert
60
62
  certfile = File.read("#{Dir.pwd}/#{app}_#{$mode}.pem")
61
63
  openSSLContext = OpenSSL::SSL::SSLContext.new
62
64
  openSSLContext.cert = OpenSSL::X509::Certificate.new(certfile)
63
- openSSLContext.key = OpenSSL::PKey::RSA.new(certfile)
64
- $certkey["#{app}"] = openSSLContext
65
+ openSSLContext.key = OpenSSL::PKey::RSA.new(certfile)
66
+ $certkey["#{app}"] = openSSLContext
65
67
  end
66
- }
68
+ }
67
69
  return true
68
70
  end
69
71
 
70
72
  unless check_cert then
71
- puts "1: please provide certificate key pem file under current directory, name should be: appid_dev.pem for development and appid_prod.pem for production"
72
- puts "2: edit your ass.yml under current directory"
73
- puts "3: run ass"
74
- puts "4: iOS Client: in AppDelegate file, didRegisterForRemoteNotificationsWithDeviceToken method should access url below:"
73
+ html = <<-END
74
+ 1: please provide certificate key pem file under current directory, name should be: appid_dev.pem for development and appid_prod.pem for production
75
+ 2: edit your ass.yml under current directory
76
+ 3: run ass
77
+ 4: iOS Client: in AppDelegate file, didRegisterForRemoteNotificationsWithDeviceToken method should access url below:
78
+ END
75
79
  $apps.each { |app|
76
- puts "'#{app}'s registration url: http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken"
80
+ html << "'#{app}'s registration url: http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken"
77
81
  }
78
- puts "5: Server: cron should access 'curl http://localhost:#{$port}/v1/app/push/{messages}/{pid}' to send push message"
82
+ html << "5: Server: cron should access 'curl http://localhost:#{$port}/v1/app/push/{messages}/{pid}' to send push message"
83
+ puts html
79
84
  exit
80
85
  else
81
- puts "*"*80
82
- puts "Apple Service Server(#{$VERSION}) is Running ..."
83
- puts "Push Notification Service: Enabled"
84
- puts "Mode: #{$mode}"
85
- puts "Port: #{$port}"
86
- puts "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} " unless "#{$timer}".to_i == 0
87
- puts "*"*80
86
+ html = <<-END
87
+ #{'*'*80}
88
+ Apple Service Server(#{$VERSION}) is Running ...
89
+ Push Notification Service: Enabled
90
+ Mode: #{$mode}
91
+ Port: #{$port}
92
+ END
93
+ html << "#{'*'*80}"
94
+ html << "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} " unless "#{$timer}".to_i == 0
95
+ html << "\n"
96
+ html << "access http://localhost:#{$port}/ for more information"
97
+ html << "\n"
98
+ html << "#{'*'*80}"
99
+ puts html
88
100
  end
89
101
 
90
102
  ############################################################
@@ -97,7 +109,7 @@ unless File.exist?("#{Dir.pwd}/ass.db") then
97
109
  $DB.create_table :tokens do
98
110
  primary_key :id
99
111
  String :app, :unique => false, :null => false
100
- String :token, :unique => true, :null => false, :size => 100
112
+ String :token, :unique => false, :null => false, :size => 100
101
113
  index [:app, :token]
102
114
  end
103
115
 
@@ -123,25 +135,6 @@ unless $timer == 0 then
123
135
  puts "running job: '#{Dir.pwd}/#{$cron}' every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'}"
124
136
  system "./#{$cron}"
125
137
  end
126
- else
127
- puts "1: How to register notification? (Client Side)"
128
- puts
129
- puts "In AppDelegate file, inside didRegisterForRemoteNotificationsWithDeviceToken method access url below to register device token:"
130
- $apps.each { |app|
131
- puts "'#{app}'s registration url: http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken"
132
- }
133
- puts
134
- puts "2: How to send push notification? (Server Side)"
135
- puts
136
- $apps.each { |app|
137
- puts "curl http://localhost:#{$port}/v1/apps/#{app}/push/{message}/{pid}"
138
- }
139
- puts
140
- puts "Note:"
141
- puts "param1 (message): push notification message you want to send, remember the message should be html escaped"
142
- puts "param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest"
143
- puts
144
- puts "*"*80
145
138
  end
146
139
 
147
140
  ############################################################
@@ -149,39 +142,34 @@ end
149
142
  ############################################################
150
143
 
151
144
  class App < Sinatra::Base
152
-
153
- set :port, "#{$port}".to_i
154
145
 
146
+ set :root, File.expand_path('../../', __FILE__)
147
+ set :port, "#{$port}".to_i
148
+ set :public_folder, File.dirname(__FILE__) + '/../public'
149
+ set :views, File.dirname(__FILE__) + '/../views'
150
+
151
+ configure :production, :development do
152
+ if "#{$log}".strip == 'on' then
153
+ enable :logging
154
+ end
155
+ end
156
+
155
157
  if "#{$mode}".strip == 'development' then
156
158
  set :show_exceptions, true
157
159
  set :dump_errors, true
158
160
  else
159
161
  set :show_exceptions, false
160
- set :dump_errors, false
162
+ set :dump_errors, false
161
163
  end
162
164
 
163
165
  get '/' do
164
- o = "Apple Service Server #{$VERSION} <br/><br/>" +
165
- "author: Eiffel(Q) <br/>email: eiffelqiu@gmail.com<br/><br/>"
166
- o += "1: How to register notification? (Client Side)<br/><br/>"
167
- o += "In AppDelegate file, inside didRegisterForRemoteNotificationsWithDeviceToken method access url below to register device token:<br/><br/>"
168
- $apps.each { |app|
169
- o += "'#{app}': http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken<br/>"
170
- }
171
- o += "<br/>2: How to send push notification? (Server Side)<br/><br/>"
172
- $apps.each { |app|
173
- o += "curl http://localhost:#{$port}/v1/apps/#{app}/push/{message}/{pid}<br/>"
174
- }
175
- o += "<br/>Note:<br/>"
176
- o += "param1 (message): push notification message you want to send, remember the message should be html escaped<br/>"
177
- o += "param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest<br/>"
178
- o
166
+ erb :index
179
167
  end
180
168
 
181
169
  $apps.each { |app|
182
170
  get "/v1/apps/#{app}/:token" do
183
- puts "[#{params[:token]}] was added to '#{app}'"
184
- o = Token.first(:token => params[:token])
171
+ puts "[#{params[:token]}] was added to '#{app}'" if "#{$mode}".strip == 'development'
172
+ o = Token.first(:app => app , :token => params[:token])
185
173
  unless o
186
174
  Token.insert(
187
175
  :app => app,
@@ -192,10 +180,10 @@ class App < Sinatra::Base
192
180
 
193
181
  get "/v1/apps/#{app}/push/:message/:pid" do
194
182
  message = CGI::unescape(params[:message])
195
- puts message
183
+ puts message if "#{$mode}".strip == 'development'
196
184
  pid = params[:pid]
197
185
 
198
- puts "'#{message}' was sent to (#{app}) with pid: [#{pid}]"
186
+ puts "'#{message}' was sent to (#{app}) with pid: [#{pid}]" if "#{$mode}".strip == 'development'
199
187
 
200
188
  @push = Token.where(:app => app)
201
189
  @exist = Push.first(:pid => pid)
@@ -220,8 +208,8 @@ class App < Sinatra::Base
220
208
  # pack the token to convert the ascii representation back to binary
221
209
  tokenData = [tokenText].pack('H*')
222
210
  # construct the payload
223
- po = { :aps => { :alert => "#{message}", :badge => 1 }}
224
- payload = ActiveSupport::JSON.encode(po)
211
+ po = {:aps => {:alert => "#{message}", :badge => 1}}
212
+ payload = ActiveSupport::JSON.encode(po)
225
213
  # construct the packet
226
214
  packet = [0, 0, 32, tokenData, 0, payload.length, payload].pack("ccca*cca*")
227
215
  # read our certificate and set up our SSL context
@@ -0,0 +1,1058 @@
1
+ /*!
2
+ * Bootstrap Responsive v2.1.1
3
+ *
4
+ * Copyright 2012 Twitter, Inc
5
+ * Licensed under the Apache License v2.0
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
9
+ */
10
+
11
+ .clearfix {
12
+ *zoom: 1;
13
+ }
14
+
15
+ .clearfix:before,
16
+ .clearfix:after {
17
+ display: table;
18
+ line-height: 0;
19
+ content: "";
20
+ }
21
+
22
+ .clearfix:after {
23
+ clear: both;
24
+ }
25
+
26
+ .hide-text {
27
+ font: 0/0 a;
28
+ color: transparent;
29
+ text-shadow: none;
30
+ background-color: transparent;
31
+ border: 0;
32
+ }
33
+
34
+ .input-block-level {
35
+ display: block;
36
+ width: 100%;
37
+ min-height: 30px;
38
+ -webkit-box-sizing: border-box;
39
+ -moz-box-sizing: border-box;
40
+ box-sizing: border-box;
41
+ }
42
+
43
+ .hidden {
44
+ display: none;
45
+ visibility: hidden;
46
+ }
47
+
48
+ .visible-phone {
49
+ display: none !important;
50
+ }
51
+
52
+ .visible-tablet {
53
+ display: none !important;
54
+ }
55
+
56
+ .hidden-desktop {
57
+ display: none !important;
58
+ }
59
+
60
+ .visible-desktop {
61
+ display: inherit !important;
62
+ }
63
+
64
+ @media (min-width: 768px) and (max-width: 979px) {
65
+ .hidden-desktop {
66
+ display: inherit !important;
67
+ }
68
+ .visible-desktop {
69
+ display: none !important ;
70
+ }
71
+ .visible-tablet {
72
+ display: inherit !important;
73
+ }
74
+ .hidden-tablet {
75
+ display: none !important;
76
+ }
77
+ }
78
+
79
+ @media (max-width: 767px) {
80
+ .hidden-desktop {
81
+ display: inherit !important;
82
+ }
83
+ .visible-desktop {
84
+ display: none !important;
85
+ }
86
+ .visible-phone {
87
+ display: inherit !important;
88
+ }
89
+ .hidden-phone {
90
+ display: none !important;
91
+ }
92
+ }
93
+
94
+ @media (min-width: 1200px) {
95
+ .row {
96
+ margin-left: -30px;
97
+ *zoom: 1;
98
+ }
99
+ .row:before,
100
+ .row:after {
101
+ display: table;
102
+ line-height: 0;
103
+ content: "";
104
+ }
105
+ .row:after {
106
+ clear: both;
107
+ }
108
+ [class*="span"] {
109
+ float: left;
110
+ min-height: 1px;
111
+ margin-left: 30px;
112
+ }
113
+ .container,
114
+ .navbar-static-top .container,
115
+ .navbar-fixed-top .container,
116
+ .navbar-fixed-bottom .container {
117
+ width: 1170px;
118
+ }
119
+ .span12 {
120
+ width: 1170px;
121
+ }
122
+ .span11 {
123
+ width: 1070px;
124
+ }
125
+ .span10 {
126
+ width: 970px;
127
+ }
128
+ .span9 {
129
+ width: 870px;
130
+ }
131
+ .span8 {
132
+ width: 770px;
133
+ }
134
+ .span7 {
135
+ width: 670px;
136
+ }
137
+ .span6 {
138
+ width: 570px;
139
+ }
140
+ .span5 {
141
+ width: 470px;
142
+ }
143
+ .span4 {
144
+ width: 370px;
145
+ }
146
+ .span3 {
147
+ width: 270px;
148
+ }
149
+ .span2 {
150
+ width: 170px;
151
+ }
152
+ .span1 {
153
+ width: 70px;
154
+ }
155
+ .offset12 {
156
+ margin-left: 1230px;
157
+ }
158
+ .offset11 {
159
+ margin-left: 1130px;
160
+ }
161
+ .offset10 {
162
+ margin-left: 1030px;
163
+ }
164
+ .offset9 {
165
+ margin-left: 930px;
166
+ }
167
+ .offset8 {
168
+ margin-left: 830px;
169
+ }
170
+ .offset7 {
171
+ margin-left: 730px;
172
+ }
173
+ .offset6 {
174
+ margin-left: 630px;
175
+ }
176
+ .offset5 {
177
+ margin-left: 530px;
178
+ }
179
+ .offset4 {
180
+ margin-left: 430px;
181
+ }
182
+ .offset3 {
183
+ margin-left: 330px;
184
+ }
185
+ .offset2 {
186
+ margin-left: 230px;
187
+ }
188
+ .offset1 {
189
+ margin-left: 130px;
190
+ }
191
+ .row-fluid {
192
+ width: 100%;
193
+ *zoom: 1;
194
+ }
195
+ .row-fluid:before,
196
+ .row-fluid:after {
197
+ display: table;
198
+ line-height: 0;
199
+ content: "";
200
+ }
201
+ .row-fluid:after {
202
+ clear: both;
203
+ }
204
+ .row-fluid [class*="span"] {
205
+ display: block;
206
+ float: left;
207
+ width: 100%;
208
+ min-height: 30px;
209
+ margin-left: 2.564102564102564%;
210
+ *margin-left: 2.5109110747408616%;
211
+ -webkit-box-sizing: border-box;
212
+ -moz-box-sizing: border-box;
213
+ box-sizing: border-box;
214
+ }
215
+ .row-fluid [class*="span"]:first-child {
216
+ margin-left: 0;
217
+ }
218
+ .row-fluid .span12 {
219
+ width: 100%;
220
+ *width: 99.94680851063829%;
221
+ }
222
+ .row-fluid .span11 {
223
+ width: 91.45299145299145%;
224
+ *width: 91.39979996362975%;
225
+ }
226
+ .row-fluid .span10 {
227
+ width: 82.90598290598291%;
228
+ *width: 82.8527914166212%;
229
+ }
230
+ .row-fluid .span9 {
231
+ width: 74.35897435897436%;
232
+ *width: 74.30578286961266%;
233
+ }
234
+ .row-fluid .span8 {
235
+ width: 65.81196581196582%;
236
+ *width: 65.75877432260411%;
237
+ }
238
+ .row-fluid .span7 {
239
+ width: 57.26495726495726%;
240
+ *width: 57.21176577559556%;
241
+ }
242
+ .row-fluid .span6 {
243
+ width: 48.717948717948715%;
244
+ *width: 48.664757228587014%;
245
+ }
246
+ .row-fluid .span5 {
247
+ width: 40.17094017094017%;
248
+ *width: 40.11774868157847%;
249
+ }
250
+ .row-fluid .span4 {
251
+ width: 31.623931623931625%;
252
+ *width: 31.570740134569924%;
253
+ }
254
+ .row-fluid .span3 {
255
+ width: 23.076923076923077%;
256
+ *width: 23.023731587561375%;
257
+ }
258
+ .row-fluid .span2 {
259
+ width: 14.52991452991453%;
260
+ *width: 14.476723040552828%;
261
+ }
262
+ .row-fluid .span1 {
263
+ width: 5.982905982905983%;
264
+ *width: 5.929714493544281%;
265
+ }
266
+ .row-fluid .offset12 {
267
+ margin-left: 105.12820512820512%;
268
+ *margin-left: 105.02182214948171%;
269
+ }
270
+ .row-fluid .offset12:first-child {
271
+ margin-left: 102.56410256410257%;
272
+ *margin-left: 102.45771958537915%;
273
+ }
274
+ .row-fluid .offset11 {
275
+ margin-left: 96.58119658119658%;
276
+ *margin-left: 96.47481360247316%;
277
+ }
278
+ .row-fluid .offset11:first-child {
279
+ margin-left: 94.01709401709402%;
280
+ *margin-left: 93.91071103837061%;
281
+ }
282
+ .row-fluid .offset10 {
283
+ margin-left: 88.03418803418803%;
284
+ *margin-left: 87.92780505546462%;
285
+ }
286
+ .row-fluid .offset10:first-child {
287
+ margin-left: 85.47008547008548%;
288
+ *margin-left: 85.36370249136206%;
289
+ }
290
+ .row-fluid .offset9 {
291
+ margin-left: 79.48717948717949%;
292
+ *margin-left: 79.38079650845607%;
293
+ }
294
+ .row-fluid .offset9:first-child {
295
+ margin-left: 76.92307692307693%;
296
+ *margin-left: 76.81669394435352%;
297
+ }
298
+ .row-fluid .offset8 {
299
+ margin-left: 70.94017094017094%;
300
+ *margin-left: 70.83378796144753%;
301
+ }
302
+ .row-fluid .offset8:first-child {
303
+ margin-left: 68.37606837606839%;
304
+ *margin-left: 68.26968539734497%;
305
+ }
306
+ .row-fluid .offset7 {
307
+ margin-left: 62.393162393162385%;
308
+ *margin-left: 62.28677941443899%;
309
+ }
310
+ .row-fluid .offset7:first-child {
311
+ margin-left: 59.82905982905982%;
312
+ *margin-left: 59.72267685033642%;
313
+ }
314
+ .row-fluid .offset6 {
315
+ margin-left: 53.84615384615384%;
316
+ *margin-left: 53.739770867430444%;
317
+ }
318
+ .row-fluid .offset6:first-child {
319
+ margin-left: 51.28205128205128%;
320
+ *margin-left: 51.175668303327875%;
321
+ }
322
+ .row-fluid .offset5 {
323
+ margin-left: 45.299145299145295%;
324
+ *margin-left: 45.1927623204219%;
325
+ }
326
+ .row-fluid .offset5:first-child {
327
+ margin-left: 42.73504273504273%;
328
+ *margin-left: 42.62865975631933%;
329
+ }
330
+ .row-fluid .offset4 {
331
+ margin-left: 36.75213675213675%;
332
+ *margin-left: 36.645753773413354%;
333
+ }
334
+ .row-fluid .offset4:first-child {
335
+ margin-left: 34.18803418803419%;
336
+ *margin-left: 34.081651209310785%;
337
+ }
338
+ .row-fluid .offset3 {
339
+ margin-left: 28.205128205128204%;
340
+ *margin-left: 28.0987452264048%;
341
+ }
342
+ .row-fluid .offset3:first-child {
343
+ margin-left: 25.641025641025642%;
344
+ *margin-left: 25.53464266230224%;
345
+ }
346
+ .row-fluid .offset2 {
347
+ margin-left: 19.65811965811966%;
348
+ *margin-left: 19.551736679396257%;
349
+ }
350
+ .row-fluid .offset2:first-child {
351
+ margin-left: 17.094017094017094%;
352
+ *margin-left: 16.98763411529369%;
353
+ }
354
+ .row-fluid .offset1 {
355
+ margin-left: 11.11111111111111%;
356
+ *margin-left: 11.004728132387708%;
357
+ }
358
+ .row-fluid .offset1:first-child {
359
+ margin-left: 8.547008547008547%;
360
+ *margin-left: 8.440625568285142%;
361
+ }
362
+ input,
363
+ textarea,
364
+ .uneditable-input {
365
+ margin-left: 0;
366
+ }
367
+ .controls-row [class*="span"] + [class*="span"] {
368
+ margin-left: 30px;
369
+ }
370
+ input.span12,
371
+ textarea.span12,
372
+ .uneditable-input.span12 {
373
+ width: 1156px;
374
+ }
375
+ input.span11,
376
+ textarea.span11,
377
+ .uneditable-input.span11 {
378
+ width: 1056px;
379
+ }
380
+ input.span10,
381
+ textarea.span10,
382
+ .uneditable-input.span10 {
383
+ width: 956px;
384
+ }
385
+ input.span9,
386
+ textarea.span9,
387
+ .uneditable-input.span9 {
388
+ width: 856px;
389
+ }
390
+ input.span8,
391
+ textarea.span8,
392
+ .uneditable-input.span8 {
393
+ width: 756px;
394
+ }
395
+ input.span7,
396
+ textarea.span7,
397
+ .uneditable-input.span7 {
398
+ width: 656px;
399
+ }
400
+ input.span6,
401
+ textarea.span6,
402
+ .uneditable-input.span6 {
403
+ width: 556px;
404
+ }
405
+ input.span5,
406
+ textarea.span5,
407
+ .uneditable-input.span5 {
408
+ width: 456px;
409
+ }
410
+ input.span4,
411
+ textarea.span4,
412
+ .uneditable-input.span4 {
413
+ width: 356px;
414
+ }
415
+ input.span3,
416
+ textarea.span3,
417
+ .uneditable-input.span3 {
418
+ width: 256px;
419
+ }
420
+ input.span2,
421
+ textarea.span2,
422
+ .uneditable-input.span2 {
423
+ width: 156px;
424
+ }
425
+ input.span1,
426
+ textarea.span1,
427
+ .uneditable-input.span1 {
428
+ width: 56px;
429
+ }
430
+ .thumbnails {
431
+ margin-left: -30px;
432
+ }
433
+ .thumbnails > li {
434
+ margin-left: 30px;
435
+ }
436
+ .row-fluid .thumbnails {
437
+ margin-left: 0;
438
+ }
439
+ }
440
+
441
+ @media (min-width: 768px) and (max-width: 979px) {
442
+ .row {
443
+ margin-left: -20px;
444
+ *zoom: 1;
445
+ }
446
+ .row:before,
447
+ .row:after {
448
+ display: table;
449
+ line-height: 0;
450
+ content: "";
451
+ }
452
+ .row:after {
453
+ clear: both;
454
+ }
455
+ [class*="span"] {
456
+ float: left;
457
+ min-height: 1px;
458
+ margin-left: 20px;
459
+ }
460
+ .container,
461
+ .navbar-static-top .container,
462
+ .navbar-fixed-top .container,
463
+ .navbar-fixed-bottom .container {
464
+ width: 724px;
465
+ }
466
+ .span12 {
467
+ width: 724px;
468
+ }
469
+ .span11 {
470
+ width: 662px;
471
+ }
472
+ .span10 {
473
+ width: 600px;
474
+ }
475
+ .span9 {
476
+ width: 538px;
477
+ }
478
+ .span8 {
479
+ width: 476px;
480
+ }
481
+ .span7 {
482
+ width: 414px;
483
+ }
484
+ .span6 {
485
+ width: 352px;
486
+ }
487
+ .span5 {
488
+ width: 290px;
489
+ }
490
+ .span4 {
491
+ width: 228px;
492
+ }
493
+ .span3 {
494
+ width: 166px;
495
+ }
496
+ .span2 {
497
+ width: 104px;
498
+ }
499
+ .span1 {
500
+ width: 42px;
501
+ }
502
+ .offset12 {
503
+ margin-left: 764px;
504
+ }
505
+ .offset11 {
506
+ margin-left: 702px;
507
+ }
508
+ .offset10 {
509
+ margin-left: 640px;
510
+ }
511
+ .offset9 {
512
+ margin-left: 578px;
513
+ }
514
+ .offset8 {
515
+ margin-left: 516px;
516
+ }
517
+ .offset7 {
518
+ margin-left: 454px;
519
+ }
520
+ .offset6 {
521
+ margin-left: 392px;
522
+ }
523
+ .offset5 {
524
+ margin-left: 330px;
525
+ }
526
+ .offset4 {
527
+ margin-left: 268px;
528
+ }
529
+ .offset3 {
530
+ margin-left: 206px;
531
+ }
532
+ .offset2 {
533
+ margin-left: 144px;
534
+ }
535
+ .offset1 {
536
+ margin-left: 82px;
537
+ }
538
+ .row-fluid {
539
+ width: 100%;
540
+ *zoom: 1;
541
+ }
542
+ .row-fluid:before,
543
+ .row-fluid:after {
544
+ display: table;
545
+ line-height: 0;
546
+ content: "";
547
+ }
548
+ .row-fluid:after {
549
+ clear: both;
550
+ }
551
+ .row-fluid [class*="span"] {
552
+ display: block;
553
+ float: left;
554
+ width: 100%;
555
+ min-height: 30px;
556
+ margin-left: 2.7624309392265194%;
557
+ *margin-left: 2.709239449864817%;
558
+ -webkit-box-sizing: border-box;
559
+ -moz-box-sizing: border-box;
560
+ box-sizing: border-box;
561
+ }
562
+ .row-fluid [class*="span"]:first-child {
563
+ margin-left: 0;
564
+ }
565
+ .row-fluid .span12 {
566
+ width: 100%;
567
+ *width: 99.94680851063829%;
568
+ }
569
+ .row-fluid .span11 {
570
+ width: 91.43646408839778%;
571
+ *width: 91.38327259903608%;
572
+ }
573
+ .row-fluid .span10 {
574
+ width: 82.87292817679558%;
575
+ *width: 82.81973668743387%;
576
+ }
577
+ .row-fluid .span9 {
578
+ width: 74.30939226519337%;
579
+ *width: 74.25620077583166%;
580
+ }
581
+ .row-fluid .span8 {
582
+ width: 65.74585635359117%;
583
+ *width: 65.69266486422946%;
584
+ }
585
+ .row-fluid .span7 {
586
+ width: 57.18232044198895%;
587
+ *width: 57.12912895262725%;
588
+ }
589
+ .row-fluid .span6 {
590
+ width: 48.61878453038674%;
591
+ *width: 48.56559304102504%;
592
+ }
593
+ .row-fluid .span5 {
594
+ width: 40.05524861878453%;
595
+ *width: 40.00205712942283%;
596
+ }
597
+ .row-fluid .span4 {
598
+ width: 31.491712707182323%;
599
+ *width: 31.43852121782062%;
600
+ }
601
+ .row-fluid .span3 {
602
+ width: 22.92817679558011%;
603
+ *width: 22.87498530621841%;
604
+ }
605
+ .row-fluid .span2 {
606
+ width: 14.3646408839779%;
607
+ *width: 14.311449394616199%;
608
+ }
609
+ .row-fluid .span1 {
610
+ width: 5.801104972375691%;
611
+ *width: 5.747913483013988%;
612
+ }
613
+ .row-fluid .offset12 {
614
+ margin-left: 105.52486187845304%;
615
+ *margin-left: 105.41847889972962%;
616
+ }
617
+ .row-fluid .offset12:first-child {
618
+ margin-left: 102.76243093922652%;
619
+ *margin-left: 102.6560479605031%;
620
+ }
621
+ .row-fluid .offset11 {
622
+ margin-left: 96.96132596685082%;
623
+ *margin-left: 96.8549429881274%;
624
+ }
625
+ .row-fluid .offset11:first-child {
626
+ margin-left: 94.1988950276243%;
627
+ *margin-left: 94.09251204890089%;
628
+ }
629
+ .row-fluid .offset10 {
630
+ margin-left: 88.39779005524862%;
631
+ *margin-left: 88.2914070765252%;
632
+ }
633
+ .row-fluid .offset10:first-child {
634
+ margin-left: 85.6353591160221%;
635
+ *margin-left: 85.52897613729868%;
636
+ }
637
+ .row-fluid .offset9 {
638
+ margin-left: 79.8342541436464%;
639
+ *margin-left: 79.72787116492299%;
640
+ }
641
+ .row-fluid .offset9:first-child {
642
+ margin-left: 77.07182320441989%;
643
+ *margin-left: 76.96544022569647%;
644
+ }
645
+ .row-fluid .offset8 {
646
+ margin-left: 71.2707182320442%;
647
+ *margin-left: 71.16433525332079%;
648
+ }
649
+ .row-fluid .offset8:first-child {
650
+ margin-left: 68.50828729281768%;
651
+ *margin-left: 68.40190431409427%;
652
+ }
653
+ .row-fluid .offset7 {
654
+ margin-left: 62.70718232044199%;
655
+ *margin-left: 62.600799341718584%;
656
+ }
657
+ .row-fluid .offset7:first-child {
658
+ margin-left: 59.94475138121547%;
659
+ *margin-left: 59.838368402492065%;
660
+ }
661
+ .row-fluid .offset6 {
662
+ margin-left: 54.14364640883978%;
663
+ *margin-left: 54.037263430116376%;
664
+ }
665
+ .row-fluid .offset6:first-child {
666
+ margin-left: 51.38121546961326%;
667
+ *margin-left: 51.27483249088986%;
668
+ }
669
+ .row-fluid .offset5 {
670
+ margin-left: 45.58011049723757%;
671
+ *margin-left: 45.47372751851417%;
672
+ }
673
+ .row-fluid .offset5:first-child {
674
+ margin-left: 42.81767955801105%;
675
+ *margin-left: 42.71129657928765%;
676
+ }
677
+ .row-fluid .offset4 {
678
+ margin-left: 37.01657458563536%;
679
+ *margin-left: 36.91019160691196%;
680
+ }
681
+ .row-fluid .offset4:first-child {
682
+ margin-left: 34.25414364640884%;
683
+ *margin-left: 34.14776066768544%;
684
+ }
685
+ .row-fluid .offset3 {
686
+ margin-left: 28.45303867403315%;
687
+ *margin-left: 28.346655695309746%;
688
+ }
689
+ .row-fluid .offset3:first-child {
690
+ margin-left: 25.69060773480663%;
691
+ *margin-left: 25.584224756083227%;
692
+ }
693
+ .row-fluid .offset2 {
694
+ margin-left: 19.88950276243094%;
695
+ *margin-left: 19.783119783707537%;
696
+ }
697
+ .row-fluid .offset2:first-child {
698
+ margin-left: 17.12707182320442%;
699
+ *margin-left: 17.02068884448102%;
700
+ }
701
+ .row-fluid .offset1 {
702
+ margin-left: 11.32596685082873%;
703
+ *margin-left: 11.219583872105325%;
704
+ }
705
+ .row-fluid .offset1:first-child {
706
+ margin-left: 8.56353591160221%;
707
+ *margin-left: 8.457152932878806%;
708
+ }
709
+ input,
710
+ textarea,
711
+ .uneditable-input {
712
+ margin-left: 0;
713
+ }
714
+ .controls-row [class*="span"] + [class*="span"] {
715
+ margin-left: 20px;
716
+ }
717
+ input.span12,
718
+ textarea.span12,
719
+ .uneditable-input.span12 {
720
+ width: 710px;
721
+ }
722
+ input.span11,
723
+ textarea.span11,
724
+ .uneditable-input.span11 {
725
+ width: 648px;
726
+ }
727
+ input.span10,
728
+ textarea.span10,
729
+ .uneditable-input.span10 {
730
+ width: 586px;
731
+ }
732
+ input.span9,
733
+ textarea.span9,
734
+ .uneditable-input.span9 {
735
+ width: 524px;
736
+ }
737
+ input.span8,
738
+ textarea.span8,
739
+ .uneditable-input.span8 {
740
+ width: 462px;
741
+ }
742
+ input.span7,
743
+ textarea.span7,
744
+ .uneditable-input.span7 {
745
+ width: 400px;
746
+ }
747
+ input.span6,
748
+ textarea.span6,
749
+ .uneditable-input.span6 {
750
+ width: 338px;
751
+ }
752
+ input.span5,
753
+ textarea.span5,
754
+ .uneditable-input.span5 {
755
+ width: 276px;
756
+ }
757
+ input.span4,
758
+ textarea.span4,
759
+ .uneditable-input.span4 {
760
+ width: 214px;
761
+ }
762
+ input.span3,
763
+ textarea.span3,
764
+ .uneditable-input.span3 {
765
+ width: 152px;
766
+ }
767
+ input.span2,
768
+ textarea.span2,
769
+ .uneditable-input.span2 {
770
+ width: 90px;
771
+ }
772
+ input.span1,
773
+ textarea.span1,
774
+ .uneditable-input.span1 {
775
+ width: 28px;
776
+ }
777
+ }
778
+
779
+ @media (max-width: 767px) {
780
+ body {
781
+ padding-right: 20px;
782
+ padding-left: 20px;
783
+ }
784
+ .navbar-fixed-top,
785
+ .navbar-fixed-bottom,
786
+ .navbar-static-top {
787
+ margin-right: -20px;
788
+ margin-left: -20px;
789
+ }
790
+ .container-fluid {
791
+ padding: 0;
792
+ }
793
+ .dl-horizontal dt {
794
+ float: none;
795
+ width: auto;
796
+ clear: none;
797
+ text-align: left;
798
+ }
799
+ .dl-horizontal dd {
800
+ margin-left: 0;
801
+ }
802
+ .container {
803
+ width: auto;
804
+ }
805
+ .row-fluid {
806
+ width: 100%;
807
+ }
808
+ .row,
809
+ .thumbnails {
810
+ margin-left: 0;
811
+ }
812
+ .thumbnails > li {
813
+ float: none;
814
+ margin-left: 0;
815
+ }
816
+ [class*="span"],
817
+ .row-fluid [class*="span"] {
818
+ display: block;
819
+ float: none;
820
+ width: 100%;
821
+ margin-left: 0;
822
+ -webkit-box-sizing: border-box;
823
+ -moz-box-sizing: border-box;
824
+ box-sizing: border-box;
825
+ }
826
+ .span12,
827
+ .row-fluid .span12 {
828
+ width: 100%;
829
+ -webkit-box-sizing: border-box;
830
+ -moz-box-sizing: border-box;
831
+ box-sizing: border-box;
832
+ }
833
+ .input-large,
834
+ .input-xlarge,
835
+ .input-xxlarge,
836
+ input[class*="span"],
837
+ select[class*="span"],
838
+ textarea[class*="span"],
839
+ .uneditable-input {
840
+ display: block;
841
+ width: 100%;
842
+ min-height: 30px;
843
+ -webkit-box-sizing: border-box;
844
+ -moz-box-sizing: border-box;
845
+ box-sizing: border-box;
846
+ }
847
+ .input-prepend input,
848
+ .input-append input,
849
+ .input-prepend input[class*="span"],
850
+ .input-append input[class*="span"] {
851
+ display: inline-block;
852
+ width: auto;
853
+ }
854
+ .controls-row [class*="span"] + [class*="span"] {
855
+ margin-left: 0;
856
+ }
857
+ .modal {
858
+ position: fixed;
859
+ top: 20px;
860
+ right: 20px;
861
+ left: 20px;
862
+ width: auto;
863
+ margin: 0;
864
+ }
865
+ .modal.fade.in {
866
+ top: auto;
867
+ }
868
+ }
869
+
870
+ @media (max-width: 480px) {
871
+ .nav-collapse {
872
+ -webkit-transform: translate3d(0, 0, 0);
873
+ }
874
+ .page-header h1 small {
875
+ display: block;
876
+ line-height: 20px;
877
+ }
878
+ input[type="checkbox"],
879
+ input[type="radio"] {
880
+ border: 1px solid #ccc;
881
+ }
882
+ .form-horizontal .control-label {
883
+ float: none;
884
+ width: auto;
885
+ padding-top: 0;
886
+ text-align: left;
887
+ }
888
+ .form-horizontal .controls {
889
+ margin-left: 0;
890
+ }
891
+ .form-horizontal .control-list {
892
+ padding-top: 0;
893
+ }
894
+ .form-horizontal .form-actions {
895
+ padding-right: 10px;
896
+ padding-left: 10px;
897
+ }
898
+ .modal {
899
+ top: 10px;
900
+ right: 10px;
901
+ left: 10px;
902
+ }
903
+ .modal-header .close {
904
+ padding: 10px;
905
+ margin: -10px;
906
+ }
907
+ .carousel-caption {
908
+ position: static;
909
+ }
910
+ }
911
+
912
+ @media (max-width: 979px) {
913
+ body {
914
+ padding-top: 0;
915
+ }
916
+ .navbar-fixed-top,
917
+ .navbar-fixed-bottom {
918
+ position: static;
919
+ }
920
+ .navbar-fixed-top {
921
+ margin-bottom: 20px;
922
+ }
923
+ .navbar-fixed-bottom {
924
+ margin-top: 20px;
925
+ }
926
+ .navbar-fixed-top .navbar-inner,
927
+ .navbar-fixed-bottom .navbar-inner {
928
+ padding: 5px;
929
+ }
930
+ .navbar .container {
931
+ width: auto;
932
+ padding: 0;
933
+ }
934
+ .navbar .brand {
935
+ padding-right: 10px;
936
+ padding-left: 10px;
937
+ margin: 0 0 0 -5px;
938
+ }
939
+ .nav-collapse {
940
+ clear: both;
941
+ }
942
+ .nav-collapse .nav {
943
+ float: none;
944
+ margin: 0 0 10px;
945
+ }
946
+ .nav-collapse .nav > li {
947
+ float: none;
948
+ }
949
+ .nav-collapse .nav > li > a {
950
+ margin-bottom: 2px;
951
+ }
952
+ .nav-collapse .nav > .divider-vertical {
953
+ display: none;
954
+ }
955
+ .nav-collapse .nav .nav-header {
956
+ color: #777777;
957
+ text-shadow: none;
958
+ }
959
+ .nav-collapse .nav > li > a,
960
+ .nav-collapse .dropdown-menu a {
961
+ padding: 9px 15px;
962
+ font-weight: bold;
963
+ color: #777777;
964
+ -webkit-border-radius: 3px;
965
+ -moz-border-radius: 3px;
966
+ border-radius: 3px;
967
+ }
968
+ .nav-collapse .btn {
969
+ padding: 4px 10px 4px;
970
+ font-weight: normal;
971
+ -webkit-border-radius: 4px;
972
+ -moz-border-radius: 4px;
973
+ border-radius: 4px;
974
+ }
975
+ .nav-collapse .dropdown-menu li + li a {
976
+ margin-bottom: 2px;
977
+ }
978
+ .nav-collapse .nav > li > a:hover,
979
+ .nav-collapse .dropdown-menu a:hover {
980
+ background-color: #f2f2f2;
981
+ }
982
+ .navbar-inverse .nav-collapse .nav > li > a:hover,
983
+ .navbar-inverse .nav-collapse .dropdown-menu a:hover {
984
+ background-color: #111111;
985
+ }
986
+ .nav-collapse.in .btn-group {
987
+ padding: 0;
988
+ margin-top: 5px;
989
+ }
990
+ .nav-collapse .dropdown-menu {
991
+ position: static;
992
+ top: auto;
993
+ left: auto;
994
+ display: block;
995
+ float: none;
996
+ max-width: none;
997
+ padding: 0;
998
+ margin: 0 15px;
999
+ background-color: transparent;
1000
+ border: none;
1001
+ -webkit-border-radius: 0;
1002
+ -moz-border-radius: 0;
1003
+ border-radius: 0;
1004
+ -webkit-box-shadow: none;
1005
+ -moz-box-shadow: none;
1006
+ box-shadow: none;
1007
+ }
1008
+ .nav-collapse .dropdown-menu:before,
1009
+ .nav-collapse .dropdown-menu:after {
1010
+ display: none;
1011
+ }
1012
+ .nav-collapse .dropdown-menu .divider {
1013
+ display: none;
1014
+ }
1015
+ .nav-collapse .nav > li > .dropdown-menu:before,
1016
+ .nav-collapse .nav > li > .dropdown-menu:after {
1017
+ display: none;
1018
+ }
1019
+ .nav-collapse .navbar-form,
1020
+ .nav-collapse .navbar-search {
1021
+ float: none;
1022
+ padding: 10px 15px;
1023
+ margin: 10px 0;
1024
+ border-top: 1px solid #f2f2f2;
1025
+ border-bottom: 1px solid #f2f2f2;
1026
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1027
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1028
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1029
+ }
1030
+ .navbar-inverse .nav-collapse .navbar-form,
1031
+ .navbar-inverse .nav-collapse .navbar-search {
1032
+ border-top-color: #111111;
1033
+ border-bottom-color: #111111;
1034
+ }
1035
+ .navbar .nav-collapse .nav.pull-right {
1036
+ float: none;
1037
+ margin-left: 0;
1038
+ }
1039
+ .nav-collapse,
1040
+ .nav-collapse.collapse {
1041
+ height: 0;
1042
+ overflow: hidden;
1043
+ }
1044
+ .navbar .btn-navbar {
1045
+ display: block;
1046
+ }
1047
+ .navbar-static .navbar-inner {
1048
+ padding-right: 10px;
1049
+ padding-left: 10px;
1050
+ }
1051
+ }
1052
+
1053
+ @media (min-width: 980px) {
1054
+ .nav-collapse.collapse {
1055
+ height: auto !important;
1056
+ overflow: visible !important;
1057
+ }
1058
+ }