kingwmj 发表于 2011-06-08 13:09

貌似用ruby写出的代码比perl还要短啊。

本帖最后由 kingwmj 于 2011-06-08 17:21 编辑

看了几个小程序,感觉比perl要短。
请高手用perl缩写如下代码,能更短一点吗?楼下的说原来那个太弱了,现在换了一个,据说是最小的飞信客户端,还能再小一点吗?#!/usr/bin/ruby
# Using GPL v2
# Author:: DongYuwei(mailto:newdongyuwei@gmail.com)
# 更新部分内容应对2010年7月25日飞信升级

require 'uri'
require 'net/http'
require 'net/https'
require "socket"
require 'rexml/document'
require 'digest/md5'
require 'digest/sha1'
require "iconv"

class Fetion
        def initialize(phone_num , password)
                @phone_num = phone_num;
                @password = password;
                @domain = "fetion.com.cn";
                @login_xml = '<args><device type="PC" version="0" client-version="3.5.2540" /><caps value="simple-im;im-session;temp-group;personal-group" /><events value="contact;permission;system-message;personal-group" /><user-info attributes="all" /><presence><basic value="400" desc="" /></presence></args>';
                self.init
        end
       
        def init
                doc = REXML::Document.new(self.get_system_config())
                sipc_proxy = ""
                doc.elements.each("//sipc-proxy") do |element|# using regexp should be faster
                        sipc_proxy = element.text
                end
                @SIPC = SIPC.new(sipc_proxy);
               
                sipc_url = ""
                #ssi-app-sign-in
                doc.elements.each("//ssi-app-sign-in-v2") do |element|
                        sipc_url = element.text
                end
                @fetion_num = self.get_fetion_num(self.SSIAppSignIn(sipc_url))
        end
       
        def login()
                request1 = sprintf("R %s SIP-C/2.0\r\nF: %s\r\nI: 1\r\nQ: 1 R\r\nL: %s\r\n\r\n",@domain, @fetion_num, @login_xml.length)
                request1 = request1 + @login_xml
                server_response = @SIPC.request(request1)
                @nonce = server_response.scan(/nonce="(.*)"/)
               
                request2 = sprintf("R %s SIP-C/2.0\r\nF: %s\r\nI: 1\r\nQ: 2 R\r\nA: Digest response=\"%s\",cnonce=\"%s\"\r\nL: %s\r\n\r\n", @domain, @fetion_num, self.get_response(), @cnonce, @login_xml.length)
                request2 = request2 + @login_xml
                @SIPC.request(request2)
        end
       
        def send_sms(phone, sms_text)
                sms_text = Iconv.iconv("UTF-8","UTF-8",sms_text)
                request = sprintf("M %s SIP-C/2.0\r\nF: %s\r\nI: 2\r\nQ: 1 M\r\nT: tel:%s\r\nN: SendSMS\r\nL: %s\r\n\r\n",@domain, @fetion_num, phone, sms_text.length)
                request = request + sms_text
                @SIPC.request(request)
        end
       
        def send_sms_to_self(sms_text)
                sms_text = Iconv.iconv("UTF-8","UTF-8",sms_text)
                request = sprintf("M %s SIP-C/2.0\r\nF: %s\r\nI: 2\r\nQ: 1 M\r\nT: %s\r\nN: SendCatSMS\r\nL: %s\r\n\r\n",@domain, @fetion_num, @uri, sms_text.length)
                request = request + sms_text
                @SIPC.request(request)
        end

        def logout()
                logout_request = sprintf("R %s SIP-C/2.0\r\nF: %s\r\nI: 1 \r\nQ: 3 R\r\nX: 0\r\n\r\n", @domain, @fetion_num)
                @SIPC.request(logout_request)
        end
       
        def get_response()
                @cnonce = Digest::MD5.hexdigest(rand.to_s)
                key = Digest::MD5.digest(@fetion_num + ":" + @domain + ":" + @password)
                h1 = Digest::MD5.hexdigest(key + ":" + @nonce + ":" + @cnonce).upcase
                h2 = Digest::MD5.hexdigest("REGISTER:" + @fetion_num).upcase
                return Digest::MD5.hexdigest(h1+":" + @nonce + ":" + h2).upcase
        end
       
        def get_system_config()
                uri = URI.parse("http://nav.fetion.com.cn/nav/getsystemconfig.aspx")
                http = Net::HTTP.new(uri.host, uri.port)
                params = sprintf('<config><user mobile-no="%s" /><client type="PC" version="3.5.2540" platform="W5.1" /><servers version="0" /><service-no version="0" /><parameters version="0" /><hints version="0" /><http-applications version="0" /><client-config version="0" /></config>',@phone_num)
                headers = {
                  'Content-Type' => 'application/x-www-form-urlencoded'
                }
                resp = http.post(uri.path, params, headers)
                return resp.body
        end
       
        def SSIAppSignIn(url)
                uri = URI.parse(url)
                path = uri.path + "?mobileno=" + @phone_num + "&pwd=" + @password
                http = Net::HTTP.new(uri.host,uri.port)
                http.use_ssl = true
                http.verify_mode = OpenSSL::SSL::VERIFY_NONE # turn off SSL warning
                resp, xml = http.get(path, nil)
               
                ok = "200"
                doc = REXML::Document.new(xml)
                doc.elements.each("//results") do|element|
         ok = element.attribute("status-code").value
       end
       if ok != "200"#421 verification picture?
            return self.SSIAppSignIn(url)
       end
                return xml
        end
   
        def get_fetion_num(xml)
                @uri = ""
                doc = REXML::Document.new(xml)
                doc.elements.each("//results/user") do |element|
                  @uri = element.attribute("uri").value
                end       
                return @uri.scan(/sip:(+)@/)
        end
