typo 3.99.1 → 3.99.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,7 +22,7 @@ class ArticlesController < ContentController
22
22
  :conditions =>
23
23
  ['published = ? AND contents.created_at < ? AND blog_id = ?',
24
24
  true, Time.now, this_blog.id],
25
- :order_by => "contents.created_at DESC",
25
+ :order_by => "contents.published_at DESC",
26
26
  :include => [:categories, :tags])
27
27
  end
28
28
 
@@ -200,6 +200,7 @@ class ArticlesController < ContentController
200
200
  def render_grouping(klass)
201
201
  return list_groupings(klass) unless params[:id]
202
202
 
203
+ @page_title = "#{this_blog.blog_name} - #{klass.to_s.underscore} #{params[:id]}"
203
204
  @articles = klass.find_by_permalink(params[:id]).articles.find_already_published rescue []
204
205
  auto_discovery_feed :type => klass.to_s.underscore, :id => params[:id]
205
206
  render_paginated_index("Can't find posts with #{klass.to_prefix} '#{h(params[:id])}'")
@@ -138,9 +138,9 @@ class Blog < ActiveRecord::Base
138
138
  end
139
139
 
140
140
  def article_url(article, only_path = true, anchor = nil)
141
- url_for(:year => article.created_at.year,
142
- :month => sprintf("%.2d", article.created_at.month),
143
- :day => sprintf("%.2d", article.created_at.day),
141
+ url_for(:year => article.published_at.year,
142
+ :month => sprintf("%.2d", article.published_at.month),
143
+ :day => sprintf("%.2d", article.published_at.day),
144
144
  :title => article.permalink, :anchor => anchor,
145
145
  :only_path => only_path)
146
146
  end
@@ -1,4 +1,5 @@
1
1
  require_dependency 'spam_protection'
2
+ require 'sanitize'
2
3
 
3
4
  class Comment < Content
4
5
  include TypoGuid
@@ -48,10 +49,8 @@ class Comment < Content
48
49
  end
49
50
  end
50
51
 
51
-
52
-
53
52
  def body_html_postprocess(value, controller)
54
- controller.send(:sanitize, controller.send(:auto_link, value))
53
+ sanitize(controller.send(:auto_link, value),'a href, b, br, i, p, em, strong, pre, code')
55
54
  end
56
55
 
57
56
  def default_text_filter_config_key
@@ -1,5 +1,5 @@
1
1
  class ContentObserver < ActiveRecord::Observer
2
2
  def before_save(content)
3
- content.populate_html_fields
3
+ # content.populate_html_fields
4
4
  end
5
5
  end
data/bin/typo CHANGED
@@ -1,6 +1,41 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'installer/typo-installer'
3
+ require 'installer/rails-installer'
4
+
5
+ class TypoInstaller < RailsInstaller
6
+ application_name 'typo'
7
+ support_location 'the Typo mailing list'
8
+ rails_version '1.1.4'
9
+
10
+ def install_sequence
11
+ stop
12
+
13
+ backup_database
14
+ pre_migrate_database
15
+ copy_files
16
+ freeze_rails
17
+ create_default_config_files
18
+ create_directories
19
+ create_initial_database
20
+ set_initial_port_number
21
+ expand_template_files
22
+
23
+ migrate
24
+ sweep_cache
25
+ save
26
+
27
+ run_rails_tests
28
+
29
+ start
30
+ end
31
+
32
+ # Sweep the cache
33
+ def sweep_cache
34
+ Dir.chdir(install_directory)
35
+ message "Cleaning out #{@@app_name.capitalize}'s cache"
36
+ status = system("rake -s sweep_cache > /dev/null 2> /dev/null")
37
+ end
38
+ end
4
39
 
5
40
  # Installer program
6
41
  directory = ARGV[1]
@@ -55,7 +55,7 @@ This macro takes a number of parameters:
55
55
  imageurl = details['source']
56
56
  imagelink = flickrimage.url
57
57
 
58
- caption ||= flickrimage.description
58
+ caption ||= sanitize(CGI.unescapeHTML(flickrimage.description))
59
59
  title ||= flickrimage.title
60
60
  alt ||= title
61
61
 
@@ -0,0 +1,8 @@
1
+ class Plugins::Textfilters::TextileAndMarkdownController < TextFilterPlugin::Markup
2
+ plugin_display_name "Textile with Markdown"
3
+ plugin_description 'Textile and Markdown markup languages'
4
+
5
+ def self.filtertext(controller,content,text,params)
6
+ RedCloth.new(text).to_html
7
+ end
8
+ end
@@ -3,6 +3,6 @@ class Plugins::Textfilters::TextileController < TextFilterPlugin::Markup
3
3
  plugin_description 'Textile markup language'
4
4
 
5
5
  def self.filtertext(controller,content,text,params)
6
- RedCloth.new(text).to_html
6
+ RedCloth.new(text).to_html(:textile)
7
7
  end
8
8
  end
@@ -24,6 +24,7 @@ You'll need the following software installed on your system:
24
24
 
25
25
  Most modern Unix systems should have all four of these easily available in pre-built form.
26
26
 
27
+
27
28
  Installing Typo
28
29
  ---------------
29
30
 
@@ -46,6 +47,14 @@ Installing Typo
46
47
  installer/apache.conf.example to run your Typo installation under Apache.
47
48
 
48
49
 
50
+ Starting and Stopping Typo
51
+ --------------------------
52
+
53
+ To stop Typo from running, run `typo stop /path/to/typo`. To restart it, run
54
+ `typo start /path/to/typo`. Since this Typo install uses Mongrel, not FastCGI,
55
+ you can't depend on your web server restarting it automatically on reboot. You'll need to either create an init script or cron reboot entry to restart it, depending on your host and/or privilege level.
56
+
57
+
49
58
  TODO
50
59
  ----
51
60
 
@@ -0,0 +1,33 @@
1
+ # Apache 1.3 HTTP proxy example for Typo with Mongrel
2
+ #
3
+ # Before any of this will work, you need to make sure that the mod_proxy
4
+ # modules are loaded. For shared hosting, your provider will have do this
5
+ # globally. The line required looks like this, although the exact path may
6
+ # vary:
7
+ #
8
+ # LoadModule proxy_module /usr/lib/apache/modules/mod_proxy.so
9
+ #
10
+ # Then you'll want a VirtualHost section that looks about like this:
11
+
12
+ <VirtualHost blog.example.com>
13
+ ServerName blog.example.com
14
+ ServerAlias www.blog.example.com
15
+
16
+ # Change this to your email address
17
+ ServerAdmin webmaster@localhost
18
+
19
+ # Change these to be valid paths for your host. The DocumentRoot path
20
+ # isn't very important because we don't actually use it for anything.
21
+ # For security's sake, it's best that it points to an empty directory,
22
+ # but that's not critical.
23
+ DocumentRoot /var/www/blog
24
+ ErrorLog /var/log/apache2/blog_error.log
25
+ CustomLog /var/log/apache2/blog_access.log combined
26
+
27
+ ServerSignature On
28
+
29
+ # This is the important part--it sets up proxying.
30
+ ProxyRequests Off
31
+ ProxyPass / $RAILS_URL
32
+ ProxyPassReverse / $RAILS_URL
33
+ </VirtualHost>
@@ -0,0 +1,40 @@
1
+ # Apache 2.0/2.2 HTTP proxy example for Typo with Mongrel
2
+ #
3
+ # Before any of this will work, you need to make sure that the mod_proxy and
4
+ # mod_proxy_http modules are loaded. For shared hosting, your provider will
5
+ # have do this globally. The two lines required look like this, although the
6
+ # exact path may vary:
7
+ #
8
+ # LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
9
+ # LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
10
+ #
11
+ # Then you'll want a VirtualHost section that looks about like this:
12
+
13
+ <VirtualHost blog.example.com>
14
+ ServerName blog.example.com
15
+ ServerAlias www.blog.example.com
16
+
17
+ # Change this to your email address
18
+ ServerAdmin webmaster@localhost
19
+
20
+ # Change these to be valid paths for your host. The DocumentRoot path
21
+ # isn't very important because we don't actually use it for anything.
22
+ # For security's sake, it's best that it points to an empty directory,
23
+ # but that's not critical.
24
+ DocumentRoot /var/www/blog
25
+ ErrorLog /var/log/apache2/blog_error.log
26
+ CustomLog /var/log/apache2/blog_access.log combined
27
+
28
+ ServerSignature On
29
+
30
+ # This is the important part--it sets up proxying.
31
+ ProxyRequests Off
32
+ <Proxy *>
33
+ Order deny,allow
34
+ Allow from all
35
+ </Proxy>
36
+
37
+ ProxyPass / $RAILS_URL
38
+ ProxyPassReverse / $RAILS_URL
39
+ ProxyPreserveHost On
40
+ </VirtualHost>
@@ -0,0 +1,6 @@
1
+ # This is untested and incomplete.
2
+ # See http://mongrel.rubyforge.org/docs/lighttpd.html
3
+ #
4
+ proxy.balance = "fair"
5
+ proxy.server = ( "/" =>
6
+ ( ( "host" => "$RAILS_HOST", "port" => $RAILS_PORT ) ) )
@@ -26,7 +26,8 @@ class RailsInstaller
26
26
  end
27
27
 
28
28
  def initialize(install_directory)
29
- @install_directory = install_directory
29
+ # use an absolute path, not a relative path.
30
+ @install_directory = File.expand_path(install_directory)
30
31
 
31
32
  @config = read_yml(config_file) rescue nil
32
33
  @config ||= Hash.new
@@ -54,7 +55,7 @@ class RailsInstaller
54
55
  message ''
55
56
  message "#{@@app_name.capitalize} is now running on http://#{`hostname`.chomp}:#{config['port-number']}"
56
57
  message "Use '#{@@app_name} start #{install_directory}' to restart after boot."
57
- message "Look in installer/apache.conf.example to see how to integrate with Apache."
58
+ message "Look in installer/*.conf.example to see how to integrate with your web server."
58
59
  end
59
60
 
60
61
  # The default install sequence. Override this if you need to add extra
@@ -70,6 +71,7 @@ class RailsInstaller
70
71
  create_directories
71
72
  create_initial_database
72
73
  set_initial_port_number
74
+ expand_template_files
73
75
 
74
76
  migrate
75
77
  save
@@ -124,6 +126,8 @@ class RailsInstaller
124
126
  # Backup the database
125
127
  def backup_database
126
128
  return unless File.exists? db_file
129
+ Dir.chdir(install_directory)
130
+
127
131
  return unless config['database'] == 'sqlite'
128
132
  new_db_file = db_file+"-#{Time.now.strftime('%Y%m%d-%H%M')}.sql"
129
133
 
@@ -139,6 +143,7 @@ class RailsInstaller
139
143
 
140
144
  message "Reading files from #{source_directory}"
141
145
  new_files = sha1_hash_directory_tree(source_directory)
146
+ new_files.delete('/config/database.yml') # Never copy this.
142
147
 
143
148
  # Next, we compare the original install hash to the current hash. For each
144
149
  # entry:
@@ -179,6 +184,7 @@ class RailsInstaller
179
184
  end
180
185
 
181
186
  write_yml(files_yml,new_files)
187
+ Dir.chdir(install_directory)
182
188
  end
183
189
 
184
190
  # Copy one file from source_directory to install_directory, creating directories as needed.
@@ -343,7 +349,6 @@ class RailsInstaller
343
349
 
344
350
  return unless old_schema_version > 0
345
351
 
346
- Dir.chdir(install_directory)
347
352
 
348
353
  # Are we downgrading?
349
354
  if old_schema_version > new_schema_version
@@ -358,7 +363,6 @@ class RailsInstaller
358
363
 
359
364
  # Migrate the database
360
365
  def migrate
361
- Dir.chdir(install_directory)
362
366
  message "Migrating #{@@app_name.capitalize}'s database to newest release"
363
367
  status = system("rake -s migrate")
364
368
 
@@ -369,9 +373,8 @@ class RailsInstaller
369
373
 
370
374
  # Sweep the cache
371
375
  def run_rails_tests
372
- Dir.chdir(install_directory)
373
376
  message "Running tests. This may take a minute or two"
374
- status = system("rake -s test > /dev/null 2> /dev/null")
377
+ status = system_silently("rake -s test")
375
378
 
376
379
  if status
377
380
  message "All tests pass. Congratulations."
@@ -433,6 +436,34 @@ class RailsInstaller
433
436
  specs.last.full_gem_path
434
437
  end
435
438
 
439
+ def system_silently(command)
440
+ if RUBY_PLATFORM =~ /mswin32/
441
+ null = 'NUL:'
442
+ else
443
+ null = '/dev/null'
444
+ end
445
+
446
+ system("#{command} > #{null} 2> #{null}")
447
+ end
448
+
449
+ def expand_template_files
450
+ rails_host = config['bind-address'] || `hostname`.chomp
451
+ rails_port = config['port-number'].to_s
452
+ rails_url = "http://#{rails_host}:#{rails_port}"
453
+ Dir[File.join(install_directory,'installer','*.template')].each do |template_file|
454
+ output_file = template_file.gsub(/\.template/,'')
455
+ next if File.exists?(output_file) # don't overwrite files
456
+
457
+ message "expanding #{File.basename(output_file)} template"
458
+
459
+ text = File.read(template_file).gsub(/\$RAILS_URL/,rails_url).gsub(/\$RAILS_HOST/,rails_host).gsub(/\$RAILS_PORT/,rails_port)
460
+
461
+ File.open(output_file,'w') do |f|
462
+ f.write text
463
+ end
464
+ end
465
+ end
466
+
436
467
  # Execute a command-line command
437
468
  def execute_command(*args)
438
469
  if args.size < 2
@@ -0,0 +1,107 @@
1
+ #
2
+ # $Id: sanitize.rb 3 2005-04-05 12:51:14Z dwight $
3
+ #
4
+ # Copyright (c) 2005 Dwight Shih
5
+ # A derived work of the Perl version:
6
+ # Copyright (c) 2002 Brad Choate, bradchoate.com
7
+ #
8
+ # Permission is hereby granted, free of charge, to
9
+ # any person obtaining a copy of this software and
10
+ # associated documentation files (the "Software"), to
11
+ # deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify,
13
+ # merge, publish, distribute, sublicense, and/or sell
14
+ # copies of the Software, and to permit persons to
15
+ # whom the Software is furnished to do so, subject to
16
+ # the following conditions:
17
+ #
18
+ # The above copyright notice and this permission
19
+ # notice shall be included in all copies or
20
+ # substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
23
+ # OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24
+ # LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ # FITNESS FOR A PARTICULAR PURPOSE AND
26
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
27
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
28
+ # OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
30
+ # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31
+ # OTHER DEALINGS IN THE SOFTWARE.
32
+ #
33
+
34
+ def sanitize( html, okTags='a href, b, br, i, p' )
35
+ # no closing tag necessary for these
36
+ soloTags = ["br","hr"]
37
+
38
+ # Build hash of allowed tags with allowed attributes
39
+ tags = okTags.downcase().split(',').collect!{ |s| s.split(' ') }
40
+ allowed = Hash.new
41
+ tags.each do |s|
42
+ key = s.shift
43
+ allowed[key] = s
44
+ end
45
+
46
+ # Analyze all <> elements
47
+ stack = Array.new
48
+ result = html.gsub( /(<.*?>)/m ) do | element |
49
+ if element =~ /\A<\/(\w+)/ then
50
+ # </tag>
51
+ tag = $1.downcase
52
+ if allowed.include?(tag) && stack.include?(tag) then
53
+ # If allowed and on the stack
54
+ # Then pop down the stack
55
+ top = stack.pop
56
+ out = "</#{top}>"
57
+ until top == tag do
58
+ top = stack.pop
59
+ out << "</#{top}>"
60
+ end
61
+ out
62
+ end
63
+ elsif element =~ /\A<(\w+)\s*\/>/
64
+ # <tag />
65
+ tag = $1.downcase
66
+ if allowed.include?(tag) then
67
+ "<#{tag} />"
68
+ end
69
+ elsif element =~ /\A<(\w+)/ then
70
+ # <tag ...>
71
+ tag = $1.downcase
72
+ if allowed.include?(tag) then
73
+ if ! soloTags.include?(tag) then
74
+ stack.push(tag)
75
+ end
76
+ if allowed[tag].length == 0 then
77
+ # no allowed attributes
78
+ "<#{tag}>"
79
+ else
80
+ # allowed attributes?
81
+ out = "<#{tag}"
82
+ while ( $' =~ /(\w+)=("[^"]+")/ )
83
+ attr = $1.downcase
84
+ valu = $2
85
+ if allowed[tag].include?(attr) then
86
+ out << " #{attr}=#{valu}"
87
+ end
88
+ end
89
+ out << ">"
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ # eat up unmatched leading >
96
+ while result.sub!(/\A([^<]*)>/m) { $1 } do end
97
+
98
+ # eat up unmatched trailing <
99
+ while result.sub!(/<([^>]*)\Z/m) { $1 } do end
100
+
101
+ # clean up the stack
102
+ if stack.length > 0 then
103
+ result << "</#{stack.reverse.join('></')}>"
104
+ end
105
+
106
+ result
107
+ end