顯示具有 Ruby 標籤的文章。 顯示所有文章
顯示具有 Ruby 標籤的文章。 顯示所有文章

2014-07-29

Raspberry Pi Wi-Fi Honeypot & bitmap font to Bitmap

Raspberry Pi Wi-Fi Honeypot

source link

& bitmap font to Bitmap(ruby專用call system,其他語言請自行替換)
system("convert -colors 2 -size 120x20 xc:white -fill black -pointsize 16 -font ./wenquanyi_10pt.pcf -draw \"text 0,11 '喵很可愛呼嚕'\" -compress none pbm:-")
& bitmap font (CJK)

文泉驛

螢火飛

或是去用x11專用的來玩,類似

xfonts-intl-chinese_1.2.1-8_all.deb


萬點螢火飛新宋,一泓文泉驛正黑。#fonts

2014-06-17

Ruby XML RPC Server and Client (Std lib)

大概就是最近需要使用API server但找不到最simple的解法

so~ 大概看了一下std lib發現好用的東西:XML-RPC server / client

but...建議使用WEBrickServlet而非XML RPC Server...因為可以進行mount

just code :

[[server]]

require 'webrick'
require 'xmlrpc/server'
require 'json'

API_KEY = "api_v1_bata"

##service
api_servlet = XMLRPC::WEBrickServlet.new

api_servlet.set_valid_ip(
  /127\.0\.0\.1/ ,
  /192\.168\.\d{,3}\.\d{,3}/
)

api_servlet.add_handler("info") do |func|
  ans = nil
  case func
  when 'hihi'
    ans = 'yooo'
  else
    ans = 'hooo'
  end

  ans
end

api_servlet.set_default_handler do |name, *args|
  raise XMLRPC::FaultException.new(-404, "no #{name}")
end

##no_service
default_servlet = XMLRPC::WEBrickServlet.new

default_servlet.set_default_handler do |name, *args|
  '^_^...no service'
end

##main_server
$rpc_api_server = WEBrick::HTTPServer.new(
  :BindAddress => '',
  :Port => 8080,
  :AccessLog => "",
)

#...multi version or service...
$rpc_api_server.mount("/#{API_KEY}" , api_servlet )
#default
$rpc_api_server.mount('/' , default_servlet )
$rpc_api_server.start

[[client]]

require "xmlrpc/client"

API_KEY = "api_v1_bata"

server = XMLRPC::Client.new("127.0.0.1", "/#{API_KEY}", 8080)

param = server.call("info", 'hihi')
#=> yooo

param = server.call("info", '....')
#=> hooo

server = XMLRPC::Client.new("127.0.0.1", "/", 8080)

param = server.call("info", 'hihi')
#=> ^_^...no service

no gem & simple & easy :)

but 沒有辦法取得client端的remote ip...但可以limit client ip

so~ 建議intranet Server to Server使用即可

2014-01-03

Ruby Gzip / Zip Stream

just code

require 'zip' #gem 'rubyzip'
require 'zlib'
require 'stringio'

##gzip_reader

  strio = StringIO.new(gzip_body)
  Zlib::GzipReader.new(strio).read

#=> ori_body


##gzip_writer

  strio = StringIO.new("")
  gz = Zlib::GzipWriter.new(strio)
  gz.write("foobar")
  gz.close
  strio.string

#=> gzip_body


##zip_io_reader

  str_io = StringIO.new(zip_body)
  file = {}
  Zip::InputStream.open(zip_io) do |io|
    while (entry = io.get_next_entry)
      file[entry.name] = io.read
    end
  end

#=> file = {:file_name => file_body}


##zip_io_writer

  #file = [:file_name => file_body]
  file = {}
  strio = Zip::OutputStream.write_buffer do |io|
    file.each_pair do |file_name , file_body|
      io.put_next_entry(file_name)
      io.write(file_body)
    end
  end
  strio.string

#=> zip_body

2013-04-17

Ruby & Websocket & websocket-js 支援與詳解

首先,此處使用em-websocket的gem來做websocket server

之後,直接看code才解釋

require 'rubygems'
require 'em-websocket'

EventMachine.set_descriptor_table_size(65535)

EventMachine.run do

  EventMachine::WebSocket.start(:host => '0.0.0.0', :port => 843) do |ws|
    ws.onopen do |handshake| ; end
    ws.onclose do ; end
    ws.onmessage do |msg| ; end
  end

  #im root
  EventMachine.set_effective_user( "nobody" )
  #im nobody

  EventMachine::WebSocket.start(:host => '0.0.0.0', :port => 8080) do |ws|

    ws.onopen do |handshake|
      #your code
    end
    ws.onclose do
      #your code
    end
    ws.onmessage do |msg|
      #your code
    end
  end
