對抗垃圾信!請您點這裡:

我的E-mail:
我的Skype:My status

2007年6月16日

Ruby library -- SMS

這個Library搭配http://www.twsms.com才可以使用喔!
有任何問題可以直接回這篇文章,或者寫信問我,我信箱是Gmail的,帳號跟我的這個部落格帳號一樣

我先說用法好了:

require 'twsms'
sms = TWSMS.new(username, password) # 帳號密碼
sms.sendSMS(mobile, message) # mobile: 目標手機號碼  message: 要傳的訊息
原始碼:
=begin
  == Information ==
  === Copyright: Apache 2.0
  === Author: CFC < zusocfc@gmail.com >
  === Prog. Name: TWSMS lib
  === Version: 0.1
  == Introduction ==
    TWSMS(Taiwan SMS)
    TWSMS is a SMS sender, it must use with http://www.twsms.com.
    There has no any library for the SMS system in Taiwan. So, I just coded this and release this version.
    This version just support for sending SMS.
  == Featured ==
   
  == Using TWSMS ==
    It just support for standalone class now.
    require it before you use.
  === Using TWSMS by standalone class
    require 'twsms'
    sms = TWSMS.new('username', 'password')
    sms.sendSMS('09xxxxxxxx', 'Hi, there! TWSMS library is so easy to use!')
    sms.sendSMS('09xxxxxxxx', 'Send SMS with options',
        :popup => 1,
        :type => "now",
        :mo => "Y")
=end

%w|uri cgi net/http|.each{|r| require r}

class TWSMS
  def initialize(username, password)
    @uname, @upwd = username, password
    @options = {
      :type => "now", # Sending type: now, vld
      :popup => "",
      :mo => "Y".upcase,
      :vldtime => "86400",
      :modate => "",
      :dlvtime => "",
      :wapurl => "",
      :encoding => "big5"
    }
   
    @errors = {
      -1.to_s.to_sym => "Send failed",
      -2.to_s.to_sym => "Username or password is invalid",
      -3.to_s.to_sym => "Popup tag error",
      -4.to_s.to_sym => "Mo tag error",
      -5.to_s.to_sym => "Encoding tag error",
      -6.to_s.to_sym => "Mobile tag error",
      -7.to_s.to_sym => "Message tag error",
      -8.to_s.to_sym => "vldtime tag error",
      -9.to_s.to_sym => "dlvtime tag error",
      -10.to_s.to_sym => "You have no point",
      -11.to_s.to_sym => "Your account has been blocked",
      -12.to_s.to_sym => "Type tag error",
      -13.to_s.to_sym => "You can't send SMS message by dlvtime tag if you use wap push",
      -14.to_s.to_sym => "Source IP has no permission",
      -99.to_s.to_sym => "System error!! Please contact the administrator, thanks!!"
    }
    @args = []
    @url ||= "http://api.twsms.com/send_sms.php?"
    @url += "username=" + @uname
    @url += "&password=" + @upwd
  end
 
  def sendSMS(mobile, message, opt={})
    @options[:mobile], @options[:message] = mobile, message
    @options.merge!(opt).each{|k, v| @args << k.to_s + "=" + CGI::escape(v.to_s)}
    @url += "&" + @args.join("&")
    self.chk_val
    chk_errors(Net::HTTP.get(URI.parse(@url)))
  end
 
  def chk_val
    @options[:dlvtime] = "" unless @options[:type] == "dlv"
    @options[:wapurl] = "" if @options[:type] != ("push" && "upush")
  end
 
  def chk_errors(resp)
    resp = resp.split("=")[1]
    if @errors.has_key?(resp.to_s.to_sym)
      puts "==========", "Error!! Message: ", @errors[resp.to_s.to_sym]
    else
      puts "==========", "Message has been send! Your message id is: " + resp.to_s
    end
  end
 
  protected :chk_val
end
晚點丟到Google Code Hosting上去...

