mail_relay 0.1.0

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.
Files changed (56) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +73 -0
  3. data/Rakefile +22 -0
  4. data/lib/mail_relay.rb +5 -0
  5. data/lib/mail_relay/base.rb +149 -0
  6. data/lib/mail_relay/version.rb +3 -0
  7. data/spec/base_spec.rb +113 -0
  8. data/spec/coverage/assets/0.7.1/application.css +1110 -0
  9. data/spec/coverage/assets/0.7.1/application.js +626 -0
  10. data/spec/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  11. data/spec/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  12. data/spec/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  13. data/spec/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  14. data/spec/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  15. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  16. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  17. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  18. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  19. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  20. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  21. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  22. data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  23. data/spec/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  24. data/spec/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  25. data/spec/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  26. data/spec/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  27. data/spec/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  28. data/spec/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  29. data/spec/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  30. data/spec/coverage/assets/0.7.1/favicon_green.png +0 -0
  31. data/spec/coverage/assets/0.7.1/favicon_red.png +0 -0
  32. data/spec/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  33. data/spec/coverage/assets/0.7.1/loading.gif +0 -0
  34. data/spec/coverage/assets/0.7.1/magnify.png +0 -0
  35. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  36. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  37. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  38. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  39. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  40. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  41. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  42. data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  43. data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  44. data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  45. data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  46. data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  47. data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  48. data/spec/coverage/index.html +1052 -0
  49. data/spec/fixtures/list.eml +35 -0
  50. data/spec/fixtures/list.eml~ +36 -0
  51. data/spec/fixtures/regular.eml +35 -0
  52. data/spec/fixtures/regular.eml~ +66 -0
  53. data/spec/fixtures/simple.eml +15 -0
  54. data/spec/fixtures/simple.eml~ +15 -0
  55. data/spec/spec_helper.rb +19 -0
  56. metadata +252 -0
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Pascal Zumkehr
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,73 @@
1
+ = Mail Relay
2
+
3
+ Retrieves messages from a mail server and resends them to a list of receivers.
4
+
5
+ First of all, you need a mail domain with a catch-all account. Configure the access to this account for {Mail}[https://github.com/mikel/mail]:
6
+
7
+ Mail.defaults do
8
+ retriever_method(:pop3, address: 'localhost',
9
+ port: 995,
10
+ user_name: 'catchall',
11
+ password: 'secret',
12
+ enable_ssl: true)
13
+ end
14
+
15
+ The sending configuration is also done over Mail. See their documentation how to change the defaults.
16
+
17
+
18
+ Then create your own subclass of <tt>MailRelay::Base</tt> and overwrite the following methods:
19
+
20
+ class RootRelay < MailRelay::Base
21
+ # Is the mail sent to a valid relay address?
22
+ def relay_address?
23
+ true
24
+ end
25
+
26
+ # Is the mail sender allowed to post to this address
27
+ def sender_allowed?
28
+ true
29
+ end
30
+
31
+ # List of receiver email addresses for the resent email.
32
+ def receivers
33
+ ['root@example.com']
34
+ end
35
+ end
36
+
37
+
38
+ Every email from the server is processed in an own RootRelay instance and available there as +message+.
39
+ Several methods like +envelope_receiver_name+ or +sender_email+ are available to help you implement above methods.
40
+ Two callback methods, +reject_not_existing+ and +reject_not_allowed+, are called if the email is not sent to a
41
+ valid relay address or if the sender is not allowed to post. So the main method boils down to the following:
42
+
43
+ def relay
44
+ if relay_address?
45
+ if sender_allowed?
46
+ resend_to(receivers)
47
+ else
48
+ reject_not_allowed
49
+ end
50
+ else
51
+ reject_not_existing
52
+ end
53
+ end
54
+
55
+ After processing, the email is deleted from the server.
56
+
57
+ Now you only need to run your relay regularly, for example with
58
+ {Delayed::Job}[https://github.com/collectiveidea/delayed_job] or some other queue system:
59
+
60
+ RootRelay.relay_current
61
+
62
+
63
+ The following values may be configured for your relay:
64
+
65
+ retrieve_count (5):: Maximum number of emails to retrieve in one batch. +relay_current+ will run as many batches until all currently available emails are processed.
66
+
67
+ receiver_header (X-Envelope-To):: The name of an X Header that contains the envelope receiver of the email. This header may be set by your mail server.
68
+
69
+
70
+
71
+ (c) 2013 Pascal Zumkehr MIT
72
+
73
+ {<img src="https://secure.travis-ci.org/codez/mail_relay.png" />}[http://travis-ci.org/codez/mail_relay]
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env rake
2
+ require "rubygems"
3
+ require "bundler/setup"
4
+
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+
9
+ require "rspec/core/rake_task"
10
+ RSpec::Core::RakeTask.new(:spec)
11
+
12
+
13
+ require 'rdoc/task'
14
+ RDoc::Task.new(:rdoc) do |rdoc|
15
+ rdoc.rdoc_dir = 'rdoc'
16
+ rdoc.title = 'mail_relay'
17
+ rdoc.options << '--line-numbers'
18
+ rdoc.rdoc_files.include('README.rdoc')
19
+ rdoc.rdoc_files.include('lib/**/*.rb')
20
+ end
21
+
22
+ task :default => :spec
@@ -0,0 +1,5 @@
1
+ require 'mail'
2
+ require 'mail_relay/base'
3
+
4
+ module MailRelay
5
+ end
@@ -0,0 +1,149 @@
1
+ module MailRelay
2
+ # A generic email relay object. Retrieves messages from a mail server and resends them to a list of recievers.
3
+ # In subclasses, override the methods #relay_address?, #sender_allowed? and #receivers
4
+ # to constrain which mails are sent to whom.
5
+ class Base
6
+
7
+ class << self
8
+ # Define a header that contains the original receiver address.
9
+ # This header could be set by the mail server.
10
+ attr_accessor :receiver_header
11
+
12
+ # Number of emails to retrieve in one batch.
13
+ attr_accessor :retrieve_count
14
+
15
+ # Retrieve, process and delete all mails from the mail server.
16
+ def relay_current
17
+ begin
18
+ last_exception = nil
19
+
20
+ mails = Mail.find_and_delete(:count => retrieve_count) do |message|
21
+ begin
22
+ new(message).relay
23
+ rescue Exception => e
24
+ last_exception = e
25
+ end
26
+ end
27
+
28
+ raise(last_exception) if last_exception
29
+
30
+ end while mails.size >= retrieve_count
31
+ end
32
+
33
+ end
34
+
35
+ self.retrieve_count = 5
36
+ self.receiver_header = 'X-Envelope-To'
37
+
38
+
39
+ attr_reader :message
40
+
41
+ def initialize(message)
42
+ @message = message
43
+ end
44
+
45
+ # Process the given email.
46
+ def relay
47
+ if relay_address?
48
+ if sender_allowed?
49
+ resend_to(receivers)
50
+ else
51
+ reject_not_allowed
52
+ end
53
+ else
54
+ reject_not_existing
55
+ end
56
+ end
57
+
58
+ # Send the same mail as is to all receivers, if any.
59
+ def resend_to(destinations)
60
+ if destinations.size > 0
61
+ add_custom_message_destinations
62
+ message.destinations = destinations
63
+ message.header['Precedence'] = 'list'
64
+ deliver(message)
65
+ end
66
+ end
67
+
68
+ # If the email sender was not allowed to post messages, this method is called.
69
+ # Silently ignores the message by default.
70
+ def reject_not_allowed
71
+ # do nothing
72
+ end
73
+
74
+ # If the email is sent to an address that is not a valid relay, this method is called.
75
+ # Silently ignores the message by default.
76
+ def reject_not_existing
77
+ # do nothing
78
+ end
79
+
80
+ # The receiver account that originally got this email.
81
+ # You probably have to re-implement this method depending on your mail server setup.
82
+ # Returns only the part before the @ sign.
83
+ def envelope_receiver_name
84
+ receiver_from_x_header ||
85
+ receiver_from_received_header ||
86
+ raise("Could not determine original receiver for email:\n#{message.header}")
87
+ end
88
+
89
+ # The email address of the sender. As found in the from header.
90
+ def sender_email
91
+ @sender_email ||= message.from && message.from.first
92
+ end
93
+
94
+
95
+ # Heuristic method to find actual receiver of the message.
96
+ # May return nil if could not determine.
97
+ def receiver_from_received_header
98
+ if received = message.received
99
+ received = received.first if received.respond_to?(:first)
100
+ received.info[/ for .*?([^\s<>]+)@[^\s<>]+/, 1]
101
+ end
102
+ end
103
+
104
+ # Try to read the envelope receiver from the given x header
105
+ def receiver_from_x_header
106
+ if field = message.header[self.class.receiver_header]
107
+ field.to_s.split('@', 2).first
108
+ end
109
+ end
110
+
111
+ # Is the mail sent to a valid relay address?
112
+ def relay_address?
113
+ true
114
+ end
115
+
116
+ # Is the mail sender allowed to post to this address
117
+ def sender_allowed?
118
+ true
119
+ end
120
+
121
+ # List of receiver email addresses for the resent email.
122
+ def receivers
123
+ []
124
+ end
125
+
126
+
127
+ private
128
+
129
+ def deliver(message)
130
+ if defined?(ActionMailer::Base)
131
+ ActionMailer::Base.wrap_delivery_behavior(message)
132
+ end
133
+ message.deliver
134
+ end
135
+
136
+ def add_custom_message_destinations
137
+ class << message
138
+ def destinations
139
+ @destinations || []
140
+ end
141
+
142
+ def destinations=(destinations)
143
+ @destinations = destinations
144
+ end
145
+ end
146
+ end
147
+
148
+ end
149
+ end
@@ -0,0 +1,3 @@
1
+ module MailRelay
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe MailRelay::Base do
4
+
5
+ let(:simple) { Mail.new(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'simple.eml'))) }
6
+ let(:regular) { Mail.new(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'regular.eml'))) }
7
+ let(:list) { Mail.new(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'list.eml'))) }
8
+
9
+ let(:relay) { MailRelay::Base.new(message) }
10
+
11
+ let(:last_email) { Mail::TestMailer.deliveries.last }
12
+
13
+ describe "#receiver_from_received_header" do
14
+ subject { relay }
15
+
16
+ context "simple" do
17
+ let(:message) { simple }
18
+
19
+ its(:receiver_from_received_header) { should be_nil }
20
+ its(:receiver_from_x_header) { should be_nil }
21
+ end
22
+
23
+ context "regular" do
24
+ let(:message) { regular }
25
+
26
+ its(:receiver_from_received_header) { should == 'receiver' }
27
+ its(:receiver_from_x_header) { should == 'receiver' }
28
+ end
29
+
30
+ context "list" do
31
+ let(:message) { list }
32
+
33
+ its(:receiver_from_received_header) { should == 'receiver' }
34
+ its(:receiver_from_x_header) { should == 'receiver' }
35
+ end
36
+ end
37
+
38
+ describe "#envelope_receiver_name" do
39
+ context "regular" do
40
+ let(:message) { regular }
41
+
42
+ it "returns receiver" do
43
+ relay.envelope_receiver_name.should == 'receiver'
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#relay" do
49
+ let(:message) { regular }
50
+
51
+ subject { last_email }
52
+
53
+ context "without receivers" do
54
+ before { relay.relay }
55
+
56
+ it { should be_nil }
57
+ end
58
+
59
+ context "with receivers" do
60
+ let(:receivers) { %w(a@example.com b@example.com) }
61
+ before do
62
+ relay.stub(:receivers).and_return(receivers)
63
+ relay.relay
64
+ end
65
+
66
+ it { should_not be_nil }
67
+ its(:destinations) { should == receivers }
68
+ its(:to) { should == ['receiver@example.com'] }
69
+ its(:from) { should == ['sender@example.com'] }
70
+ end
71
+ end
72
+
73
+ describe ".relay_current" do
74
+ it "processes all mails" do
75
+ MailRelay::Base.retrieve_count = 5
76
+
77
+ first = true
78
+ Mail.should_receive(:find_and_delete) do |options, &block|
79
+ msgs = first ? [1,2,3,4,5] : [6,7,8]
80
+ msgs.each {|m| block.call(m) }
81
+ first = false
82
+ msgs
83
+ end.twice
84
+
85
+ m = mock
86
+ m.stub(:relay)
87
+ MailRelay::Base.stub(:new).and_return(m)
88
+ MailRelay::Base.should_receive(:new).exactly(8).times
89
+
90
+ MailRelay::Base.relay_current
91
+ end
92
+
93
+ it "fails after one batch" do
94
+ MailRelay::Base.retrieve_count = 5
95
+
96
+ first = true
97
+ Mail.should_receive(:find_and_delete) do |options, &block|
98
+ msgs = first ? [1,2,3,4,5] : [6,7,8]
99
+ msgs.each {|m| block.call(m) }
100
+ first = false
101
+ msgs
102
+ end
103
+
104
+ m = mock
105
+ mock.stub(:relay)
106
+ MailRelay::Base.stub(:new).with(anything).and_return(m)
107
+ MailRelay::Base.stub(:new).with(3).and_raise("failure!")
108
+ MailRelay::Base.should_receive(:new).exactly(5).times
109
+
110
+ expect { MailRelay::Base.relay_current }.to raise_error('failure!')
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,1110 @@
1
+ /* -----------------------------------------------------------------------
2
+
3
+
4
+ Blueprint CSS Framework 0.9
5
+ http://blueprintcss.org
6
+
7
+ * Copyright (c) 2007-Present. See LICENSE for more info.
8
+ * See README for instructions on how to use Blueprint.
9
+ * For credits and origins, see AUTHORS.
10
+ * This is a compressed file. See the sources in the 'src' directory.
11
+
12
+ ----------------------------------------------------------------------- */
13
+
14
+ /* reset.css */
15
+
16
+ html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, nav, section {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
17
+ article, aside, dialog, figure, footer, header, hgroup, nav, section {display:block;}
18
+ body {line-height:1.5;}
19
+ table {border-collapse:separate;border-spacing:0;}
20
+ caption, th, td {text-align:left;font-weight:normal;}
21
+ table, td, th {vertical-align:middle;}
22
+ blockquote:before, blockquote:after, q:before, q:after {content:"";}
23
+ blockquote, q {quotes:"" "";}
24
+ a img {border:none;}
25
+
26
+ /* typography.css */
27
+ html {font-size:100.01%;}
28
+ body {font-size:82%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
29
+ h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
30
+ h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
31
+ h2 {font-size:2em;margin-bottom:0.75em;}
32
+ h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
33
+ h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
34
+ h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
35
+ h6 {font-size:1em;font-weight:bold;}
36
+ h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
37
+ p {margin:0 0 1.5em;}
38
+ p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;}
39
+ p img.right {float:right;margin:1.5em 0 1.5em 1.5em;}
40
+ a:focus, a:hover {color:#000;}
41
+ a {color:#009;text-decoration:underline;}
42
+ blockquote {margin:1.5em;color:#666;font-style:italic;}
43
+ strong {font-weight:bold;}
44
+ em, dfn {font-style:italic;}
45
+ dfn {font-weight:bold;}
46
+ sup, sub {line-height:0;}
47
+ abbr, acronym {border-bottom:1px dotted #666;}
48
+ address {margin:0 0 1.5em;font-style:italic;}
49
+ del {color:#666;}
50
+ pre {margin:1.5em 0;white-space:pre;}
51
+ pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
52
+ li ul, li ol {margin:0;}
53
+ ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;}
54
+ ul {list-style-type:disc;}
55
+ ol {list-style-type:decimal;}
56
+ dl {margin:0 0 1.5em 0;}
57
+ dl dt {font-weight:bold;}
58
+ dd {margin-left:1.5em;}
59
+ table {margin-bottom:1.4em;width:100%;}
60
+ th {font-weight:bold;}
61
+ thead th {background:#c3d9ff;}
62
+ th, td, caption {padding:4px 10px 4px 5px;}
63
+ tr.even td {background:#efefef;}
64
+ tfoot {font-style:italic;}
65
+ caption {background:#eee;}
66
+ .small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
67
+ .large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
68
+ .hide {display:none;}
69
+ .quiet {color:#666;}
70
+ .loud {color:#000;}
71
+ .highlight {background:#ff0;}
72
+ .added {background:#060;color:#fff;}
73
+ .removed {background:#900;color:#fff;}
74
+ .first {margin-left:0;padding-left:0;}
75
+ .last {margin-right:0;padding-right:0;}
76
+ .top {margin-top:0;padding-top:0;}
77
+ .bottom {margin-bottom:0;padding-bottom:0;}
78
+
79
+ /* forms.css */
80
+ label {font-weight:bold;}
81
+ fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
82
+ legend {font-weight:bold;font-size:1.2em;}
83
+ input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;}
84
+ input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;}
85
+ input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;}
86
+ input.text, input.title {width:300px;padding:5px;}
87
+ input.title {font-size:1.5em;}
88
+ textarea {width:390px;height:250px;padding:5px;}
89
+ input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;}
90
+ form.inline {line-height:3;}
91
+ form.inline p {margin-bottom:0;}
92
+ .error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
93
+ .error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
94
+ .notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
95
+ .success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
96
+ .error a {color:#8a1f11;}
97
+ .notice a {color:#514721;}
98
+ .success a {color:#264409;}
99
+ .box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;}
100
+ hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;}
101
+ hr.space {background:#fff;color:#fff;visibility:hidden;}
102
+ .clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
103
+ .clearfix, .container {display:block;}
104
+ .clear {clear:both;}
105
+ /*
106
+ github.com style (c) Vasily Polovnyov <vast@whiteants.net>
107
+ */
108
+
109
+
110
+ pre code {
111
+ }
112
+
113
+ pre .comment,
114
+ pre .template_comment,
115
+ pre .diff .header,
116
+ pre .javadoc {
117
+ color: #998;
118
+ font-style: italic
119
+ }
120
+
121
+ pre .keyword,
122
+ pre .css .rule .keyword,
123
+ pre .winutils,
124
+ pre .javascript .title,
125
+ pre .lisp .title {
126
+ color: #000;
127
+ font-weight: bold
128
+ }
129
+
130
+ pre .number,
131
+ pre .hexcolor {
132
+ color: #458
133
+ }
134
+
135
+
136
+ pre .string,
137
+ pre .tag .value,
138
+ pre .phpdoc,
139
+ pre .tex .formula {
140
+ color: #d14
141
+ }
142
+
143
+ pre .subst {
144
+ color: #712;
145
+ }
146
+
147
+ pre .constant,
148
+ pre .title,
149
+ pre .id {
150
+ color: #900;
151
+ font-weight: bold
152
+ }
153
+
154
+ pre .javascript .title,
155
+ pre .lisp .title,
156
+ pre .subst {
157
+ font-weight: normal
158
+ }
159
+
160
+ pre .class .title,
161
+ pre .haskell .label,
162
+ pre .tex .command {
163
+ color: #458;
164
+ font-weight: bold
165
+ }
166
+
167
+ pre .tag,
168
+ pre .tag .title,
169
+ pre .rules .property,
170
+ pre .django .tag .keyword {
171
+ color: #000080;
172
+ font-weight: normal
173
+ }
174
+
175
+ pre .attribute,
176
+ pre .variable,
177
+ pre .instancevar,
178
+ pre .lisp .body {
179
+ color: #008080
180
+ }
181
+
182
+ pre .regexp {
183
+ color: #009926
184
+ }
185
+
186
+ pre .class {
187
+ color: #458;
188
+ font-weight: bold
189
+ }
190
+
191
+ pre .symbol,
192
+ pre .ruby .symbol .string,
193
+ pre .ruby .symbol .keyword,
194
+ pre .ruby .symbol .keymethods,
195
+ pre .lisp .keyword,
196
+ pre .tex .special,
197
+ pre .input_number {
198
+ color: #990073
199
+ }
200
+
201
+ pre .builtin,
202
+ pre .built_in,
203
+ pre .lisp .title {
204
+ color: #0086b3
205
+ }
206
+
207
+ pre .preprocessor,
208
+ pre .pi,
209
+ pre .doctype,
210
+ pre .shebang,
211
+ pre .cdata {
212
+ color: #999;
213
+ font-weight: bold
214
+ }
215
+
216
+ pre .deletion {
217
+ background: #fdd
218
+ }
219
+
220
+ pre .addition {
221
+ background: #dfd
222
+ }
223
+
224
+ pre .diff .change {
225
+ background: #0086b3
226
+ }
227
+
228
+ pre .chunk {
229
+ color: #aaa
230
+ }
231
+
232
+ pre .tex .formula {
233
+ opacity: 0.5;
234
+ }
235
+ /*
236
+ * jQuery UI CSS Framework @VERSION
237
+ *
238
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
239
+ * Dual licensed under the MIT or GPL Version 2 licenses.
240
+ * http://jquery.org/license
241
+ *
242
+ * http://docs.jquery.com/UI/Theming/API
243
+ */
244
+
245
+ /* Layout helpers
246
+ ----------------------------------*/
247
+
248
+ .ui-helper-hidden { display: none; }
249
+ .ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
250
+ .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
251
+ .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
252
+ .ui-helper-clearfix { display: inline-block; }
253
+ /* required comment for clearfix to work in Opera \*/
254
+ * html .ui-helper-clearfix { height:1%; }
255
+ .ui-helper-clearfix { display:block; }
256
+ /* end clearfix */
257
+ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
258
+
259
+
260
+ /* Interaction Cues
261
+ ----------------------------------*/
262
+ .ui-state-disabled { cursor: default !important; }
263
+
264
+
265
+ /* Icons
266
+ ----------------------------------*/
267
+
268
+ /* states and images */
269
+ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
270
+
271
+
272
+ /* Misc visuals
273
+ ----------------------------------*/
274
+
275
+ /* Overlays */
276
+ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
277
+
278
+
279
+ /*
280
+ * jQuery UI CSS Framework @VERSION
281
+ *
282
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
283
+ * Dual licensed under the MIT or GPL Version 2 licenses.
284
+ * http://jquery.org/license
285
+ *
286
+ * http://docs.jquery.com/UI/Theming/API
287
+ *
288
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
289
+ */
290
+
291
+
292
+ /* Component containers
293
+ ----------------------------------*/
294
+ .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
295
+ .ui-widget .ui-widget { font-size: 1em; }
296
+ .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
297
+ .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
298
+ .ui-widget-content a { color: #222222; }
299
+ .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
300
+ .ui-widget-header a { color: #222222; }
301
+
302
+ /* Interaction states
303
+ ----------------------------------*/
304
+ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
305
+ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
306
+ .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
307
+ .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
308
+ .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
309
+ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
310
+ .ui-widget :active { outline: none; }
311
+
312
+ /* Interaction Cues
313
+ ----------------------------------*/
314
+ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
315
+ .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
316
+ .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
317
+ .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
318
+ .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
319
+ .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
320
+ .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
321
+ .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
322
+
323
+ /* Icons
324
+ ----------------------------------*/
325
+
326
+ /* states and images */
327
+ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
328
+ .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
329
+ .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
330
+ .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
331
+ .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
332
+ .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
333
+ .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
334
+ .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
335
+
336
+ /* positioning */
337
+ .ui-icon-carat-1-n { background-position: 0 0; }
338
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
339
+ .ui-icon-carat-1-e { background-position: -32px 0; }
340
+ .ui-icon-carat-1-se { background-position: -48px 0; }
341
+ .ui-icon-carat-1-s { background-position: -64px 0; }
342
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
343
+ .ui-icon-carat-1-w { background-position: -96px 0; }
344
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
345
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
346
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
347
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
348
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
349
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
350
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
351
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
352
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
353
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
354
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
355
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
356
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
357
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
358
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
359
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
360
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
361
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
362
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
363
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
364
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
365
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
366
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
367
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
368
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
369
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
370
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
371
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
372
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
373
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
374
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
375
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
376
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
377
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
378
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
379
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
380
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
381
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
382
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
383
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
384
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
385
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
386
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
387
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
388
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
389
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
390
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
391
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
392
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
393
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
394
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
395
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
396
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
397
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
398
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
399
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
400
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
401
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
402
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
403
+ .ui-icon-extlink { background-position: -32px -80px; }
404
+ .ui-icon-newwin { background-position: -48px -80px; }
405
+ .ui-icon-refresh { background-position: -64px -80px; }
406
+ .ui-icon-shuffle { background-position: -80px -80px; }
407
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
408
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
409
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
410
+ .ui-icon-folder-open { background-position: -16px -96px; }
411
+ .ui-icon-document { background-position: -32px -96px; }
412
+ .ui-icon-document-b { background-position: -48px -96px; }
413
+ .ui-icon-note { background-position: -64px -96px; }
414
+ .ui-icon-mail-closed { background-position: -80px -96px; }
415
+ .ui-icon-mail-open { background-position: -96px -96px; }
416
+ .ui-icon-suitcase { background-position: -112px -96px; }
417
+ .ui-icon-comment { background-position: -128px -96px; }
418
+ .ui-icon-person { background-position: -144px -96px; }
419
+ .ui-icon-print { background-position: -160px -96px; }
420
+ .ui-icon-trash { background-position: -176px -96px; }
421
+ .ui-icon-locked { background-position: -192px -96px; }
422
+ .ui-icon-unlocked { background-position: -208px -96px; }
423
+ .ui-icon-bookmark { background-position: -224px -96px; }
424
+ .ui-icon-tag { background-position: -240px -96px; }
425
+ .ui-icon-home { background-position: 0 -112px; }
426
+ .ui-icon-flag { background-position: -16px -112px; }
427
+ .ui-icon-calendar { background-position: -32px -112px; }
428
+ .ui-icon-cart { background-position: -48px -112px; }
429
+ .ui-icon-pencil { background-position: -64px -112px; }
430
+ .ui-icon-clock { background-position: -80px -112px; }
431
+ .ui-icon-disk { background-position: -96px -112px; }
432
+ .ui-icon-calculator { background-position: -112px -112px; }
433
+ .ui-icon-zoomin { background-position: -128px -112px; }
434
+ .ui-icon-zoomout { background-position: -144px -112px; }
435
+ .ui-icon-search { background-position: -160px -112px; }
436
+ .ui-icon-wrench { background-position: -176px -112px; }
437
+ .ui-icon-gear { background-position: -192px -112px; }
438
+ .ui-icon-heart { background-position: -208px -112px; }
439
+ .ui-icon-star { background-position: -224px -112px; }
440
+ .ui-icon-link { background-position: -240px -112px; }
441
+ .ui-icon-cancel { background-position: 0 -128px; }
442
+ .ui-icon-plus { background-position: -16px -128px; }
443
+ .ui-icon-plusthick { background-position: -32px -128px; }
444
+ .ui-icon-minus { background-position: -48px -128px; }
445
+ .ui-icon-minusthick { background-position: -64px -128px; }
446
+ .ui-icon-close { background-position: -80px -128px; }
447
+ .ui-icon-closethick { background-position: -96px -128px; }
448
+ .ui-icon-key { background-position: -112px -128px; }
449
+ .ui-icon-lightbulb { background-position: -128px -128px; }
450
+ .ui-icon-scissors { background-position: -144px -128px; }
451
+ .ui-icon-clipboard { background-position: -160px -128px; }
452
+ .ui-icon-copy { background-position: -176px -128px; }
453
+ .ui-icon-contact { background-position: -192px -128px; }
454
+ .ui-icon-image { background-position: -208px -128px; }
455
+ .ui-icon-video { background-position: -224px -128px; }
456
+ .ui-icon-script { background-position: -240px -128px; }
457
+ .ui-icon-alert { background-position: 0 -144px; }
458
+ .ui-icon-info { background-position: -16px -144px; }
459
+ .ui-icon-notice { background-position: -32px -144px; }
460
+ .ui-icon-help { background-position: -48px -144px; }
461
+ .ui-icon-check { background-position: -64px -144px; }
462
+ .ui-icon-bullet { background-position: -80px -144px; }
463
+ .ui-icon-radio-off { background-position: -96px -144px; }
464
+ .ui-icon-radio-on { background-position: -112px -144px; }
465
+ .ui-icon-pin-w { background-position: -128px -144px; }
466
+ .ui-icon-pin-s { background-position: -144px -144px; }
467
+ .ui-icon-play { background-position: 0 -160px; }
468
+ .ui-icon-pause { background-position: -16px -160px; }
469
+ .ui-icon-seek-next { background-position: -32px -160px; }
470
+ .ui-icon-seek-prev { background-position: -48px -160px; }
471
+ .ui-icon-seek-end { background-position: -64px -160px; }
472
+ .ui-icon-seek-start { background-position: -80px -160px; }
473
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
474
+ .ui-icon-seek-first { background-position: -80px -160px; }
475
+ .ui-icon-stop { background-position: -96px -160px; }
476
+ .ui-icon-eject { background-position: -112px -160px; }
477
+ .ui-icon-volume-off { background-position: -128px -160px; }
478
+ .ui-icon-volume-on { background-position: -144px -160px; }
479
+ .ui-icon-power { background-position: 0 -176px; }
480
+ .ui-icon-signal-diag { background-position: -16px -176px; }
481
+ .ui-icon-signal { background-position: -32px -176px; }
482
+ .ui-icon-battery-0 { background-position: -48px -176px; }
483
+ .ui-icon-battery-1 { background-position: -64px -176px; }
484
+ .ui-icon-battery-2 { background-position: -80px -176px; }
485
+ .ui-icon-battery-3 { background-position: -96px -176px; }
486
+ .ui-icon-circle-plus { background-position: 0 -192px; }
487
+ .ui-icon-circle-minus { background-position: -16px -192px; }
488
+ .ui-icon-circle-close { background-position: -32px -192px; }
489
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
490
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
491
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
492
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
493
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
494
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
495
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
496
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
497
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
498
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
499
+ .ui-icon-circle-check { background-position: -208px -192px; }
500
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
501
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
502
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
503
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
504
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
505
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
506
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
507
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
508
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
509
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
510
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
511
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
512
+
513
+
514
+ /* Misc visuals
515
+ ----------------------------------*/
516
+
517
+ /* Corner radius */
518
+ .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
519
+ .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
520
+ .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
521
+ .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
522
+ .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
523
+ .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
524
+ .ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
525
+ .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
526
+ .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
527
+
528
+ /* Overlays */
529
+ .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
530
+ .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
531
+ /*
532
+ * FancyBox - jQuery Plugin
533
+ * Simple and fancy lightbox alternative
534
+ *
535
+ * Examples and documentation at: http://fancybox.net
536
+ *
537
+ * Copyright (c) 2008 - 2010 Janis Skarnelis
538
+ *
539
+ * Version: 1.3.1 (05/03/2010)
540
+ * Requires: jQuery v1.3+
541
+ *
542
+ * Dual licensed under the MIT and GPL licenses:
543
+ * http://www.opensource.org/licenses/mit-license.php
544
+ * http://www.gnu.org/licenses/gpl.html
545
+ */
546
+
547
+ #fancybox-loading {
548
+ position: fixed;
549
+ top: 50%;
550
+ left: 50%;
551
+ height: 40px;
552
+ width: 40px;
553
+ margin-top: -20px;
554
+ margin-left: -20px;
555
+ cursor: pointer;
556
+ overflow: hidden;
557
+ z-index: 1104;
558
+ display: none;
559
+ }
560
+
561
+ * html #fancybox-loading { /* IE6 */
562
+ position: absolute;
563
+ margin-top: 0;
564
+ }
565
+
566
+ #fancybox-loading div {
567
+ position: absolute;
568
+ top: 0;
569
+ left: 0;
570
+ width: 40px;
571
+ height: 480px;
572
+ background-image: url('fancybox.png');
573
+ }
574
+
575
+ #fancybox-overlay {
576
+ position: fixed;
577
+ top: 0;
578
+ left: 0;
579
+ bottom: 0;
580
+ right: 0;
581
+ background: #000;
582
+ z-index: 1100;
583
+ display: none;
584
+ }
585
+
586
+ * html #fancybox-overlay { /* IE6 */
587
+ position: absolute;
588
+ width: 100%;
589
+ }
590
+
591
+ #fancybox-tmp {
592
+ padding: 0;
593
+ margin: 0;
594
+ border: 0;
595
+ overflow: auto;
596
+ display: none;
597
+ }
598
+
599
+ #fancybox-wrap {
600
+ position: absolute;
601
+ top: 0;
602
+ left: 0;
603
+ margin: 0;
604
+ padding: 20px;
605
+ z-index: 1101;
606
+ display: none;
607
+ }
608
+
609
+ #fancybox-outer {
610
+ position: relative;
611
+ width: 100%;
612
+ height: 100%;
613
+ background: #FFF;
614
+ }
615
+
616
+ #fancybox-inner {
617
+ position: absolute;
618
+ top: 0;
619
+ left: 0;
620
+ width: 1px;
621
+ height: 1px;
622
+ padding: 0;
623
+ margin: 0;
624
+ outline: none;
625
+ overflow: hidden;
626
+ }
627
+
628
+ #fancybox-hide-sel-frame {
629
+ position: absolute;
630
+ top: 0;
631
+ left: 0;
632
+ width: 100%;
633
+ height: 100%;
634
+ background: transparent;
635
+ }
636
+
637
+ #fancybox-close {
638
+ position: absolute;
639
+ top: -15px;
640
+ right: -15px;
641
+ width: 30px;
642
+ height: 30px;
643
+ background-image: url('fancybox.png');
644
+ background-position: -40px 0px;
645
+ cursor: pointer;
646
+ z-index: 1103;
647
+ display: none;
648
+ }
649
+
650
+ #fancybox_error {
651
+ color: #444;
652
+ font: normal 12px/20px Arial;
653
+ padding: 7px;
654
+ margin: 0;
655
+ }
656
+
657
+ #fancybox-content {
658
+ height: auto;
659
+ width: auto;
660
+ padding: 0;
661
+ margin: 0;
662
+ }
663
+
664
+ #fancybox-img {
665
+ width: 100%;
666
+ height: 100%;
667
+ padding: 0;
668
+ margin: 0;
669
+ border: none;
670
+ outline: none;
671
+ line-height: 0;
672
+ vertical-align: top;
673
+ -ms-interpolation-mode: bicubic;
674
+ }
675
+
676
+ #fancybox-frame {
677
+ position: relative;
678
+ width: 100%;
679
+ height: 100%;
680
+ border: none;
681
+ display: block;
682
+ }
683
+
684
+ #fancybox-title {
685
+ position: absolute;
686
+ bottom: 0;
687
+ left: 0;
688
+ font-family: Arial;
689
+ font-size: 12px;
690
+ z-index: 1102;
691
+ }
692
+
693
+ .fancybox-title-inside {
694
+ padding: 10px 0;
695
+ text-align: center;
696
+ color: #333;
697
+ }
698
+
699
+ .fancybox-title-outside {
700
+ padding-top: 5px;
701
+ color: #FFF;
702
+ text-align: center;
703
+ font-weight: bold;
704
+ }
705
+
706
+ .fancybox-title-over {
707
+ color: #FFF;
708
+ text-align: left;
709
+ }
710
+
711
+ #fancybox-title-over {
712
+ padding: 10px;
713
+ background-image: url('fancy_title_over.png');
714
+ display: block;
715
+ }
716
+
717
+ #fancybox-title-wrap {
718
+ display: inline-block;
719
+ }
720
+
721
+ #fancybox-title-wrap span {
722
+ height: 32px;
723
+ float: left;
724
+ }
725
+
726
+ #fancybox-title-left {
727
+ padding-left: 15px;
728
+ background-image: url('fancybox.png');
729
+ background-position: -40px -90px;
730
+ background-repeat: no-repeat;
731
+ }
732
+
733
+ #fancybox-title-main {
734
+ font-weight: bold;
735
+ line-height: 29px;
736
+ background-image: url('fancybox-x.png');
737
+ background-position: 0px -40px;
738
+ color: #FFF;
739
+ }
740
+
741
+ #fancybox-title-right {
742
+ padding-left: 15px;
743
+ background-image: url('fancybox.png');
744
+ background-position: -55px -90px;
745
+ background-repeat: no-repeat;
746
+ }
747
+
748
+ #fancybox-left, #fancybox-right {
749
+ position: absolute;
750
+ bottom: 0px;
751
+ height: 100%;
752
+ width: 35%;
753
+ cursor: pointer;
754
+ outline: none;
755
+ background-image: url('blank.gif');
756
+ z-index: 1102;
757
+ display: none;
758
+ }
759
+
760
+ #fancybox-left {
761
+ left: 0px;
762
+ }
763
+
764
+ #fancybox-right {
765
+ right: 0px;
766
+ }
767
+
768
+ #fancybox-left-ico, #fancybox-right-ico {
769
+ position: absolute;
770
+ top: 50%;
771
+ left: -9999px;
772
+ width: 30px;
773
+ height: 30px;
774
+ margin-top: -15px;
775
+ cursor: pointer;
776
+ z-index: 1102;
777
+ display: block;
778
+ }
779
+
780
+ #fancybox-left-ico {
781
+ background-image: url('fancybox.png');
782
+ background-position: -40px -30px;
783
+ }
784
+
785
+ #fancybox-right-ico {
786
+ background-image: url('fancybox.png');
787
+ background-position: -40px -60px;
788
+ }
789
+
790
+ #fancybox-left:hover, #fancybox-right:hover {
791
+ visibility: visible; /* IE6 */
792
+ }
793
+
794
+ #fancybox-left:hover span {
795
+ left: 20px;
796
+ }
797
+
798
+ #fancybox-right:hover span {
799
+ left: auto;
800
+ right: 20px;
801
+ }
802
+
803
+ .fancy-bg {
804
+ position: absolute;
805
+ padding: 0;
806
+ margin: 0;
807
+ border: 0;
808
+ width: 20px;
809
+ height: 20px;
810
+ z-index: 1001;
811
+ }
812
+
813
+ #fancy-bg-n {
814
+ top: -20px;
815
+ left: 0;
816
+ width: 100%;
817
+ background-image: url('fancybox-x.png');
818
+ }
819
+
820
+ #fancy-bg-ne {
821
+ top: -20px;
822
+ right: -20px;
823
+ background-image: url('fancybox.png');
824
+ background-position: -40px -162px;
825
+ }
826
+
827
+ #fancy-bg-e {
828
+ top: 0;
829
+ right: -20px;
830
+ height: 100%;
831
+ background-image: url('fancybox-y.png');
832
+ background-position: -20px 0px;
833
+ }
834
+
835
+ #fancy-bg-se {
836
+ bottom: -20px;
837
+ right: -20px;
838
+ background-image: url('fancybox.png');
839
+ background-position: -40px -182px;
840
+ }
841
+
842
+ #fancy-bg-s {
843
+ bottom: -20px;
844
+ left: 0;
845
+ width: 100%;
846
+ background-image: url('fancybox-x.png');
847
+ background-position: 0px -20px;
848
+ }
849
+
850
+ #fancy-bg-sw {
851
+ bottom: -20px;
852
+ left: -20px;
853
+ background-image: url('fancybox.png');
854
+ background-position: -40px -142px;
855
+ }
856
+
857
+ #fancy-bg-w {
858
+ top: 0;
859
+ left: -20px;
860
+ height: 100%;
861
+ background-image: url('fancybox-y.png');
862
+ }
863
+
864
+ #fancy-bg-nw {
865
+ top: -20px;
866
+ left: -20px;
867
+ background-image: url('fancybox.png');
868
+ background-position: -40px -122px;
869
+ }
870
+
871
+ /* IE */
872
+
873
+ #fancybox-loading.fancybox-ie div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); }
874
+ .fancybox-ie #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); }
875
+
876
+ .fancybox-ie #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
877
+ .fancybox-ie #fancybox-title-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); }
878
+ .fancybox-ie #fancybox-title-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); }
879
+ .fancybox-ie #fancybox-title-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); }
880
+
881
+ .fancybox-ie #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); }
882
+ .fancybox-ie #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); }
883
+
884
+ .fancybox-ie .fancy-bg { background: transparent !important; }
885
+
886
+ .fancybox-ie #fancy-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); }
887
+ .fancybox-ie #fancy-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); }
888
+ .fancybox-ie #fancy-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); }
889
+ .fancybox-ie #fancy-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); }
890
+ .fancybox-ie #fancy-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); }
891
+ .fancybox-ie #fancy-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); }
892
+ .fancybox-ie #fancy-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); }
893
+ .fancybox-ie #fancy-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
894
+ #loading {
895
+ position: fixed;
896
+ left: 40%;
897
+ top: 50%; }
898
+
899
+ a {
900
+ color: #333333;
901
+ text-decoration: none; }
902
+ a:hover {
903
+ color: black;
904
+ text-decoration: underline; }
905
+
906
+ body {
907
+ font-family: "Lucida Grande", Helvetica, "Helvetica Neue", Arial, sans-serif;
908
+ padding: 12px;
909
+ background-color: #333333; }
910
+
911
+ h1, h2, h3, h4 {
912
+ color: #1c2324;
913
+ margin: 0;
914
+ padding: 0;
915
+ margin-bottom: 12px; }
916
+
917
+ table {
918
+ width: 100%; }
919
+
920
+ #content {
921
+ clear: left;
922
+ background-color: white;
923
+ border: 2px solid #dddddd;
924
+ border-top: 8px solid #dddddd;
925
+ padding: 18px;
926
+ -webkit-border-bottom-left-radius: 5px;
927
+ -webkit-border-bottom-right-radius: 5px;
928
+ -webkit-border-top-right-radius: 5px;
929
+ -moz-border-radius-bottomleft: 5px;
930
+ -moz-border-radius-bottomright: 5px;
931
+ -moz-border-radius-topright: 5px;
932
+ border-bottom-left-radius: 5px;
933
+ border-bottom-right-radius: 5px;
934
+ border-top-right-radius: 5px; }
935
+
936
+ .dataTables_filter, .dataTables_info {
937
+ padding: 2px 6px; }
938
+
939
+ abbr.timeago {
940
+ text-decoration: none;
941
+ border: none;
942
+ font-weight: bold; }
943
+
944
+ .timestamp {
945
+ float: right;
946
+ color: #dddddd; }
947
+
948
+ .group_tabs {
949
+ list-style: none;
950
+ float: left;
951
+ margin: 0;
952
+ padding: 0; }
953
+ .group_tabs li {
954
+ display: inline;
955
+ float: left; }
956
+ .group_tabs li a {
957
+ font-family: Helvetica, Arial, sans-serif;
958
+ display: block;
959
+ float: left;
960
+ text-decoration: none;
961
+ padding: 4px 8px;
962
+ background-color: #aaaaaa;
963
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(#dddddd), to(#aaaaaa));
964
+ background: -moz-linear-gradient(#dddddd, #aaaaaa);
965
+ background: linear-gradient(#dddddd, #aaaaaa);
966
+ text-shadow: #e5e5e5 1px 1px 0px;
967
+ border-bottom: none;
968
+ color: #333333;
969
+ font-weight: bold;
970
+ margin-right: 8px;
971
+ border-top: 1px solid #efefef;
972
+ -webkit-border-top-left-radius: 2px;
973
+ -webkit-border-top-right-radius: 2px;
974
+ -moz-border-radius-topleft: 2px;
975
+ -moz-border-radius-topright: 2px;
976
+ border-top-left-radius: 2px;
977
+ border-top-right-radius: 2px; }
978
+ .group_tabs li a:hover {
979
+ background-color: #cccccc;
980
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(#eeeeee), to(#aaaaaa));
981
+ background: -moz-linear-gradient(#eeeeee, #aaaaaa);
982
+ background: linear-gradient(#eeeeee, #aaaaaa); }
983
+ .group_tabs li a:active {
984
+ padding-top: 5px;
985
+ padding-bottom: 3px; }
986
+ .group_tabs li.active a {
987
+ color: black;
988
+ text-shadow: white 1px 1px 0px;
989
+ background-color: #dddddd;
990
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(white), to(#dddddd));
991
+ background: -moz-linear-gradient(white, #dddddd);
992
+ background: linear-gradient(white, #dddddd); }
993
+
994
+ .file_list {
995
+ margin-bottom: 18px; }
996
+
997
+ a.src_link {
998
+ background: url("./magnify.png") no-repeat left 50%;
999
+ padding-left: 18px; }
1000
+
1001
+ tr, td {
1002
+ margin: 0;
1003
+ padding: 0; }
1004
+
1005
+ th {
1006
+ white-space: nowrap; }
1007
+ th.ui-state-default {
1008
+ cursor: pointer; }
1009
+ th span.ui-icon {
1010
+ float: left; }
1011
+
1012
+ td {
1013
+ padding: 4px 8px; }
1014
+ td.strong {
1015
+ font-weight: bold; }
1016
+
1017
+ .source_table h3, .source_table h4 {
1018
+ padding: 0;
1019
+ margin: 0;
1020
+ margin-bottom: 4px; }
1021
+ .source_table .header {
1022
+ padding: 10px; }
1023
+ .source_table pre {
1024
+ margin: 0;
1025
+ padding: 0;
1026
+ white-space: normal;
1027
+ color: black;
1028
+ font-family: "Monaco", "Inconsolata", "Consolas", monospace; }
1029
+ .source_table code {
1030
+ color: black;
1031
+ font-family: "Monaco", "Inconsolata", "Consolas", monospace; }
1032
+ .source_table pre {
1033
+ background-color: #333333; }
1034
+ .source_table pre ol {
1035
+ margin: 0px;
1036
+ padding: 0px;
1037
+ margin-left: 45px;
1038
+ font-size: 12px;
1039
+ color: white; }
1040
+ .source_table pre li {
1041
+ margin: 0px;
1042
+ padding: 2px 6px;
1043
+ border-left: 5px solid white; }
1044
+ .source_table pre li code {
1045
+ white-space: pre;
1046
+ white-space: pre-wrap; }
1047
+ .source_table pre .hits {
1048
+ float: right;
1049
+ margin-left: 10px;
1050
+ padding: 2px 4px;
1051
+ background-color: #444444;
1052
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(#222222), to(#666666));
1053
+ background: -moz-linear-gradient(#222222, #666666);
1054
+ background: linear-gradient(#222222, #666666);
1055
+ color: white;
1056
+ font-family: Helvetica, "Helvetica Neue", Arial, sans-serif;
1057
+ font-size: 10px;
1058
+ font-weight: bold;
1059
+ text-align: center;
1060
+ border-radius: 6px; }
1061
+
1062
+ #footer {
1063
+ color: #dddddd;
1064
+ font-size: 12px;
1065
+ font-weight: bold;
1066
+ margin-top: 12px;
1067
+ text-align: right; }
1068
+ #footer a {
1069
+ color: #eeeeee;
1070
+ text-decoration: underline; }
1071
+ #footer a:hover {
1072
+ color: white;
1073
+ text-decoration: none; }
1074
+
1075
+ .green {
1076
+ color: #009900; }
1077
+
1078
+ .red {
1079
+ color: #990000; }
1080
+
1081
+ .yellow {
1082
+ color: #ddaa00; }
1083
+
1084
+ .source_table .covered {
1085
+ border-color: #009900; }
1086
+ .source_table .missed {
1087
+ border-color: #990000; }
1088
+ .source_table .never {
1089
+ border-color: black; }
1090
+ .source_table .skipped {
1091
+ border-color: #ffcc00; }
1092
+ .source_table .covered:nth-child(odd) {
1093
+ background-color: #cdf2cd; }
1094
+ .source_table .covered:nth-child(even) {
1095
+ background-color: #dbf2db; }
1096
+ .source_table .missed:nth-child(odd) {
1097
+ background-color: #f7c0c0; }
1098
+ .source_table .missed:nth-child(even) {
1099
+ background-color: #f7cfcf; }
1100
+ .source_table .never:nth-child(odd) {
1101
+ background-color: #efefef; }
1102
+ .source_table .never:nth-child(even) {
1103
+ background-color: #f4f4f4; }
1104
+ .source_table .skipped:nth-child(odd) {
1105
+ background-color: #fbf0c0; }
1106
+ .source_table .skipped:nth-child(even) {
1107
+ background-color: #fbffcf; }
1108
+
1109
+
1110
+