スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
ん~
ちょっとパスワードなどについて考え中。

せっかくパスワードを導入しても平文で流れては意味がないというのをよく聞く。

自分の目で確かめないと気がすまないので、WinDumpやWireshark(Ethereal名前変ったみたいね)を入れてみた。

どちらも見たいパケットを思ったように見れない(←使い方がわからんせい)。 Wiresharkでtelnetを覗いてみたけどたしかに平文で流れている。しかし、パスワードであるが1文字1文字ごとに通信しているっぽいので、この状態からパスワードを盗むことは困難に思える。 解析結果をなにかのファイルに保存して、スクリプトを書いて見やすい形にするのか、それとももっとうまい設定の方法があるのか。他のアプリケーションを使うべきなのか。 とりあえず、ちゃんと暗号通信がなされているのかどうか確認する術を持たないといけない気がする。

3way Handshake ・ TCP ・ パケット ああ全部知ってるけど見方がわからねーよ。てか、見たいのはアプリケーション層かプレゼンテーション層だよ。

たぶんフィルターのかけ方にコツがいるんだろうなぁ
とりあえず src と dst と ポート は指定できるが。これ調べるならこれだろってのがわからん。

追記:
でも http の場合は post も クッキーのやりとりも簡単にみれてしまうなぁ・・・ httpsの出番なのか・・・ もうちょい詳しくやり取りの仕組みをつかまんと。
スポンサーサイト
近くにいたりするのでおもしろい
おもいあたる節があるので、

非常におもしろいです。

http://blogs.yahoo.co.jp/engineer_ryuseigun/folder/829276.html

おるわー
プログラマに欲しいCSSのクラス

ターミナル


ターミナルでコマンドを打った様子を載せたいとき

.terminal {
margin: 5px;
padding: 5px;
background-color: #000000;
color: #ffffff;
}

使用例
<div class="terminal">$ ls</div>
$ ls
セッション管理をやってみた
>>http://www.dab.hi-ho.ne.jp/sasa/biboroku/perl/session.html
を 参考にさせていただいてセッション管理をやってみました。

今回ちょっとだけ改良させていただいたソースを載せます。
次は、>>「なんも考えないでパスワード認証 CGI」との合わせ技をやろうと考え中。

ファイル名:session_start.cgi
#!/usr/bin/perl -w

#main--------------------------------
use strict;
use CGI;
use CGI::Session qw/-ip_match/;

my $session=CGI::Session->new(undef,undef,{Directory=>'./.session'});
$session->expire('+1h'); #有効期限は1時間

my $sid = $session->id;
$session->param('hidden','YOU DO NOT KNOW BUT ....'); #セッション経由で引き渡す項目と値

print_html($sid);
#-----------------------------------

#サブルーチン-----------------------
sub print_html{
my $sid = shift;
my $cgi=CGI->new;
print $cgi->header(-charset=>'UTF-8',
-cookie=>$cgi->cookie(-name=>'CGISESSID',
-value=>$sid)),
#headerによりcookieにセッションidを保管
$cgi->start_html(-lang=>'ja',
-encoding=>'UTF-8',
-title=>'セッション管理を始めよう(Cookieを使用してます)');
print <<HTML_VIEW;
<h1>セッション管理を始めましょう(Cookieを使用してます)</h1>
<p>あなたのセッションIDは$sidです</p>
<form action="./session_end.cgi" method="post">
<input type="submit" value=" 認証する ">
</form>
HTML_VIEW
print $cgi->end_html;
}
#-----------------------------------



ファイル名:session_end.cgi
#!/usr/bin/perl -w

#main-----------------------------------------------------------------
use strict;
use CGI;
use CGI::Session qw/-ip_match/;

my $cgi=CGI->new;

my $sid=$cgi->cookie('CGISESSID')||$cgi->param('CGISESSID')||undef;
#1.cookieからCGISESSIDを探す
#2.cookieから取れなかったらurlパラメータを探す.
#3.どちらも取得できなかったらundef.
my $session=CGI::Session->new(undef,$sid,{Directory=>'./.session'});
#4.取得したセッションidが有効ならそのまま.無効なら別のidを発番.

my $hidden_message = '';
if(defined $sid && $sid eq $session->id){
#cookieかurlパラメータから値を取得でき,かつ有効なid
$hidden_message = $session->param('hidden');
print_html('セッション有効!(^^)v', $cgi, $sid, $hidden_message);
}
elsif(defined $sid && $sid ne $session->id){
#cookie,またはurlパラメータから値を取得できた.しかしidとしては無効
print_html('セッションは無効じゃぞ', $cgi, $sid, $hidden_message);
#不要なidはさっさと消去
#先にcloseをしないと,deleteで
#'(in cleanup) could not flush: Couldn't unlink .session/cgisess_CGISESSID'
#が発生する.エラーが出てもファイルは消える.
#closeは遅いらしい
$session->close;
$session->delete;
}
else{
#cookie,またはurlパラメータから値を取得できない.
print_html('セッションは無効(;_;)', $cgi, $sid, $hidden_message);
}

#サブルーチン--------------------------------------------
sub print_html{
my ($message, $cgi, $sid, $hidden_message) = @_;
print $cgi->header(-charset=>'UTF-8'),
$cgi->start_html(-lang=>'ja',
-encoding=>'UTF-8',
-title=>'セッション管理受取側');

print<<"HTML_VIEW";
<p>$message</p>
<p>セッションIDは「$sid」でした</p>
<p>実は裏では「$hidden_message」というメッセージがやりとりされています</p>
HTML_VIEW
print $cgi->end_html;
}
#--------------------------------------------------------

ブックマークを作ってみる
とかくRailsだ。なんだーとWebアプリではフレームワークが大人気。

で、よく作成例に出されるのがソーシャルブックマークと呼ばれるものだったりする。でもこの例、今までソーシャルブックマーク使ったことない人にはピンとこないし。データベースまわりの処理をプログラムからやったことがないと またまたピンとこない。ここでは、MySQLとPerlを用いてソーシャルブックマークを作ってみた。

テーブルがひとつなんて、そんな設計でいいのかあ! などといった文句は一切受け付けられない。ここはあくまでPerlからSQLを使ってどうやってデータベースとやり取りするかに重点がおかれている(というか単なる覚書です)。でもそういえばPerl側からjoinとかどうやるんだろうなぁ。今、「情報システム演習II」の教材を持ち出してきました。joinなどのテーブルの結合はselect文でできましたね・・・。

それでは まずMySQLクライアントでの操作を一気に掲載する。

mysql> grant all privileges on bookmark_db.* to nakanishi@localhost identified by 'nakanishidayo';


mysql> create database bookmark_db;

mysql> use bookmark_db

mysql> create table bookmark_table(
-> user_name varchar(255),
-> url varchar(255),
-> comment varchar(255)
-> );

mysql> insert into bookmark_table values('rongon', 'http://www.yahoo.co.jp/', 'すばらしいページだ');

mysql> insert into bookmark_table values('dai', 'http://days.yahoo.co.jp/','なんともすぱらしい');

mysql> select * from bookmark_table;
+-----------+--------------------------+-----------------------------+
| user_name | url | comment |
+-----------+--------------------------+-----------------------------+
| rongon | http://www.yahoo.co.jp/ | すばらしいページだ |
| dai | http://days.yahoo.co.jp/ | なんともすぱらしい |
+-----------+--------------------------+-----------------------------+

mysql> exit


次いでPerlのソースです

ファイル名:bookmark.pl
#!/usr/bin/perl -w
use strict;
use DBI;

my ($user_name, $url, $comment);

print "☆あなたのユーザー名は何?☆\n";
print "名前教えてよ> ";
chomp($user_name = <STDIN>);
print "\n☆あ、$user_nameか! この前ブックマークしてたよね ☆\n";

#データベースにコネクト-----------------------
my $dbh = DBI->connect('DBI:mysql:bookmark_db:localhost:3306', 'nakanishi',
'nakanishidayo');
#---------------------------------------------

#セレクトにより取り出す-----------------------
my $sth = $dbh->prepare("select * from bookmark_table where user_name = ?");
$sth->bind_param(1, $user_name);
$sth->execute;
#----------------------------------------------

print "☆今まで、ブックマークしてたやつ 出しちゃうね!☆\n";
#取り出したものを表示--------------------------
my @recode;
while ( @recode = $sth->fetchrow_array ){
($url, $comment) = ($recode[1], $recode[2]);
print "URL:$url COMMENT:$comment\n";
}
#-----------------------------------------------

print "\n☆今回もブックマークしてくよね☆\n";
#強制的にブックマークさせる--------------------
print "URL教えてよ> ";
chomp($url = <STDIN>);
print "一言どうぞ> ";
chomp($comment = <STDIN>);
#-----------------------------------------------

