Today's the day

向软件大牛炫耀我会焊单片机,向硬件大牛炫耀我会写 Rails,向软硬件大牛炫耀我生物,向软硬件生物大牛炫耀我会折腾期货 -_-bbb

用 Ruby 求定积分

纯属无聊……

曾经以为求积分之类的是个很复杂的过程,对那些可以求出积分值的计算程序佩服不以,昨日脑子不知道为什么忽然想到这个问题,翻了翻书,发现这个问题很简单~

用最简单的矩形法,Ruby 代码如下:

  1. def integral(a, b, n = 100)
  2.     sum = 0.0
  3.     dx = (b - a)/n.to_f
  4.     n.times do
  5.         a += dx
  6.         sum = sum + (yield a)*dx
  7.     end
  8.     sum
  9. end

n 为精度,Ruby 的 block 真方便,如果要求:

$$\int_0^1 (x^2-x^3) \mathrm{d}x$$

那么就是:

  1. integral(0, 1) {|x| x**2 - x**3}

如果要求:

$$\int_0^\pi sin(x) \mathrm{d}x$$

那么就是:

  1. integral(0, Math::PI) {|x| Math.sin(x)}

如果函数很复杂,也可以在外面定义一个 f(x),然后写成 integral(a, b) {|x| f(x)},相当美观~

看看结果:

  1. puts integral(0, Math::PI) {|x| Math.sin(x)}
  2. >> 1.99983550388745

$\int_0^\pi sin(x) \mathrm{d}x$ 的准确值是 2,看来精度还不错~


嗯嗯……其实本文的真正意义在于,很久很久之前给 is-Programmer 实现了插入 TeX 公式的功能,这是我第一次用上……

用 File.expand_path 过滤文件名

一些情况下,要从用户哪里得到文件名或者目录名参数,比如文件读取、上传、删除,创建目录,还有 typo 那个 theme_controller 中的 css 和 js 缓存。

恶意用户可以输入含有 "../.." 这样的字符的参数,从而跳转到上级目录,读取或者删除一些其他目录的文件,所以必须要过滤,比如 typo 的 theme_controller.rb 代码中:

  1. def render_theme_item(type, file, mime = nil)
  2.   ...
  3.   if file.split(%r{[\\/]}).include?("..")
  4.     return (render :text => "Not Found", :status => 404)
  5.   end
  6.   ...

file 来自 params[:filename],检查 file 中是否含有 "..",如果有的话,就不做任何动作返回 404。

但是这样并不能解决所有的问题,参数可以被 URI 编码成 %xx%xx 的形式,而且天知道还有什么字符可以跳转到上级目录

最近在看 《Adcanced Rails》这书,上面写了种不错的方法:

  1. name = params[:filename]
  2.  
  3. base_path = File.expand_path(File.join(RAILS_ROOT, "public"))
  4. file_path = File.join(base_path, name)
  5.  
  6. if File.expand_path(file_path).start_with?(base_path)
  7.   data = File.read(file_path)
  8. else
  9.   raise "Access denied"
  10. end

File.expand_path 这方法可以扩展路径字符中所有的特殊字符,包括 "~", "..", ".",形成平坦的路径字符串( 原来我一直以为 File.join 也有这个功效…… ),最后只要检查一下文件的最终地址,开头是否为安全的目录即可,这样就可以轻松的将用户的读取范围限制在 base_path 之下了~

 

自写 html 闭合的一个 Bug

前阵子拿自己写的那个 html 闭合函数,洋洋得意的替换掉了 RubyfulSoup 那个大库,结果却没有发现隐藏在其中的一个 Bug。

当初虽然找了不少 html 样本进行测试,最后却忘记测试 self-close 标签存在的情况,多亏了 獨立的圓 帮我找出了这个问题

Bug 就是如果 html 中有 <br/> <img ... /> 这样的标签,闭合函数就会错误的再追加 </br> </img> 这样的标签在简介末尾,要不是导致 獨立的圓 的 Blog 格式混乱,不知道什么时候才能发现这个问题。

知道了问题所在,修正就很简单了,下面就是改善过的版本,不知道还有没有没有考虑到的地方,高亮部分是改动的部分:

  1. def close_html(html)
  2.     stream = html.scan( /<\s*[\/]*[^>^\/]+>/ ).map { |x| x[ /<\s*([^>^\s]* )[^>]*>/, 1]}
  3.     stack = []
  4.     stream.each do |x|
  5.         if x =~ /^\//
  6.             stack.pop if x[1..-1] == stack.last
  7.         else
  8.             stack.push x
  9.         end
  10.     end
  11.     stack.reverse.each {|x| html << "</#{x}>\n"}
  12.     html
  13. end

Rails 2.1 Release

转自: http://weblog.rubyonrails.org/2008/6/1/rails-2-1-time-zones-dirty-caching-gem-dependencies-caching-etc

Over the past six months, we’ve had 1,400 contributors creating patches and vetting them. This has resulted in 1,600+ patches. A truly staggering number. And lots of that has made it into this release.

New features
The new major features are:

Partial Updates 大期待,其实原来一直以为 Rails 里面早就有了这个功能 ,没想到现在才有,想想现在更新文章的浏览计数,就要把整篇文章再保存一遍,真让人不爽。

正好 Chito 1.0.6 刚完工,1.0.7 就迁移到 Rails 2.1 上去。

Chito 也支持浮动窗口了

Chito 边栏的功能是插件提供的,虽然在 “外观 -> 边栏" 下可以调整边栏的位置,但是想要调整某个边栏项的设置,就得跑到 “插件” 下去找,非常麻烦。

同样处境的,还有导航栏的设置,还有将来的评论过滤器的设置,所以搞个像 WP 那样的浮动设置很有必要。

正好看到了 Prototype Window,这个不错的窗口库,构建于 prototype 和 script.aculo.us 库之上,对于 Rails 项目来说很合适。

还附带了 Rails 的 Helper 文件,方便到家~