YurtCMS 0.3.1 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,72 @@
1
+
2
+ class ParseSSI
3
+ attr_reader :web_root, :top, :bottom, :vars
4
+
5
+ def initialize web_root
6
+ @vars = {}
7
+ @web_root = web_root
8
+ return
9
+ end
10
+
11
+ def parse file
12
+
13
+ # the parse routine currently understands only 3 SSI attributes
14
+ #
15
+ # <!--#echo var="FOO" -->
16
+ #
17
+ # <!--#include virtual="/path/to/file" -->
18
+ #
19
+ # <!--#set var="FOO" value="bar" -->
20
+ #
21
+ # more may be added if required.
22
+
23
+ result = File.read( @web_root + "/" + file )
24
+
25
+ 1 while result.sub!(/<!--#(\w+)\s(.*?)\s*-->(\n+)?/) do |match|
26
+ attrs = parse_attributes($2)
27
+ case $1
28
+ when 'echo'
29
+ @vars[ attrs['var'] ]
30
+ when 'include'
31
+ attrs['virtual'].gsub!(/\$\{(\w+)\}/) do |m|
32
+ if $1
33
+ @vars[$1]
34
+ else
35
+ m
36
+ end
37
+ end
38
+ File.read( @web_root + "/" + attrs['virtual'] )
39
+ when 'set'
40
+ @vars[ attrs['var'] ] = attrs['value']
41
+ ''
42
+ else
43
+ match
44
+ end
45
+ end
46
+ result
47
+ end
48
+
49
+ def parse_attributes(source)
50
+ attrs = Hash.new
51
+ source.scan( /(\w+)="([^"]*)"/ ) do |match|
52
+ attrs[$1] = $2
53
+ end
54
+ return attrs
55
+ end
56
+
57
+ def set_tag var, value
58
+ [ '<!--#set var="' + var + '" value="', value.to_s, '" -->', "\n" ].join
59
+ end
60
+
61
+ def virtual_include_tag path
62
+ [ '<!--#include virtual="' + path.to_s + '" -->', "\n" ].join
63
+ end
64
+
65
+ def file_include_tag path
66
+ [ '<!--#include virtual="' + @web_root + path.to_s + '" -->', "\n" ].join
67
+ end
68
+
69
+ def echo_tag var
70
+ [ '<!--#echo var="' + var + '" -->', "\n" ].join
71
+ end
72
+ end
@@ -1,12 +1,12 @@
1
-
2
1
  require 'yaml'
3
2
 
4
-
5
3
  class YurtCMS
6
- attr_reader :data_store, :web_root, :includes, :metatags, :partial, :ext
4
+ attr_reader :yurt_root, :data_store, :web_root, :includes, :metatags, :partial, :ext
7
5
  def initialize yurt_root
8
6
  require 'rubygems'
9
- require_gem 'BlueCloth'
7
+ require 'bluecloth' # i used to have require_gem, but i don't think it's needed
8
+ require 'rubypants'
9
+ require 'parse_ssi'
10
10
 
11
11
  @yurt_root = sanitize_path( yurt_root )
12
12
  @data_store = [ @yurt_root, "content/" ].join
@@ -15,6 +15,7 @@
15
15
  @metatags = ".metatags"
16
16
  @partial = ".partial"
17
17
  @ext = ".html"
18
+ @ssi = ParseSSI.new(@web_root)
18
19
  end
19
20
 
20
21
  def merge path, file
@@ -93,14 +94,15 @@
93
94
  end
94
95
 
95
96
  def make_metatags input
96
- t = [ '<!--#set var="TITLE" value="', input.title, '" -->', "\n" ].join if input.title =~ /\w/
97
- d = [ '<!--#set var="DESCRIPTION" value="', input.description, '" -->', "\n" ].join if input.description =~ /\w/
98
- k = [ '<!--#set var="KEYWORDS" value="', input.keywords, '" -->', "\n" ].join if input.keywords =~ /\w/
97
+ t = @ssi.set_tag('TITLE', input.title) if input.title =~ /\w/
98
+ d = @ssi.set_tag('DESCRIPTION', input.description) if input.description =~ /\w/
99
+ k = @ssi.set_tag('KEYWORDS', input.keywords) if input.keywords =~ /\w/
99
100
 
100
101
  [ t, d, k ].join
101
102
  end
102
103
 
103
104
  def parse_content c
105
+ #RubyPants.new(BlueCloth.new(c).to_html,1).to_html
104
106
  BlueCloth.new(c).to_html
105
107
  end
106
108
 