#ブックマークをデータベースに反映--------------
$sth = $dbh->prepare("insert into bookmark_table values(?, ?, ?)");
$sth->bind_param(1, $user_name);
$sth->bind_param(2, $url);
$sth->bind_param(3, $comment);
$sth->execute;
#-----------------------------------------------

print "また来てね!!$user_name\n";


お気づきでしょうか? 作ったのはWebアプリではなく。コマンドプロンプトで動きます。

というかMySQLクライアントからは
mysql> insert into bookmark_table values('rongon', 'http://www.yahoo.co.jp/', 'すばらしいページだ');

と ' ',' ',' ' という形でinsertしてるのにPerlからだと
$sth = $dbh->prepare("insert into bookmark_table values(?, ?, ?)");
と ' ' が要らなくなるとか細かすぎる。
Apache中級者像
Apacheの設定で中級者向けだと思うものを初学者のビンゴ中西がピックアップ!
初学者なんで、よくわからん。

-----------------ビンゴ中西の考える中級者像----------------------
● .htaccess を使ってアクセス制御ができる
● ブラウザにキャッシュさせないようにする(CGI開発時などに極めて便利)
-----------------------------------------------------------------

.htaccess を使ってアクセス制御ができる


:一連の流れ:
1).htaccessを制御したいディレクトリに作成
2)アクセスできるユーザーとパスワードを登録
3)Apacheを再起動
:一連の流れ:

1)ファイル名:.htaccess
AuthUserFile /home/nakanishi/.htpasswd
AuthName "Please enter your ID and password"
AuthType Basic
require valid-user

を制御したいディレクトリに置く。

2)nakanishiのホームディレクトリで、
$ htpasswd -c .htpasswd nakanishi
New password: nakanishidayo
Re-type new password: nakanishidayo


$ cat .htpasswd 
nakanishi:vCVbhzTIBes.g

となった。

3)
# /etc/init.d/httpd restart



わけわかんなかったこと:
httpd.confファイルのどこも AllowOverride None → AllowOverride All に変えていないのにちゃんとアクセス制御できた。パスワードの暗号化ってどうやるんだ?


キャッシュをさせないようにする(CGI開発時などに極めて便利)


:一連の流れ:
1)httpd.confにFilesディレクティブを追記する。
2)Apacheを再起動
:一連の流れ:

1)httpd.confに
<Files ~ "\.(cgi|html|php|jpe?g|gif|png)$">
Header set Pragma no-cache
Header set Cache-Control no-cache
</Files>
を追記。

えー それどこに書いたらいいのー
httpd.confって行数多すぎでしょー 絶対適当な場所におけるわけないやんか!!
と思ったので
403行目~406行目
<Files ~ "^\.ht">
Order allow,deny
Deny from all
</Files>

とあった次の行に追記しました。

2)
# /etc/init.d/httpd restart

おお!!Firefoxの「Live HTTP headers」で
Cache-Control: max-age=0
と表示されたのを確認!!!!

ちなみに、CGIに限って言えばCGI.pm のheaderメソッドを使えばキャッシュを残さないようにしてくれてるみたいですね。
ビンゴ中西のほげほげの古い記事より:http://bingobingobingo.blog49.fc2.com/blog-entry-169.html

参考資料:
http://httpd.apache.org/docs/2.2/ja/howto/auth.html
http://ash.jp/env/srv/htaccess.htm
http://www.seo-equation.com/html/htaccess/cache_control
初めてMySQLとPerlの連帯でプログラムが書けました(後編)
<<前編へ

はじめに作って、実行はされるがうんともすんとも言わなかったスクリプトから掲載。

#########################################################
#!/usr/bin/perl -w
use strict;
use DBI;

my $dbh = DBI->connect('DBI:mysql:counterdb:localhost:3306', 'nakanishi', 'nakanishidayo') || die "sine";
my $sth = $dbh->prepare("select count from counter_table")|| die "sine";
$sth->execute || die "sine";
my $count;
while ( $count = $sth->fetchrow_array ){
print "$count";
$count++;
}
$sth = $dbh->prepare("update counter_table set count = ?") || die "sine";
$sth->bind_param(1, $count) || die "sine";
$sth->execute;
#########################################################



ついで、参考ページをおもいっきり使わせてもらったバージョン。これでうごきました。

#########################################################
#!/usr/bin/perl

use strict;
use DBI;

my $dsn = 'DBI:mysql:counterdb:localhost:3306';
my $user = 'nakanishi';
my $password = 'nakanishidayo';

my $dbh = DBI->connect($dsn, $user, $password,
{RaiseError => 1, PrintError => 0, AutoCommit => 0 }) || die "$!";
eval {
&mainwork();
$dbh->commit;
$dbh->disconnect;
};
if ( $@ ){
$dbh->rollback;
$dbh->disconnect;
}

exit 0;

#--------------------------
sub mainwork {
my $sql = "select count from counter_table";

my $sth = $dbh->prepare($sql);
$sth->execute;

while ( my $arr_ref = $sth->fetchrow_arrayref ){
my ($count) = @$arr_ref;
print "$count\n";
$count++;
my $sql = "update counter_table set count = ?";
my $sth = $dbh->prepare($sql);
$sth->bind_param(1, $count);
my $rows = $sth->execute;

# 正常時は、ここで 1行だけ更新されるものとする。
if ( $rows != 1 ){
die "更新行数が異常!";
}
}
}
#########################################################


実行されるたび 1ずつ増える。ただそれだけです・・・
初めてMySQLとPerlの連帯でプログラムが書けました(前編)
複雑すぎる!! いや、体系だったまとまった資料をネットから拾ってくるのに時間がかかりすぎるのが問題である。とりあえずMySQLをFedora5にインストールするところから始まります。1コマンド打つたびに独り言が入ってます。

参考にさせていただいたページ:-------------------
http://tech.bayashi.net/pdmemo/perl_dbi_mysql.html
http://fedorasrv.com/mysql.shtml
http://www.develop-memo.com/database/mysql/mysqloperate.html
http://www.fedoraz.com/index.php?itemid=13

http://ash.jp/db/dbi_dbd.htm
http://hata.cc/msql/psql2.htm
http://www.mitene.or.jp/~rnk/TIPS_ORCL_UPDATE.htm
http://68user.blog27.fc2.com/blog-entry-3.html
http://www.rfs.jp/sb/perl/dbi/06.html
------------------------------------------------

それでは、MySQLをインストールしたときの記録です。

# yum -y install mysql-server

MySQLと同時にPerlのデータベースまわりに必要なモジュールもインストールされたもよう。

# service mysqld start もしくは # /etc/rc.d/init.d/mysqld start

MySQLといっても所詮クライアント・サーバモデル。 デーモンの起動。
しかし この2通りの起動のさせ方の違いがわからん。

# mysql -u root

mysqlコマンドでMySQLに管理が移ります。
ftpコマンドやtelnetコマンドもしくはperl -MCPAN -e shellみたいにコマンドプロンプトが mysql> に変わります。

ftp なら ftp>
telnet なら telnet> 
perl -MCPAN -e shell なら cpan> ですね。

そうか、こいつらって クライアント なんだ。クライアントのコマンドプロンプトがでてるんだぁああ!今、気づいた。

mysql> set password for root@localhost=password('rootdayo');

かなりトリッキーなパスワードの設定の仕方のように思える。
root@localhostが左辺値で、password( )関数に引数'ルートのパスワード'を与えて代入ってことだろうか。

mysql> exit

あんまり意味なく1回出る。

# mysql -u root -p
Enter password: rootdayo

パスワードの認証に成功して、またMySQLの管理下に潜伏成功!!コマンドプロンプトは mysql> に

mysql> grant all privileges on counterdb.* to nakanishi@localhost identified by 'nakanishidayo';

なげーぇ あまりに長い!! なんだこの命令は!!!???

grant は 「与える」
privilege は 「特権」 っていう意味の英単語なのかぁああ そんなの知らねぇよ 初耳だよ。
しかも、話はまだ終わってなくて この1行で 
●ユーザー
●ユーザーのパスワード
●データーベース
の3つを同時に登録かよ!!!! Linuxなら
●useradd
●userpasswd
●mkdir
の3ステップいるところなんじゃないだろうかぁああああ!!!!これがデータベース文化なのかあああ!!!!

mysql> exit

ここで おもむろに1回出る!!


# mysql -u nakanishi -p
Enter password: nakanishidayo

nakanishiとしてmysqlクライアントに入りなおしだ!!!!!!(意味なく興奮してきた)

mysql> create database counterdb;

おいおい、ここでデータベース作るんかい!!!!!
ってことは さっきは3つ同時に登録したわけじゃなくて ユーザーとユーザーのパスワードを登録してただけかい!!!!で、まだできてないデータベースの権限の話を俺はmysqlクライアントを通してmysqlサーバとしてたってわけ??なんて未来の話を聞いてくれるヤツなんだ。データベースがありませんて文句言わないのか!!!

mysql> use counterdb