end

class SIPC
        def initialize(sipc_addr)
                uri = sipc_addr.split(":")
                @socket = TCPSocket.new(uri, uri.to_i)
        end

        # send SIP request
        def request(sip_request)
                puts sip_request
                @socket.write_nonblock(sip_request)
                #select read_nonblock and rescue is the key
                IO.select [@socket]
                res = ""
                begin
                        while chunk = @socket.read_nonblock(4096)
                                res = res + chunk
                        end
                rescue
                        puts "Error: #{$!}"
                end
                puts res
                return res
        end
end

#for test
if __FILE__ == $0
    fetion = Fetion.new("13651368727","password")
    fetion.login()
    fetion.send_sms_to_self("test-ruby-fetion")
    #fetion.send_sms("mobileID","any sms")
end

zuerrong 发表于 2011-06-08 13:41

看了几个小程序,感觉比perl要短。
kingwmj 发表于 2011-06-08 13:09 http://bbs.chinaunix.net/images/common/back.gif


    越是过度封装的语言,越是短小。
ruby是天生为OO而写的高级语言,短小正常。

2gua 发表于 2011-06-08 14:04

那就让Perl高手来写个,看看哪个短?

kingwmj 发表于 2011-06-08 16:29

回复 3# 2gua


    找了一个比较短的ruby 端口扫描的,perl高手来缩写啊。

zuerrong 发表于 2011-06-08 16:49

回复2gua


    找了一个比较短的ruby 端口扫描的,perl高手来缩写啊。
kingwmj 发表于 2011-06-08 16:29 http://bbs.chinaunix.net/images/common/back.gif


    faint,这种代码用perl写一个更短的轻而易举。甚至想不比它短都难。

zuerrong 发表于 2011-06-08 16:51

本帖最后由 zuerrong 于 2011-06-08 16:52 编辑

发重复了。

zuerrong 发表于 2011-06-08 16:51

使用了诸如sinatra框架的ruby代码短小而强大,才是perl无法比拟的。

kingwmj 发表于 2011-06-08 17:17

使用了诸如sinatra框架的ruby代码短小而强大,才是perl无法比拟的。
zuerrong 发表于 2011-06-08 16:51 http://bbs.chinaunix.net/images/common/back.gif

你把这个弄来,看一看啊。我水平太低,不懂啊。

兰花仙子 发表于 2011-06-08 17:20

require 'rubygems'
require 'sinatra'

def hello_world
    "hello world"
end

get '/' do
    hello_world
end

zhlong8 发表于 2011-06-08 17:20

其实 Perler 看到这个问题第一个想法应该是:这么通用的功能应该有个模块吧?于是 goole cpan port scan
第一行就是。然后

cpan POE::Component::Client::TCP::Muti

然后就有了个portscan.pl 还带命令行参数的 :mrgreen:

Ruby 强在抽象,这种小而精的事在 Perl
页: [1] 2
查看完整版本: 貌似用ruby写出的代码比perl还要短啊。