mieki256's diary



2016/01/12(火) [n年前の日記]

#1 [dxruby][dxrubyws] DXRubyWSのチュートリアル文書に従って試してみる。その2

_DXRubyWS の、 _doc/tutorial02.txt を写経して動作確認してみる。

最も簡単なコード。 :

_tuto21.rb
require_relative './lib/dxrubyws'
require_relative './lib/standardgui'

WS.desktop.add_control(WS::WSWindow.new(100,100,300,200,"TutorialWindow"))

Window.loop do
  WS.update
end
tuto21.gif
ウインドウが表示された。マウスでドラッグ移動、サイズ変更ができるし、閉じるボタンを押せばウインドウを閉じることもできる。

標準GUIを使う時は、
require_relative './lib/standardgui'
を、最初のほうに書いておくものらしい。

WS::WSWindow.new() でウインドウを作って、WS.desktop.add_control() で画面に登録しているのかな。たぶん。

ボタンを配置して、ボタンを押したら反応させる。 :

まずは、ボタンを配置。

_tuto22.rb
require_relative './lib/dxrubyws'
require_relative './lib/standardgui'

# ウインドウを生成
window = WS::WSWindow.new(100,100,300,200,"TutorialWindow")

# 画面に登録
WS.desktop.add_control(window)

# ボタンを生成
button = WS::WSButton.new(10,10,100,20,"TutorialButton")

# ウインドウ(のクライアント領域)に登録
window.client.add_control(button)

Window.loop do
  WS.update
end
tuto22.png
ボタンを表示することができた。

tutorial02.txt には…。
  • WSWindowオブジェクトはコンテナの集合体。タイトルバーとクライアント領域に分かれてる。
  • ユーザがコントロールを配置するのはクライアント領域のほう。
  • クライアント領域は、WSWindow#clientでアクセスすることができる。
と書いてある。

ボタンに反応させてみる。

_tuto23.rb
require_relative './lib/dxrubyws'
require_relative './lib/standardgui'

window = WS::WSWindow.new(100,100,300,200,"TutorialWindow")
WS.desktop.add_control(window)

button = WS::WSButton.new(10,10,100,20,"TutorialButton")
window.client.add_control(button)

# ボタンをクリックしたときに呼ばれる処理を登録
button.add_handler(:click) do
  # ボタンの表示位置を、右下に10ドット変更する
  button.x += 10
  button.y += 10
end

Window.loop do
  WS.update
end
tuto23.gif
ボタンを押すと、ボタンの表示位置が変わっていく。たしかに、ボタンが反応してる。

ボタンがクリックされたら ―― :click シグナルが来たら、処理がされるように設定されてる。

TutorialWindowクラスを作ってみる。 :

_tuto24.rb
require_relative './lib/dxrubyws'
require_relative './lib/standardgui'

module WS
  class TutorialWindow < WSWindow
    def initialize(*args)
      super
      button = WS::WSButton.new(10,10,100,20,"TutorialButton")
      client.add_control(button, :btn)
      button.add_handler(:click, self.method(:on_click))
    end

    def on_click(obj, tx, ty)
      client.btn.x += 10
      client.btn.y += 10
    end
  end
end

window = WS::TutorialWindow.new(100,100,300,200,"TutorialWindow")
WS.desktop.add_control(window)

Window.loop do
  WS.update
end
tuto24.gif
tuto23.rb と同じことを、クラスを作ることで実現できた。

これで、 _tutorial02.txt の内容を一通り試せた。

#2 [dxruby][dxrubyws] DXRubyWSで画像ボタンを表示してみる

DXRubyWS上で、ツールバーだか、ツールボックスだか、そんな感じの表示をしてみたい。そのためには、最低限、画像ボタンが表示できないといけない。画像ボタンを表示する方法はあるのかな。調べてみる。

画像ボタンを1つだけ表示。 :

_sample/minsample.rb を眺めると、WS::WSImageButton なるものがあるらしい。おそらくコレが、名前からして、画像ボタンなのだろう…。

_lib/StandardGUI/button.rb の中に、WSImageButton の定義がある。ソレによると…。
WS::WSImageButton.new(tx, ty, image, width, height, caption)

x : 表示位置 x
y : 表示位置 y
image : 画像オブジェクト(DXRuby の Imageオブジェクト)
width : 横幅。nil なら自動調整
height : 縦幅。nil なら自動調整
caption : キャプション文字列
こんな感じなのだろう。たぶん。おそらく。

