Perl

Submit時のダブルクリック防止

運用している WEBサイトでフォームからの投稿ボタンやリセットボタンをダブルクリックされての不具合が頻発したので対策を施した。

スマホ端末のユーザーは問題ないのだが、PC環境でダブルクリックの癖が抜けない人が居るらしい。

参考にしたサイトは下記…というかそのまんまである。

JS本体

var dblClickFlag = null;

function ThroughDblClick() {
    // ダブルクリック(連続ポスト)の制御
    if (dblClickFlag == null) {
        dblClickFlag = 1;
        return true;
    } else {
        return false;
    }
}

onSubmitから呼び出す

<script>
var dblClickFlag = null;

function ThroughDblClick() {
    // ダブルクリック(連続ポスト)の制御
    if (dblClickFlag == null) {
        dblClickFlag = 1;
        return true;
    } else {
        return false;
    }
}
</script>

<form action="" method="post" onSubmit="return ThroughDblClick();">
   <input type="submit" value="送信">
</form>

2回目以降がFalseになるかをテスト

test.html に下記をコピペしてテストしてみる。

<script>
var dblClickFlag = null;

function ThroughDblClick() {
    console.log(dblClickFlag == null);
    // ダブルクリック(連続ポスト)の制御
    if (dblClickFlag == null) {
        dblClickFlag = 1;
        return true;
    } else {
        return false;
    }
}
</script>

<form action="" method="post" onSubmit="return ThroughDblClick();">
   <input type="submit" value="送信">
   <input type="button" value="test" onclick="ThroughDblClick();">
</form>
  1. Chromeで test.html ファイルを表示させてデベロッパーツールを起動
  2. testボタンをダブルクリック
  3. Consoleタブで 1度目 true / 2度目以降 false となることを確認できればOK

Downloadした CGI Scriptを Severへ Uploadするときは改行コードを修正する必要あり

Windowsから Linuxに移行してから Webで Downloadした CGIスクリプトをそのまま FTPアプリでアップロードすると必ずエラーになる。 試行錯誤して原因は、主要な CGIスクリプトの改行コードが CRLFとなっていたことでした。

Linux環境でダウンロードして解凍するというプロセスによってそうなるのかどうかは解明できていませんが、これを LFに変えてやることで問題なくスクリプトが動作しました。

いつも何も考えずにアップレードして「あれ!」となるのでしっかり備忘録に記しておこうと考えた次第。そういえば、Mac環境のときもそうだった気がする。UNIX系の症状かも知れないのでもう少しググって調べてみよう…

たくさんファイルがある時は、いちいち Terminalを開くのは面倒なので Emacsでやっている。

  (defun convert-encode-to-utf8 ()
	"Convert character code of the file to utf-8."
	(interactive)
	(let ((file (buffer-file-name)))
	  (if (not (use-region-p))
		  (compile (concat "nkf -w -Lu --overwrite " file)))))

  (defun convert-encode-to-sjis ()
	"Convert character code of the file to utf-8."
	(interactive)
	(let ((file (buffer-file-name)))
	  (if (not (use-region-p))
		  (compile (concat "nkf -s -Lu --overwrite " file)))))

Perlで未定義値かどうかを判定する方法

機嫌よく動いていた自作のスクリプトに

use warnings; 

を入れたら作業そのものは止まることなく終了するのだけれど、

Use of uninitialized value ... 

と叱られるようになった。