つくったデータベースに移動だ!! ;(セミコロン)はここはいらんのか!!

mysql> create table counter_table(count int(100));

カウントするためのテーブルを作ろう!! このアプリケーション、データベース使う必要あるの?というツッコミはまったく受け入れられない。こんなに設定苦労してんだから、こっちとらぁ。

mysql> show tables;
+---------------------+
| Tables_in_counterdb |
+---------------------+
| counter_table |
+---------------------+

とりあえず ちゃんとできてるみたいだ うわーい。

mysql> select * from counter_table;

テーブルの中身を覗いてみようと思ったけど Empty set (0.00 sec) と返された。空だってさ。
うん、知ってるよ。彼はなんと0秒でこれを判断したんだ!!!!


mysql> insert into counter_table values(0);

とりあえずだ、とりあえず、カウンターなんだから初期値0じゃないだろうか!よしテーブル入れとけ!!

mysql> select * from counter_table;
+-------+
| count |
+-------+
| 0 |
+-------+

おしゃ 入ったぜーーーー!!!!

mysql> exit

もうやることないはず、出とこう。早くPerlをいじりたいぜ。

>>後編へ
Apacheの動作についての考察
<<前へ
ここでは、Apacheの動作について考察を行いました。
CGIはいったいどのユーザーにより実行されているんだろう?といった疑問から実験をし、確かめてみました。つまり、Apacheとアクセス権限についての考察です。

suEXECが大きく絡んできています。本記事は間違いを含んでいるかもしれません。ここはセキュリティ上大きな問題になりますので、正確なところはhttp://httpd.apache.org/docs/2.0/ja/suexec.htmlなどの資料にあたってください。
あくまでビンゴ中西の実験による考察(推測)をお届します。


さて、Apacheの設定を終えた現在、
3)230行目、231行目(デフォルトのまま)
User apache
Group apache

となっています。ひとつ疑問が浮かびました。 apacheなんていうユーザーを作った覚えがない。ユーザーは useradd というコマンドにより行いますが、apacheなんていうユーザーを作った記憶がありません。なのにこんな設定でよいのでしょうか? apacheというユーザーがいるのか確認してみる必要がありそうです。

# cat /etc/passwd | grep apache


とパスワードのファイルを見てみることにしました。すると、
apache:x:48:48:Apache:/var/www:/sbin/nologin

と表示されました。確かに apacheがユーザーとして存在するようです。

ここで、ルートになった状態で
# su apache
とapacheになってみようと試みましたが、
This account is currently not available.
と表示されてしまい。ユーザをスイッチ(変更)できませんでした。
su はスイッチユーザーの略です。スーパーユーザーの略ではありませんので注意してください!

あれー おかしいな変更できひんやん。

と思いましたが、もう一度パスワードファイルを覗いたときの結果を見てみますと
apache:x:48:48:Apache:/var/www:/sbin/nologin

となっています。 最後に nologin とありますから、シェルによるログインはできないようです。


ちょっとここで、話をLinuxのアクセス権限に移します。Linuxには

●所有者(オーナー)
●グループ
●その他

という3つの属性に対してファイルもしくはディレクトリの権限を決めます。
ls -ld /home/nakanishi/public_html/
で /home/nakanishi/public_html/ ディレクトリのアクセス権限を調べてみますと、
drwxr-xr-x nakanishi nakanishi
でした。

/home/nakanishiディレクトリの所有者はnakanishi で グループもnakanishiであることを示しています。
所有者への権限はrwx グループへの権限はr-x その他への権限はr-xですね。よってユーザーapacheがこのディレクトリにアクセスする場合は
その他の権限で見ることになりますから r-x で「読み込み」と「実行権限」の2つが与えられていることなります。ですから、ブラウザからこのディレクトリはアクセス可能です。ブラウザからのアクセスはすべてapacheユーザーが請け負っていると考えることができます(自分で簡単なHTTPサーバを書いてみると理解の助けになるでしょう)。多くの場合、apacheユーザーは「その他」に与えられた権限を持っていると考えることができます。

それではここで、http://bingobingobingo.blog49.fc2.com/blog-entry-362.htmlのアップローダを考えてみます。

これはファイルを任意のディレクトリに書き込め(アップロード)にいけますが、もしこのアップローダの所有者が nakanishi だったとしましょう。
すると、
drwxrwx--- some_user nakanishi
となっているディレクトリに対してファイルを書き込み(アップロード)できてしまいます。

えーぇ!ブラウザからの処理は apacheユーザー が請け負っているはずではぁああ!!! 

となりますが、CGIは実行ファイルです。Apacheは実行ファイルを実行するときに suEXEC を発動させます。たぶん「Switch User Execute」の略でしょう ユーザーをスイッチしてから実行ファイルを実行します。誰にスイッチするのでしょうか? 実行ファイルの所有者です。このアップローダの所有者がnakanishiだった場合、
nakanishiに与えられた権限はすべて行えてしまいます。ですから、
drwxrwx--- some_user nakanishi
となっているディレクトリは「グループ」であるnakanishiに「書き込み」「実行」を与えていますので、ここにブラウザを通してファイルを書き込むことが可能となります。このディレクトリは外部に見せたくないからと apache に対してなんの権限も与えなかったとしても、apache は ユーザーを変身できますので、このようなことになります。注意した方がよいでしょう。


まとめ:
Apacheはrootユーザーにより起動されるが、apacheユーザーが仕事を請け負っています。この apacheユーザーが実行ファイルを扱うとき、その実行ファイルの所有者に変身します。これによりapacheユーザーには与えられていない処理も可能になります。詳しいことはhttp://httpd.apache.org/docs/2.0/ja/suexec.htmlなどをあたってください。
CGIの動作確認
<<前へ
CGIのテスト用に以下のファイルを用意しました。コピペして使ってください。

ファイル名:test.cgi
#!/usr/bin/perl -w
use strict;
use CGI;

my $cgi = new CGI;

print $cgi->header(-charset=>'utf-8');
print $cgi->start_html(-lang=>'ja', -encoding=>'utf-8', -title=>'test.cgi');

print "CGI無事に成功しました!!!<br />";

print $cgi->end_html;
#end



CGIを動かせるディレクトリでこのファイルを作ったならばアクセス権を755にしなければなりません。
# chmod 755 test.cgi

としてください。

Perlで書かれていますので Perlの文法が正しいかチェックします。
# perl -wc test.cgi

syntax OK なら、問題ありません。

念のためコマンドプロンプトから実行しておく方がよいでしょう。
# ./test.cgi

以下のように表示されれば成功です。
Content-Type: text/html; charset=utf-8

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<title>test.cgi</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
CGI無事に成功しました!!!<br />
</body>
</html>


ではブラウザから見てみましょう。これだけチェックしてもエラーになることがあります。



もし、CGIを実行してみて Internal Server Error が出た場合はApacheのエラーログを参照するのが有効です。

# locate httpd | grep error

とコマンドプロンプトで実行すると、エラー用のログファイルを発見できますので、
# cat -n /var/log/httpd/error_log

とファイルを見てみると有益な情報が得られます。(今回それらしいファイルerror_logを発見できました)



なお、suexecというApacheの機能により
suexec policy violation: see suexec log for more details
というエラーをerror_logファイル内に見ることがあるかもしれません。そんなときは

# find / -name "*suexec*"

などすると /var/log/httpd/suexec.log が見つかりますので、これを見てみます。
すると、directory is writable by others: というエラーメッセージが見つかりました。 これは、ディレクトリが「others」より書き込まれます。と言っているようです。
見てみますと test.cgi を含んでいるディレクトリの権限が

drwxrwxr-x

となっていました。グループに w がありますのでグループに書き込み権限を与えてしまっています。えー「その他」には書き込み権限与えてないやん。と思いつつも、

# chmod 755 目的のディレクトリ


とすると動きました!!! いやー実はこのエラーで2時間以上苦しんだんです・・・

参考ページがなければ解決はなかったでしょう・・・

参考ページ:http://blog.hitokoto.org/2006/02/cgi_1.php

>>次へ
具体的な設定例 (目標 CGIを可能にするなど)
<<前へ
それでは具体的な設定例について書きます。環境はFedora5です。
ほぼデフォルトのままで変更点は4項目しかありません。

コマンドプロンプトでの
# rpm -qa | grep httpd

の結果、 httpd-2.2.0-5.1.2 となりましたのでバージョンは2.2.0-5.1.2でいいのかなぁ。。。

行番号はApacheのバージョンなどにより微妙に変化しますので参考までにどうぞ。
なお、デフォルトのまま記載しているものも多いです。

設定目標:----------------------------------------------
ユーザー毎のpublic_htmlディレクトリを公開ディレクトリとします。
ユーザーnakanishiを例にとった場合、
Linux環境下/home/nakanishi/public_html/を公開ディレクトリとします。
ブラウザからは、http://your_host.co.jp/~nakanishi/でアクセスできるものとします。
CGIは基本的にどのディレクトリでも動くようにします。
---------------------------------------------------------