Updated:
TWSMS on Google Code Hosting: http://code.google.com/p/twsms/
SMSender on RubyForge: http://rubyforge.org/projects/smsender/

2007年6月12日

find_by_randomize -- 讓ActiveRecord可以亂數取資料

請在model內加入:

def self.find_by_randomize
  ids = self.find(:all, :select => [id])
  self.find(ids[rand(ids.size)]["id"].to_i)
end
這樣一來,就可以取亂數選取資料了!

請參考這篇:為你的 Active Record 做出多采多姿的 find

當然囉.. thegiive那個就是我修改的範本:P

2007年5月15日

具有破壞版面功用的HTML標籤:plaintext

剛剛寫程式寫到一半忽然想到這個破壞力極大的標籤
雖然這個標籤不會造成多大的危害,但是在某些網站上,還是可以造成一定程度的破壞
所以請各位Web Developers注意,過濾掉這個標籤:<plaintext>
另外,HTML的註解標籤也請過濾,也就是:<!--
這兩個都可以破壞版面!
結果請看這邊:
http://willh.org/cfc/cfc_priv/plaintext.htm

解決方式:
如果是使用黑名單來擋HTML標籤,請把plaintext給加入
如果沒有使用檔標籤的套件,請盡快使用
如果沒有辦法使用檔標籤的套件,請透過Regular Expression幹掉它!

2007年5月13日

php+ruby(with ActiveRecord)又一新範例 -- RSS聯撥器

上個例子,我們用PHP + Ruby 搭配ActiveRecord的方式來寫資料新增的程式
今天我們就來延伸應用一下,要做什麼呢? RSS聯撥器!
有鑒於GoogleReader的RSS聯撥器產生出來的東西太醜(只能修改一兩個小地方.. 我總覺得那好胖=  =),乾脆自己寫個來用
Demo網址改天再PO上來,我們先來寫程式比較重要:P
主機請記得先裝好Ruby、PHP、Apache跟MySQL;OS要啥都沒差,我比較建議LAMP的配置XD
我們來建立一個叫做feeds的目錄包含一個子目錄,叫做lib:

  mkdir -p feeds/lib
 
先跳到feeds/lib新增幾個會被require的檔案:

  cd feeds/lib
  touch connect.rb model.rb require.rb

以下是各個檔案的用處:
- connect.rb
  資料庫連線初始化
- model.rb
  資料表模型宣告
- rqeuire.rb
  會用到的額外library引入

原始碼:

  - connect.rb
    #!/usr/bin/env ruby;require 'lib/require';ActiveRecord::Base.establish_connection({:adapter => "mysql",:host => "localhost",:username => "username",:password => "password",:database => "others"})
  - model.rb
    #!/usr/bin/env ruby;require 'lib/connect';class Feed < ActiveRecord::Base;end
  - require.rb
    #!/usr/bin/env ruby;%w|rubygems active_record hpricot open-uri|.each{|lib| require lib}

一切搞定後,我們可以開始來建立資料庫了!

  mysql> create database others;
  mysql> use others;
  mysql> create table feeds(id int, uri varchar(255));
  mysql> describe feeds;
 
看看資料表結構是否正確!
接著回到上一層目錄,新增底下的幾個檔案:

  touch index.php list.rb new.htm new_record.rb save.php

- index.php
  網站首頁,會列出目前的RSS feed
- save.php
  儲存RSS feed網址
- list.rb
  處理RSS feed
- new_record.rb
  將RSS feed網址存入資料庫(也可以直接用php寫.. 我是沒有意見)
- new.htm
  新增RSS feed網址的表單