foreach my $line (@log){
    chomp($line);
    my ($no,$name,$date,$mail,$comment,$pass)=split(/,/,$line);
    # $comment が空だった場合の処理
    if($comment eq ""){
	$comment=$no;$c++
    }
    if ($c > 7){  # 7日分を取得したら繰り返し終了
	last
    }
	....

上記を走らせたときに下記の部分で前述の警告が出る。

if($comment eq ""){
	$comment=$no;$c++
}

$comment が存在しなかったときに他の変数を代入する…

という条件式のつもりでしたが、存在しない(未定義の)変数だよ! という警告なのである。落ち着いて考えたら当たり前ですね。ググってみたら未定義値かどうかを判定する defined関数 というのがあるのを知りました。

if (defined $name) {
  ...
}

上記では定義されている場合に処理させるというものですが、私の場合は値が未定義だった場合に処理をさせたいので unless を使えばいいという情報を得たので下記のように修正して警告が出なくなりました。めでたし(^o^)

# $comment が未定義だった場合の処理
unless (defined $comment){
	$comment=$no;$c++
}

Formをhtmlに直接表示しないでcgiで別窓表示する

読者からのFeedbackを受け付けるためにホームページ上のコンテンツごとにメールフォームを貼っていた。 SPAM対策はしてあったがそれでもそれをくぐり抜けて攻撃されることが多くなったので、各ページにフォームを貼り付けるのはやめてCGIで表示させるようにした。

Perl:文字列前後のスペース&タブを削除

運営している俳句サイトで自動句会システムを作動させている。

ユーザーが自分が詠んだ俳句をテキストフォームを使って投稿するという仕組みなのですが、キーボードからの入力ではなくて、コピー貼付け操作をされる方も多く、意図しないスペースが入ったまま投稿されるケースが多いです。そのままですとシステムが正常に処理できないことがあるので、投稿受付時に不要なスペースやタブを自動的に削除するように対策を施すことにしました。

文字列前後の半角スペース&タブを削除

正規表現を使って文字列$valの末尾の半角スペース&タブを削除するスクリプトは以下の通り。

$val =~ s/\s*(.*?)\s*$/$1/;

テストスクリプトで確認してみましょう。

## 文字列前後のスペース&タブ削除
$val = "This is a pen.     ";
$val =~ s/\s*(.*?)\s*$/$1/;
print $val;

文字列前後の全角スペースを削除

全角スペースの削除は、少しやっかいです。使用する文字コードによって異なるからです。

$val =~ s/\x81\x40//g;  SJIS
$val =~ s/\xa1\xa1//g;  EUC
$val =~ s/\xE3\x80\x80//g;  utf-8

UpFtpをMacとLinuxとで共用する方法

UpFtpと言うのは、結城浩さんの作られたMakeWebと併せて使うためのFTP自動化ツールのことです。

  • Makeweb:テキストをXHTMLに変換するPerlスクリプト
  • UpFtp:ホームページ更新用Perlスクリプト

これらのツールを使えば、MakeWeb記法(Markdown記法のような書式)で書いた、index.txtをMakeWebでコンパイルしてindex.htmlを生成させ、UpFtpでサーバーに送って更新する…という手順を下記のように makefileに書き、make -k するだけで自動処理されます。

makefile

target = index.html
a.out:all
all: $(target)

.SUFFIXES: .txt .html
.txt.html:
	perl ~/Dropbox/Web/GH/mw/makeweb.pl $< $@ # index.txt to index.html
	perl ~/Dropbox/Web/GH/upftp/upftp.pl 

異なる環境でデータを共有するのはDropboxが便利

Dropboxは、Windows/Linux/macOSとマルチ環境で使えるので、WEB構築の元データを複数端末で共有するのには一番適している。同期速度などの点でも他のクラウドと比較して一番早い。

ぼくの場合は、どの環境もユーザーフォルダの直下にDropboxをインストールしているので、以下のようPATH構成になる。

  • Windows C:\Users/minoru/Dropbox
  • Lnux /home/minoru/Dropbox
  • Mac /Users/minoru/Dropbox

Makefileの場合は、~/Dropboxと書くことで認識してくれるので容易に共用設定が書けるが、UpFtpの設定ファイルの場合は、以下のようにフルパスを書く必要があるので工夫が必要となる。

# Local root directory (in fullpath)
my $localrootdir = "";
# File list (in fullpath)
my $filelist = "";

ユーザフォルダーを変数で取得

フルパスを直書きするとマルチ環境で共用できないので、変数を取得してそれを共通で使えるようにします。

Mac/Linuxの場合

MacもLinuxも同じUNIXなので以下の方法でユーザーフォルダのPATHを取得できる。

$home = $ENV{"HOME"}
$home = %USERPROFILE%

Mac/Linux共用の設定

私の場合は、以下のように書くことでうまく動いている。

# Get HOME directory from environment variables
my $home = $ENV{"HOME"};
# Local root directory (in fullpath)
my $localrootdir = "$home/Dropbox/Web/GH";
# File list (in fullpath)
my $filelist = "$home/Dropbox/Web/GH/upftp/filelist.txt";

Windows/Mac(Linux)共用の設定

ここからは確認できていないので無責任になるけれども、OSを判別する特殊変数を使って分岐させる必要がある。