1)44行目(デフォルトのまま)
ServerTokens OS

2)57行目(デフォルトのまま)
ServerRoot "/etc/httpd"

3)230行目、231行目(デフォルトのまま)
User apache
Group apache

4)250行目(デフォルトのまま)
ServerAdmin root@localhost

5)280行目(デフォルトのまま)
DocumentRoot "/var/www/html"

6)290行目~293行目と305行目~334行目(!!CGIを実行可能に!!)
長いので変更点のみ記載
    Options FollowSymLinks ExecCGI
 と
    Options Indexes FollowSymLinks ExecCGI

両者、Optionsディレクティブに ExecCGI を書き足しました。
(そこ以外はデフォルトのまま)
なお、
Options All
とする荒技(?)もあります。
余談ですが、-ExecCGI とマイナスをつけるとCGIを実行できなくなります。これに対して +ExecCGI とプラスを付ける場合がありますが、これは ExecCGI とプラスを付けなかった場合と同じ意味になります。

7)348行目~363行目(デフォルトのまま)
<IfModule mod_userdir.c>
#
# UserDir is disabled by default since it can confirm the presence
# of a username on the system (depending on home directory
# permissions).
#
#UserDir disable

#
# To enable requests to /~user/ to serve the user's public_html
# directory, remove the "UserDir disable" line above, and uncomment
# the following line instead:
#
UserDir public_html

</IfModule>

8)369行目~380行目(!!CGIを実行可能に!!)
やはり変更点のみ記載
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec ExecCGI

ExecCGIを書き加えました。同様に
Options All
の技もあり。

9)390行目(!!ちょっと変更!!)
DirectoryIndex index.html index.html.var index.cgi

index.cgiを加えました。

10)523行目(デフォルトのまま)
ServerSignature On

11)538行目や563行目などなど(デフォルトのまま)
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
他の行は略します

12)569行目~574行目(デフォルトのままで本当によいのか・・・)
デフォルトのままなので飛ばします
Options None
の部分がNoneでいいのか気がかりなのですが・・・

13)734行目(デフォルトのまま)
LanguagePriority en ca cs da de el eo es et fr he hr it ja 以下略

14)750行目(デフォルトのまま)
AddDefaultCharset UTF-8

15)781行目(!!CGIを実行可能に!!)
#AddHandler cgi-script .cgi → AddHandler cgi-script .cgi

コメントをはずしました。


最後に設定ファイルの文法が間違っていないかコマンドプロンプトから
# httpd -t
とチェックして OKがでれば、
# /etc/rc.d/init.d/httpd restart
でリスタートさせます。

次の記事は、CGIの動作確認、およびエラーの発見の仕方についてです。

>>次へ
Apacheにおいて知っておいたほうがよいであろう設定項目
つわー もう多くてわけがわからねー 初学者にとって知っておいたほうがよいだろうっていうApacheのディレクティブってなんなんだ~!
というわけで勝手に初学者である私、ビンゴ中西が必要そうなディレクティブをピックアップ!!!!

1)
ServerTokens

クライアントに返信するサーバ応答ヘッダに含める情報を指定します。
ServerTokens Full
だと全情報を返します。セキュリティが気になる方にはこのディレクティブ!!


2)
ServerRoot

Apacheの設定ファイルなどが入っている根っことなるディレクトリを示します。
デフォルトで
ServerRoot "/etc/httpd"
となっていましたが、確かに /etc/httpd/conf/httpd.conf に設定ファイルがありました。


3)
User と Group

HTTPデーモンが誰によって動かされているかを示す。
User nakanishi
Group nakanishi

だと、ユーザーnakanishiでグループもnakanishiであることを示している(はず)。


4)
ServerAdmin

Webサーバとして世界に公開するなら気にしたほうがよいディレクティブ。僕は公開するつもりはないので、そのままにします。


5)
DocumentRoot

あれ、さっき載ってなかったけ!?ってそれは2)ServerRootだ!!!!
このディレクティブはかなり重要です。
DocumentRoot "/var/www/html"
となってたとしましょう。するとLinux環境下での /var/www/html があなたのWebサーバでのルートと見なされます。
つまり例えば、
http://your_host.co.jp/
とあなたのサーバがアクセスされた場合には、
Linux環境下の/var/www/html がアクセスされたことになります。


6)
<Directory />
Options
AllowOverride
</Directory>
 と
<Directory "/var/www/html">
Options
AllowOverride
Order
Allow
</Directory>

そのディレクトリに対しての細かい設定ができます。パスはLinux環境下でのパスです。
ルートディレクトリとDocumentRootで指定したディレクトリについては設定しておいた方がよさそうです。


7)
<IfModule mod_userdir.c>
UserDir
</IfModule>

UserDir public_html
としておくと、ユーザ毎にあるpublic_htmlディレクトリを公開できるようになるようです。
つまり、あなたのLinuxマシーンにユーザーnakanishiがいたとすると、
http://your_host.co.jp/~nakanishi/ で、
Linux環境下の /home/nakanishi/public_html にアクセスできます。


