2010年12月24日金曜日

[MA-11-5] トグル操作による表示窓のON/OFF

Windowレイヤーに配置した表示窓を,キー操作によりON/OFFさせる.
具体的には,Windowレイヤーの表示窓オブジェクトをMCとし,そのMCを2フレームに分割する.
1フレーム目は空とし,2フレーム目に表示窓オブジェクトを配置する.
そして,ActionScript側でキー操作を受け取り,MCの1フレーム目~2フレーム目の移動を交互に行う.

サンプル
var key_obj:Object = new Object();
key_obj.onKeyDown = function():Void {
 var code = Key.getCode();
 if (code == Key.SPACE) {
  mcInfo.gotoAndStop(mcInfoNum + 1);
  stop();
 }
}
Key.addListener(key_obj);


※もちろんvisible使ってもOK
サンプル
var key_obj:Object = new Object();
key_obj.onKeyDown = function():Void {
 var code = Key.getCode();
 if (code == Key.SPACE) {
  _root.mcInfo._visible = true;
  //_root.mcInfo._visible = false;
 }
}
Key.addListener(key_obj);

2010年12月22日水曜日

[MA-11-4] HTMLからSWFへの引数渡し


20101217.swf

1.FLAファイルにwindowレイヤー追加
ActionScript(windowレイヤー)
user = _root.user;
money = _root.money;

2.windowレイヤーにダイナミックテキストを2つ設置
(それぞれ変数名を「user」「money」とする)

3.SWFファイルをパブリッシュ

4.SWFと同時に生成されたHTMLファイルを編集
(修正箇所:2)
<param name="movie" value="20101217.swf" />
→
<param name="movie" value="20101217.swf?user=sato&money=100" />
<embed src="20101217.swf" quality="high" bgcolor="#ffffff" width="300" height="200" name="20101217" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
→
<embed src="20101217.swf?user=sato&money=100" quality="high" bgcolor="#ffffff" width="300" height="200" name="20101217" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />

5.SWFとHTMLをアップロードし,動作確認

ダウンロード1
ダウンロード2

2010年12月16日木曜日

[SA-5-1-4] Perlを用いたCGIを使ってWEBアプリ化(完成)

index.html
<HTML>
<HEAD>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=UTF-8">
 <TITLE>Connect MySQL(Perl) 1</TITLE>
</HEAD>

<BODY>
<FORM ACTION="/cgi-bin/connectDB3.cgi" METHOD="get" ENCTYPE="application/x-www-form-urlencoded">
 num       :<INPUT TYPE="TEXT" NAME="num" SIZE="4"><BR>
 host_name :<INPUT TYPE="TEXT" NAME="host_name" SIZE="12"><BR>
 ip_address:<INPUT TYPE="TEXT" NAME="ip_address" SIZE="24"><BR>
 <INPUT TYPE="hidden" name="command" value="insert">
 <INPUT TYPE="SUBMIT" NAME="Submit" VALUE="実行"><BR>
</FORM>
</BODY>

</HTML>

connectDB3.cgi
#!/usr/bin/perl

use DBI;
$user = '[user]';
$passwd = '[pass]';
$db = DBI->connect('DBI:mysql:sa:localhost', $user, $passwd);

if( $ENV{'REQUEST_METHOD'} eq "GET" ) {
    $std = $ENV{'QUERY_STRING'};
} else {
    read( STDIN, $std, $ENV{'CONTENT_LENGTH'} );
}
print "Content-Type: text/html\n\n\n";

print <<HEADER;
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=UTF-8">
<title>Connect MySQL(Perl) 2</title>
</head>
<body>
HEADER

print "Method :", $ENV{'REQUEST_METHOD'},"<br>\n";
print "Data   :", $std, "<br>\n";

print "<br>";

my @pairs = split(/&/,$std);
foreach $pair (@pairs){
    my($name, $value) = split(/=/, $pair);
    $value =~ tr/+/ /;
#    print "$name : $value<br>";
    $form{$name} = $value;
    print "\$form{$name} = $value<br>"
}

print "<br>";

if($form{command} eq 'insert'){
 if($form{num} eq '' || $form{host_name} eq '' || $form{ip_address} eq ''){
  print "登録できません";
 }else{
  $sth = $db->prepare("INSERT INTO server_list (num,host_name,ip_address) VALUES ('$form{num}','$form{host_name}','$form{ip_address}')");
  $sth->execute;
  print "登録完了";
  $sth->finish;
 }
}
$db->disconnect;

print <<FOOTER;
</body>
</html>
FOOTER

[SA-5-1-2] PerlでCGI

1.Hello World!
#vi /var/www/cgi-bin/hello.cgi

hello.cgi
#!/usr/bin/perl

print "Content-type: text/html\n";
print "\n";
print "Hello World!";

#chmod 755 hello.cgi
ブラウザから
http://(サーバのIPアドレス)/cgi-bin/hello.cgi
を確認.


2.GET/POST
connectDB3.cgi
#!/usr/bin/perl

# GETメソッドの場合
if( $ENV{'REQUEST_METHOD'} eq "GET" ) {
    $std = $ENV{'QUERY_STRING'};
# POSTメソッドの場合
} else {
    read( STDIN, $std, $ENV{'CONTENT_LENGTH'} );
}
print "Content-Type: text/html\n\n\n";
print "Method :", $ENV{'REQUEST_METHOD'},"<br>\n";
print "Data   :", $std, "<br>\n";

my @pairs = split(/&/,$std);
foreach $pair (@pairs){
    my($name, $value) = split(/=/, $pair);
    $value =~ tr/+/ /;
    print "$name : $value<br>";
}

ブラウザから,[SA-5-1-2]で作成したファイル
http://(サーバのIPアドレス)/index.html
を確認.
(Method, Data, num, host_name, ip_address, num, host_nameの各項目の値が表示されます)

[卒業研究] Visual BasicからのXMLファイル入出力

以下サンプルコード(一部抜粋)

書き込み
Dim i As Integer
i = 1
Dim xml = XDocument.Load(savedXmlFileName)
For Each op In outputPictList
    Dim str1 = xml.Descendants("Objects").FirstOrDefault()
    str1.Add(New XElement("Pict"))
    Dim str2 = xml.Descendants("Pict").LastOrDefault
    str2.Add(New XElement("pictNum", pictList(i, 0)))
    str2.Add(New XElement("indexNum", pictList(i, 1)))
    str2.Add(New XElement("viewFileName", pictList(i, 2)))
    str2.Add(New XElement("fileFullPath", pictList(i, 3)))
    str2.Add(New XElement("rotateDegree", pictList(i, 4)))
    str2.Add(New XElement("statusOfMarker", pictList(i, 5)))
    str2.Add(New XElement("pictTitle", pictList(i, 6)))

    xml.Save(savedXmlFileName)
    i = i + 1
Next

読み込み
Dim doc1 = XDocument.Load(savedXmlFileName)
Dim query1 = From c In doc1.Descendants("Pict")
                Where c.Element("fileFullPath") IsNot Nothing

Dim i As Integer
i = 1
For Each c In query1
    pictList(pictNum, 0) = pictNum
    pictList(pictNum, 1) = c.Element("indexNum").Value
    pictList(pictNum, 2) = c.Element("viewFileName").Value
    pictList(pictNum, 3) = c.Element("fileFullPath").Value
    pictList(pictNum, 4) = c.Element("rotateDegree").Value
    pictList(pictNum, 5) = c.Element("statusOfMarker").Value
    pictList(pictNum, 6) = c.Element("pictTitle").Value
    CheckedListBox1.Items.Add(pictNum & " : " & c.Element("viewFileName").Value)
    i = i + 1

    pictNum = pictNum + 1
Next

XMLファイル
<?xml version="1.0" encoding="utf-8"?>
<Objects>
  <Pict>
    <pictNum>1</pictNum>
    <indexNum>1</indexNum>
    <viewFileName>Chrysanthemum.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Chrysanthemum.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict1</pictTitle>
  </Pict>
  <Pict>
    <pictNum>2</pictNum>
    <indexNum>2</indexNum>
    <viewFileName>Desert.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Desert.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict2</pictTitle>
  </Pict>
  <Pict>
    <pictNum>3</pictNum>
    <indexNum>3</indexNum>
    <viewFileName>Hydrangeas.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Hydrangeas.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict3</pictTitle>
  </Pict>
  <Pict>
    <pictNum>4</pictNum>
    <indexNum>4</indexNum>
    <viewFileName>Jellyfish.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Jellyfish.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict4</pictTitle>
  </Pict>
  <Pict>
    <pictNum>5</pictNum>
    <indexNum>5</indexNum>
    <viewFileName>Koala.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Koala.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict5</pictTitle>
  </Pict>
  <Pict>
    <pictNum>6</pictNum>
    <indexNum>6</indexNum>
    <viewFileName>Lighthouse.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Lighthouse.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict6</pictTitle>
  </Pict>
  <Pict>
    <pictNum>7</pictNum>
    <indexNum>7</indexNum>
    <viewFileName>Penguins.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Penguins.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict7</pictTitle>
  </Pict>
  <Pict>
    <pictNum>8</pictNum>
    <indexNum>8</indexNum>
    <viewFileName>Tulips.jpg</viewFileName>
    <fileFullPath>C:\Users\username\Desktop\pict\Tulips.jpg</fileFullPath>
    <rotateDegree>0</rotateDegree>
    <statusOfMarker>0</statusOfMarker>
    <pictTitle>pict8</pictTitle>
  </Pict>
</Objects>

2010年12月15日水曜日

[SA-5-1-3] Perlを用いたCGIを使ってWEBアプリ化

index.html(sample)
<HTML>
<HEAD>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=UTF-8">
 <TITLE>Connect MySQL(Perl) 1</TITLE>
</HEAD>

<BODY>
<FORM ACTION="cgi-bin/sample3.cgi" METHOD="POST" ENCTYPE="application/x-www-form-urlencoded">
 num:<INPUT TYPE="TEXT" NAME="num" SIZE="4"><BR>
 host_name:<INPUT TYPE="TEXT" NAME="host_name" SIZE="12"><BR> ip_address:<INPUT TYPE="TEXT" NAME="ip_address" SIZE="24"><BR>

 <SELECT NAME="command">
  <OPTION SELECTED VALUE="insert">INSERT</OPTION>
 </SELECT>

 <INPUT TYPE="SUBMIT" NAME="Submit" VALUE="実行"><BR>
</FORM>
</BODY>

</HTML>



connectDB3.cgi(sample)
#!/usr/bin/perl
use DBI;
$user = '[user name]';
$passwd = '[password]';
$db = DBI->connect('DBI:mysql:sa:localhost', $user, $passwd);

# FORMからデータを読み込む
$len = $ENV{'CONTENT_LENGTH'};
read(STDIN, $std, $len);
@args = split(/&/, $std);
foreach $arg ( @args ){
 ($name, $val ) = split(/=/, $arg);
 $val =~ s/\+/ /g;
 $form{$name} = $val;
}

print <<HEADER;
Content-type: text/html
<html>
 <head>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=UTF-8">
 <title>Connect MySQL(Perl) 2</title>
 </head>
 <body>
HEADER

if($form{command} eq 'insert'){
 if($form{name} eq '' ){
  print "<h1>nameが空白では登録できません</h1>";
 }else{
  $sth = $db->prepare("insert into list (num,host_name,ip_address) values ('$form{num}','$form{host_name}','$form{ip_address}')");
  $sth->execute;
  print "<h1>登録完了</h1>";
  $sth->finish;
 }
}

$db->disconnect;

print <<FOOTER;
</body>
</html>
FOOTER

WebサーバのCGI関連の設定確認
vi /etc/httpd/conf/httpd.conf
AddHandler cgi-script .cgi .pl

[memo] Adobe CS5 Edition比較

