YurtCMS 0.3.1 → 0.4.1

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.
@@ -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