8)
<Directory /home/*/public_html>
AllowOverride
Options
<Limit GET POST OPTIONS>
Order
Allow
</Limit>
<LimitExcept GET POST OPTIONS>
Order
Deny
</LimitExcept>
</Directory>

ユーザ毎の公開ディレクトリの細かい設定ができます。7)の項目でUserDir public_htmlとしているなら、重要になってくるでしょう。


9)
DirectoryIndex

普通、ファイル名を指定しないとアクセスできませんが、index.htmlなどのファイルは指定しなくても見れます。それはデフォルトでこのディレクティブにより設定されているからです。
え、どういうこと?? ってなりますから具体例をしまします。
5)の項目で
DocumentRoot "/var/www/html"
とし、
DirectoryIndex index.html
としたとしましょう。
そして、/var/www/htmlディレクトリに index.html というファイルを作ります。 
ここでhttp://your_host.co.jp/とあなたのサーバにアクセスするとファイル名を指定していないはずなのに先ほど作ったindex.htmlがアクセスされます。
つまり、ファイル名を指定しなかった場合に参照(アクセス)されるファイル名を示します。


10)
ServerSignature

セキュリティに気を払う人は知っておいた方がよいような気がする・・・・


11)
Alias
 と 
ScriptAlias

DocumentRootと同じ発想で考えればよいと思う。
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
だと、
http://your_host.co.jp/cgi-bin/ でアクセスされた場合
Linux環境下の /var/www/cgi-bin/ がアクセスされたことになる。


12)
<Directory "/var/www/cgi-bin">
AllowOverride
Options
Order
Allow
</Directory>

11)のScriptAliasで指定した先のディレクトリの設定をしておきたいのが人情というものだろう。


13)
LanguagePriority

あなたのWebサーバのファイルの言語を設定する場所。日本人的には
LanguagePriority ja
となってさえいればよいような気がするが、初期状態のままにしておこう。jaを設定の先頭に持ってくる管理者もいる。


14)
AddDefaultCharset

文字コードの設定だ。CGIスクリプト作成時に文字コードが違ったりして泣いちゃいそうになるかもしれないのでCGI作成者は知っておいた方がよいかも。


15)
AddHandler

うーむ。よくわからないのだが、CGIを使いたいのなら、
AddHandler cgi-script .cgi
とすべきであるようである。たいてい始めはコメントアウトされてあるので注意が必要である。
これを書かない場合、拡張子.cgiのファイルも text/plain と見なされて実行されないようである。このディレクティブでちゃんと指定してあげれば拡張子.cgiが実行されるようだ。

>>次へ
ブリーフケース アップローダも実装
ファイルのアップローダもできたんで、ソースだけ載せちゃいます。
いやー 苦労した。


注意)以下のソースを参考にしてセキュリティホールになったとしても責任はとれませんのでご了承ください。

ファイル名:check_list2.cgi
#!/usr/bin/perl -w
use strict;
use CGI;

my $cgi = new CGI;
my $dir = $cgi->param('dir');
if($dir eq ""){ $dir = "/home/naka/public_html/"; }

print $cgi->header(-charset=>'euc-jp');
print $cgi->start_html(-lang=>'ja', -encoding=>'euc-jp', -title=>'check_list2.cgi');

my @lists;
if( -d $dir ){
chdir "$dir";
@lists = `ls $dir`;
foreach(@lists){
chomp $_;
}
print <<"HTML_VIEW";
<form action="./up_loader.cgi" method="post" enctype="multipart/form-data">
<p><input type="file" name="filename" /></p>
<input type="hidden" name="dir" value="$dir" />

<p>
<input type="submit" value="送信" />
<input type="reset" value="リセット" />
</p>
</form>
<p>今は$dirにいます</p>
HTML_VIEW
}

foreach my $list(@lists){
if( -d $list ){
my $next_query = $dir . $list . "/";
print "<a href=\"./check_list2.cgi?dir=$next_query\">";
print "<img alt=\"dir.gif\" border=\"0\" src=\"./dir.gif\" />";
print "$list";
print "</a><br />\n";
}elsif( -f $list ){
$dir =~ m|(/home/naka/public_html/)(.*)|;
my $next_query = "/~naka/" . $2 . $list;
print "<a href=\"$next_query\">";
print "<img alt=\"file.gif\" border=\"0\" src=\"./file.gif\" />";
print "ファイル $list";
print "</a><br />\n";
}
}

print $cgi->end_html;
#end



ファイル名:up_loader.cgi
#!/usr/bin/perl -w

# モジュール読み込み
use strict;
use CGI;

# POSTサイズの上限
$CGI::POST_MAX = 1024 * 1024 * 50; # 50MB

my $query = new CGI;
my $dir = $query->param('dir');
if($dir eq ""){ $dir = "/home/naka/public_html/"; }

# 送られてきたデータを処理する -----------------
# ファイル取得
my $FH = $query->upload('filename');

# エラーチェック
if ($query->cgi_error) {
my $err = $query->cgi_error;
error("$err") if ($err);
}

error("File transfer error.") unless (defined($FH));

# MIMEタイプ取得
my $mimetype = $query->uploadInfo($FH)->{'Content-Type'};

$FH =~ m/([\d\w\.]*?)$/;
my $file = $1;

# ファイル保存 ---------------------------------
my ($buffer);
my $full_path = $dir . $file;
open (OUT, ">$full_path") || error("uooooo can't open $full_path");
binmode (OUT);
while(read($FH, $buffer, 1024)){
print OUT $buffer;
}
close (OUT);
close ($FH) if ($CGI::OS ne 'UNIX'); # Windowsプラットフォーム用
chmod (0666, "$full_path");


# HTML出力 -------------------------------------
print $query->header(-charset=>'euc-jp'),
$query->start_html(-lang=>'ja', -encoding=>'euc-jp', -title=>'up_loader.cgi');

print <<"HTML_VIEW";
<h1>ファイルアップロード</h1>
<p>ファイルのアップロードが完了しました。</p>
<ul>
<li>フルパス : $full_path</li>
<li>ファイル名: $file</li>
<li>MIMEタイプ: $mimetype</li>
</ul>
<a href="./check_list2.cgi">トップへ戻る</a>
HTML_VIEW

print $query->end_html;
exit;

# エラー出力 -----------------------------------
sub error {
my $mes = shift;

print $query->header(-charset=>'euc-jp'),
$query->start_html(-lang=>'ja', -encoding=>'euc-jp', -title=>'up_loder.cgi');

print <<"HTML_VIEW";
<h1>ERROR</h1>
<p>$mes</p>
HTML_VIEW

print $query->end_html;
exit;
}
__END__



あ、ディレクトリ(フォルダ)を新しく作れないことに気づいた。現状だと、ファイルのアップロードしかできない。

アップロードの参考資料はもちろん
http://www.ss.iij4u.or.jp/~somali/web/_perl_upload.htmlを参考とさせていただきました。
ブリーフケース ダウンロードのみ実装
「Yahoo!ブリーフケース」というYahoo!のサービスがあります。
これは、ファイルを自分のパソコンではなくて、ネットの向こうに保存しておけるという便利なものです。

これをちょっと機能は劣りますが真似してみました。まだ完成形ではないので、URLは公開しません。

Yahoo!ブリーフケースはもちろんファイルの保存をできるわけなんですが、僕が今回作ったのはダウンロードのみ行えるようになっています。

ソースは以下の通りです。
まあ、これは ろんごんサーバが商用ではないので、ある程度ゆるめの設定にしてくれているから可能になったように思います。

注意)以下のソースを参考にしてセキュリティホールになったとしても責任はとれませんのでご了承ください。

ファイル名:check_list.cgi
#!/usr/bin/perl -w
use strict;
use CGI;

my $cgi = new CGI;
my $dir = $cgi->param('dir');
if($dir eq ""){ $dir = "/home/naka/public_html/"; }

print $cgi->header(-charset=>'euc-jp');
print $cgi->start_html(-lang=>'ja', -encoding=>'euc-jp', -title=>'check_list.cgi');

my @lists;
if( -d $dir ){
chdir "$dir";
@lists = `ls $dir`;
foreach(@lists){
chomp $_;
}
}

foreach my $list(@lists){
if( -d $list ){
my $next_query = $dir . $list . "/";
print "<a href=\"./check_list.cgi?dir=$next_query\">";
print "<img alt=\"dir.gif\" border=\"0\" src=\"./dir.gif\" />";
print "$list";
print "</a><br />\n";
}elsif( -f $list ){
$dir =~ m|(/home/naka/public_html/)(.*)|;
my $next_query = "/~naka/" . $2 . $list;
print "<a href=\"$next_query\">";
print "<img alt=\"file.gif\" border=\"0\" src=\"./file.gif\" />";
print "ファイル $list";
print "</a><br />\n";
}
}

print $cgi->end_html;
#end



説明:
my $dir = $cgi->param('dir');
if($dir eq ""){ $dir = "/home/naka/public_html/"; }

クエリーを処理しています。クエリーは1つしか受け取っていません。クエリーにはLinux環境下でのフルパスが入るように設計しました。

ApacheとLinuxではディレクトリの見え方が違っています(Document Rootの兼ね合い)ので、初期位置として /home/naka/public_html/ を教えています。 なお、始めてこのCGIを起動した場合はクエリーは空です。

my @lists;
if( -d $dir ){
chdir "$dir";
@lists = `ls $dir`;
foreach(@lists){
chomp $_;
}
}

念のためクエリーがディレクトリであるか調べています。ディレクトリなら、Linux環境的にカレントディレクトリを移動します(chdir "$dir";)。

@lists = `ls $dir`; によって、カレントディレクトリ下のディレクトリ名およびファイル名を@listsに代入します。 改行コードがはいってたので、chompもしました。


最後に、foreach my $list(@lists){ }の中についてです。
if( -d $list ){
my $next_query = $dir . $list . "/";
print "<a href=\"./check_list.cgi?dir=$next_query\">";
print "<img alt=\"dir.gif\" border=\"0\" src=\"./dir.gif\" />";
print "$list";
print "</a><br />\n";
}

-d $list でディレクトリであるかチェックできます。よってこのif文はディレクトリに対しての処理です。ディレクトリならもう一度 ls したいですよね。 ですからクエリーに次のディレクトリにあたるフルパスを与えてこのCGI(check_list.cgi)を呼び出しています。 $next_query が次のクエリーになります。

elsif( -f $list ){
$dir =~ m|(/home/naka/public_html/)(.*)|;
my $next_query = "/~naka/" . $2 . $list;
print "<a href=\"$next_query\">";
print "<img alt=\"file.gif\" border=\"0\" src=\"./file.gif\" />";
print "ファイル $list";
print "</a><br />\n";
}

-f $list はファイルであるか確認できます。ですから、これらの行はファイルだった場合に行われる処理です。 ファイルであるならもうCGIを呼び出す必要はありません。ただ、リンクを素直に飛べばよいだけです。しかし、少し注意がいります。このスクリプトではLinux環境下でのパスを扱ってきましたので、Apacheから見たパスに変換しています。
なんも考えないでパスワード認証 CGI
いま、ユーザ名とパスワードを入力してもらいログイン後はそのユーザが閲覧できるページのみ閲覧してもらうというシステムを考え中です。

パスワード認証して1ページ分だけ遷移できるものを作りました。

ココ↓です
http://ideon.dyndns.org/~naka/from_blog_cgi/AUTH_TEST/no_idea_check_password.html
ココ↑です


ログイン後にもっといろんなページを移動(遷移)したいならセッション管理の必要性があると思います。


ファイル名:no_idea_check_password.html
<?xml version="1.0" encoding="euc-jp"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<title>認証ページ</title>
</head>
<body>
<h1>認証します</h1>

<form action="./no_idea_check_password.cgi" method="post">
ユーザ名   :<input type="text" name="user_name" size="20"> ← bingo<br /><br />
PASSWORD:<input type="password" name="password" size="20"> ← nakanishi<br />
<input type="submit" value=" 認証する ">
</form>

</body>
</html>



ファイル名:no_idea_check_password.cgi
#!/usr/bin/perl -w

use strict;
use CGI;

my %authentication = ("bingo" => "nakanishi");

# オブジェクト作成
my $query = new CGI;

# パラメータ取得
my $user_name = $query->param('user_name');
my $password = $query->param('password');

print $query->header(-type=>'text/html', -charset=>'euc-jp'),
$query->start_html(-lang=>'ja', -encoding=>'euc-jp', -title=>'no_idea_check_password.cgi');

if($password eq ""){ print "パスワードがはいってません"; print $query->end_html; exit; }
if($password eq $authentication{"$user_name"}){
print <<"HTML_VIEW";
<h1>認証成功(^^)v</h1>
<ul>
<li>ユーザ名:$user_name</li>
<li>PASSWORD:$password</li>
</ul>
HTML_VIEW
}else{
print <<"HTML_VIEW";
<h1>認証失敗(><)</h1>
あなたは、いったい誰ですか?
HTML_VIEW
}

print $query->end_html;
exit;



ユーザとパスワードをどのように引いているかなんですが、
my %authentication = ("bingo" => "nakanishi");

とハッシュによりスクリプトの中に直に埋め込んでいます。
今日得たLinux全般に役に立ちそうな知識
Fedora5を用いて proftpd(FTPサーバのひとつ)をほぼ丸1日かけてインストールできた。

とりあえず、今日得たLinux全般に役に立ちそうな知識を載せる(Fedoraに特化した内容もあるかもしれないが・・・)。



1) 設定ファイルの文法をチェックしてくるアプリケーションとそうでないものがある。

例:proftpdにはチェック機能あり
    proftpd -t /etc/proftpd/proftpd.conf


2) /var/log/messages というファイルのログをまず見に行くのが吉。 

使用例:cat -n /var/log/messages


3) findを使っていこう。やっぱり locate だと変更が反映されてないときがある。 

使用例:find / -name "*proftp*"


4) デーモンの起動の方法には 
   
    1. スタンドアローン【stand alone】 で起動
    2. xinetd もしくは inetd を用いて起動
  
   の2通りのやりかたがある。

スタンドアローンの起動の例: /etc/init.d/proftpd start
xinetdを用いた起動の例  : xinetdの設定をいじった後で、
                  /etc/rc.d/init.d/xinetd restart

さて、この2通りの方法であるが、デーモンの設定ファイルにどちらの方法で起動するのか明記しておかねばならない。

例:proftpd.conf
スタンドアローンの場合
ServerType                     standalone

xinetdもしくはinetdを用いる場合
ServerType                      inetd

と記述する


5) netstatで、使用中のポートを調べる。

使用例:netstat -ap | grep ftp


6) /etc/hosts.deny と /etc/hosts.allow に注意を払おう。

例:hosts.allow に許可がないとアクセスできない


7) インストールしたアプリケーションの設定ファイルは /etc ディレクトリ下にできているのが普通。

例:/etc/proftpd.conf
あ、できた Web版 source2html
ソースをHTML形式に変換する perl2html.pl(source2html) を作ってきました。

今まで、

1)コマンドプロンプトから変換させたいファイルを引数として与える
2)Perl/Tkを用いてGUIで変換させたいファイルを選ぶ

の2種類作ってきましたが、これをWebでできるようにしてみました。

ココ↓です
>>http://ideon.dyndns.org/~naka/from_blog_cgi/2HTML/web_substitution.html
ココ↑です

参照から、変換させたいファイルを選んでもらえれば pre タグで囲まれたソースが表示されます。

以下、ソースです。

ファイル名:web_substitution.html
<?xml version="1.0" encoding="euc-jp"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<title>アップロード用フォーム</title>
</head>
<body>
<h1>アップロード用フォーム</h1>

<form action="web_substitution.cgi" method="post" enctype="multipart/form-data">
<p><input type="file" name="filename" /></p>
<p>
<input type="submit" value="送信" />
<input type="reset" value="リセット" />
</p>
</form>

</body>
</html>


ファイル名:web_substitution.cgi
#!/usr/bin/perl -w

# モジュール読み込み
use strict;
use Jcode;
use CGI;

$CGI::POST_MAX = 1024 * 1024 * 50; # 50MB

# オブジェクト作成
my $query = new CGI;

# ファイル取得
my $FH = $query->upload('filename');


# MIMEタイプ取得
my $mimetype = $query->uploadInfo($FH)->{'Content-Type'};

binmode $FH;
my @lines = <$FH>;
foreach my $line (@lines){
$line = Jcode->new($line)->euc;
}

# HTML出力
print $query->header(-type=>'text/html', -charset=>'euc-jp'),
$query->start_html(-lang=>'ja', -encoding=>'euc-jp', -title=>'web_substitution.cgi');

print <<"HTML_VIEW";
<h1>ファイルアップロード</h1>
<ul>
<li>ファイル名:$FH</li>
<li>MIMEタイプ:$mimetype</li>
</ul>
HTML_VIEW

print "<pre>";
print "&lt;pre&gt;";
foreach my $line (@lines){
$line =~ s/&/&amp;amp;/g; # アンパサンド
$line =~ s/"/&amp;quot;/g; # 括弧のエスケープ
#$line =~ s/ /&amp;nbsp;/g; # 空白(使わず)
$line =~ s/\t/ /g;
#$line =~ s/\,/&amp;#044;/g;  # カンマのエスケープ(使わず)
$line =~ s/</&amp;lt;/g; # タグの排除
$line =~ s/>/&amp;gt;/g; # タグの排除

print "$line";
}
print "&lt;/pre&gt;";
print "</pre>";

print $query->end_html;
exit;




参考資料:
http://www.ss.iij4u.or.jp/~somali/web/_perl_upload.html
http://www.melma.com/backnumber_14785_1152969/


追記:
文字コードで結構苦しんで、Jcodeに落ち着いたんですが、UTF-8のBOMつきファイルを受け取った場合は、BOMの部分が?になっちゃうみたいですねぇ。。。
イベント多いなぁ
Kansai.pm 第2回Perl翻訳フェスタ
日程:2007年2月24日(土) 10:00~22:00(途中参加・途中退室自由)



第3回LiveCoding
日程:2007年02月24日(土)



YAPC::Asia 2007 Tokyo
日時:2007/04/04-05 (水-木) 9:30-18:00




2月24日に二つも!!!!

でもって、4月4日、5日って平日じゃない!!?
せっかく東京にいるのに(というか住みだす)、この日会社どうなってるの?
slコマンド経験してみましたw
Linuxで ls と打とうして sl って間違って打っちゃったら汽車が走ったよ おい!! というコマンドslを試しました。


汽車(蒸気機関車) 英訳:Steam Locomotive
なるほど SL ね!!っていうコマンドらしいです。


まあ、ls を sl と打ち間違えたことはないですが・・・(というかそもそもLinuxのコマンド打ち間違えるのって怖すぎる) slコマンドを体験するための参考ページはこちらです>>http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/

さてさて、では 僕がLinux上でどのようにslコマンドをインストール(というかコンパイルしたか載せます) 

yum でいけるかと思ったら失敗しました。でも、あきらめない。ソースがいるんだと思い。

# wget http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/sl/sl.tar

sl.tar をダウンロード。

# tar xvf sl.tar

拡張子が .tar ですから、アーカイブファイルで圧縮なし!
ということはtarコマンドに与えるオプションは xvf だ!! 

x アーカイブファイルの展開
v アーカイブ処理したファイルの一覧表示
f アーカイブファイルの名前を指定


要は xで展開であることを示して、vで展開されたファイルの表示ですね。fいらないんじゃないか?と思いはずしてみたら無理でしたね。fがないと展開したいアーカイブファイルを指定できないんですね。

# cd sl

slディレクトリに移動

# make

コンパイルですね。

# sl
bash: sl: command not found

あれ? ないじゃない?? と一瞬思ったが!
カレントディレクトリにパス通してないじゃないか!

# ./sl

おお、起動した!!

# cat README

READMEがあったので読んでみた。
オプションが載っていたので、それぞれ試してみた。

といった流れでした。 ソース見てみましたがやっぱりcursesが使われてましたね。


curses というとあれですね。僕のPKゲームですねそこで、

# wget http://ideon.dyndns.org/~naka/saigo_kadai/saigo.exe

これで、実行ファイルをいきなりGET

# chmod 755 saigo.exe

実行しようとしたけど 権限がなかったので chmod で付与。

# ./saigo.exe

よし、遊べたぞ!! なお、文字コードはeuc-jpでお願いします。
すごいやん Perl/Tk
すごいよ Perl/Tk

えー なんですか? それは? ってなるんですが、

Tkと呼ばれるものを用いるとPerlでGUIプログラム(つまり窓プログラムもといウインドウプログラム)が簡単に書けます。

そこで、以前僕が作っていた perl2html.pl というプログラムをGUIで、できるようにしてみました。これは、perlのソースをHTMLに変換するというプログラムでした(つまり < とか > を変換してくれる)。しかし、変換させたいファイルをプログラムの起動時に引数として与えるという使い勝手の悪いものでした(あ、実はソースならなんでもよくてPerl以外のファイルも変換してくれます)。

そこで
>>http://www.geocities.jp/m_hiroi/perl_tk/perltk07.html
を参考にさせていただいて、特に何も考えずにプログラムしても、ほらこの通り。

2HTML1.jpg



2HTML2.jpg



2HTML3.jpg


2HTML4.jpg


ほらこの通り < > などが実体参照に変換されて pre タグで囲まれました(^^)

あとはマウスで選択してブログになりなんなりに貼っつければOK

・・・

実は、Ctr+A でテキスト部を全部選択できなくなってしまったというオチがついてしまった・・・ だからコピペしたいなと思ったら全部をマウスで選択しないといけない・・・

Tkに用意されているbindメソッドと呼ばれるメソッドがキー入力の処理に使われているようなので、このメソッドを用いれば以上の問題は回避できるかもしれない・・・

P.S.
Windows環境で窓を作りたいなら GUI: Win32 なんていうモジュールもあるっぽい 詳しく調べてないけど。。。
Ruby勉強会@関西-14
Ruby勉強会@関西-14に行かせていただきました。

うん。行ってよかった。

「Ruby 初心者向けレッスン第11回」で じゃんけんプログラムを作りましたので載せます。

その前に、じゃんけんの勝敗を判定するアルゴリズムですが、
数学的にはおかしくなりますが


チョキ < グー < パー < チョキ < グー < パー
0 < 1 < 2 < 0 < 1 < 2


のように、グー・チョキ・パーを対応付けれることを大学1回生のとき習ったことを覚えていました。しかし、 どうやってif文に落とし込むか思いつかない・・・orz

ですが、グループ(I 班でした)でプログラミングということでしたから、天才的なお方に解答を思いついて頂きました(爆) まあ、どうなるのかはソースの方を見てもらうことにしましょう。

いやー まったく書けないと思ったんですが、TAの方が親切で ちゃんとじゃんけんプログラムを仕上げることができました(仕様に忠実ではないですがw)。ありがとうございます。 しかし、ちょっと長い間やりすぎてたかも(汗) うるさかったようでしたら ごめんなさい。


説明:
ruby janken.rb で起動

起動すると、
┌──────────────
│じゃんけんゲーム開始     
│>             
│               
└──────────────
とコマンドプロンプトのように 入力待ちになりますので、
G だと グー
H だと チョキ
P だと パー
を表しますので G H P のどれかを入力してください。
Q で 終了です。

なお 終了時点で勝率の計算をしていますが、一度も戦っていなかったりすると、0で割るのでエラーが発生したりしますが、そのあたりは考慮にいれておりません・・・

それでは ソースです。雰囲気だけでもつかんでください。って見本にしない方がいいと思いますが・・・・


require 'mathn'
puts 'じゃんけんゲーム開始'
win = 0
lose = 0

loop do
print "> "
human_hand = gets.chomp

if(human_hand == 'Q')
puts '終了します'
puts "あなたの勝率は#{win/(win+lose)*100}%です"
   puts 'さようなら'
break
end

computer = rand(3)
computer_hand={ 0 => 'H', 1 => 'G', 2 => 'P', }[computer]
puts "あなた#{human_hand} VS コンピュータ#{computer_hand}"
human={ 'H' => 0, 'G' => 1, 'P' => 2, }[human_hand]
puts '┌────────────────────────┐'


if((human+2)%3 == computer)
puts '│ v(^^)あなたの勝ちです(^^)v │'
win += 1
elsif ((human+1)%3 == computer)
puts '│ m(><)コンピュータの勝ちです(><)m │'
lose += 1
else
puts '│ !あいこ! │'
end

puts '└────────────────────────┘'

end




今回の開発で気づいたこと(教えていただいたこと)
●Rubyには ++ 演算子がない。 win++ とできないので win += 1
●print の中などで使われる #{ } の中にはRubyのコードが書ける
●ハッシュ{ 'H'=> 1 以下略 }[キー] という形でハッシュが使える(というか、ハッシュをよその言語でも使いこなせてなかったので使いどころがわかってうれしい)

とまあ こんなところでしょうか。
なお、今回は時間がなかったということからRubyの特徴であるオブジェクト指向は用いませんでした(ってソース見ればわかるか・・・)。
部屋を決めてきました
東の都の部屋を決めてきました。

就職活動で京の都から東の都まで毎週のように移動していたのだが、久しぶりに東の都へ。

私の就職活動には、ひとつゆずれないルールがありました

東の都に移動する必要があった場合に交通費が出ない会社は受けない!

というものでした。 あんた、そんなお金あるわけないでしょーーー!!! というものです。


しかし、今回 実費で新幹線乗りました・・・・・

一説によると Officious~(「お節介な~」の意らしい)
となってますが、住むところに関しては これっぽちもOfficiousでないので、泣きそうです(笑)

親が、自営業なものですから、そんな手当があるほうが恵まれてるんだとか思ってましたが(←すり込み?)

いや皆、普通に手当てついてるやんか!!
驚愕の格差を感じてしまった・・・・・・


ところで、10回以上東の都に移動してたはずなのに一度も富士山を見ることができなかったんですねぇ。 曇っていたせいか、はたまた、心に余裕がなかったせいか・・・・

しかし、今回 見れたよ フジヤマが!!!!!

超でけーーーー

070215_0837~01.jpg


写真ではお伝えすることができないくらいでかかった。
いやー びっくりするぐらい晴れてたから 車内では、軽い撮影大会が始まってたので僕も撮りましたw
Operaを導入してさらに floatの研究
私が、馬鹿だったAcid2に合格しているOperaを実験に使わなくては!!

実験6
float_test6.jpg


<div style="float:left;  width:100px; height:100px; background:#85B1E3; ">div001</div>
<div style=" width:50px; height:50px; background:#9EE385; ">div002</div>
<div style=" width:100px; height:100px; background:#E3D385; ">div003</div>
<div style=" width:100px; height:100px; background:#E38585; ">div004</div>



なんでだーーーー
一番目のdiv を float: left; にしたということは、下に続く要素が全部右に流れるんじゃないのかーーー!!??

つまり、

ビンゴ中西予想では、
  
div001 div002
div003
div004

なのだが・・・・

Opera と IE がそれらしい動きだが、 Firefoxにいたってはまったくわけがわからん。

浮かばれない曲者 float を超分析してみる
参考資料:
>>CSSでfloatを指定したボックスを含むボックスの背景が出なくなる件
>>floatは「回り込み」ではない

なるほど、floatの仕事は ただ浮かせるというモノらしい。
それと、なにやら流れがあって、その流れが断ち切れたりするらしい。

よくわからん・・・ 自分でいじればわかるだろうか・・・実験しました・・・


実験1
float_test1.jpg

<div style="             width:100px; height:100px; background:#85B1E3; ">div001</div>
<div style="float:right; width:50px; height:50px; background:#9EE385; ">div002</div>
<div style=" width:100px; height:100px; background:#E3D385; ">div003</div>
<div style=" width:100px; height:100px; background:#E38585; ">div004</div>



実験2
float_test2.jpg

<div style="             width:100px; height:100px; background:#85B1E3; ">div001</div>
<div style="float:left; width:50px; height:50px; background:#9EE385; ">div002</div>
<div style=" width:100px; height:100px; background:#E3D385; ">div003</div>
<div style=" width:100px; height:100px; background:#E38585; ">div004</div>



実験3
float_test3.jpg

<div style="float:left;  width:100px; height:100px; background:#85B1E3; ">div001</div>
<div style="float:left; width:50px; height:50px; background:#9EE385; ">div002</div>
<div style=" width:100px; height:100px; background:#E3D385; ">div003</div>
<div style=" width:100px; height:100px; background:#E38585; ">div004</div>



実験4
float_test4.jpg

<div style="float:left;  width:100px; height:100px; background:#85B1E3; ">div001</div>
<div style="float:left; width:50px; height:50px; background:#9EE385; ">div002</div>
<div style="clear:both; width:100px; height:100px; background:#E3D385; ">div003</div>
<div style=" width:100px; height:100px; background:#E38585; ">div004</div>



実験5
float_test5.jpg

<div style="float:left;  width:100px; height:100px; background:#85B1E3; ">div001</div>
<div style="float:left; width:50px; height:50px; background:#9EE385; ">div002</div>
<div style="clear:both; width:100px; height:100px; background:#E3D385; ">div003</div>
<div style="float:left; width:100px; height:100px; background:#E38585; ">div004</div>


頭が悪いせいか・・・ まったく理解できません・・・・・orz
どうやったら

div1 div2
div3 div4

って 横に並ぶんだ・・・

なお、実験につかったdivは、とてもわかりやすい説明の
>>5日で分かるスタイルシート・CSS講座
のソースを参照させていただきました。



さて、ここでアドバイスをいただきました。

div
span1 span2 br
span3 span4
/div

は、どうでしょうか? というものです・・・
divはブロックレベルなので改行されるのでうっとうしい、そこでインラインレベルであるspanを使おうじゃないか! というものです。

・・・・

しかし、 spanはインラインレベルなので width と height を設定できないという罠が・・・・ 
なんてどっちつかずなんだ・・・ orz

ちなみに spanでwidth と height を設定できちゃうというバグがIEにあるようです・・・・
プリプロセッサがダメならPerlで置換だ!!!零式
前回の記事の続きです。(もう飽きた?w)

あんまり パー璧でもなかったんで改良です。
今度は 引数に 1 を与えるとコメントアウトしてくれて 2 を与えるとそのコメントを除去してくれます。

さて、なにがパー璧じゃなかったかというと、
コメントアウトした後、もう一度以前のスクリプトを実行するとさらにコメントアウトされて /*/* */*/ みたいな構造になっちゃたわけですねぇ・・・・ ということで今回のスクリプトは 2回目以降はコメントアウトしないようにしました。

ちゃんと コメントアウトできるし、コメントアウトの除去もしてくれるし たぶん大丈夫のはず。

使い方:
perl tikan.pl

です:-)


さて正規表現ですが 否定[^ ]を使ったのと、( ) をエスケープしたのが初めてなので ちょい不安です。

                         tikan.pl と命名
###############################################################################
#!/usr/local/bin/perl
use strict;

my $commentout = shift @ARGV;
if($commentout == 1){
print "I add commentout\n";
}elsif($commentout == 2){
print "I remove commnetout\n";
}else{
print "1: add commnetout\n";
print "2: remove commnetout\n";
exit;
}


my @files = glob( '*.c *.cpp' );

foreach my $file (@files){
my $flag = 0;
my $new_file = "temp.c";

if($file =~ /.*\.(c|cpp)$/){
open(IN, "<$file");
my @lines = <IN>;
close(IN);

foreach my $line (@lines) {
if($commentout == 1){
if($line =~ s|([^/\*])(my_debugf\(.*?\);)([^\*/])|$1/*$2*/$3|g){
$flag = 1;
}
}elsif($commentout == 2){
if($line =~ s|/\*(my_debugf(.*?);)\*/|$1|g){
$flag = 1;
}
}
}

