cartoonist 0.0.3.5 → 0.0.4

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 (43) hide show
  1. data/app/assets/javascripts/application.js.erb +2 -0
  2. data/app/assets/stylesheets/admin.css.scss +16 -0
  3. data/app/controllers/admin_controller.rb +93 -0
  4. data/app/controllers/application_controller.rb +38 -0
  5. data/app/controllers/cache_controller.rb +34 -0
  6. data/app/controllers/settings_controller.rb +35 -0
  7. data/app/controllers/site_controller.rb +49 -0
  8. data/app/controllers/static_cache_controller.rb +19 -0
  9. data/app/helpers/application_helper.rb +74 -0
  10. data/app/helpers/cache_helper.rb +17 -0
  11. data/app/models/backup.rb +11 -0
  12. data/app/models/database_file.rb +2 -0
  13. data/app/models/markdown.rb +17 -0
  14. data/app/models/page_cache.rb +102 -0
  15. data/app/models/setting.rb +258 -0
  16. data/app/models/simple_template.rb +20 -0
  17. data/app/models/sitemap_entry.rb +5 -0
  18. data/app/models/static_cache.rb +47 -0
  19. data/app/models/tweetable.rb +17 -0
  20. data/app/views/admin/main.html.erb +7 -0
  21. data/app/views/admin/sign_in.html.erb +19 -0
  22. data/app/views/cache/index.html.erb +61 -0
  23. data/app/views/layouts/admin.html.erb +43 -0
  24. data/app/views/layouts/application.html.erb +134 -0
  25. data/app/views/layouts/application.rss.erb +16 -0
  26. data/app/views/layouts/application.xml.erb +2 -0
  27. data/app/views/layouts/general_admin.html.erb +10 -0
  28. data/app/views/layouts/sign_in.html.erb +12 -0
  29. data/app/views/settings/initial_setup.html.erb +25 -0
  30. data/app/views/settings/show.html.erb +39 -0
  31. data/app/views/site/robots.text.erb +1 -0
  32. data/app/views/site/sitemap.xml.erb +12 -0
  33. data/app/views/static_cache/index.html.erb +29 -0
  34. data/cartoonist.gemspec +3 -2
  35. data/config/locales/en.yml +99 -0
  36. data/db/migrate/20120320043253_create_database_files.rb +9 -0
  37. data/db/migrate/20120401014029_create_settings.rb +12 -0
  38. data/lib/cartoonist/engine.rb +129 -0
  39. data/lib/cartoonist.rb +236 -0
  40. data/public/errors/404.html +13 -0
  41. data/public/errors/422.html +11 -0
  42. data/public/errors/500.html +13 -0
  43. metadata +41 -2
