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 之下了~

 

编译原理,再开~

看完了《形式语言与自动机导论》,虽然后面的章节明显没有前面看得认真 ,但是对形式语言这块算是有了个总体的认识,DFA、正则表达式、Context-Free Languages、图灵机这些东西之间有什么关系,顿时清楚了很多~

当初看得屁滚尿流败下阵来的《编译原理》,也准备再开,虽然还是没有信心能看完,但是应该比上次好得多

伟大的编译器之神,保佑我吧~~ 

Chito 1.0.6 上传完毕

下载在 http://www.chitolog.org

最近比较折腾,拖了很久,幸运的是修正了在 is-Programmer 使用期间发现的 bug ,更新内容可以参考这里

自写 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