@@ -110,14 +112,8 @@
110
112
  end
111
113
 
112
114
  [
113
- '<!--#set var="PAGE" value="',
114
- path,
115
- '" -->',
116
- "\n",
117
- '<!--#include virtual="/includes/',
118
- template,
119
- '" -->',
120
- "\n"
115
+ @ssi.set_tag('PAGE', path),
116
+ @ssi.virtual_include_tag('/includes/' + template),
121
117
  ].join
122
118
  end
123
119
 
@@ -86,7 +86,7 @@
86
86
  Element.show('spinner');
87
87
  // use an argument looking like this: document.forms["newfile"].content.value
88
88
 
89
- var url = "/yurt/yurt.cgi/preview/"
89
+ var url = "/preview/"
90
90
  var pars = 'c=' + escape( content );
91
91
  var target = 'nf_preview';
92
92
 
@@ -125,16 +125,17 @@
125
125
  <div id="workspace">
126
126
  </div>
127
127
  <ul id="directory_actions" class="actions" style="display: none;">
128
- <li><a href="/yurt/yurt.cgi/open" class="first" onclick="openFolder(this.href); return false;">Open</a></li>
129
- <li><a href="/yurt/yurt.cgi/new_folder" onclick="dispatch(this.href); return false;">New folder...</a></li>
130
- <li><a href="/yurt/yurt.cgi/new_file" onclick="dispatch(this.href); return false;">New file...</a></li>
131
- <li><a href="/yurt/yurt.cgi/delete" onclick="dispatch(this.href); return false;">Delete</a></li>
128
+ <li><a href="/open" class="first" onclick="openFolder(this.href); return false;">Open</a></li>
129
+ <li><a href="/new_folder" onclick="dispatch(this.href); return false;">New folder...</a></li>
130
+ <li><a href="/new_file" onclick="dispatch(this.href); return false;">New file...</a></li>
131
+ <li><a href="/delete" onclick="dispatch(this.href); return false;">Delete</a></li>
132
132
  </ul>
133
133
  <ul id="file_actions" class="actions" style="display: none;">
134
- <li><a href="/yurt/yurt.cgi/edit" class="first" onclick="dispatch(this.href); return false;">Edit file...</a></li>
135
- <li><a href="/yurt/yurt.cgi/delete" onclick="dispatch(this.href); return false;">Delete</a></li>
134
+ <li><a href="/edit" class="first" onclick="dispatch(this.href); return false;">Edit file...</a></li>
135
+ <li><a href="/delete" onclick="dispatch(this.href); return false;">Delete</a></li>
136
136
  </ul>
137
137
  <div id="spinner" style="display: none;"><img src="/yurt/media/images/spinner.gif" width="16" height="16" border="0" alt="" /></div>
138
+ <div id="staging"><a href="/staging/">View the site in a staging environment</a></div>
138
139
  </body>
139
140
  </html>
140
141
 
@@ -182,3 +182,24 @@
182
182
  font-family: monospace;
183
183
  }
184
184
 
185
+ #staging {
186
+ position: absolute;
187
+ top: 50px;
188
+ left: 600px;
189
+ height: 20px;
190
+ background-color: #eeeeea;
191
+ border: 1px solid black;
192
+ border-bottom: 0px none;
193
+ font-family: Geneva, verdana;
194
+ font-size: 12px;
195
+ padding: 4px;
196
+ }
197
+
198
+ #staging a {
199
+ color: #000;
200
+ text-decoration: none;
201
+ }
202
+
203
+ #staging a:hover {
204
+ text-decoration: underline;
205
+ }
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby -rubygems
2
2
 
3
3
  require 'yurtcms'
4
+ require 'parse_ssi'
4
5
  require 'camping'
5
6
  require 'bluecloth'
6
7
 
@@ -105,6 +106,74 @@ module Yurt::Controllers
105
106
  render :cancel
106
107
  end
107
108
  end