@@ -0,0 +1,25 @@
1
+ <%= form_tag "/settings/save_initial_setup", :method => :post do %>
2
+ <p>
3
+ <%= t "settings.initial_setup.username" %><input type="text" name="admin_username" value="<%= t "settings.initial_setup.default_username" %>" autofocus="autofocus" />
4
+ </p>
5
+
6
+ <p>
7
+ <%= t "settings.initial_setup.name" %><input type="text" name="admin_name" value="<%= t "settings.initial_setup.default_name" %>" />
8
+ </p>
9
+
10
+ <p>
11
+ <%= t "settings.initial_setup.password" %><input type="password" name="admin_password" />
12
+ </p>
13
+
14
+ <p>
15
+ <%= t "settings.initial_setup.domain" %><input type="text" name="domain" />
16
+ </p>
17
+
18
+ <p>
19
+ <%= t "settings.initial_setup.site_name" %><input type="text" name="site_name" />
20
+ </p>
21
+
22
+ <p>
23
+ <input type="submit" value="<%= t "settings.initial_setup.save" %>" />
24
+ </p>
25
+ <% end %>
@@ -0,0 +1,39 @@
1
+ <div class="tabs">
2
+ <% Setting.tabs.each do |tab| %>
3
+ <a href="/settings/<%= tab %>" class="tab <%= "selected_tab" if tab == params[:id].to_sym %>"><%= t tab, :scope => "settings.show.tabs" %></a>
4
+ <% end %>
5
+ </div>
6
+
7
+ <%= form_tag "/settings/#{@tab.label}", :method => :put do %>
8
+ <% @tab.sections.each do |section| %>
9
+ <div class="section">
10
+ <h2><%= t section, :scope => "settings.show.sections.#{@tab.label}" %></h2>
11
+
12
+ <% @tab[section].settings.each do |setting| %>
13
+ <%# Other setting types to come later %>
14
+ <% next unless Setting::Meta[setting].select_from || [:string, :boolean, :int].include?(Setting::Meta[setting].type) %>
15
+ <p>
16
+ <input type="hidden" name="included_settings[]" value="<%= setting %>" />
17
+ <label>
18
+ <%= t setting, :scope => "settings.show.settings" %>
19
+ <% if Setting::Meta[setting].select_from %>
20
+ <select name="<%= setting %>">
21
+ <% Setting::Meta[setting].select_from_options.each do |option| %>
22
+ <option value="<%= option %>" <%= selected option, Setting[setting] %>><%= option %></option>
23
+ <% end %>
24
+ <select name="<%= setting %>" value="<%= Setting[setting] %>">
25
+ <% elsif Setting::Meta[setting].type == :string %>
26
+ <input type="text" name="<%= setting %>" value="<%= Setting[setting] %>" size="60" />
27
+ <% elsif [:int, :float].include?(Setting::Meta[setting].type) %>
28
+ <input type="text" name="<%= setting %>" value="<%= Setting[setting] %>" size="10" />
29
+ <% elsif Setting::Meta[setting].type == :boolean %>
30
+ <input type="checkbox" name="<%= setting %>" value="true" <%= checked Setting[setting] %> />
31
+ <% end %>
32
+ </label>
33
+ </p>
34
+ <% end %>
35
+ </div>
36
+ <% end %>
37
+
38
+ <input type="submit" value="<%= t "settings.show.save" %>" />
39
+ <% end %>
@@ -0,0 +1 @@
1
+ Sitemap: http://<%= Setting[:domain] %>/sitemap.xml
@@ -0,0 +1,12 @@
1
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
2
+ <% @entries.each do |entry| %>
3
+ <url>
4
+ <loc>http://<%= Setting[:domain] %><%= entry.path %></loc>
5
+ <lastmod><%= entry.formatted_lastmod %></lastmod>
6
+ <changefreq><%= entry.changefreq %></changefreq>
7
+ <% if entry.priority %>
8
+ <priority><%= entry.priority %></priority>
9
+ <% end %>
10
+ </url>
11
+ <% end %>
12
+ </urlset>
@@ -0,0 +1,29 @@
1
+ <p>
2
+ <%= form_tag "/static_cache/expire_all", :method => :post, :class => "inline" do %>
3
+ <input type="submit" value="<%= t "static_cache.index.expire_all" %>" />
4
+ <% end %>
5
+ </p>
6
+
7
+ <p>
8
+ <table class="cache">
9
+ <thead>
10
+ <tr>
11
+ <th><%= t "static_cache.index.page" %></th>
12
+ <th></th>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <% @caches.each do |cache| %>
17
+ <tr>
18
+ <td><%= cache.name %></td>
19
+
20
+ <td>
21
+ <%= form_tag "/static_cache/#{u cache.name}", :method => :delete do %>
22
+ <input type="submit" value="<%= t "static_cache.index.expire" %>" />
23
+ <% end %>
24
+ </td>
25
+ </tr>
26
+ <% end %>
27
+ </tbody>
28
+ </table>
29
+ </p>
data/cartoonist.gemspec CHANGED
@@ -1,7 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cartoonist"
3
- s.version = "0.0.3.5"
4
- s.date = "2012-04-12"
3
+ raise "Cannot find version file!" unless File.exists?(File.join(File.dirname(__FILE__), "../CARTOONIST_VERSION"))
4
+ s.version = File.read File.join(File.dirname(__FILE__), "../CARTOONIST_VERSION")
5
+ s.date = Time.now.strftime "%Y-%m-%d"
5
6
  s.summary = "Cartoonist Core"
6
7
  s.description = "This provides the main functionality and plugin api for Cartoonist."
7
8
  s.authors = ["Mike Virata-Stone"]