Edition Design Standard Design Premium Web Premium Production Premium Master Collection
定価 \198,450 \249,900 \236,250 \261,450 \397,950
単体合計価格 \334,530 \591,450 \554,385 \633,255 \928,085
アカデミック定価 \67,830 \100,380 \100,380 \83,370 \125,790
アカデミック参考価格(amazon) \54,827 \91,245 \82,111 \75,702 \102,888
CLP価格(参考) \49,800 \73,277 \73,277 \60,860 \91,827
Photoshop CS5 Extended * * * * *
Illustrator CS5 * * * * *
InDesign CS5 * *     *
Acrobat 9 Pro * * *   *
Flash Catalyst CS5   * * * *
Flash Professional CS5   * * * *
Flash Builder 4 Standard     *   *
Dreamweaver CS5   * *   *
Fireworks CS5   * *   *
Contribute CS5     *   *
Adobe Premiere Pro CS5       * *
After Effects CS5       * *
Soundbooth CS5       * *
Adobe OnLocation CS5       * *
Encore CS5       * *
Bridge CS5 * * * * *
Device Central CS5 * * * * *
  Dynamic Link       * *

※お勧めはInDesign CS5まで含まれるDesign Premiumです.

2010年12月10日金曜日

[MA-11-3] DBと連携したFlash(キャラクタの動作作り込み)

前回作成したキャラクタは,前後左右の4面しか用意していないが,よりリアルな動作を実現する為に,キャラクタの各方向に対してモーションを付与する.
具体的には,characterレイヤーの各フレームに配置したムービークリップ「front」「back」「right」「left」に対して複数のフレームを用意し,実際にキャラクターが動いているように見せかける仕掛けとする.



20101208.swf

ダウンロード

2010年12月9日木曜日

[SA-5-1-1] PerlからDBへの接続

Perlを用いてDBに接続する.

[user name]
[password]
[DB name]sa

DBIの導入
$ cpan
CPAN> install DBI

DBに値を挿入する.
[insert value]'','13','sa012','10.2.3.112'

connectDB.pl
#!/usr/bin/perl
use DBI;

$user = '[user name]';
$passwd = '[password]';
$db = DBI->connect('DBI:mysql:[DB name]:localhost', $user, $passwd);
$sth = $db->prepare("INSERT INTO server_list VALUES ([insert value])");
$sth->execute;
$sth->finish;
$db->disconnect;


DBに格納されている値を取り出し,全て表示する.
connectDB2.pl
#!/usr/bin/perl
use DBI;

$user = '[user name]';
$passwd = '[password]';
$db = DBI->connect('DBI:mysql:[DB name]:localhost', $user, $passwd);
$sth = $db->prepare("[検索条件]");
$sth->execute;
$num_rows = $sth->rows;
print "該当 $num_rows 件\n";
for ($i=0; $i<$num_rows; $i++) {
 @a = $sth->fetchrow_array;
 print "[値の表示]";
}
$sth->finish;
$db->disconnect;

[検索条件]
SELECT * FROM server_list

[値の表示]
id=$a[0], num=$a[1] host_name =$a[2] ip_address =$a[3] \n

2010年12月8日水曜日

[memo]cookieもしくは,それに類する手法を用いたユーザートラッキングの方法と懸念

cookieもしくは,それに類する手法を用いたユーザートラッキングの実装
(倫理的問題,技術的問題が存在する)

[用途]
行動ターゲティング広告
オプトアウト(opt-out)(*1)

[使用される技術]
データの永続化
Flash:Local Shared Object
HTTP:cookie
Silverlight:ローカルストレージ
HTML5:ローカルストレージ
HTTP:HTTPレスポンスヘッダであるETagの利用
PNGキャッシュクッキー:セッションデータをRGBのパラメータとしてエンコードしたPNGファイルを生成(*2)

[実際の事例]
楽天:ad4U(*3) [参考]

(*1)ユーザの許諾無く、一方的に広告メールを送りつけること.また,それを拒否して広告を送付しないよう企業に依頼すること.
(*2)期間20年指定でキャッシュさせる.再アクセス時には304 Not Modified を返して表示させ,HTML5のCanvasタグでピクセルを読んで復号.
(*3)閲覧履歴を直接取得するのではなく,ブラウザの過去に閲覧した事のあるリンクの色を変える機能を流用し,楽天側で予め用意した(ユーザーが見ていそうな)リンクのリストをユーザー側に送り,そのリンクの色が何色に変化したかを取得する事で,ユーザーがリスト中のどのリンクを閲覧していたかを把握する方法. [参考]

データの永続化DEMO
[参考]

[MA-11-2] DBと連携したFlash(基礎部分作成)

最終的にはDBと連携したFlashファイルを作成するが,まずはステージ上を上下左右キーで操作できるキャラクタを作成し,配置する.



20101201.swf

ダウンロード

2010年12月2日木曜日

[memo] システム開発関連

SIerの責任について
参考

ソフトウェア開発手法:アジャイル
参考

オープンソースとは?(伽藍とバザール)
参考

[SA-4-6] FTPによるファイル送信(Shell Script)

バックアップしたファイルは,そのままサーバ上に保管するのではなく,ロケーションの異なるサーバにコピーすると,より安全である(ディザスタリカバリ).
そこで,定期的にファイルの転送をサーバに行わせるために,ファイルの転送を自動的に行うShellScriptを作成する.

内部でFTPクライアントを使用しているため,事前にFTPクライアントをインストール
#yum install ftp

また,ファイルの送信先サーバがFTPサーバとしてもどう際してる必要がある為,ローカルで動作確認を行う為には,FTPサーバをインストールする必要がある.
#yum install vsftpd
#service vsftpd start
#chkconfig vsftpd on

転送試験に使用するファイル用意
$vi ~/script/test.txt

転送試験の際の受信用ディレクトリ用意
$mkdir ~/script/receive


ftp_put.bash
#!/bin/bash

################################################
# 設定
################################################
# 送信するファイル
L_FILE="/home/(ユーザー名)/script/test.txt"
# 送信先ホスト
R_HOST="localhost"
# 送信先ディレクトリ
R_DIR="/home/(ユーザー名)/script/receive"

################################################
# 関数
################################################
# ファイルを FTP で送信する
# 入力
#   $1: 送信するファイル名
#   $2: 送信先ホスト名
#   $3: 送信先ディレクトリ
#   $4: 一時作業ディレクトリ
# 終了ステータス
#   0: 成功
#   1: 失敗
ftp_put_file () {
    local l_file="$1"
    local r_host="$2"
    local r_dir="$3"
    local tmpdir="$4"

    local filename="${l_file##*/}"
    local r_file="${r_dir}/${filename}"
    local log="${tmpdir}/ftp_put.log"

    local status

    # FTP を実行
    ftp -v -g "${r_host}" <<-EOF > "${log}" 2>&1
 quote NOOP
 put "${l_file}" "${r_file}"
 quote NOOP
 EOF

    # 結果チェック(1)
    status=$?
    if [ "${status}" -ne 0 ]; then
 return "${status}"
    fi

    # 結果チェック(2)
    ftp_chk_transfer "${log}"

    # 失敗した場合にはエラーメッセージ(かもしれないもの)
    # の最後の3行を標準エラー出力に表示
    if [ $? -ne 0 ]; then
 grep -v '^[123][0-9][0-9]' "${log}" | tail -3 1>&2
 return 1
    fi

    return 0
}

# FTP によるファイル送受信を、ログからチェックする
# 入力
#   $1: 転送ログ
# 終了ステータス
#   0: 転送成功
#   1: 転送失敗
ftp_chk_transfer () {
    local state="START"
    local code
    local msg_first
    local msg_rest

    # ログファイルを読みながらのループ
    while read code msg_first msg_rest; do
 case "${state}" in
 # 最初の NOOP 実行前
 START)
     if [ "${code} ${msg_first}" == "200 NOOP" ]; then
  state=TRANS_START
     fi
     ;;
        # PASV/PORT でのコネクション確立中
 TRANS_START)
     case "${code}" in
     125 | 150)
  state=TRANS_DATA
  ;;
     200)
  if [ "${msg_first}" == NOOP ]; then
      # 想定外
      state="ERROR"
      break
  fi
  ;;
     esac
     ;;
 # データ転送中
 TRANS_DATA)
     case "${code}" in
     226 | 250)
  # 転送成功
  state=SUCCESS
  break
  ;;
     200)
  if [ "${msg_first}" == NOOP ]; then
      # 想定外
      state="ERROR"
      break
  fi
  ;;
     esac
     ;;
 esac
    done < "$1"

    # 以下の test の結果が関数の終了ステータス
    [ "${state}" == "SUCCESS" ]
    return
}

################################################
# メイン処理
################################################
# util_common.bash を読み込む(make_tmp_dir/clean_tmp_dir)
FILE_UTIL=util_common.bash
. "${FILE_UTIL}" 2> /dev/null \
    || . "${0%/*}/${FILE_UTIL}" 2> /dev/null
if [ $? -ne 0 ]; then
    echo "Can't load ${FILE_UTIL}!" 1>&2
    exit 1
fi

# 作業ディレクトリの作成
tmpdir=$(make_tmp_dir 2>/dev/null)
if [ $? -ne 0 ]; then
    echo "Can't create temporary directory!" 1>&2
    exit 2
fi

# trap の設定
SIGNALS="HUP INT QUIT PIPE TERM"
trap "{ clean_tmp_dir; exit; }" ${SIGNALS}

ftp_put_file \
    "${L_FILE}" \
    "${R_HOST}" \
    "${R_DIR}" \
    "${tmpdir}"

status=$?

# 作業ディレクトリの削除と trap 解除
clean_tmp_dir
trap ${SIGNALS}

# スクリプトの終了ステータスを
#  ftp_put_file の終了ステータスに
exit ${status}

.netrc(設定ファイル)
machine localhost login <ユーザー名> password <パスワード>

[卒業研究] 卒業論文の書き方

卒業論文は卒業研究の単なる作業メモではなく,文章として「読める」ものでなければならない.

つまり,行った事や結果の羅列ではなく,まず卒業研究として行った事の,そもそもの妥当性や事情を説明した上で,内容の説明を行い,最後に結果や今後の展望について纏める必要がある.

これによって卒業研究が世の中でどのような位置付けにあるかが,読者に伝わる.

具体的には,起承転結を意識して記述すると良い.

また論文を書く際の心構えについては,こちらのサイトが参考になる.

2010年12月1日水曜日

[SA-4-5] ファイル差分バックアップ(Shell Script)

内部でrcsコマンドを使用しているため,事前にrcsをインストール
#yum install rcs

backup_etc.bash
#!/bin/bash
# usage:
# 1. BACKUP_ROOT(/var/tmp/backup) に、バックアップをとりたいファイルへの
#    シンボリックリンクを張ります
#    例: cd ${BACKUP_ROOT}; ln -s /etc/nsswitch.conf
# 2. backup_etc.bash を引数なしで実行します

# バックアップ作成用ディレクトリ
BACKUP_ROOT="/var/tmp/backup"

# バックアップ作成用ディレクトリ内の最大の深さ
MAX_DEPTH=2

# RCS のチェックインメッセージ(空白/タブを入れないこと)
CHECKIN_MSG="Automatic_RCS_backup"

# 引数に応じて、
#   「ディレクトリの深さ + 1」
# を表す glob パターンを生成する
# usage: make_pattern <depth>
# ex. make_pattern 1 → "*/*"
make_pattern () {
    local -i i=$1
    local pattern="*"

    while [ $i -gt 0 ]; do
        pattern="${pattern}/*"
        let "i--"
    done

    echo "${pattern}"
}

# RCS の ci (チェックイン)コマンドを使って差分バックアップをとります
# 引数: なし
make_rcs_backup () {
    local dir
    local pattern=$(make_pattern ${MAX_DEPTH})
    local lock_user
    local file
    local msg

    # CHECKIN_MSG が設定されている場合だけ
    # msg 変数の内容を -m"メッセージ" とします
    msg=${CHECKIN_MSG:+"-m${CHECKIN_MSG}"}

    # BACKUP_ROOT に移動
    pushd "${BACKUP_ROOT}" > /dev/null

    # RCS という名前以外のディレクトリを探す
    # ※BSDシステムでは find -x . -type d ... とすること
    find . -xdev -type d \( -name RCS -prune -o -print \) | \
        while read dir; do
            case "${dir}" in
                ${pattern})
                    # MAX_DEPTH を越えたものは対象外
                    continue
                    ;;
            esac

     # 対象ディレクトリに移動
            cd "${BACKUP_ROOT}/${dir}"
     if [ ! -d RCS ]; then
  mkdir RCS
            fi

     # ファイルごとに ci を実行
            for file in *; do
  if [ -d "${file}" ]; then
      continue
  fi

  ci ${msg} -l "${file}" < /dev/null > /dev/null 2>&1
  if [ $? -ne 0 ]; then
      echo "backup FAIL: ${file}" 1>&2
  fi
     done
        done            

    # 最初いたディレクトリに戻る
    popd > /dev/null
}