if( $flag ){
open(OUT, ">$new_file");
foreach(@lines){
print OUT $_;
}
close(OUT);

rename( $file, "$file.orig" );
rename( $new_file, $file );
}
}
}
###############################################################################



とまあ このようにプログラムがどのように改良されていくかを追った、そんなの開発ノートにつければいいんじゃないの的なブログでした。
プリプロセッサがダメならPerlで置換だ!!!改
前回の記事の続きです。

↓これで パー璧じゃないだろうか!!??
Cygwinが不要になったぜ!

                         tikan.pl と命名
#################################################################
#!/usr/local/bin/perl
use strict;

my @files = glob( '*.c *.cpp' );

foreach my $file (@files){
my $flag = 0;
my $new_file = "temp.c";

if($file =~ /.*\.(c|cpp)$/){
open(IN, "<$file");
my @lines = <IN>;
close(IN);

foreach my $line (@lines) {
if($line =~ s|(my_debugf(.*?);)|/*$1*/|g){
$flag = 1;
}
}

if( $flag ){
open(OUT, ">$new_file");
foreach(@lines){
print OUT $_;
}
close(OUT);

rename( $file, "$file.orig" );
rename( $new_file, $file );

}
}
}
#################################################################


使い方:
perl tikan.pl

glob を使ったのでシェルの展開が不要! Perlすごいぞぉ!!!