サンプルソースを書いてみることにしよう。以下の画像を使って、画像ボタンを表示してみる。この画像は、CC0 / Public Domain ってことで。

toolbar.png


_imagebutton_test.rb
# ImageButton(画像ボタン)を表示してみる

require_relative 'lib/dxrubyws'
require_relative 'lib/standardgui'

module WS

  # 画像ボタンを表示してみるウインドウのクラス
  class ImageButtonWindow < WSWindow

    # コンストラクタ。初期化処理
    def initialize(*args)
      super

      # 画像を用意する。アイコンが、8x3個、並んでる
      imgs = Image.loadTiles("toolbar.png", 8, 3)

      # 画像ボタンを生成
      # 引数として、(x, y, Imageオブジェクト, ボタン横幅, ボタン縦幅, caption) を渡す
      # 横幅、縦幅の指定が nil なら、画像サイズ+αで調整してくれる
      x, y = 10, 10
      w, h = nil, nil
      imgbtn = WS::WSImageButton.new(x, y, imgs[1], w, h, "Open")

      # 画像ボタンをクライアント領域に追加
      client.add_control(imgbtn, :btn)

      # ボタンが押された時の処理を設定
      imgbtn.add_handler(:click, self.method(:on_click))
    end

    # ボタンを押した時の処理
    def on_click(obj, tx, ty)
      # ファイル選択ダイアログを開いてみる
      filter = [
        ["PNGファイル(*.png)", "*.png"],
        ["すべてのファイル(*.*)", "*.*"]
      ]
      filepath = Window.openFilename(filter, "ファイルを選択してください")

      unless filepath
        # キャンセルされた
        puts "Cancel."
      else
        # ファイルが選ばれた
        puts filepath
      end
    end
  end
end

# ウインドウを生成
window = WS::ImageButtonWindow.new(8, 8, 320, 96, "ImageButtonWindow")

# 画面に追加
WS.desktop.add_control(window)

Window.loop do
  WS.update
end
imagebutton_test.png
画像ボタンが表示できた。

マウスカーソルをボタンの上に持ってくると、説明のためのバルーン表示(?)までしてくれるのだな…。素晴らしい。

けど、マウスカーソルでバルーン表示が隠れちゃって、文字が読めないから、イラッとするのだな…。微妙に残念。バルーンの表示位置については、改善が必要な予感。

画像ボタンをたくさん表示。 :

画像ボタンが表示できたので、ツールバーだか、ツールボックスだか、そんな感じのウインドウも表示してみたい。

_imagebutton_test2.rb
# ImageButton(画像ボタン)を表示して、ツールボックスっぽく並べてみる

require_relative 'lib/dxrubyws'
require_relative 'lib/standardgui'

module WS

  # ツールボックスっぽく表示してみるウインドウクラス
  class ToolBoxWindow < WSWindow

    # コンストラクタ。初期化処理
    def initialize(*args)
      super

      # アイコン画像を読み込む。アイコンが、8x3個、並んでる
      imgs = Image.loadTiles("toolbar.png", 8, 3)

      # アイコン種類を定義
      icon_list = [
        # 画像番号, caption, 押された時の処理名
        [0, "New", :create_new_data],
        [1, "Open", :load_data],
        [2, "Save", nil],
        [3, "Export", nil],

        [11, "Zoom +", nil],
        [12, "Zoom -", nil],
        [13, "Brush Size +", nil],
        [14, "Brush Size -", nil],

        [17, "Swap Fg/Bg Color", nil],
        [16, "Grid on/off", nil],
        [15, "Undo", nil],

        [4, "Pen", nil],
        [5, "Erase", nil],
        [6, "Line", nil],
        [7, "Rectangle", nil],

        [8, "Rectangle Fill", nil],
        [9, "Fill", nil],
        [10, "Text", nil],
      ]

      # アイコンの数だけループする
      x = 0
      y = 0
      i = 0
      icon_list.each do |d|
        idx, caption, job_sym = d

        # マウスカーソルでバルーン表示が隠れてしまうので、少し修正
        caption = "    " + caption + " "

        # 画像ボタンを生成
        # 引数として、(x, y, Imageオブジェクト, ボタン横幅, ボタン縦幅, caption) を渡す
        # 横幅、縦幅の指定が nil なら、画像サイズ+αで調整してくれる
        imgbtn = WS::WSImageButton.new(x, y, imgs[idx], nil, nil, caption)

        # 画像ボタンをクライアント領域に追加
        client.add_control(imgbtn, :btn)

        if job_sym != nil
          # ボタンが押された時の処理を設定
          imgbtn.add_handler(:click, self.method(job_sym))
        end

        i += 1

        # 次のボタンの表示位置を決める
        if i % 11 == 0
          x = 0
          y += imgbtn.height
        else
          x += imgbtn.width
        end
      end
    end

    # Newボタンを押した時の処理
    def create_new_data(obj, tx, ty)
      puts "create new data"
    end

    # Openボタンを押した時の処理
    def load_data(obj, tx, ty)

      # ファイル選択ダイアログを開いてみる
      filter = [
        ["PNGファイル(*.png)", "*.png"],
        ["すべてのファイル(*.*)", "*.*"]
      ]
      filepath = Window.openFilename(filter, "ファイルを選択してください")

      unless filepath
        # キャンセルされた
        puts "Cancel."
      else
        # ファイルが選択された
        puts filepath
      end
    end
  end