109
+
110
+ class Static < R '/(static|staging|media|yurt)/(.*)$'
111
+ MIME_TYPES = {'.css' => 'text/css', '.js' => 'text/javascript', '.jpg' => 'image/jpeg', '.gif' => 'image/gif', '.png' => 'image/png', '.html' => 'text/html'}
112
+
113
+ def get path_source, path
114
+ @y = get_yurtcms
115
+
116
+ case path_source
117
+ when "yurt"
118
+ web_root = [ @y.yurt_root, 'yurt/' ].join
119
+ path_to_file = [ @y.yurt_root, 'yurt/', path ].join
120
+ when "media"
121
+ web_root = [ @y.web_root, 'media/' ].join
122
+ path_to_file = [ @y.web_root, 'media/', path ].join
123
+ else
124
+ web_root = @y.web_root
125
+ path_to_file = [ @y.web_root, path ].join
126
+ end
127
+
128
+
129
+ if path =~ /\.\./ # sample test to prevent directory traversal attacks
130
+ @status = "404"
131
+ "404 - Not Found"
132
+ return
133
+ end
134
+
135
+ # not sure if this would be a reasonable assumption to make -- or
136
+ # if this is the right place to do this
137
+ if File.directory?(path_to_file)
138
+ path_to_file = path_to_file + "/index.html"
139
+ path = path + "index.html"
140
+ end
141
+
142
+ # bulletproofing access to the files
143
+ unless File.exists?(path_to_file)
144
+ @status = "404"
145
+ "404 - Not Found"
146
+ return
147
+ end
148
+ unless File.file?(path_to_file)
149
+ @status = "403"
150
+ "403 - Forbidden"
151
+ return
152
+ end
153
+ unless File.readable?(path_to_file)
154
+ @status = "403"
155
+ "403 - Forbidden"
156
+ return
157
+ end
158
+ unless File.size?(path_to_file)
159
+ @status = "403"
160
+ "403 - Forbidden"
161
+ return
162
+ end
163
+
164
+ @headers['Content-Type'] = MIME_TYPES[path_to_file[/\.\w+$/, 0]] || "text/plain"
165
+
166
+ # I set this up as a case in case I need to handle alternative mime types.
167
+ case @headers['Content-Type']
168
+ when 'text/html'
169
+ p = ParseSSI.new(web_root)
170
+ @p = p.parse(path).gsub(/href="\//, 'href="/static/').gsub(/"\/media/, '"/static/media')
171
+ render :static
172
+ else
173
+ @headers['X-Sendfile'] = path_to_file
174
+ end
175
+ end
176
+ end
108
177
  end
109
178
 
110
179
  module Yurt::Helpers
@@ -126,25 +195,15 @@ end
126
195
 
127
196
  module Yurt::Views
128
197
 
129
- # If you have a `layout' method like this, it
130
- # will wrap the HTML in the other methods. The
131
- # `self << yield' is where the HTML is inserted.
132
- # def layout
133
- # html do
134
- # title { 'My Yurt' }
135
- # body { self << yield }
136
- # end
137
- # end
138
-
139
198
  # The `index' view. Inside your views, you express
140
199
  # the HTML in Ruby. See http://code.whytheluckystiff.net/markaby/.
141
200
  def index
142
- p 'This is the index view.'
201
+ text File.read("index.html")
143
202
  end
144
203
 
145
204
  def open_folder
146
205
  text '<ul class="listing">'
147
- @contents.each do |file, type|
206
+ @contents.sort.each do |file, type|
148
207
  li :class => type[0] do
149
208
  a :href => "#", :onclick => "return false;", :id => @p + "/" + file do
150
209
  text file
@@ -170,7 +229,7 @@ module Yurt::Views
170
229
 
171
230
  def new_file
172
231
  text %Q(
173
- <form action="/yurt/yurt.cgi/new_file/" method="post" name="newfile" class="dialog_box" id="newfile" onsubmit="dispatch_post('/yurt/yurt.cgi/new_file/', 'newfile');return false;">
232
+ <form action="/new_file/" method="post" name="newfile" class="dialog_box" id="newfile" onsubmit="dispatch_post('/new_file/', 'newfile');return false;">
174
233
  <fieldset>
175
234
  <legend>
176
235
  <a href="#" onclick="toggleTabs('nf_dialog', 'nf_preview', 'nf_help');return false;">New File</a> |
@@ -188,8 +247,8 @@ module Yurt::Views
188
247
  </div>
189
248
  <textarea name="content" class="contentarea">#{ @f['content'] }</textarea>
190
249
  <input type="hidden" name="path" value="#{@f['path']}" />
191
- <input type="button" name="add" value="Save" onclick="dispatch_post('/yurt/yurt.cgi/new_file/', 'newfile')" />
192
- <input type="button" name="cancel" value="Cancel" onclick="dispatch('/yurt/yurt.cgi/cancel')" />
250
+ <input type="button" name="add" value="Save" onclick="dispatch_post('/new_file/', 'newfile')" />
251
+ <input type="button" name="cancel" value="Cancel" onclick="dispatch('/cancel')" />
193
252
  </div>
194
253
  <div id="nf_preview" class="preview" style="display: none;">
195
254
  </div>
@@ -326,7 +385,7 @@ module Yurt::Views
326
385
 
327
386
  def new_folder
328
387
  text %Q(
329
- <form action="/yurt/yurt.cgi/new_folder/" method="post" name="newfolder" class="dialog_box" id="newfolder" onsubmit="dispatch_post('/yurt/yurt.cgi/new_folder/', 'newfolder');return false;">
388
+ <form action="/new_folder/" method="post" name="newfolder" class="dialog_box" id="newfolder" onsubmit="dispatch_post('/new_folder/', 'newfolder');return false;">
330
389
  <fieldset>
331
390
  <legend>
332
391
  <a href="#" onclick="toggleTabs('nf_dialog', 'nf_help');return false;">New Folder</a> |
@@ -335,8 +394,8 @@ module Yurt::Views
335
394
  <div id="nf_dialog" class="dialog">
336
395
  <label><input type="text" name="foldername" value="" /> Folder name</label>
337
396
  <input type="hidden" name="path" value="#{@p}" />
338
- <input type="button" name="add" value="Save" onclick="dispatch_post('/yurt/yurt.cgi/new_folder/', 'newfolder')" />
339
- <input type="button" name="cancel" value="Cancel" onclick="dispatch('/yurt/yurt.cgi/cancel')" />
397
+ <input type="button" name="add" value="Save" onclick="dispatch_post('/new_folder/', 'newfolder')" />
398
+ <input type="button" name="cancel" value="Cancel" onclick="dispatch('/cancel')" />
340
399
  </div>
341
400
  <div id="nf_help" class="help" style="display: none;">
342
401
  <p>Please use characters that you would normally expect to be valid for your folder/directory name. We suggest using upper and lower case letters, numbers, and the following punctuation (sans quotes): ".", "_", "-". If you try to type in illegal characters, the application will convert them to underscores.</p>
@@ -384,6 +443,9 @@ module Yurt::Views
384
443
  end
385
444
  end
386
445
 
446
+ def static
447
+ text @p
448
+ end
387
449
  end
388
450
 
389
451
  if __FILE__ == $0
@@ -1,11 +1,13 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- require File.dirname(__FILE__) +'/../lib/yurtcms'
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+ require 'yurtcms'
5
+ require 'parse_ssi'
4
6
  require 'test/unit'
5
7
 
6
8
  class Input
7
- attr_reader :title, :keywords, :description, :partial, :content, :path, :filename
8
- attr_writer :title, :keywords, :description, :partial, :content, :path, :filename
9
+ attr_reader :title, :keywords, :description, :partial, :content, :path, :filename, :template
10
+ attr_writer :title, :keywords, :description, :partial, :content, :path, :filename, :template
9
11
  end
10
12
 
11
13
  class TestYurtFS < Test::Unit::TestCase
@@ -43,6 +45,7 @@ class TestYurtFS < Test::Unit::TestCase
43
45
  i.content = "This is *the* content of the file."
44
46
  i.path = "/"
45
47
  i.filename = "my_file"
48
+ i.template = "template.html"
46
49
 
47
50
  @y.write_all_files( i )
48
51
 
@@ -1,6 +1,8 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- require File.dirname(__FILE__) +'/../lib/yurtcms'
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+ require 'yurtcms'
5
+ require 'parse_ssi'
4
6
  require 'test/unit'
5
7
 
6
8
  class Input
@@ -126,6 +128,7 @@ class TestYurtCMS < Test::Unit::TestCase
126
128
  end
127
129
 
128
130
  def test_make_placeholder
131
+ warn @y.make_placeholder( 'solutions/foo', 'template.html' )
129
132
  assert_equal( "<!--#set var=\"PAGE\" value=\"solutions/foo\" -->\n<!--#include virtual=\"/includes/template.html\" -->\n", @y.make_placeholder( 'solutions/foo', 'template.html' ) )
130
133
  end
131
134
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: YurtCMS
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.1
7
- date: 2006-11-13 00:00:00 -05:00
6
+ version: 0.4.1
7
+ date: 2007-01-08 00:00:00 -05:00
8
8
  summary: The Web CMS that does less!
9
9
  require_paths:
10
10
  - lib
@@ -29,6 +29,7 @@ authors:
29
29
  - Robert Hahn
30
30
  files:
31
31
  - bin/yurt
32
+ - lib/parse_ssi.rb
32
33
  - lib/yurtcms.rb
33
34
  - site/content
34
35
  - site/htdocs