原始碼我就直接貼了

  - index.php
    <html>
      <head>
        <title></title>
      </head>
      <body>
        <a href="new.htm">Create</a>
        <ul>
    <?php
      exec("ruby list.rb", $args);
      for($i=0;$i<count($args);$i+=3)
        echo "<li><a href=\"" . $args[$i+1] . "\" title=\"作者:" . $args[$i+2] . "\">" . $args[$i] . "</a> -- " . $args[$i+2] . "</li>";
    ?>
        </ul>
      </body>
    </html>

  - save.php
    <?php
      exec("ruby new_record.rb " . $_POST["feed_uri"], $arg);
      if ($arg) echo "<script>location.href=\"index.php\";</script>";
    ?>
 
  - list.rb
    #!/usr/bin/env ruby
    =begin
        Filename: list.rb
    =end
    require 'lib/model'

    Feed.find(:all).each{|feed|
        doc = Hpricot(open(feed.uri))
        rss = doc.search("entry")
        max = rss.size > 3 ? 3 : rss.size
        max.times {|i|
          break if rss.nil?
          puts rss[i].search("title").text.gsub(/\n/, " ") # Return the title of the article to the PHP file.
          puts rss[i].search("link[@rel='alternate']")[0]["href"].gsub(/\n/, " ") # Return the link of the article to the PHP file.
          puts rss[i].search("author/name").text.gsub(/\n/, " ") # Return the author of the article to the PHP file.
        }
    }

  - new_record.rb
    #!/usr/bin/env ruby
    =begin
      Filename: new_record.rb
    =end
    require 'lib/model';puts Feed.new({:uri => ARGV[0]}).save
 
  - new.htm
    <html>
      <head>
        <title></title>
      </head>
      <body>
        <form action="save.php" method="post">
          <p>Please input the feed url:<input type="text" name="feed_uri" /></p>
          <p><input type="submit" value="Save!" /></p>
        </form>
     </body>
    </html>
 
OK,這樣就可以啦XD

2007年5月9日

PHP + Ruby with ActiveRecord 範例

如果老闆要求使用php,可是您卻是Ruby狂熱者,這.. 怎辦呢?
沒關係! 一樣用Ruby寫,php只要做一點點的處理就好!
How to? php中有這個函式:exec
( 本範例實作於Windows XP Professional搭配InstantRails;在其他作業系統上沒有測試過,不過各位還是可以嘗試看看 )
我們來試試看吧!
先寫個test.rb:

  #!/usr/bin/env ruby
  #
  # Filename: test.rb
  #
  puts "Hello"
  puts "world"
 
再寫個test.php:

  <?php
    exec("test.rb", $args);
    foreach($arg as $args)
      echo $arg . "<br />";
  ?>

將兩個檔案放在同一個目錄下後,打開瀏覽器瀏覽test.php;看!是不是顯示結果出來了?
OK,我們直接來用ActiveRecord幫我們新增資料吧!
我們需要一張普通頁面、一張php網頁跟一個ruby檔案:

  #!/usr/bin/env ruby
  #
  # Filename: ar.rb
  #
  require 'rubygems'
  gem 'activerecord'
  ActiveRecord::Base.establish_connection(
    :adapter => 'mysql',
    :host => 'localhost',
    :username => 'root',
    :password => '',
    :database => 'cal'
  )
 
  class Event < ActiveRecord::Base;end
 
  name, descr = ARGV[0], ARGV[1]
  puts Event.new({:name => name, :descr => descr, :date => Date.today, :time => Time.now}).save

好了,接下來是普通頁面,這是送出表單:
 
  <!-- Filename: ar_form.html -->
  <html>
    <head>
      <title>PHP with Ruby and ActiveRecord</title>
    </head>
    <body>
      <form action="ar_save.php" method="POST">
        Username: <input type="text" name="usrname" /><br />
        Description: <textarea name="descr"></textarea><br />
        <input type="submit" value="Save it!" />
      </form>
    </body>
  </html>
 
這是php網頁:

  <?php
    // Filename: ar_save.php
    exec("2.rb " . $_POST["usrname"] . " " . $_POST["descr"], $arg);
    if($arg[0]) echo "Success!";
  ?>