end

# ツールボックスウインドウを生成
window = WS::ToolBoxWindow.new(8, 8, 320, 96, "ToolBoxWindow")

# 画面に追加
WS.desktop.add_control(window)

Window.loop do
  WS.update
end
imagebutton_test2.png
それらしい表示ができた。

ウインドウのサイズを、値を直接指定して決めてるあたりが、なんだかダサイ…。
  • ボタンをずらずら並べていったら、自動でウインドウサイズも変わってほしいし、
  • 逆に、ウインドウサイズを変更したら、ボタンが横に並ぶ個数も自動で変わったりしてほしい。
けど、そのあたりの処理は、今後の課題ってことで。

#3 [dxruby][dxrubyws] DXRubyWSでチェックボックスを表示してみる

DXRubyWS で、チェックボックスを表示してみたい。

_sample/minsample.rb を眺めると、WS::WSCheckBox なるものがある。名前からして、コレがチェックボックスだな…。

さらに、 _lib/StandardGUI/checkbox.rb を眺めると…。
WS::WSCheckBox.new(tx, ty, width, caption)

tx : 表示位置 x
ty : 表示位置 y
width: 横幅
caption : キャプション文字列
他にも…。 それらを踏まえてサンプルソースを書いてみる。

_checkbox_test.rb
# DXRubyWSでチェックボックスを表示してみるテスト

require_relative 'lib/dxrubyws'
require_relative 'lib/standardgui'

module WS

  # チェックボックスを表示してみるウインドウクラス
  class CheckBoxWindow < WSWindow

    # コンストラクタ。初期化処理
    def initialize(*args)
      super

      @chkbox = []

      chkbox_list = [
        "Character",
        "Fg Color",
        "Bg Color",
      ]

      x, y = 8, 8
      w, h = 0, 0
      chkbox_list.each do |caption|

        # チェックボックスを生成
        # (x, y, width, caption) を渡す
        cb = WS::WSCheckBox.new(x, y, 120, caption)

        # あらかじめチェックを入れておく
        cb.checked = true

        # クライアント領域に追加
        client.add_control(cb, :chkbox)

        # 状態が変更された時の処理を登録
        cb.add_handler(:change, self.method(:on_change))

        # 後で参照するかもしれないから一応記憶しておく
        @chkbox.push(cb)

        # 次の表示位置を求める
        y += cb.height + 4
      end
    end

    # 状態が変更された時の処理
    def on_change(obj, checked)
      puts "#{obj.caption}, #{checked}"
    end
  end
end

# ウインドウを生成して画面に登録
window = WS::CheckBoxWindow.new(8, 8, 120, 120, "CheckBoxWindow")
WS.desktop.add_control(window)

Window.loop do
  WS.update
end
checkbox_test.png
それらしく表示された。

チェックを入れたり外したりすると、on_change メソッドが呼ばれて、キャプションとチェック状態が標準出力に出力される。

#4 [vine][linux] Apache2にDOS攻撃対策のモジュールを入れてみたり

最近、たまに、自宅サーバにDOS攻撃っぽいアクセスがあって、自宅サーバが無反応になってしまう時があるのです。

DOS攻撃と言っても、おそらくはSPAM業者が、投稿可能なページだの、リンク元が残るページだのを見つけて、宣伝URLを書き込もうと大量アクセスして失敗してるとかそんな感じだろうと勝手に想像してるのですが。何にせよ、HTTPサーバも含めて、自宅サーバが沈黙しちゃうのは困るわけで。

何か対策は無いのかとググってみたら、Apache2 に mod_evasive なるモジュールを入れると対策らしきことができるそうで。

_Apache,Linux - ApacheのDOS攻撃対策 - Qiita
_Apache DoS攻撃にそなえる | Developers.IO