@@ -0,0 +1,99 @@
1
+ en:
2
+ admin:
3
+ general:
4
+ actions:
5
+ backup: Download Backup
6
+ reload: Update and Reload
7
+ layout:
8
+ actions: Actions
9
+ cache: Cache
10
+ section: General
11
+ settings: Settings
12
+ static_cache: Static Cache
13
+ layout:
14
+ tab:
15
+ general: General
16
+ logout: Logout
17
+ not_live_warning: development
18
+ production_warning: PRODUCTION
19
+ user_heading: "%{user}:"
20
+ application:
21
+ layout:
22
+ disqus:
23
+ noscript_pre_link: "Please enable JavaScript to view the "
24
+ noscript_link: Disqus comments.
25
+ noscript_post_link:
26
+ logo: Logo
27
+ navigation:
28
+ follow_on_twitter: Follow us on Twitter
29
+ follow_on_twitter_title: Follow us on Twitter
30
+ cache:
31
+ index:
32
+ cached: cached
33
+ expire: Expire
34
+ expire_all: Expire all
35
+ expire_m: Expire m
36
+ expire_tmp: Expire tmp
37
+ expire_www: Expire www
38
+ m: m
39
+ m_tmp: m tmp
40
+ not_cached: not cached
41
+ page: Page
42
+ www: www
43
+ www_tmp: www tmp
44
+ settings:
45
+ initial_setup:
46
+ default_name: Anonymous
47
+ default_username: admin
48
+ domain: "Domain: "
49
+ name: "Name: "
50
+ password: "Password: "
51
+ save: Save
52
+ site_name: "Site Name: "
53
+ username: "Username: "
54
+ show:
55
+ save: Save
56
+ sections:
57
+ advanced:
58
+ general: General
59
+ general:
60
+ general: General
61
+ social_and_analytics:
62
+ disqus: Disqus
63
+ google_analytics: Google Analytics
64
+ twitter: Twitter
65
+ settings:
66
+ domain: "Domain: "
67
+ site_name: "Site Name: "
68
+ site_heading: "Site Heading: "
69
+ site_update_description: "Site Update Description: "
70
+ theme: "Theme: "
71
+ schedule: "Schedule: "
72
+ copyright_starting_year: "Copyright Starting Year: "
73
+ copyright_owners: "Copyright Owners: "
74
+ default_title: "Default Title: "
75
+ default_tweet: "Default Tweet: "
76
+ twitter_enabled: "Twitter Enabled: "
77
+ twitter_handle: "Twitter Handle: "
78
+ twitter_consumer_key: "Twitter Consumer Key: "
79
+ twitter_consumer_secret: "Twitter Consumer Secret: "
80
+ twitter_oauth_token: "Twitter Oauth Token: "
81
+ twitter_oauth_token_secret: "Twitter Oauth Token Secret: "
82
+ google_analytics_enabled: "Google Analytics Enabled: "
83
+ google_analytics_account: "Google Analytics Account: "
84
+ disqus_enabled: "Disqus Enabled: "
85
+ disqus_shortname: "Disqus Shortname: "
86
+ disqus_comic_category: "Disqus Comic Category: "
87
+ disqus_blog_post_category: "Disqus Blog Post Category: "
88
+ disqus_page_category: "Disqus Page Category: "
89
+ admin_users: "Admin Users: "
90
+ secret_token: "Secret Token: "
91
+ tabs:
92
+ advanced: Advanced
93
+ general: General
94
+ social_and_analytics: Social & Analytics
95
+ static_cache:
96
+ index:
97
+ expire: Expire
98
+ expire_all: Expire all
99
+ page: Page
@@ -0,0 +1,9 @@
1
+ class CreateDatabaseFiles < ActiveRecord::Migration
2
+ def change
3
+ create_table :database_files do |t|
4
+ t.string :filename
5
+ t.binary :content, :null => false
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSettings < ActiveRecord::Migration
2
+ def change
3
+ create_table :settings do |t|
4
+ t.string :label, :null => false
5
+ t.text :value
6
+ t.boolean :locked, :default => false, :null => false
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :settings, :label, :unique => true
11
+ end
12
+ end
@@ -1,4 +1,133 @@
1
1
  module Cartoonist