rename を使ったので、元のソースが上書きされたようにコメントアウトされる。

私はsedコマンドだと、このように置換された結果が置換対象のファイルに反映されると思ってたが、sedも標準出力に結果を表示するだけのようなので、このPerlスクリプトの方がよい。あとは、 コメントアウトをはずす仕組みを実装すればよいね:D



>>続き
プリプロセッサがダメならPerlで置換だ!!!
またまた デバッグ出力に関する記事の続きです。


my_debugf という関数をデバッグ出力のために作ったんですが、いかんせん使いたくなくなったときに、コンパイルしないようにできない。 

そこで、カレントディレクトリにあるファイルの中に

my_debugf(以下略);

とあれば、

/*my_debuf(以下略);*/ と置換する

を思いついたので、この記事の一番下に載せるPerlスクリプトを書きました。これをLinuxのシェルの力を借りて実行します。

使用例:
perl tikan.pl *

これで、カレントディレクトリにある .c .cpp で終わるファイルの中に my_debugf 関数があればコメントアウトしてくれます。

現状ではファイルを上書きして置換するのではなく、置換した後の様子をコマンドプロンプトに表示します。でもまあ、あたらしくファイル作ってそっちに置換結果を書き込むとか応用はたやすい。


「えーぇ 俺、Windows環境なんでLinuxのシェルみたく * を展開できないよーー」