てなわけで、自宅サーバ、Vine Linux 6.x にもインストールしてみたり。

wget でソースを入手して、tar で解凍して、解凍したフォルダに入って。
wget http://www.zdziarski.com/blog/wp-content/uploads/2010/02/mod_evasive_1.10.1.tar.gz
tar zxvf mod_evasive_1.10.1.tar.gz
cd mod_evasive

ここから、apxs という、apache にモジュールを追加するためのツールを使って、コンパイルして .so を作ってモジュール追加をするのだけど。
*1

ここで、ちょっとハマってしまった。今現在の Vine Linux上で apxs を使う時は、/usr/sbin/apxs ではなく、/usr/bin/apxs を使わないとダメなようで。前者は apache 1.x 用で、後者が apache 2.x 用なのではないかと。たぶん。分かんないけど。単に apxs -i -a -c mod_evasive20.c と打ってみたら、エラーがバンバン出て困り果ててしまった。/usr/bin/apxs と打たないとダメ。

# /usr/bin/apxs -i -a -c mod_evasive20.c
なんか色々メッセージが表示されてるけど、追加されたっぽい。

/var/log に mod_evasive というフォルダを作って、そこにログを入れることにする。
mkdir /var/log/mod_evasive
chown か chmod も必要なのだろうか。

/etc/apache2/conf/httpd.conf に設定を追加。
# この行は自動で追加されているはず
LoadModule evasive20_module   /usr/lib/apache2/modules/mod_evasive20.so

# 同一ページに2秒間で3回アクセスされたら、
# あるいは、同一サイトに1秒間で30回アクセスされたら、
# 180秒間ブロックする例
<IfModule mod_evasive20.c>
    DOSHashTableSize 3097
    DOSPageCount 3
    DOSSiteCount 30
    DOSPageInterval 2
    DOSSiteInterval 1
    DOSBlockingPeriod 180
    DOSWhitelist 127.0.0.1
    DOSWhitelist 192.168.1.*
    DOSLogDir "/var/log/mod_evasive"
    DOSEmailNotify "-s 'DoS Alert' hoge@fuga.com"
</IfModule>

設定ファイルに問題が無いかチェック。
# apache2 -t
Syntax OK

apache2 を再起動。
# service apache2 restart

テストスクリプトが動かない。 :

mod_evasive には、test.pl というテスト用スクリプトがついてきているのだけど、コレがどうもうまく動かない。

Windowsが動いてる別PCに持ってきて、アクセス先のURL? URI? を修正して、AcivePerl を使って動かしてみたものの、いきなり最初から403しか返ってこない。変だな…。ホワイトリストに入れてるから、200が返ってくるはずだけど…。

自宅サーバ上で、ホワイトリスト行を無効にして apache2 を再起動してから test.pl を走らせてみたものの、これも最初から403。200なんて一度も出てこない。何故。

かといって、ブラウザでアクセスできないかというとそんなことはなく。フツーにページが見れてるわけで。

test.pl の中身は、こんな感じで。
# test.pl: small script to test mod_dosevasive's effectiveness

use IO::Socket;
use strict;

for(0..100) {
    my $response;

    my $SOCKET = new IO::Socket::INET( Proto => "tcp",
                                       PeerAddr => "127.0.0.1:80");

    if (! defined $SOCKET) { die $!; }

    print $SOCKET "GET /?$_ HTTP/1.0\n\n";
    $response = <$SOCKET>;
    print $response;
    close($SOCKET);
}
もちろん、PeerAddr => "127.0.0.1:80" は書き換えて試してるけど。何がおかしいんだろう…。

サーバ側のログを眺めてみたけど、別のログに記録が残っていて、首を捻ったり。test.pl は、"GET /?0 HTTP/1.0" とか "GET /?1 HTTP/1.0" という形でなんかくれよーくれくれくれー、とアクセスしてるわけだけど。その手のアクセスは、Nimdaウイルス等からアクセスされた時に残るログのほうに記録されてる。なんでそっちに行っちゃうんだ…?

_2004/04/19 にやってた設定が効いてるみたい。ホストが不明なアクセスは隔離するようにしていることで、こういうことになっている、のかも。よく分かってないけど。

*1: apxs を使う際、Linuxディストリによっては、httpd-devel だか apache2-devel だかのパッケージが必要になる時もあるらしいので、apt-get だか yum だかでインストールしておく必要があるのかもしれないがよくわかってない。

以上、1 日分です。

過去ログ表示

Prev - 2016/01 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project