end


首先,EventMachine.set_descriptor_table_size(65535)
這邊設定最大的設定值,不過因為Linux有設定openfile的最大數量,可使用指令`ulimit -a`來進行查詢

$ ulimit -a

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024  ### 這個數量
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited


所以這個使用者只能最高有1024個connection,必須修改類似Linux下的limit.conf,應該在這個path下
`/etc/security/limits.conf`
然後增加類似

somebody  soft  nofile  65535
somebody  hard  nofile  65535

才可以突破1024數量的限制,所以OS必須要設定才行,EventMachine就再輔助設定一次,但其無法覆蓋OS的設定值

之後是Flash PolicyFile的問題(類似使用websocket-js來用Flash轉介使用websocket協定,讓IE和舊版本的瀏覽器只要有Flash就可以使用websocket),新版的v9+的Flash,在建立WebSocket時"一定"會先送出843 port來要求連線的授權,所以必須在843 port開一個service回應授權(em-websocket原生內定就會直接回傳,所以不用實作,要開而已),當然你可以就這樣把服務開在那邊,就不用像demo一樣必須開兩個port,只是可能client端的網管會把不常用的port進行封鎖,就會連結不到之類的(Chrome / Firefox有原生支援websocket,其實就不會用到這個port的)...且843 port因為小於1024,所以會需要root的權限,所以盡可能越乾淨越好

EventMachine.set_effective_user( "nobody" )

這行以上的為root權限(因為843 port必須為root才能開啓),而此行以下的為設定的使用者,一些比較複雜且dirty的code就可以放在這邊之後,相對的比較安定就是,且port與843分離,實際的流量也會準確些就是了

okay以上大概是這樣,解決幾個最大的問題
1.最大的連線數,突破1024的限制
2.Flash授權書的問題
3.執行使用者的問題(root => nobody)

2013-01-11

Ruby : array to method arguments

話說...很多Ruby求學過程中,應該會學到這樣的code

def abc(key , *args)
  puts key
  puts args.join(',')
end

> abc(1,2,3,4,5)
#=> 1
#=> "2,3,4,5"


簡單的來說可以把mehtod做類似overloading的動作,不過overloading是多個不同的method,而這個只是把傳入值打成一個array而已

不過這太簡單的,很多語言也都有實作,但,反過來怎解?把一個array打成多個傳入值

> abc(1,[2,3,4,5])
#=> 1
#=> "[2,3,4,5]" #Array


相同的code...fail,這應該不是我們想要的,而且一般而言,如果要達到這件事情,需要多個變數和判斷才能完完整整的打進去,所以這邊用新的寫法,也就是*對於Array的用法,非常類似*args,其實就是做相同的事情,把一個東西合併,也把一個東西打平

#A
> abc(1,*[2,3,4,5])

#B
> abc(1,*[2,3],*[4,5])

#C
> x = [2,3,4,5]
> abc(1,*x)

#A,B,C:
#=> 1
#=> "2,3,4,5"


上面三個結果輸出都一樣,okay,你得到它了,看起來很evil但實際是很直覺的,而*array這用法只能在傳入時使用,一般情況不能使用就是了,所以這世界真實案例是怎樣?

Rails下有個很簡單方便的例子,類似Model.where的寫法,可以傳入Hash,可是Hash就不能自己下condition(變得會只有"and"串接),也就是SQL的部份,所以如何組SQL出來?

def select_me
  condition = ['kind = 3']

  params.keys.each do |key|
     case key
     when :user_id
       condition[0] += "AND id = ?"
       condition << params[:user_id].to_i
     when :is_locked
       condition[0] += "AND `lock` = ?"
       condition << params[:is_locked].to_i == 0 ? 1 : 0
     when :amount_range
       amount_temp = params[:amount_range].split(/_/).map{|i|i.to_i}.sort
       if amount_temp.lenght == 2
         condition[0] += "AND amount BETWEEN ? AND ?"
         condition += amount_temp
       end
    end
  end
  @user = User.where(*condition)
end


okay...以上是demo,簡單的來說你把Array組好就把傳入值全都組好了,不用過多的暫存變數,一切都很歡樂的,然而這用法其實非常優於傳入hash再另外做解離的動作,因為你把傳入值名稱等都定義好,其實一切就變得更精確,不用另外額外寫doc來描述hash內應該需要些什麼,類似


def save_log(user_id , remote_ip , from_action , from_controller , browser_agent , session_key , cookie_token , time_now = Time.now)
  #...
end


對於懶得維護doc的人而言,傳入值的變數名稱其實就已經說明了一切,且如果用IDE之類的東西,也會直接提醒,反查也一看就知道之類的...hmmm~ anyway推薦這好用的方式給您,以上