2
2
  class Engine < ::Rails::Engine
3
+ config.before_initialize do
4
+ # Add in various configuration from plugins
5
+ Rails.application.config.assets.precompile += ["admin.css"]
6
+ Rails.application.config.assets.precompile += Cartoonist::Asset.all
7
+ Rails.application.config.paths["db/migrate"] += Cartoonist::Migration.all
8
+
9
+ if File.directory? File.join(Rails.root, "public/errors")
10
+ Rails.application.config.exceptions_app = ActionDispatch::PublicExceptions.new(File.join Rails.root, "public/errors")
11
+ else
12
+ Rails.application.config.exceptions_app = ActionDispatch::PublicExceptions.new(File.join File.dirname(__FILE__), "../../public/errors")
13
+ end
14
+ end
15
+
16
+ config.to_prepare do
17
+ if Setting.table_exists?
18
+ secret_token_changed = lambda do
19
+ # Your secret key for verifying the integrity of signed cookies.
20
+ # If you change this key, all old signed cookies will become invalid!
21
+ # Make sure the secret is at least 30 characters and all random,
22
+ # no regular words or you'll be exposed to dictionary attacks.
23
+ Cartoonist::Application.config.secret_token = Setting[:secret_token]
24
+ end
25
+
26
+ twitter_auth_changed = lambda do
27
+ Twitter.configure do |config|
28
+ config.consumer_key = Setting[:twitter_consumer_key]
29
+ config.consumer_secret = Setting[:twitter_consumer_secret]
30
+ config.oauth_token = Setting[:twitter_oauth_token]
31
+ config.oauth_token_secret = Setting[:twitter_oauth_token_secret]
32
+ end
33
+ end
34
+
35
+ Setting.define :domain, :order => 1
36
+ Setting.define :site_name, :order => 2
37
+ Setting.define :site_heading, :order => 3
38
+ Setting.define :site_update_description, :order => 4
39
+ Setting.define :theme, :type => :symbol, :default => :cartoonist_default_theme, :order => 5, :select_from => lambda { Cartoonist::Theme.all }
40
+ Setting.define :schedule, :type => :array, :default => [:monday, :wednesday, :friday], :order => 6
41
+ Setting.define :copyright_starting_year, :type => :int, :order => 7
42
+ Setting.define :copyright_owners, :order => 8
43
+ Setting.define :default_title, :order => 9
44
+ Setting.define :admin_users, :type => :hash, :order => 10
45
+
46
+ Setting::Tab.define :social_and_analytics, :order => 1 do
47
+ Setting::Section.define :google_analytics, :order => 1 do
48
+ Setting.define :google_analytics_enabled, :type => :boolean, :order => 1
49
+ Setting.define :google_analytics_account, :order => 2
50
+ end
51
+
52
+ Setting::Section.define :twitter, :order => 2 do
53
+ Setting.define :twitter_enabled, :type => :boolean, :order => 1
54
+ Setting.define :default_tweet, :order => 2
55
+ Setting.define :twitter_handle, :order => 3
56
+ Setting.define :twitter_consumer_key, :onchange => twitter_auth_changed, :order => 4
57
+ Setting.define :twitter_consumer_secret, :onchange => twitter_auth_changed, :order => 5
58
+ Setting.define :twitter_oauth_token, :onchange => twitter_auth_changed, :order => 6
59
+ Setting.define :twitter_oauth_token_secret, :onchange => twitter_auth_changed, :order => 7
60
+ end
61
+
62
+ Setting::Section.define :disqus, :order => 3 do
63
+ Setting.define :disqus_enabled, :type => :boolean, :order => 1
64
+ Setting.define :disqus_shortname, :order => 2
65
+ Setting.define :disqus_comic_category, :order => 3
66
+ Setting.define :disqus_blog_post_category, :order => 4
67
+ Setting.define :disqus_page_category, :order => 5
68
+ end
69
+ end
70
+
71
+ Setting::Tab.define :advanced, :order => 2 do
72
+ Setting.define :secret_token, :default => "ThisTokenMustBeRegenerated....", :onchange => secret_token_changed
73
+ end
74
+
75
+ secret_token_changed.call
76
+ twitter_auth_changed.call
77
+ end
78
+ end
79
+
80
+ Cartoonist::Admin::Tab.add :general, :url => "/admin", :order => 3
81
+ Cartoonist::Navigation::Link.add :url => (lambda { "https://twitter.com/#{Setting[:twitter_handle]}" }), :class => "follow-us", :label => "application.layout.navigation.follow_on_twitter", :title => "application.layout.navigation.follow_on_twitter_title", :order => 2
82
+ Cartoonist::Migration.add_for self
83
+
84
+ Cartoonist::Backup.for :files do
85
+ DatabaseFile.order(:id).all
86
+ end
87
+
88
+ Cartoonist::Backup.for :settings do
89
+ Setting.order(:id).all
90
+ end
91
+
92
+ Cartoonist::Routes.add do
93
+ match "favicon" => "site#favicon", :defaults => { :format => "ico" }
94
+ match "sitemap" => "site#sitemap", :defaults => { :format => "xml" }
95
+ match "robots" => "site#robots", :defaults => { :format => "text" }
96
+
97
+ resources :cache do
98
+ collection do
99
+ post "expire_www"
100
+ post "expire_m"
101
+ post "expire_tmp"
102
+ post "expire_all"
103
+ end
104
+ end
105
+
106
+ resources :static_cache, :constraints => { :id => /.*/ } do
107
+ collection do
108
+ post "expire_all"
109
+ end
110
+ end
111
+
112
+ resources :admin do
113
+ collection do
114
+ get "cache_cron"
115
+ get "backup"
116
+ get "logout"
117
+ get "main"
118
+ get "reload"
119
+ get "sign_in"
120
+ post "sign_in"
121
+ get "tweet_cron"
122
+ end
123
+ end
124
+
125
+ resources :settings do
126
+ collection do
127
+ get "initial_setup"
128
+ post "save_initial_setup"
129
+ end
130
+ end
131
+ end
3
132
  end