OK,讓我們來試試看吧!
Look!! It works!!
現在,我們來寫個ar_read.rb跟ar_read.php來讀取資料吧:

  # Filename: ar_read.rb
  require 'rubygems'
  gem 'activerecord'
  ActiveRecord::Base.establish_connection(
    :adapter  => "mysql",
    :host     => "localhost",
    :username => "root",
    :password => "",
    :database => "cal"
  )
  class Event < ActiveRecord::Base;end
  events = Event.find(:all, :conditions => "name = '#{ARGV[0]}'")
  events.each{ |event|
    puts event.name
    puts event.descr
    puts event.date.to_s(:db)
    puts event.time.strftime("%H:%M:%S")
  } 

  <?php
    // Filename: ar_read.php
    exec("ar_read.rb " . $_GET["name"], $args);
    $info = array();
    for($i=0, $j=0;$i<count($args);$i+=4, $j++){
      $info[$j]["name"] = $args[$i];
      $info[$j]["descr"] = $args[$i+1];
      $info[$j]["date"] = $args[$i+2];
      $info[$j]["time"] = $args[$i+3];
    }
    for($j=0;$j<count($info);$j++)
      echo "Name => " . $info[$j]["name"] . "<br />Description => " . $info[$j]["descr"] . "<br />Date => " . $info[$j]["date"] . "<br />Time => " . $info[$j]["time"] . "<br />";
  ?>
 
看看結果,hmmm.. 看起來真棒!
嗯?如何?Ruby + ActiveRecord的威力很強大吧?
為什麼不要直接用PHP寫就好? 因為光寫SQL你就想跳樓,何必呢?
記住,在Ruby的檔案中,不可以用:

  puts 1, 2, 3

這種方法,會造成php收不到回傳,因此必須用這種寫法:

  puts 1
  puts 2
  puts 3

或者就是:

  puts 1; puts 2; puts 3

端看個人喜好囉!

2007年4月30日

Array.longest ( Array.which_long?修改版 )

感謝在Ruby-talk上的:

Chris Carter
David A. Black
Harry
Robert Dober
James Edward
:)
原本的程式碼太長,而且使用內建的功能組合起來就好
再者,原本的程式會把陣列的元素強制轉型為String

新的程式碼為:
class Array
  def longest
    # Harry <http://www.kakueki.com/ruby/list.html>
    self.select{|r| r.to_s.size == self.max{|x, y| x.to_s.size <=> y.to_s.size}.to_s.size}
  end
end
這個程式是由Harry所寫出的,底下轉貼原文:

On 4/29/07, Billy Hsu <ruby.maillist@gmail.com> wrote:
> Thanks for your reply, I learned more on this thread :P
> But I have a question:
> If I have an array contain:
>   ary = [1, 12, 234, "456"]
> there has two elements which size is 3, but the longest method just returned
> one of them.
> I can't solve it :(
>

Is this what you are looking for?
Do you want all longest elements?

big = [1, 12, 234,45,978, "456"].max {|x,y| x.to_s.size <=> y.to_s.size}
p [1, 12, 234,45,978, "456"].select {|r| r.to_s.size == big.to_s.size}
由於Harry不喜歡被張貼信箱,因此我將他的網站給貼上來:
http://www.kakueki.com/ruby/list.html
A Look into Japanese Ruby List in English

再一次謝謝Harry的幫助:)
也謝謝其他人,讓我學到許多東西:D
Thanks again and again!!

CFC --


2007年4月28日

Array.which_long? -- 剛出爐的函式

class Array
def which_long?
# Version 1.0
# Coded by CFC <>
# PLEASE DO NOT REMOVE THE COMMENT OF THIS FUNCTION, THANKS A LOT.
# Usage:
# ['a', 'ab', 'abc' 1234].which_long?
# => 1234
self.size.times{|i| self[i]=self[i].to_s}
max, long = 0, String.new
self.each{|item| item.size > max ? (max = item.size; long = item) : next}
long
end
end


以上是原始碼,使用方式如下:

puts ['a', 'ab', 'abc', 1234].which_long?
=> 1234

授權還沒定,不過大家還是可以拿去使用:P
請不要拿掉註解.. 謝謝