という方、ご安心を。このPerlスクリプトもWindows上でテストしました。

Window上では Cygwin を使えばいいのだ!!!!

Cygwinは /cygdrive/c/ がCドライブとのマウントポイントになっています。ですから Windowsでこの私が書いたPerlスクリプトを動かしたいなら おもむろに cd /cygdrive/c/ でCドライブへ移動して、そこから目的のフォルダに移動すればよい(難点は日本語の名前のフォルダに移動できないこと)。

ということで ソースです↓

                         tikan.pl と命名
#################################################################
#!/usr/local/bin/perl
use strict;

foreach my $file (@ARGV){
my $flag = 0;
if($file =~ /.*\.(c|cpp)$/){
open(IN, "<$file");
my @lines = <IN>;
close(IN);

foreach my $line (@lines) {
if($line =~ s|(my_debugf(.*?);)|/*$1*/|g){
$flag = 1;
}
}

if( $flag ){
print "\n/*************$file***************/\n";
foreach (@lines){
print;
}
print "/**********************************/\n";
}

}
}
#################################################################



てか sedコマンドで なんとかなったりしないものなのかしら・・・



>>続き
Perl屋さん
2月24日(土)にkansai.pmの催しがあるので行かせていただこう。


追記:
むむむ、Rubyの勉強会もあるっぽい・・・・

しかし、日付的にどうなんだ・・・・

く~気づくのが遅れた・・・


最近は卒研でITmedia Newsも見てない自分がいたことに、卒研発表が終わって気づいた。
最終的には vfprintf
前回の記事では minprintf なんていうややこしい関数を使いました・・・

しっかし 最終的には

        my_debug.cと命名   
/************************************/
#include "my_debug.h"

void my_debugf(char *fmt, ...)
{
#if DEBUG

va_list args;
va_start( args, fmt );
vfprintf( stderr, fmt, args );
va_end( args );


#endif
}
/************************************/


で、いけたんだよねぇ・・・・

vfprintf もとい vprintf系説明してくれてるページが少なすぎる・・・

参考資料:
http://www.t3.rim.or.jp/~matsuuch/COMP/cprog/cdebug.htm



>>続き
minprintf で解決した
前回の記事で、デバッグ用のprintfの取り扱い方について書きましたが、%dや%sが使えないという問題をかかえていました。可変長引数の関数を使えば乗り越えれることに薄々気づいていたので実装しました。

われらがバイブル プログラミング言語C のminprintfを使わせていただきました。

         my_debug.hと命名
/************************************/
#ifndef __my_debug_h__
#define __my_debug_h__

#include <stdarg.h>
#include <stdio.h>
#define DEBUG 1

void minprintf(char *fmt, ...);

#endif
/************************************/


                             my_debug.cと命名
/******************************************************************************/
#include "my_debug.h"

void minprintf(char *fmt, ...)
{
#if DEBUG

va_list ap;
char *p, *sval;
int ival;
double dval;

va_start(ap, fmt);
for(p = fmt; *p; p++){
if(*p != '%') {
putchar(*p);
continue;
}
switch(*++p){
case 'd':
ival = va_arg(ap, int);
printf("%d", ival);
break;
case 'f':
dval = va_arg(ap, double);
printf("%f", dval);
break;
case 's':
for(sval = va_arg(ap, char *); *sval; sval++){
putchar(*sval);
}
break;
default:
putchar(*p);
break;
}
}
va_end(ap);

#endif
}
/******************************************************************************/


使用例:
/******************************************************/
#include <stdio.h>
#include "my_debug.h"

int main(void){
minprintf("デバッグを%s %d\n", "行います", 1);
return 0;
}
/******************************************************/


よし、これでOKに違いない。

しかし、DEBUG 0 の場合も厳密には minprintf は一応処理される(DEBUG 0 なので素通り)わけだから、関数呼び出し等のオーバーヘッドは計測されてしまうか・・・・ うーん



>>続き
ブログ検索

プロフィール

ビンゴ中西
Perlが好きである。
プログラミング言語のほとんどは独学。独学の過程で多くのプログラム仲間にも色々教わりました。

FC2カウンター

カレンダー

01 | 2007/02 | 03
- - - - 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 - - -

ブロとも申請フォーム

この人とブロともになる

| ホーム | 次のページ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。