4
133
  end
data/lib/cartoonist.rb CHANGED
@@ -1,3 +1,239 @@
1
1
  module Cartoonist
2
+ module Admin
3
+ class Tab
4
+ attr_reader :key, :url, :order
5
+
6
+ @@all = {}
7
+ @@cached_order = []
8
+
9
+ def initialize(key, options)
10
+ @key = key
11
+ @url = options[:url]
12
+ @order = options[:order]
13
+ end
14
+
15
+ class << self
16
+ def all
17
+ @@cached_order
18
+ end
19
+
20
+ def [](key)
21
+ @@all[key].url
22
+ end
23
+
24
+ def add(key, options)
25
+ @@all[key] = Cartoonist::Admin::Tab.new key, options
26
+ @@cached_order = @@all.values.sort do |a, b|
27
+ if a.order && b.order
28
+ a.order <=> b.order
29
+ elsif a.order && !b.order
30
+ -1
31
+ elsif b.order && !a.order
32
+ 1
33
+ else
34
+ a.key <=> b.key
35
+ end
36
+ end.map &:key
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ class Asset
43
+ @@all = []
44
+ @@included_js = []
45
+
46
+ class << self
47
+ # This does not include javascript files included in
48
+ # application.js. This is purely standalone assets.
49
+ def all
50
+ @@all
51
+ end
52
+
53
+ # Include the following js files into application.js.
54
+ def include_js(*js_files)
55
+ @@included_js.push *js_files
56
+ @@included_js.tap &:uniq!
57
+ end
58
+
59
+ def included_js
60
+ @@included_js
61
+ end
62
+
63
+ def included_js?
64
+ @@included_js.present?
65
+ end
66
+
67
+ def add(*assets)
68
+ @@all.push *assets
69
+ @@all.tap &:uniq!
70
+ end
71
+ end
72
+ end
73
+
74
+ class Backup
75
+ @@all = {}
76
+
77
+ class << self
78
+ def all
79
+ @@all
80
+ end
81
+
82
+ def for(key, &block)
83
+ @@all[key.to_sym] = block
84
+ end
85
+ end
86
+ end
87
+
88
+ class Migration
89
+ @@all = []
90
+
91
+ class << self
92
+ def all
93
+ @@all
94
+ end
95
+
96
+ def add_for(engine)
97
+ add_dirs engine.paths["db/migrate"].existent
98
+ end
99
+
100
+ def add_dirs(*dirs)
101
+ @@all.push *dirs
102
+ @@all.tap &:uniq!
103
+ end
104
+ end
105
+ end
106
+
107
+ class Navigation
108
+ class Link
109
+ attr_reader :preview_url, :class, :label, :title, :order
110
+
111
+ @@all = []
112
+ @@cached_order = []
113
+
114
+ def initialize(options)
115
+ @url = options[:url]
116
+ @preview_url = options[:preview_url]
117
+ @class = options[:class]
118
+ @label = options[:label]
119
+ @title = options[:title]
120
+ @order = options[:order]
121
+ end
122
+
123
+ def url(preview = false)
124
+ if preview && @preview_url
125
+ result = @preview_url
126
+ else
127
+ result = @url
128
+ end
129
+
130
+ if result.kind_of? Proc
131
+ result.call
132
+ else
133
+ result
134
+ end
135
+ end
136
+
137
+ class << self
138
+ def all
139
+ @@cached_order
140
+ end
141
+
142
+ def add(options)
143
+ @@all << Cartoonist::Navigation::Link.new(options)
144
+ @@cached_order = @@all.sort { |x, y| x.order <=> y.order }
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ class Routes
151
+ @@begin = []
152
+ @@middle = []
153
+ @@end = []
154
+
155
+ class << self
156
+ def add_begin(&block)
157
+ @@begin << block
158
+ end
159
+
160
+ def add(&block)
161
+ @@middle << block
162
+ end
163
+
164
+ def add_end(&block)
165
+ @@end << block
166
+ end
167
+
168
+ def load!(instance)
169
+ @@begin.each do |routes|
170
+ instance.instance_exec &routes
171
+ end
172
+
173
+ @@middle.each do |routes|
174
+ instance.instance_exec &routes
175
+ end
176
+
177
+ @@end.each do |routes|
178
+ instance.instance_exec &routes
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ class Sitemap
185
+ @@all = []
186
+
187
+ class << self
188
+ def all
189
+ @@all.map(&:call).flatten
190
+ end
191
+
192
+ def add(&block)
193
+ @@all << block
194
+ end
195
+ end
196
+ end
197
+
198
+ class Theme
199
+ @@all = []
200
+ @@themes = {}
201
+
202
+ class << self
203
+ def all
204
+ @@all
205
+ end
206
+
207
+ def add(theme, options)
208
+ (@@all << theme.to_sym).sort! unless @@all.include? theme.to_sym
209
+ @@themes[theme.to_sym] = options unless @@themes.include? theme.to_sym
210
+ end
211
+
212
+ def add_assets(*assets)
213
+ Cartoonist::Asset.add *assets
214
+ end
215
+
216
+ def [](key)
217
+ @@themes[key.to_sym] || {}
218
+ end
219
+
220
+ def current
221
+ self[Setting[:theme]]
222
+ end
223
+
224
+ def favicon
225
+ current[:favicon]
226
+ end
227
+
228
+ def css
229
+ current[:css]
230
+ end
231
+
232
+ def rss_logo
233
+ current[:rss_logo]
234
+ end
235
+ end
236
+ end
237
+
2
238
  require "cartoonist/engine"
3
239
  end
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Something's missing (404)</title>
5
+ </head>
6
+
7
+ <body>
8
+ <center>
9
+ <h1>Something's missing...</h1>
10
+ <p>We hope you what you are looking for!</p>
11
+ </center>
12
+ </body>
13
+ </html>
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Rejected! (422)</title>
5
+ </head>
6
+
7
+ <body>
8
+ <h1>Rejected!</h1>
9
+ <p>Sorry, please don't try again.</p>
10
+ </body>
11
+ </html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Internal error (500)</title>
5
+ </head>
6
+
7
+ <body>
8
+ <center>
9
+ <h1>Internal error!</h1>
10
+ <p>Something went wrong... we are sorry!</p>
11
+ </center>
12
+ </body>
13
+ </html>