make_rcs_backup

もしくは,rsyncを用いて差分バックアップを取る方法もある.
この場合,変更なきファイルはハードリンクとし,前回のバックアップから変更があったファイルのみ実際のコピーを行う為,バックアップの容量圧縮する事が可能となる.
rsync -av --delete --link-dest=../[過去] [現在]/ [保存名]

[MA-11-1] 新uploader

今後は,こちらのアップローダーを利用してください.

[memo] 安全なSQLの呼び出し方 (IPA)

情報処理推進機構(IPA)が公開している,SQLインジェクション攻撃等を回避する為のWebアプリケーションの安全な実装方法を解説した資料をベースに,深刻な被害が発生しがちなSQLインジェクション等について解説する.

ダウンロード(PDF) 


2010年11月26日金曜日

[MA-10-3] フリーの画像制作環境

Adobe IllustratorやCorel DRAWと同種の,Windows向けベクター形式のグラフィックエディタとして,Inkscapeがリリースされている.

また,Adobe Photoshopと同種の,Windows向けビットマップ形式のグラフィックエディタとしては,GIMPが有名である.

どちらもフリーソフトウェアな為,気軽に導入できるメリットがある.
ただし,業務用途においてはやはりAdobeの製品が一般的であるため,あくまでも補佐的な役割となるであろう.


ここで,Suzukaで使用される画像形式にPDRが存在するが,同じ作者がSVG形式をPDR形式に変換するSVG2PDRというツールをリリースしている.

こちらを利用すれば,フリーのソフトウェアのみで
  1. InkscapeでSVG形式のファイル作成
  2. SVG2PDRでPDR形式にコンバート
  3. PDRをsuzukaに読み込み,SWF出力
を行う事が可能となる.

2010年11月25日木曜日

[SA-4-4] メール送信(Shell Script)

サーバは管理者の傍らではなく,遠隔地に置かれることが多い事から,ディスク使用量/プロセス死活監視/ネットワーク疎通確認等で問題が起きた際に,サーバの画面上にアラートを表示するだけでは不十分である.
そこで,アラートが発生した際にそのメッセージをメールとしてサーバから管理者に送信する事で,トラブルの見落としを防ぐ事が可能となる.

※下記サンプルをCentOS上で動かすために,
1.sendmailのインストール
yum install sendmail
service sendmail start
chkconfig sendmail on
2.スクリプト中のsendmailのパスを変更
/usr/local/sendmail → /usr/sbin/sendmail
3.MAIL_TOを自分のメールアドレスに変更
4.iconvの記述を変更
iconv -f EUC-JP -t ISO-2022-JP → iconv -f UTF-8 -t ISO-2022-JP


mail_plain.bash
#!/bin/bash
# メール設定
MAIL_FROM="foo@example.com"
MAIL_TO="bar@example.com"
MAIL_SUBJECT="テストメール"
MAIL_ID="<$(date +%Y%m%d%H%M%S).$(id -ru).$$@$(hostname)>"
SENDMAIL=/usr/lib/sendmail

# 共通関数の読み込み
FILE_UTIL=util_common.bash
. "${FILE_UTIL}" 2> /dev/null \
    || . "${0%/*}/${FILE_UTIL}" 2> /dev/null
if [ $? -ne 0 ]; then
    echo "Can't load ${FILE_UTIL}!" 1>&2
    exit 1
fi

# 文字コードを英語に
unset_linguas

# 作業ディレクトリの作成
tmpdir=$(make_tmp_dir 2>/dev/null)
if [ $? -ne 0 ]; then
    echo "Can't create temporary directory!" 1>&2
    exit 2
fi

# trap の設定
SIGNALS="HUP INT QUIT PIPE TERM"
trap "{ clean_tmp_dir; exit; }" ${SIGNALS}

# サブジェクトを Base64 エンコーディング
subject=$(echo -n "${MAIL_SUBJECT}" |
             iconv -f EUC-JP -t ISO-2022-JP |
             perl -MMIME::Base64 -ne 'print encode_base64($_)')

# メールの作成
mail_data="${tmpdir}/mail_data"
cat <<EOF > "${mail_data}"
Mime-Version: 1.0
Content-Type: Text/Plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
From: ${MAIL_FROM}
To:   ${MAIL_TO}
Subject: =?ISO-2022-JP?B?${subject}?=
Message-Id: ${MAIL_ID}
Date: $(date +"%a, %e %b %Y %H:%M:%S %z")

--------------------------------------------------------
UPTIME
--------------------------------------------------------
$(uptime)

--------------------------------------------------------
W
--------------------------------------------------------
$(w)

--------------------------------------------------------
FREE
--------------------------------------------------------
$(free)


EOF

# メールの送信
iconv -f EUC-JP -t ISO-2022-JP "${mail_data}" |
    "${SENDMAIL}" -oi "${MAIL_TO}" > /dev/null 2>&1

# 作業ディレクトリの削除と trap 解除
clean_tmp_dir
trap ${SIGNALS}

[SA-4-3] プロセスの死活監視(Shell Script)

サーバが稼働しているからと言って,特定のアプリケーション(プロセス)も正常に動作しているとは限らない.
そこで,プロセス一覧に指定したアプリケーションが表示されているか確認し,プロセスレベルで動作している事をもって正常とみなす.
ちなみに,アプリケーションレベルでの動作確認方法としては,例えばWEBサーバであれば特定のWEBページをHTTPを用いて表示させる,等がある.

check_proc_alive.bash
#!/bin/bash
# usage: check_proc_alive.bash

# 監視対象を記述したファイル
PROGLIST=/usr/local/etc/check_progs.conf

# util_common.bash(ucb_ps) を読み込む
# 1. PATH が通っているところから読み込む
# 2. このスクリプトがディレクトリ指定付で実行されていれば、
#    このスクリプトと同じ場所から読み込む
# 3. 1., 2. でダメならエラー
FILE_UTIL=util_common.bash
. "${FILE_UTIL}" 2> /dev/null \
    || . "${0%/*}/${FILE_UTIL}" 2> /dev/null
if [ $? -ne 0 ]; then
    echo "Can't load ${FILE_UTIL}!" 1>&2
    exit 1
fi

# 指定されたプログラムのプロセス ID を取得する
#
# 使い方
#   pidof [-s] 
#
# 引数:
#   -s
#     一つでもプロセスが見つかったら、そこで処理を終える
#   prog_name
#     探すプログラムの名前
#
# 出力
#   プロセスID_1 プロセスID_2  ...
#   (プロセスが見つからない場合は空行を 1 行出力する)
#
# 終了ステータス:
#   0: プロセスが見つかった
#   1: プロセスが存在しなかった
pidof () {
    local cmd_target            # 探すコマンド
    local is_single             # -s オプションが指定されたか

    # 引数の処理
    is_single=false

    case "$1" in
      -s)
        is_single=true
 shift
 ;;
    esac

    cmd_target="$1"

    # 以下のコマンド(パイプライン)の戻値が、関数の戻値になる
    ucb_ps ax | (
 # ここからサブシェルなので、変数の設定は呼び出し元には
 # 影響しません。よって local 定義もありません
 # ただし、変数の初期化は必要です。
 pids=""

 # へッダ行は捨てます
 read line

 # 2 行目以降の処理
 while read pid tty stat time cmd args; do
     # 対象行が求めるものであるか
     was_found="false"

     if [ "${cmd}" = "${cmd_target}" ]; then
  # そのまま一致
  was_found="true"
     elif [ "${cmd##*/}" = "${cmd_target}" ]; then
  # ベース名が一致
  was_found="true"
     fi

     if ${was_found} ; then
  pids="${pids} ${pid}"
  if ${is_single}; then
      # -s が指定されていればここで終わり。
      # 終了ステータス 0
      break
  fi
     fi
 done

 # 結果の表示
 echo ${pids}

 # 終了ステータスの設定
 [ "${pids}" != "" ]
    )
}

# プロセス生存監視
# 引数なし
check_alive_procs () {
    # PROGLIST 存在チェック
    if [ ! -r "${PROGLIST}" ]; then
 echo "Can't read ${PROGLIST}"
 return 1
    fi

    # PROGLIST の行ごとのループ
    cat "${PROGLIST}" | while read prog ; do
 case "${prog}" in
     "")   continue ;;
     "#"*) continue ;;
 esac
 pids=$(pidof ${prog})
 if [ $? -ne 0 ]; then
     pids="DOWN"
 fi
 echo "${prog}: ${pids}"
    done
}

check_alive_procs

2010年11月24日水曜日

[memo] 安全なウェブサイトの作り方 (IPA)

情報処理推進機構(IPA)が公開している,サイト開発者・運営者が適切なセキュリティを考慮したサイトを作成するための資料をベースに,SQLインジェクションやOSコマンドインジェクション、クロスサイトスクリプティング(XSS)など、IPAへの届け出の多かった脆弱性や、攻撃による影響が大きい脆弱性を取り上げ、生じうる脅威や対策について解説する.

ダウンロード(PDF)

[MA-10-2] フリーの制作環境を使った作例 (Suzuka)

  1. Suzukaをここからダウンロードし,インストールする.
  2. サンプルをダウンロードする.
  3. Photoshop Elements,もしくはParaDrawを使って画像を作成.
  4. 作成した画像を使って,2のサンプルの画像を差し替え

2010年11月18日木曜日

[SA-4-2] ディスク容量の監視(Shell Script)

サーバの残りディスク容量が低下すると動作に支障があるため,ディスク容量が閾値(80%)を超えた際にメッセージを表示する.
管理者宛にメールを送信するスクリプトと組み合わせることにより,サーバの管理画面を確認することなく,サーバの残りディスク容量の低下に気がつくことが可能となる.

disk_usage.bash
#!/bin/bash

# ディスク使用量が THRESHOLD(%) を越えたら警告
#THRESHOLD="80"
THRESHOLD="10"

# 引数: なし
print_disk_usage () {
    # df コマンドのオプション
    local DF_OPTIONS="-k -l"
#    local DF_OPTIONS="-k -l /dev/sda1"
    local line used

    df ${DF_OPTIONS} |
    (
 # へッダ行をそのまま表示
        read line
#        echo "${line}"
        echo ${line}\c
        while read line; do
     # "デバイス" "総容量" "使用中" "空き容量" "使用率" ...
     set -- ${line}
     case "$1" in
              # 実存する(仮想でない)デバイスのみ対象
       /*)
  used=${5%%"%"*}
  if [ ${used} -ge ${THRESHOLD} ]; then
      echo "${line}"
  fi
  ;;
     esac
 done
    )
}

output=$(print_disk_usage)
lines=$(echo "${output}" | wc -l)

if [ ${lines} -gt 1 ]; then
    echo "${output}"
fi

[SA-4-1] PINGによる疎通確認(Shell Script)

PINGを用いてネットワークの向こう側にある機器との間の疎通確認を行うシェルスクリプト

/usr/local/etc/ping_hosts
192.168.147.1
192.168.147.2
192.168.147.3
192.168.147.4
192.168.147.5
192.168.147.6
192.168.147.7
192.168.147.8
192.168.147.9
192.168.147.10

util_common.bash
#
# 共通関数群(bash 用)
#

# BSD スタイルの ps コマンド
# 引数: ps コマンドの引数と同じ
ucb_ps () {
    local CMD_PS=/usr/ucb/ps

    if [ ! -x ${CMD_PS} ]; then
 CMD_PS=ps
    fi

    ${CMD_PS} "$@"
}

# ロケール(言語)設定をデフォルト(POSIX)にする
# 引数: なし
unset_linguas () {
    export LC_ALL=C
    export LC_MESSAGES=C
    export LANGUAGE=C
    export LANG=C
}

# 一時ディレクトリの作成
# 引数: 一時ディレクトリの親ディレクトリ
#       (省略時デフォルト: ${TMP_ROOT})
# 出力: 作成したディレクトリ名
# 終了ステータス: 0: 成功, 1: 失敗
# シェル変数:
#   TMP_ROOT(IN): 一時ディレクトリの親ディレクトリ
#                 (省略時デフォルト: ${HOME})
make_tmp_dir () {
    # 一時ディレクトリの親ディレクトリ
    local TMP_ROOT="${1:-${TMP_ROOT:-${HOME}}}"
    local tmpdir=$(basename "$0")$$

    tmpdir="${TMP_ROOT}/${tmpdir}"

    mkdir "${tmpdir}" > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
 echo "${tmpdir}"
 chmod 700 "${tmpdir}"
    else
 echo "Can't create directory: ${tmpdir}" 1>&2
 return 1
    fi
}

# 一時ディレクトリの削除
# 引数: 一時ディレクトリの親ディレクトリ
#       (省略時デフォルト: ${TMP_ROOT})
# 出力: なし
# 終了ステータス: 0: 成功, 1以上: 失敗
#   TMP_ROOT(IN): 一時ディレクトリの親ディレクトリ
#                 (省略時デフォルト: ${HOME})
clean_tmp_dir () {
    # 一時ディレクトリの親ディレクトリ
    local TMP_ROOT="${1:-${TMP_ROOT:-${HOME}}}"
    local tmpdir=$(basename "$0")$$

    tmpdir="${TMP_ROOT}/${tmpdir}"

    # ディレクトリが存在しなければエラーにします
    if [ ! -d "${tmpdir}" ]; then
 echo "No such directory: ${tmpdir}" 1>&2
 return 1
    fi
    # 対象がシンボリックの場合は、想定外のためエラーにします
    if [ -L "${tmpdir}" ]; then
 echo "Can't delete unexpected symlink: ${tmpdir}" 1>&2
 return 1
    fi
    # rm コマンドの終了ステータスをそのまま返します
    rm -rf "${tmpdir}" > /dev/null 2>&1
}


ping.bash
#!/bin/bash
# usage: ping.bash

# 監視対象ホストを記述したファイル
# (書式は 1 行に 1 ホスト)
PING_HOSTS="/usr/local/etc/ping_hosts"

# 汎用pingコマンドインターフェース
# 使い方:
#   ping_common  [  ]
# 引数:
#   hostname: ホスト名/IPアドレス
#   timeout: pingのタイムアウト(秒)
# 出力:
#   なし(エラー出力はあり)
# 終了ステータス:
#   0: 応答あり
#   1: 応答なし
#   2以上: エラー
ping_alive_common () {
    # システム(unameの結果)ごとに処理を分岐
    case $(uname -s) in
      Linux | NetBSD | OpenBSD)
        ping_alive_bsd $1 $2
        status=$?
        ;;
      SunOS)
 ping_alive_solaris $1 $2
        status=$?
 ;;
      FreeBSD)
        ping_alive_freebsd $1 $2
        status=$?
        ;;
      *)
 # 上記以外のシステムでは、自分で調べて修正してください
 echo "This system is not supported." 1>&2
 return 2
 ;;
    esac

    return ${status}
}

# Linux/NetBSD/OpenBSD用pingコマンドインタフェース
# 使い方:
#   ping_alive_bsd  [  ]
# 引数:
#   hostname: ホスト名/IPアドレス
#   timeout: pingのタイムアウト(秒)
# 出力:
#   なし(エラー出力はあり)
# 終了ステータス:
#   0: 応答あり
#   1: 応答なし(またはエラー)
#   2以上: エラー
ping_alive_bsd () {
    local timeout=${2:+"-w $2"}
    local status

    ping -c 1 ${timeout} $1 > /dev/null
    status=$?

    # 不正な引数の場合は終了ステータスは2以上(?)
    if [ $status -ge 2 ]; then
 # timeout オプションを削除して再試行
 ping -c 1 $1 > /dev/null
 status=$?
    fi

    return ${status}
}

# FreeBSD用pingコマンドインタフェース
# 使い方:
#   ping_alive_freebsd  [  ]
# 引数:
#   hostname: ホスト名/IPアドレス
#   timeout: pingのタイムアウト(秒)
# 出力:
#   なし(エラー出力はあり)
# 終了ステータス:
#   0: 応答あり
#   1: 応答なし
#   3以上: エラー
ping_alive_freebsd () {
    local timeout=${2:+"-t $2"}

    ping -c 1 ${timeout} $1 > /dev/null
    status=$?

    # 不正な引数の場合 = 古い実装は終了ステータスが2以上
    if [ $? -ge 2 -a "${timeout}" != "" ]; then
 # timeout オプションを削除して再試行
 ping -c 1 $1 > /dev/null
 status=$?
    fi

    case ${status} in
      0)
        return 0
        ;;
      1 | 2)
        return 1
        ;;
      *)
        return ${status}
        ;;
    esac
}

# Solaris(SunOS)用pingコマンドインタフェース
# 使い方:
#   ping_alive_solaris  [  ]
# 引数:
#   hostname: ホスト名/IPアドレス
#   timeout: pingのタイムアウト(秒)
# 出力:
#   なし(エラー出力はあり)
# 終了ステータス:
#   0: 応答あり
#   1: 応答なし
#   2以上: エラー
ping_alive_solaris () {
    ping $1 $2 > /dev/null
}

# 非同期 ping 実行
# 使い方:
#   ping_async  [  ] [  ]
# 引数:
#   hostname: ホスト名/IPアドレス
#   directory: ログ出力先ディレクトリ(デフォルトはカレントディレクトリ)
#   timeout: ping タイムアウト(秒)
# 出力:
#   なし
# 終了ステータス:
#   0: pingの実行に成功
#   1以上: エラー
ping_async () {
    local hostname=$1
    local resultfile="${2:+${2}/}${hostname}"
    local timeout=$3

    rm -f ${resultfile} > /dev/null 2>&1

    (
        ping_alive_common ${hostname} ${timeout} \
     > /dev/null 2> "${resultfile}"
 echo $? >> "${resultfile}"
    ) > /dev/null 2>&1 &
}

# 非同期 ping 実行結果取得
# 使い方:
#   ping_check_result  [  ]
# 引数:
#   hostname: ホスト名/IPアドレス
#   directory: ログ出力先ディレクトリ(デフォルトはカレントディレクトリ)
# 出力:
#   なし
# 終了ステータス:
#   0: 応答あり
#   1: 応答なし
#   2以上: エラー
#   70: 結果不明(結果ファイルが存在しない/読み込めない)
ping_check_result () {
    local hostname=$1
    local resultfile="${2:+${2}/}${hostname}"
    local num_line
    local status

    [ -r "${resultfile}" ] || return 70
    status=$(tail -1 "${resultfile}")

    # エラーの表示
    if [ ${status} -ge 2 ]; then
 num_line=$(wc -l "${resultfile}" | awk '{print $1}')
 if [ ${num_line} -gt 1 ]; then
     sed ${num_line}d "${resultfile}" 1>&2
 fi
    fi

    return ${status}
}

# 複数ホストへのping同時実行
# 使い方:
#   ping_from_file  [  ] [  ]
# 引数:
#   hostname: ホスト名/IPアドレス
#   directory: ログ出力先ディレクトリ(デフォルトはカレントディレクトリ)
#   timeout: ping タイムアウト(秒)
# 出力:
#   <ホスト名>: <ステータス>
#   ...
#
#   ステータスは 0:応答あり 1:応答なし 2以上:エラー
# 終了ステータス:
#   常に 0
ping_from_file () {
    local inputfile="$1"
    local hostname
    local dummy

    # 入力ファイルの読み込みチェック
    if [ ! -r "${inputfile}" ]; then
 echo "No such file/Can't read file: ${inputfile}" 1>&2
 return 1
    fi

    # 位置パラメータを以下のようにする
    # $1: result_dir(省略可), $2: timeout(省略可)
    shift

    # 第2要素以降は無視する。すなわち
    #   192.168.1.1 # ルーター
    # のような記述も OK である
    while read hostname dummy; do
 # 空行/コメント行は無視
 case "${hostname}" in
   "")   continue ;;
   "#"*) continue ;;
        esac

 ping_async ${hostname} "$@" > /dev/null
    done < "${inputfile}"

    # ping_async で実行した非同期コマンドの終了を待つ
    wait

    # 位置パラメータを以下のようにする
    # $1: result_dir(省略可)
    if [ $# -ge 2 ]; then
 set -- "$1"
    fi

    while read hostname dummy; do
 # 空行/コメント行は無視
 case "${hostname}" in
   "")   continue ;;
   "#"*) continue ;;
        esac

 ping_check_result ${hostname} "$@"
 echo "${hostname}: $?"
    done < "${inputfile}"

    return 0
}

# メイン処理

# util_common.bash を読み込む(make_tmp_dir/clean_tmp_dir)
FILE_UTIL=util_common.bash
. "${FILE_UTIL}" 2> /dev/null \
    || . "${0%/*}/${FILE_UTIL}" 2> /dev/null
if [ $? -ne 0 ]; then
    echo "Can't load ${FILE_UTIL}!" 1>&2
    exit 1
fi

# 作業ディレクトリの作成
tmpdir=$(make_tmp_dir 2>/dev/null)

if [ $? -ne 0 ]; then
    echo "Can't create temporary directory!" 1>&2
    exit 2
fi

# trap の設定
SIGNALS="HUP INT QUIT PIPE TERM"
trap "{ clean_tmp_dir; exit; }" ${SIGNALS}

# ping 監視の実行
ping_from_file "${PING_HOSTS}" "${tmpdir}"

# 作業ディレクトリの削除と trap 解除
clean_tmp_dir
trap ${SIGNALS}

2010年11月8日月曜日

[memo] docomo2010年冬/2011年春モデル発表

docomoから2010年冬/2011年春モデルの発表がありました.

注目は,既に発売が開始されているAndroidスマートフォンのGALAXY SGALAXY Tabと,3D液晶が特徴の SHARP LYNX 3D SH-03C(SoftbankのGALAPAGOS 003SHと同等?),東芝 REGZA Phone T01-C(SoftbankのREGZA Phone IS04と同等?),LGエレクトロニクス Optimus chat L-04Cあたりでしょうか?

また,次世代無線技術であるLTE(Long Term Evolution,3.9G)に対応したデータ通信対応端末も発表されています.現時点ではエリアが限定的であるため,積極的に選択する理由がありませんが,料金プラン等今後の動向には注意が必要です.

#個人的には,SHARP SH-06Cとか面白そうですが,
#小型プロジェクタと携帯電話が一体になっている必然性が薄いんだよなぁ...
#また,残念ながら,Windows Phone 7の発表はありませんでした...

2010年11月5日金曜日

[memo] レンタルサーバ/VPSの選び方

インターネット上にはレンタルサーバを提供している会社がいくつもありますが,何を選択基準とすればよいか迷う事と思います.
そこで,レンタルサーバを用いて何をしたいかに注目し,レンタルサーバ選びの際の参考となる資料を纏めてみました.

テキスト中心のサイトであったり,自身で作成した作品を公開する場としてのサイトであれば,下記特記事項を気にする必要はありませんが,少し特殊な事を行いたい場合は,以下の項目を参考にして必要となる機能を把握してもらえればと思います.


目的別必要機能

独自ドメイン利用可能ディスク容量追加DB管理者権限CRON
自分で管理できるメールアドレスが欲しい


自分で決めたURLを使いたい


ファイルの配布



DBを使いたい



独自アプリケーション



定時作業の自動化


商用サイトの構築
(企業広報)



商用サイトの構築
(ショッピングサイト)



代表的なレンタルサーバとしては,paperboy&co.(ぺぱぼ)のロリポップや,さくらインターネットのさくらのレンタルサーバがあります.


またレンタルサーバとは少し異なりますが,VPS(Virtual Private Server)サービスを利用する方法も考えられます.
レンタルサーバは,あくまでも既に構築されているOSやアプリケーションの環境を,複数人で利用する事を前提とする事で低価格を実現したサービスですので,ユーザーによっては必要な機能を満たせない事もあり得ます.
それに対しVPSサービスは,仮想環境の範囲内でユーザーが全てをコントロール可能ですので,アプリケーションの追加やユーザー独自の作り込みといった,一般的なサーバ構築で行える事のほぼ全てが可能です.場合によっては,OSの入れ替えといった事も可能となっています.
(VPSで出来ないことは...サーバのロケーション選択とハードウェアの仕様選定といったところでしょうか)

というわけで,VPSを利用すれば,環境・仕様が画一的なレンタルサーバ以上に柔軟な運用が可能になります.

低価格なVPSサービスとしては,DTIのServerMan@VPSや,さくらインターネットのさくらのVPSがあります.

2010年11月4日木曜日

[memo] ソフトバンク2010年冬/2011年春モデル発表

ソフトバンクの2010年冬/2011年春モデルが発表されました.
予想通り,スマートフォンのラインアップが充実し(しかも全モデルAndroid 2.2!),ソフトバンクのスマートフォンにかける意気込みが伝わってきます.

注目は,DELLのStreakや,SHARPのGALAPAGOS 003SHGALAPAGOS 005SHあたりでしょうか?

また,キャリアメール(S!メール)にも最初から対応している事から,iPhoneで培ったスマートフォンの運用に関するノウハウが生かされていると思われます.

ちなみに,11/8(月)にはdocomoの発表会が控えています.
Windows Phone 7とか出てくるのかな?

2010年10月27日水曜日

[memo] 携帯版クロネコヤマト情報漏洩事件

iPhoneで他人の情報…携帯ID認証に穴(読売オンライン)の記事では,あたかもiPhone固有の問題のように取り上げられているが,ヤマト運輸のニュースリリースによると,今回のトラブルは,携帯版のWebサービスにスマートフォン(の特定のアプリケーション)から(クイックログイン機能を用いて)接続した際に,正しく認証が行えなかったとある為,今回の問題はクライアント側ではなくサーバ側の認証部分の作り込みの問題だと思われる.


一般的な携帯電話向けWebサイトにおける(ログインの際にユーザー名とパスワードの組み合わせを求めない)簡単ログインの実装は,本人認証を携帯電話のハードウェアと結びつけられた固有の個体識別番号を用いて行う.
これにより,初期登録時にユーザー名と個体認識番号が結びつけられていれば,次回以降はユーザーに対して都度ユーザー名とパスワードの入力を求めなることなく,個体認識番号の確認をもって本人だとみなす事が出来る.

しかし,この個体認識番号=本人が通用するのは,個体認識番号がネットワーク上で唯一のものだと信頼できる場合のみである.
この個体認識番号が唯一のものであるという常識が通用するのは,携帯電話の接続するネットワークがクローズドであり,かつ接続する他の携帯電話も同様に改変不可能な個体認識番号を持つ場合のみである.

例えばPCからこのネットワークに接続することが可能であれば,個体認識番号のなりますましを行う事は容易である.
つまり個体認識番号による本人認証のシステムは,ネットワーク上にはキャリアの管理下にある端末しか存在しない=個体認識番号は重複しない,という前提に立っているものだと言うことが分かる.


また,昨今普及しつつあるスマートフォンには,上記個体認識番号と同列に扱うことが可能なIDは存在しない.
しかしながら,スマートフォンではPCのように多種多様なアプリケーションを動作させる事が可能となっており,例えばiPhone向けアプリケーションであるSBrowerは,本来iPhoneには実装されていない個体認識番号を内部で自動的に生成し,それを用いてあたかも日本国内向けに販売されている携帯電話を模して接続を行う.
これにより,個体認識番号が実装されていることを前提に構築されている多数の携帯向けWebに接続し,サービスを受けることが可能となっている(なってしまっている).

今回問題となっている携帯版「クロネコメンバーズのWebサービス」のクイックログイン機能は,個体認識番号の存在が前提となっているため,iPhoneから通常のブラウザを用いてクイックログイン機能を利用する事は出来ない.しかしながら上記アプリケーションを用いることで,擬似的に個体認識番号を利用することが出来,結果としてクイックログイン機能の利用が可能となっている.
しかし,個体認識番号を生成する部分に問題があり,同一の個体認識番号が生成される可能性がある
つまり,同一の個体認識番号が生成されたSBrowerのユーザーの中で,最初にユーザー情報と個体認識番号を結びつけた人のデータが,後から同一の個体認識番号を持つSBrowerを利用して接続したユーザーに漏洩してしまう可能性を排除できない.

これを,同一の個体認識番号を生成してしまうアプリケーションの問題ととらえたり,このような危険性を内包する非正規のアプリケーションを利用するユーザーの問題ととらえることも可能だが,今回は商用サイトという事もあり,サービス主管であるヤマト運輸側の問題であると思われる.
なぜならば,個人の認証というsensibleな問題を,一般のアプリケーション開発者やユーザーに被せるのは見当違いで,やはりサービスを提供する側が責任を持って正しく認証できるようにするべきである.


今後は,携帯向けWebサイトであったとしても個体認識番号を用いた簡易な実装とせず,通常のPC向けWebサイトと同様にcookieやサーバ側で用意したセッションIDを用いる必要があると言うことである.

[memo] Adobe MAX 2010

10/25よりL.A.にてAdobe MAX 2010が開催されている.
今回の話題の中心はWebサイト,電子出版,ビデオ,エンタープライズアプリケーション,ゲームといったマルチスクリーン戦略についてである.
具体的には,
  • 電子出版をサポートする「Adobe Digital Publishing Suite
  • Google TVでも採用され,ストリーミング動画の再生やWebブラウザ内からのGPUハードウェアアクセラレーション(動画再生支援)にも対応した「Flash Player」
  • TVの中でAIRアプリケーションを利用する為の 「AIR for TV」
  • 従来のコンポーネントやスキンをタッチスクリーン上でもそのまま利用可能「Flex 4.5」
  • BlackBerry社の新しいタブレット端末PlayBook向けのAIRアプリケーション開発ツール「BlackBerry PlayBook Developer Kit」
  • Android端末上でのAIRアプリの実行環境「AIR for Android」
  • PCだけではなく,テレビやタブレット,スマートフォンにも対応した「Adobe AIR 2.5
  • 様々なデバイスで利用できるアプリケーションを,各デバイス向けに提供されているアプリのストア内で配布/販売可能となる「Adobe InMarket
といった技術を統合して,Flashをベースとしたプラットフォームを強固にしていくとの事.他プラットフォームの戦略等とあわせて今後に注視したい.


また,「Adobe AIR 2.5」は H.264動画のGPU支援再生に対応している.上記の「AIR for Android」の3Dハードウェアアクセラレーション対応とあわせて,従来の「Flashは動作が重い」への批判に対する解答であると思われる.
ただしハードウェアアクセラレーションは, 対象とする機種やプラットフォームの構成に大きく左右される.そのためFlashのメリットの一つである,多数のプラットフォームへのフラットな対応が後退する可能性も含む.
例えば特定機種のみハードウェアアクセラレーションに対応し,その他機種はソフトウェアレンダリング対応となった場合,開発者は個別に対応せざるを得ず,結果として従来の利点であった複数デバイスへの対応の利点が薄れてしまう.

ちなみに,10/7のAdobeがMicrosoftに買収されるかもしれないというNew York Timesの報道に対して,AdobeのCEOは「同社は独立して成長していくことを目指す」と語ったとか.Adobe+Microsoftは面白い組み合わせだけに残念:-P

2010年10月21日木曜日

[SA-3-12] JavascriptからMySQLに接続

fig. 1


1.index.html, xmlhttp.js, backend.phpを,/var/www/html/ajaxに配置
index.html : ベースファイル
xmlhttp.js : フォームに入力された文字列を,リアルタイムにbackend.phpに渡し,結果を受け取る
backend.php : DBに接続し,結果をXMLとして出力

2.backend.phpに実行権限を付与(chmod 755 backend.php)

3.以下のアドレスにアクセスし,表示される項目を確認
(A)AJAXを利用し,表示項目を動的に絞り込み
http://[サーバのアドレス]/ajax/index.html
(B)MySQLから受け取ったデータをXML形式で表示
http://[サーバのアドレス]/ajax/backend.php?host_name=sa01

index.html
<html>
<head>
    <meta http-equiv=content-type content="text/html; charset=UTF-8">
 <title>server_list search result</title>
 
 <STYLE TYPE="text/css">
 <!--
 .table1 {
  width: 400px;
  border-collapse: collapse;
  border: 1px #708090 solid;
 }
 .table1 TD {
  border: 1px #708090 solid;
 }
 -->
 </STYLE> 
 
    <script type="text/javascript" src="xmlhttp.js"></script>
    <script type="text/javascript">
    <!--
    findText = findTextOld = "";

    function loadXmlFile(fName){
        httpObj = createXMLHttpRequest(displayData);
        if (httpObj){
            httpObj.open("GET",fName,true);
            httpObj.send(null);
        }
    }

    function displayData(){
        if ((httpObj.readyState == 4) && (httpObj.status == 200)){
            xmlData = httpObj.responseXML;
            $("result").innerHTML = parseXmlData(httpObj.responseText);
        }else{
            $("result").innerHTML = "Loading ...";
        }
    }

    function parseXmlData(xmlData){
        $("result").innerHTML = xmlData;
        idListTags = document.getElementsByTagName("id");
        numListTags = document.getElementsByTagName("num");
        host_nameListTags = document.getElementsByTagName("host_name");
        ip_addressListTags = document.getElementsByTagName("ip_address");
        idLen = idListTags.length;

        resultText = "<table class='table1'><tr><th colspan=4>server_list search result</th></tr><tr><td><b>id</b></td><td><b>num</b></td><td><b>host_name</b></td><td><b>ip_address</b></td></tr>";
        for(i=0; i<idLen; i++){
            id = idListTags[i].childNodes[0].nodeValue;
            num = numListTags[i].childNodes[0].nodeValue;
            host_name = host_nameListTags[i].childNodes[0].nodeValue;
            ip_address = ip_addressListTags[i].childNodes[0].nodeValue;
            str = host_name.match(findText);
            if (str){
                resultText += "<tr><td>" + id + "</td><td>" + num + "</td><td>" + host_name + "</td><td><a href='http://" + ip_address + "' target='_blank'>" + ip_address + "</a></td></tr>";
            }
        }
        resultText += "</table>";
        return resultText;
    }

    function inputCheck(){
        findText = document.ajaxForm.requestText.value;
        if (findText != findTextOld) {
            str_search = "./backend.php?host_name=" + findText
            loadXmlFile(str_search);
            findTextOld = findText;
        }else{
//            $("result").innerHTML = "Loading ...";
        }
        setTimeout(" inputCheck()",500); // 0.5秒毎
    }

    window.onload = inputCheck;
    // -->
    </script>
</head>
<body>
<form name="ajaxForm" onSubmit="return false">
<input type="text" value="sa00" name="requestText">
</form>
<div id="result"></div>
</body>
</html>

xmlhttp.js
// HTTP通信用、共通関数
function createXMLHttpRequest(cbFunc){
 var XMLhttpObject = null;
 try{
  XMLhttpObject = new XMLHttpRequest();
 }catch(e){
  try{
   XMLhttpObject = new ActiveXObject("Msxml2.XMLHTTP");
  }catch(e){
   try{
    XMLhttpObject = new ActiveXObject("Microsoft.XMLHTTP");
   }catch(e){
    return null;
   }
  }
 }
 if (XMLhttpObject) XMLhttpObject.onreadystatechange = cbFunc;
 return XMLhttpObject;
}
 
// document.getElementById
function $(tagId){
 return document.getElementById(tagId);
}

backend.php
<?php
 $db_user  = "[user name]";
 $db_password = "[password]";
 $db_name = "[database name]";
 $db_host  = "localhost";

//create xml
    header('Content-type: text/xml; charset=utf-8');
    echo '<?xml version="1.0"?><sa>';

 $host_name = null;

 if(isset($_GET['host_name'])) {
  $host_name = $_GET['host_name'];

  $con = mysql_connect($db_host,$db_user,$db_password) or die("error!");
  mysql_select_db($db_name,$con) or die("DB is not exist");
  $strsql = "SET CHARACTER SET UTF8";
  mysql_query($strsql,$con);
  $strsql = "SELECT id, num, host_name, ip_address FROM server_list WHERE host_name LIKE '%".$host_name."%';";
  $res = mysql_query($strsql,$con);

  while ($item = mysql_fetch_array($res)) {
   print "<server_list><id>".$item[0]."</id><num>".$item[1]."</num><host_name>".$item[2]."</host_name><ip_address>".$item[3]."</ip_address></server_list>";
  }
  mysql_close($con);
    }

    echo '</sa>'; 
?>

[卒業研究] システム構成図

fig.1 システム構成図

[卒業研究] サーバ構成案

卒業研究用サーバの構成について,いくつか候補を挙げてみます.
(可能であれば 同構成のサーバを2台用意して,開発時には本番環境と開発環境で分けて作業を進め,リリース後は開発環境をコールドスタンバイ機とする)

1. サーバ
(1-1)HP ProLiant MicroServer \35,700
http://h50146.www5.hp.com/products/servers/proliant/micro/index.html
※CPUは非力ながら,RAIDが標準で組める!コンパクトな筐体ながら,大口径FAN使用で静音!!ただしHDDが1つなので,もう1つ追加してミラーリングしたい所.
リンク1リンク2, システム構成案(PDF)

(1-2)HP ProLiant ML110 G5 \11,280(\3,300割引クーポン使用で\7,980)
http://h50146.www5.hp.com/products/old/servers/proliant/ml110g5/
http://nttxstore.jp/_II_HP13207801
※とにかく安い!!

(1-3)NEC Express5800/GT110b \16,800(\2,000割引クーポン使用で\14,800)
http://www.nec.co.jp/products/pcserver/g/gt110b/index.shtml
http://nttxstore.jp/_II_P813280396
※一昔前に格安サーバで有名だった機種.

2.OS
(2-1)CentOS \Free
http://www.centos.org/

(2-2)Red Hat Enterprise Linux(RHEL) ライセンス\Free(サポートは有料)
http://www.jp.redhat.com/rhel/

(2-3)Microsoft Windows Server 2008 R2 Standard Edition (5CAL) アカデミック版 ¥57,775
http://www.coneco.net/PriceList/1091014006/order/MONEY/

3.無停電電源装置(UPS)
(3-1)APC ES 550 BE550G-JP ¥8,663
http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=BE550G-JP&total_watts=200
http://kakaku.com/item/K0000107355/spec/

(3-2)APC RS 550 BR550G-JP ¥13,511
http://www.apc.com/products/resource/include/techspec_index.cfm?base_sku=BR550G-JP&total_watts=200
http://kakaku.com/item/K0000056754/

(3-3)オムロン BY50S ¥16,481
http://www.omron.co.jp/ped-j/dengen/product/ups/by35-50s/by35-50s.html
http://kakaku.com/item/K0000066780/spec/

※OSとの連携機能(自動シャットダウン等)を確認する必要有り.

4.モニター
(4-1)なし \0
※コスト削減の為,既存モニターを利用する.

(4-2)HP 1910m 18.5インチワイド液晶モニター \10,500
http://h50146.www5.hp.com/products/desktops/personal/monitors/1910m/

(4-3)Dell IN1920 18.5 インチ HD ワイドスクリーンフラットパネルモニタ \10,500
http://www1.jp.dell.com/content/products/compare.aspx/19_20lcd?c=jp&cs=jpdhs1&l=ja&s=dhs

※本来ならサーバ用途の場合,16:9のワイド画面ではなく従来からの4:3の方がベター(縦方向の課解像度が高ければ,表示できる行数が増えるため)だが,現状では価格の問題でワイド画面を選択せざるを得ない状況です.

5.作業用(閲覧用)端末
ノートPC?

2010年10月20日水曜日

[memo] Google AJAX Feed APIでクロスドメイン制約を回避

PHP等で外部ドメインのAtomフィードやRSSフィードを収集し,Flashを設置するサーバに格納する事が出来れば,クロスドメイン制約を回避することが可能ですが,自前のサーバが利用できる環境がない場合,このような方法をとることが出来ません.
そこで,自前でサーバを用意する必要のないGoogle AJAX Feed APIを利用すれば,クロスドメイン制約を回避することが可能となります.
※商用利用等では問題はありますが...

Google AJAX Feed API登録画面
http://code.google.com/intl/ja/apis/ajaxfeeds/signup.html



Now Loading ...

javascript
<script type="text/javascript" src="http://www.google.com/jsapi?key=(APIキー)"></script>

<script type="text/javascript">
google.load("feeds", "1");
function initialize() {
    var feed = new google.feeds.Feed("http://www.kccollege.ac.jp/news/feed.xml");
    feed.setNumEntries(5);
    feed.load(function(result) {
  var html;
  // 読み込みに成功したときの処理
  if (!result.error) {
   // サイトのタイトルを出力
   html = '<h1>
<a href="' + result.feed.link + '">' + result.feed.title + '</a></h1>';
   // 各記事の情報を順に出力
   if (result.feed.entries.length) {
    html += '<ul>';
    for (var i = 0; i < result.feed.entries.length; i++) {
     // 各記事のタイトルと概要を出力
     var entry = result.feed.entries[i];
     html += '<li><a href="' + entry.link + '">' + entry.title + '</a>';
     html += '<span class="content">' + entry.contentSnippet + '</span></li>';
    }
    html += '</ul>';
   }
  }
  // 読み込みエラー時の処理
  else {
   html = '<p>Error</p>';
  }
  // 読み込み結果を、idが「feed」の要素に流し込む
  var container = document.getElementById("feed");
  container.innerHTML = html;
    });
}
google.setOnLoadCallback(initialize);
</script>

<div id="feed"><p>Now Loading ...</p></div>


ちなみに,Google AJAX Feed APIはJavascriptからだけではなく,URLに引数を付ける形で利用することも出来ます.
以下は,XML形式で10件のデータを取得する場合の例になります.
http://ajax.googleapis.com/ajax/services/feed/load?q=http%3A%2F%2Fwww.kccollege.ac.jp%2Fnews%2Ffeed.xml&v=1.0&num=10&output=xml

[memo] 最新スマートフォン・スペック比較3

日本未導入の最新のスマートフォンのスペックを比較する.
特にWindows Phone 7はいずれ国内でもリリースされる可能性があります.
機種名Palm Pre 2Windows Phone 7 (*1)

メーカーHPMicrosoft

OSwebOS 2.0Windows Phone 7

CPU1GH 1GHz Qualcomm MSM8250

画面サイズ3.1インチ3.5-4.3インチ

解像度320x480480 x 800

RAM512MB512MB
(ROM:576MB)


本体メモリ16GB8-16GB

外部メモリ



大きさ100x60x17mm


質量145g


カメラ500万画素


インカメラ×


GPS


電子コンパス


赤外線×


ワンセグ×


Felica×


無線LANIEEE802.11b/g


BluetoothBluetooth 2.1


高速データ通信CDMA


連続待受時間約350時間(CDMA)


連続通話時間約5.5時間(CDMA)


バッテリー



充電/外部端子microUSB


FLASH10.1 beta10.1

発売時期



(*1)Windows Phone 7は単一機種ではなく,同一の仕様で複数のメーカーからリリースされています.

[memo] 最新スマートフォン・スペック比較2

auの2010年秋冬モデル/2011年春モデルのAndroidスマートフォン4機種を比較する.
OSのバージョンが異なることから,対応するFlashのバージョンが異なることに注意が必要です.
またauは,あわせてSkypeとの連携も発表している.

機種名IS03REGZA Phone IS04IS05 (*1)SIRIUS α IS06
メーカーSHARP富士通東芝モバイルコミュニケーションズSHARPPantech
OSAndroid2.1Android2.1Android2.2Android2.2
CPUSnapdragon QSD8650 1GHz


画面サイズ3.5インチ4インチ3.4インチ3.7インチ
解像度640x960480×854480×854480×800
RAM512MB


本体メモリ



外部メモリ



大きさ63×121×12.662×126×1255×112×1460×116×11
質量138g149g132g109g
カメラ約957万画素約1219万画素約800万画素
インカメラ
GPS
電子コンパス



赤外線
ワンセグ
Felica×
無線LANIEEE802.11b/g
IEEE802.11b/gIEEE802.11b/g
Bluetooth2.1+EDR
2.1+EDR2.1+EDR
高速データ通信CDMA 1X EV-DO Rev.ACDMA 1X EV-DO マルチキャリアRev.A WIN HIGH SPEED (下り最大9.2Mbps/上り最大5.5Mbps)
CDMA 1x EV-DO マルチキャリアRev.A (CDMA 1X WIN)
連続待受時間約200時間約300時間
約190時間
連続通話時間約230分約310分
約300分
バッテリー



充電/外部端子



FLASHFlash Lite 4.0Flash Lite 4.010.110.1
発売時期11月下旬以降2011年春


(*1)IS05はdocomoからSH-03Cとしてリリースされるかもしれません...

[MA-9-8] おみくじ付き携帯待ち受け画面 パラメーター調整 (FlashLite2.0/ActionScript2.0)



ma9_8.swf

「占う」ボタンのトグル動作,表示される運勢の頻度調整を追加.

ActionScript2.0(Flash Lite2.0)
buttonFlag = 0;

this.onEnterFrame = function() {
 //バッテリーレベル
 var batteryCharging = fscommand2("GetPowerSource");
 var batteryLevel = fscommand2("GetBatteryLevel");
 var maxBattery = fscommand2("GetMaxBatteryLevel");
 var batteryStatusNum = 0;
 if (batteryCharging) {
  batteryStatusNum = 10;
 } else {
  if (maxBattery == 3) {
   batteryStatusNum = batteryLevel;
  } else if (maxBattery == 100) {
   if (batteryLevel>80) {
    batteryStatusNum = 8;
   } else if (batteryLevel>60) {
    batteryStatusNum = 7;
   } else if (batteryLevel>40) {
    batteryStatusNum = 6;
   } else if (batteryLevel>20) {
    batteryStatusNum = 5;
   } else if (batteryLevel>0) {
    batteryStatusNum = 4;
   }
  }
 }
 batteryStatusNumStr.text = batteryStatusNum;
 batteryPict.gotoAndStop(batteryStatusNum + 1);
 stop();
 _global.BSN = batteryStatusNum;
 //受信レベル
 var signalLevel = fscommand2("GetSignalLevel");
 var maxSignal = fscommand2("GetMaxSignalLevel");
 var signalNum = 0;
 if (maxSignal == 4) {
  signalNum = signalLevel;
 } else if (maxSignal == 3) {
  if (signalLevel>0) {
   signalNum = signalLevel+1;
  }
 }
 signalNumStr.text = signalNum;
 antennaPict.gotoAndStop(signalNum + 1);
 stop();
 _global.SN = signalNum;
 //開閉回数
 var mySharedObject:SharedObject = SharedObject.getLocal("open");
 SharedObject.addListener("open", initHandler);
 mySharedObject.data.count = 0;
 mySharedObject.flush();
 function initHandler() {
  var date:Number = Number(mySharedObject.data.count);
  date++;
  mySharedObject.data.count = date;
  mySharedObject.flush();
  checkNumStr.text = mySharedObject.data.count;
 }
 if (buttonFlag == 0) {
  fortunePict.gotoAndStop(11);
  stop();
 }
};

fortuneButton.onRelease = function() {
 if (buttonFlag == 0) {
  fortunePict.play();
  buttonFlag = 1;
 } else if (buttonFlag == 2) {
  fortunePict.play();
  fortuneStr.text = "";
  buttonFlag = 1;
 } else {
  fortuneArray = ["大吉", "大吉", "吉", "半吉", "小吉", "末小吉", "末吉", "凶", "凶", "凶"]; 
  fortuneNum = Math.floor(Math.random() * 9) + 1;
  //バッテリーの状況によって運勢変化
  switch (_global.BSN) {
   case (0) :
    fortuneNum = fortuneNum + 2;
    break;
   case (1) :
    fortuneNum = fortuneNum + 1;
    break;
   case (3) :
    fortuneNum = fortuneNum - 1;
    break;
   case (4) :
    fortuneNum = fortuneNum + 1;
    break;
   case (8) :
    fortuneNum = fortuneNum - 1;
    break;
   case (10) :
    fortuneNum = fortuneNum - 2;
    break;
  }
  //電波の状況によっても運勢変化
  switch (_global.SN) {
   case (4) :
    fortuneNum = fortuneNum - 2;
    break;
   case (3) :
    fortuneNum = fortuneNum - 1;
    break;
   case (2) :
    fortuneNum = fortuneNum;
    break;
   case (1) :
    fortuneNum = fortuneNum + 1;
    break;
   case (0) :
    fortuneNum = fortuneNum + 2;
    break;
  }
  //特定の条件がそろった場合
  if(_global.BSN == 0 && _global.SN == 0){
   fortuneNum = 0;
  } else if (_global.BSN == 10 && _global.SN == 4){
    fortuneNum = fortuneNum - 3;
  }
  if(fortuneNum < 0){
   fortuneNum = 0;
  } else if (fortuneNum > 9){
    fortuneNum = 9;
  }
  fortuneStr.text = "あなたの運勢は、"+fortuneArray[fortuneNum]+"("+fortuneNum+")です";
  fortunePict.gotoAndStop(fortuneNum + 1);
  stop();
  buttonFlag = 2;
 }
};

2010年10月15日金曜日

[MA-9-7] おみくじ付き携帯待ち受け画面 (FlashLite2.0/ActionScript2.0)



ma9_7.swf

ActionScript2.0(Flash Lite2.0)
this.onEnterFrame = function() {
 //バッテリーレベル
 var batteryCharging = fscommand2("GetPowerSource");
 var batteryLevel = fscommand2("GetBatteryLevel");
 var maxBattery = fscommand2("GetMaxBatteryLevel");
 var batteryStatusNum = 0;
 if (batteryCharging) {
  batteryStatusNum = 10;
 } else {
  if (maxBattery == 3) {
   batteryStatusNum = batteryLevel;
  } else if (maxBattery == 100) {
   if (batteryLevel>80) {
    batteryStatusNum = 8;
   } else if (batteryLevel>60) {
    batteryStatusNum = 7;
   } else if (batteryLevel>40) {
    batteryStatusNum = 6;
   } else if (batteryLevel>20) {
    batteryStatusNum = 5;
   } else if (batteryLevel>0) {
    batteryStatusNum = 4;
   }
  }
 }
 batteryStatusNumStr.text = batteryStatusNum;
 batteryPict.gotoAndStop(batteryStatusNum + 1);
 stop();
 _global.BSN = batteryStatusNum;
 //受信レベル
 var signalLevel = fscommand2("GetSignalLevel");
 var maxSignal = fscommand2("GetMaxSignalLevel");
 var signalNum = 0;
 if (maxSignal == 4) {
  signalNum = signalLevel;
 } else if (maxSignal == 3) {
  if (signalLevel>0) {
   signalNum = signalLevel+1;
  }
 }
 signalNumStr.text = signalNum;
 antennaPict.gotoAndStop(signalNum + 1);
 stop();
 _global.SN = signalNum;
 //開閉回数
 var mySharedObject:SharedObject = SharedObject.getLocal("open");
 SharedObject.addListener("open", initHandler);
 mySharedObject.data.count = 0;
 mySharedObject.flush();
 function initHandler() {
  var date:Number = Number(mySharedObject.data.count);
  date++;
  mySharedObject.data.count = date;
  mySharedObject.flush();
  checkNumStr.text = mySharedObject.data.count;
 }
};
topButton.onRelease = function() {
 fortuneArray = ["大吉", "大吉", "吉", "半吉", "小吉", "末小吉", "末吉", "凶", "凶", "凶", "凶", "凶"]; 
 fortuneNum = Math.floor(Math.random()*(_global.BSN+_global.SN));
 fortuneStr.text = "あなたの運勢は、"+fortuneArray[fortuneNum]+"("+fortuneNum+")です";
 fortunePict.gotoAndStop(fortuneNum + 1);
 stop();
};

2010年10月14日木曜日

[SA-3-11] PHP-MySQL連携

1.php-mysqlモジュールをインストール
$ su
# yum install php-mysql
# service httpd stop
# service httpd start
# service mysqld stop
# service mysqld start

2.MySQLにデータベース,テーブル作成
$ mysql -u root -p
create database sa;

$ vi server_list.csv
,1,sa000,10.2.3.100
,2,sa001,10.2.3.101
,3,sa002,10.2.3.102
,4,sa003,10.2.3.103
,5,sa004,10.2.3.104
,6,sa005,10.2.3.105
,7,sa006,10.2.3.106
,8,sa007,10.2.3.107
,9,sa008,10.2.3.108
,10,sa009,10.2.3.109
,11,sa010,10.2.3.110
,12,sa011,10.2.3.111

$ mysql -u root -p sa
create table server_list ( id integer NOT NULL AUTO_INCREMENT PRIMARY KEY, num char(4), host_name char(20), ip_address char(15) );

show tables;

load data local infile "~/server_list.csv" into table server_list fields terminated by ',' enclosed by '"' lines terminated by '\n';
select * from server_list;

3.Windows側でPHPファイルを作成
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>server_list</title>
</head>
<body>
<?php
 $db_user  = "[user name]";
 $db_password = "[password]";
 $db_name = "[database name]";
 $db_host  = "localhost";

 $db = mysql_connect($db_host,$db_user,$db_password);
 mysql_select_db($db_name,$db); 
 $str_sql = "select * from server_list";
 $rs = mysql_query($str_sql,$db);
 $num = mysql_num_fields($rs);

 print("<table><tr><th colspan=4>server_list</th></tr>");
 echo("
 ");
 print("<tr>");
 for ($i=0;$i<$num;$i++){
  print("<td><b>".mysql_field_name($rs,$i)."</b></td>");
 }
 print("</tr>");
 while($row=mysql_fetch_array($rs)){
  echo("
 ");
  print("<tr>");
  for($j=0;$j<$num;$j++){
   print("<td>".$row[$j]."</td>");
  }
  print("</tr>");
 }

 print("</table>");

 mysql_free_result($rs);
 mysql_close($db);
?>
</body>
</html>

4.FTP後にパーミッションを755に変更

[SA-3-10] httpd設定

selinuxの無効化
# getenforce
# setenforce 0
# vi /etc/sysconfig/selinux
#SELINUX=enforcing
SELINUX=disabled
httpdの設定ファイル修正
# vi /etc/httpd/conf/httpd.conf
エラーページ等でOS名を非表示
 #ServerTokens OS
 ServerTokens Prod

エラーページ等でApacheのバージョン非表示
 #ServerSignature On
 ServerSignature Off

不要モジュールの読み込み解除
 #LoadModule auth_anon_module 
 #LoadModule ldap_module modules/mod_ldap.so
 #LoadModule auth_ldap_module modules/mod_auth_ldap.so
 #LoadModule mime_magic_module 
 #LoadModule cern_meta_module 
 #LoadModule deflate_module modules/mod_deflate.so
 #LoadModule headers_module modules/mod_headers.so
 #LoadModule usertrack_module modules/mod_usertrack.so
 #LoadModule status_module modules/mod_status.so
 #LoadModule asis_module modules/mod_asis.so
 #LoadModule info_module modules/mod_info.so
 #LoadModule vhost_alias_module 
 #LoadModule imap_module modules/mod_imap.so
 #LoadModule speling_module modules/mod_speling.so
 #LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
 #LoadModule cache_module modules/mod_cache.so
 #LoadModule disk_cache_module 
 #LoadModule file_cache_module modules/mod_file_cache.so
 #LoadModule mem_cache_module 

サーバ管理者のメールアドレス設定
 #ServerAdmin root@localhost

サーバ(FQDN)名設定
 #ServerName www.example.com:80

ドキュメントルート(/var/www/html)のCGI/SSIの実行権付与とインデックスリストの非表示
(Indexes : インデックスリスト表示, FollowSymLinks : Symlink許可, Includes : SSI許可, ExecCGI : CGI許可)
 # Options Indexes FollowSymLinks
 Options FollowSymLinks Includes ExecCGI

ディレクトリアクセス制御
(FileInfo : ファイル関係の制御, AuthConfig : 認証関係, Limit : .htaccessによるアクセス制御, or ALL : 全て許可)
 # AllowOverride None
 AllowOverride FileInfo AuthConfig Limit

ユーザディレクトリ(/home/[user]/public_htmlをhttp://localhost.localdomain/~[user]として表示)の有効化とCGI/SSIの実行権付与とインデックスリストの非表示
※各ディレクトリのパーミッションは,/home/[user] : 711, /home/[user]/public_html : 755です.
 #UserDir disable
 UserDir public_html
 <Directory /home/*/public_html>
  AllowOverride FileInfo AuthConfig Limit
  Options MultiViews SymLinksIfOwnerMatch 
  <LimitExcept GET POST OPTIONS>
   Order deny,allow
   Deny from all
  </LimitExcept>
 </Directory>
 <Directory /home/*/public_html>
  AllowOverride FileInfo AuthConfig Limit
  Options MultiViews SymLinksIfOwnerMatch IncludesNoExec ExecCGI
  <LimitExcept GET POST OPTIONS>
   Order deny,allow
   Deny from all
  </LimitExcept>
 </Directory>

iconsディレクトリのファイル一覧を非表示
<Directory "/var/www/icons">
 #Options Indexes MultiViews
 Options MultiViews
 AllowOverride None
 Order allow,deny
 Allow from all
</Directory>

Index.htmの許可
 DirectoryIndex index.html index.htm

CGIスクリプトとして.plを許可
#AddHandler cgi-script .cgi
AddHandler cgi-script .cgi .pl

アクセスログでのホストネーム使用
 #HostnameLookups Off
 HostnameLookups On

ログ分離設定
 #CustomLog logs/access_log combined
 SetEnvIf Remote_Addr 192.168.1 nolog
 SetEnvIf Remote_Addr 127.0.0.1 nolog
 SetEnvIf Request_URI "Admin.dll" wormlog nolog
 SetEnvIf Request_URI "cmd.exe" wormlog nolog
 SetEnvIf Request_URI "default.ida" wormlog nolog
 SetEnvIf Request_URI "null.ida" wormlog nolog
 SetEnvIf Request_URI "root.exe" wormlog nolog
 CustomLog logs/worm_log common env=wormlog
 CustomLog logs/access_log combined env=!nolog

/var/www以下のディレクトリを,ユーザー権限で操作可能(SFTPにてファイルのアップロードが可能)とする.
# chown -R [user name] /var/www/
# chmod -R g+w /var/www/

テスト用のhtmlファイル作成
# vi /var/www/html/index.html
もしくは
例) sftp://192.168.147.131

外部からWEBサーバへの接続確認
例) http://192.168.147.131

→[SA-1-5]

[SA-3-9] Firewall(iptables)設定

iptablesの自動起動確認
# chkconfig --list | grep tables

iptablesの自動起動停止
# chkconfig iptables off

iptablesの起動
# service iptables start

iptablesの停止
# service iptables stop
(/etc/rc.d/init.d/iptables stop)

※ip6tablesについても同様です.


iptablesの設定ファイル編集
# vi /etc/sysconfig/iptables
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT


※直接設定ファイルを編集する事は,危険が伴うため推奨されません.以下のコマンドを使用して,個別にルールを適用して下さい.

iptablesのルール初期化
# /sbin/iptables -F

外部からWEBサーバへの接続許可1(SYNフラグ,ACKフラグ)
クライアント→サーバ方向
# /sbin/iptables -A FORWARD -p TCP -s 0.0.0.0 --dport 80 -d 192.168.147.131 -j ACCEPT
-p プロトコル:tcp
--dport 送信先ポート:80
-d 送信先アドレス:192.168.147.131
-j ターゲット:ACCEPT(パケットの通過を許可)

外部からWEBサーバへの接続許可2(SYN/ACKフラグ)
サーバ→クライアント方向
# /sbin/iptables -A FORWARD -p TCP ! --syn -m state --state ESTABLISHED --sport 80 -s 192.168.147.131 -d 0.0.0.0 -j ACCEPT
-p プロトコル:tcp
--sport 送信元ポート:80
-s 送信元アドレス:192.168.147.131
! --syn フラグ:SYNフラグ以外
-m state --state ステータス:ESTABLISHED
-j ターゲット:ACCEPT(パケットの通過を許可)

2010年10月9日土曜日

[memo] スマートフォン関連開発環境まとめ

■Android [google]
http://developer.android.com/sdk/index.html

例)au IS01
1.Android SDKの入手し,インストール

2.対象機種の拡張APIや,エミュレーターにハードウェアの仕様を設定する為に,機種固有のSDK AddOnを入手し,1で入手したAndroid SDKのadd-onsフォルダ配下に配置

3.1で入手したAndroid SDKに含まれるSDK Manager.exeを起動し,Virtual Devices→New→Target:JN-DK01(SHARP Corporation) - API Level 4を選択し,新規AVD(Android Virtual Device)を作成→Start

※ARM用Androidだけではなく,x86用Androidも存在します.ISO ImageをダウンロードしてVMware Playerにインストールすれば,シミュレーターや実機が無くても,雰囲気を掴むことは出来ます.
http://www.android-x86.org/download
1.VMware Playerの設定
 後でOSをインストール
 ゲストOS:Linux(他の2.6.xカーネル)

2.Android froyo 20100812.vmxの7~8行目を編集
   scsi0:0.present = "TRUE"
   scsi0:0.fileName = "Android froyo 20100812.vmdk"
 を
   ide0:0.present = "TRUE"
   ide0:0.fileName = "Android froyo 20100812.vmdk"
 に変更

3.インストール
 installation
 Create/Modify partitions
  New→Primary→Bootable→Write→Quit
 sda1→ext3

■Windows Phone 7 [Microsoft]
開発ツール(英語版)
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce&displaylang=en

VB用テンプレート(英語版)
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=a808a69d-6119-47b7-b858-262be5c49915&displaylang=en

※上記WP7用SDKはVisual Studio 2010(英語版)用です.

Visual Studio 2010 日本語版にWindows Phone 7のテンプレートを入れる方法
http://blogs.shintak.info/archive/2010/09/22/54570.aspx


■iOS SDK [Apple]
http://developer.apple.com/devcenter/ios/index.action
※iOSのSDKを動かすためには開発環境(Xcode)が必要です.XcodeはMac OS X専用の為,iOS SDKを利用するためにはMACが必要という事になります.


■Kindle Development Kit [Amazon]
https://kindlepublishing.amazon.com/gp/vendor/sign-in?ie=UTF8&originatingURI=%2Fgp%2Fvendor%2Fmembers%2Fkindlepubs%2Fkdk%2Fhome

2010年10月8日金曜日

[MA-9-6] random関数の利用 (FlashLite2.0/ActionScript2.0)



ma9_6.swf

ランダム関数を使用すると端数が発生するため,出力された値を使って特定のフレームを表示したい場合には端数の処理が必要となります.

Math.floor 小数点以下切り捨て 0 - 9
Math.ceil 小数点以下切り上げ 1 - 10
Math.round 小数点以下四捨五入 0 - 10

ActionScript2.0(Flash Lite2.0)
topButton.onRelease = function() {
 fortuneArray = ["大吉", "大吉", "吉", "半吉", "小吉", "末小吉", "末吉", "凶", "凶", "凶"]; 
 fortuneNum = Math.floor(Math.random()*(_global.BSN+_global.SN));
 fortuneStr.text = "あなたの運勢は、"+fortuneArray[fortuneNum]+"("+fortuneNum+")";
 //gotoAndStop(fortuneNum);
};

[MA-9-5] 携帯電話の開閉回数・バッテリー状態・電波状態の表示サンプル (FlashLite2.0/ActionScript2.0)

携帯電話の開閉回数,バッテリー状態,電波状態を表示するサンプル



ma13debug.swf

ActionScript2.0(Flash Lite2.0)
this.onEnterFrame = function() {
//debug用 SharedObject利用可否チェック
 var checkSharedObject = "none";
 checkSharedObject = System.capabilities.hasSharedObjects;
 checkSharedObjectStr.text = checkSharedObject;

//debug用 キャリア判定
 maxBatteryTemp = fscommand2("GetMaxBatteryLevel");
 var carrier = "other";
 if (maxBatteryTemp == 3) {
  carrier = "au/softbank";
 } else if (maxBatteryTemp == 100) {
  carrier = "docomo";
 } else {
  carrier = "other";
 }
 carrierStr.text = carrier;

//バッテリーレベル
 var batteryCharging = fscommand2("GetPowerSource");
 var batteryLevel = fscommand2("GetBatteryLevel");
 var maxBattery = fscommand2("GetMaxBatteryLevel");
 var batteryStatusNum = 0;
 if (batteryCharging) {
  batteryStatusNum = 10;
 } else {
  if (maxBattery == 3) {
   batteryStatusNum = batteryLevel;
  } else if (maxBattery == 100) {
   if (batteryLevel>80) {
    batteryStatusNum = 8;
   } else if (batteryLevel>60) {
    batteryStatusNum = 7;
   } else if (batteryLevel>40) {
    batteryStatusNum = 6;
   } else if (batteryLevel>20) {
    batteryStatusNum = 5;
   } else if (batteryLevel>0) {
    batteryStatusNum = 4;
   }
  }
 }
 batteryStatusNumStr.text = batteryStatusNum;

//受信レベル
 var signalLevel = fscommand2("GetSignalLevel");
 var maxSignal = fscommand2("GetMaxSignalLevel");
 var signalNum = 0;
 if (maxSignal == 4) {
  signalNum = signalLevel;
 } else if (maxSignal == 3) {
  if (signalLevel>0) {
   signalNum = signalLevel+1;
  }
 }
 signalNumStr.text = signalNum;

//開閉回数
 var mySharedObject:SharedObject = SharedObject.getLocal("open");
 SharedObject.addListener("open", initHandler);
 mySharedObject.data.count = 0;
 mySharedObject.flush();
 function initHandler() {
  var date:Number = Number(mySharedObject.data.count);
  date++;
  mySharedObject.data.count = date;
  mySharedObject.flush();
  checkNumStr.text = mySharedObject.data.count;
 }
};

※PC上で動作確認を行う際は,iモードHTMLシミュレータⅡを使用すると便利です.

2010年10月7日木曜日

[SA-3-8] CentOS5.5(最小インストール)でのcrontabの利用

今回最小構成でインストールした関係で,初期状態ではcronが使えない場合もあります.
その際はvixie-cronをインストールし,利用可能な状態にしてください.
# yum install vixie-cron


crontabへの登録
$ crontab -e

crontabに登録された内容の確認
$ crontab -l

[SA-3-7] VMWare Player 3.0のNAT設定変更方法

最新のVMWare Player 3.0から,標準ではNATの設定を変更できなくなったようです.
ただし,インストーラーの中にはexeファイルが含まれているので,それを取り出して利用する事とします.

1.ダウンロードしたVMWare Playerのインストールファイルを,Windowsのコマンドライン上で,オプションを付けて実行.
VMware-player-3.1.2-301548.exe /e temp

2.作成されたtempフォルダの中のnetwork.cabをWIndowsの解凍ソフトで展開する.

3.展開されたフォルダの中のvmnetcfg.exeをVMWare Playerがインストールされたフォルダ(C:\Program Files\VMware\VMware Player)に移動する.

4. vmnetcfg.exeを実行

[SA-3-6] 最低限必要となるアプリケーションをインストール

1.yum準備
#yum install yum-fastestmirror
#yum install yum-utils

2.NTPインストール
#yum install ntp
#chkconfig ntpd on
#chkconfig --list | grep ntp
#service ntpd start

3.PHPインストール
#yum install php
#vi /etc/php.ini
memory_limit = 16M ; Maximum amount of memory a script may consume

4.Webサーバ(httpd)インストール
#yum install httpd
#vi /etc/httpd/conf/httpd.conf
KeepAlive On
<IfModule prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000
</IfModule>
<IfModule worker.c>
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>
※ログや参考となるサイトを確認しながらパラメータの微調整を行います.
#service httpd start

5.MySQL(サーバ,クライアント)インストール
#yum install mysql mysql-server
#vi /etc/my.cnf
[mysql]
default_character_set=utf8

[mysqld]
character_set-server=utf8
innodb_log_file_size=64M
innodb_buffer_pool_size=128M
#mysql_secure_installation
#service mysqld start
#chkconfig mysqld on

6.MySQLの不要ユーザー削除/新規ユーザー追加
#mysql -u root

ユーザ情報表示
select user,host,password from mysql.user;

匿名ユーザー削除
delete from mysql.user where user='';

rootパスワード設定
set password for root@localhost=password('[任意のパスワード]');
set password for root@'[ホスト名]'=password('[任意のパスワード]');
set password for root@127.0.0.1=password('[任意のパスワード]');

新規ユーザーの追加
grant all privileges on *.* to [user name]@"%" identified by '[password]' with grant option;

ユーザ情報表示(確認)
select user,host,password from mysql.user;

7.viエディタのカラー化
# yum install vim-enhanced
# alias vi='vim'
# vi /etc/bashrc
alias vi='vim'

2010年10月6日水曜日

[memo] 最新スマートフォン・スペック比較

各キャリアの最新のスマートフォンのスペックを比較する.
採用OSや付加機能から,各キャリアの今後のスマートフォンの戦略を考える.

機種名Galaxy S SC-02BIS03Xperia SO-01BiPhone 4
キャリアdocomoaudocomosoftbank
OSAndroid 2.2Android 2.1(*1)Android 1.6(*2)iOS 4
CPUSamsung
S5PC110
1GHz
Qualcomm QSD8650 Snapdragon
1GHz
Qualcomm QSD8250
Snapdragon
1GHz
Apple
A4
1GHz
画面サイズ4インチ3.5インチ4.0インチ3.5インチ
解像度800x480960×640854x480960×640
RAM512MB512MB256MB512MB
本体メモリ16GB500MB1GB16GB/32GB
外部メモリmicroSD
最大32GB
1GB同梱
microSD
最大32GB
2GB同梱
microSD
最大32GB
16GB同梱
×
大きさ122×64×9.9mm121×63×12.6mm119×63×13.1mm115.2×58.6×9.3mm
質量118g138g139g137g
カメラ500万画素
CMOS
957万画素
CCD
810万画素
CMOS
500万画素
裏面照射CMOS
インカメラ××
GPS
電子コンパス
赤外線×××
ワンセグ××
Felica×××
無線LANIEEE802.11b/g/nIEEE802.11b/gIEEE802.11b/gIEEE802.11b/g/n
BluetoothBluetooth 3.0Bluetooth 2.1Bluetooth 2.0Bluetooth 2.1
高速データ通信HSDPA
HSUPA
下り7.2Mbps
上り5.76Mbps
CDMA 1X
EV-DO Rev.A
下り3.1Mbps
上り1.8Mbps
HSDPA
HSUPA
下り7.2Mbps
上り2.0Mbps
HSDPA
HSUPA
下り7.2Mbps
上り5.8Mbps
連続待受時間約510時間約200時間約300時間(3G)約300時間(3G)
連続通話時間約380分約230分約290分(3G)約420分(3G)
バッテリー1500mAh1020mAh1500mAh1420mAh
充電/外部端子microUSBmicroUSBmicroUSBDockコネクタ
FLASHFLASH 10.1FLASH Lite 4.0(*1)××
発売時期2010年10月中2010年11月下旬2010年4月1日2010年6月24日

(*1)今後予定されるAndroid2.2へのアップデート時にFlash 10.1に対応予定
(*2)今後Android2.*へアップデート予定