资料管理软件私本管理Plus

最近开始使用私本管理Plus进行罗德斯收集物的管理(包括但不仅限于书籍)。

其能够实现的功能,已经非常接近自己所期望的管理效果了。

并且通过私本管理GOOUT还可以将资料同步到web上,实在是很方便。

不过由于用到的是CGI程序,并且联动的是不支持UTF-8的jcode.pl,所以对中文的支持不好。希望可以慢慢改进吧。感谢shela提供了支持UTF-8的修改版本,现在没有该问题了。

[8255] Re: 要望 投稿者:shela 投稿日:2017/11/12(Sun) 23:08

GOOUTのUTF8対応ですが、私が改造したものでよければ(添付ファイル)どうぞ。
ファイル名はsearch.cgiに変更してください。特殊なモジュールは使っていないはずなのでPerl 5.8.1以上の環境であればおそらく動くと思います。
また、私本管理でCSVファイルを作成する際、文字コードをUTF8またはUNICODEで保存してください。

添付:8255.txt (24KB)

8255.txt
#!/usr/bin/perl
 
#-----------------------------------------------------------
#   私本管理GOOUT for SmartPhone  By:EKAKIN
#-----------------------------------------------------------
#
#-----------------------------------------------------------
#   動作環境
#-----------------------------------------------------------
#  Perl 5.8.1 以降。
#  Perl 5.8.0 は文字コードの扱いに問題があるため、
#  文字化けを起こす等の不具合が発生する可能性があります
#  なお、jcode.plは使用しなくなりました
#-----------------------------------------------------------
#
#-----------------------------------------------------------
#   改版履歴
#-----------------------------------------------------------
#2015.01.10 Ver2.1.0    modified by shela
#           私本管理 Ver.4のバックアップデータ(*.shn,*.csv)に対応
#           ISBNのチェックディジット計算のバグ修正
#           バックアップデータのヘッダ行を無視するように修正
#           一括画像ローカル保存プラグインに対応
#2015.01.10 Ver2.0.1    検索時、特定の文字列が文字化けして正しく検索できない不具合を修正
#			画像が正しく表示されない不具合を修正
#2011.08.07 Ver2.0.0    改名
#           UI変更
#2010.08.11 Ver1.0.0    公開
#           【Thank you for kmzw】
#-----------------------------------------------------------
 
use strict;
use utf8;
use CGI qw/:standard :netscape/;
use Encode qw/decode_utf8/;
use HTML::Entities qw/encode_entities/;
 
my $TITLE       = "私本管理GOOUT";      # タイトル
my $VERSION     = "Ver 2.1.0";              # バージョン
my $SCRIPT_NAME = "$ENV{'SCRIPT_NAME'}";    # CGIファイル名
 
#-----------------------------------------------------------
#   カスタマイズ
#-----------------------------------------------------------
my $PAGE = 20;                              # 1ページに表示する件数
 
# 「No Image」画像の場所を指定します
# cgiと同じ場所の場合は「noimage.jpg」と指定します
# @niftyの場合は「http://homepage○.nifty.com/○○○/ディレクトリ/noimage.jpg」で指定します
# ↓このままでも使用できますが、変更される可能性があります
my $NOIMAGE = "http://homepage1.nifty.com/EKAKIN/cgi/goout/noimage.jpg";
 
# For iPhone
my $ICON_PATH = "http://homepage1.nifty.com/EKAKIN/cgi/goout/iphone_icon.png";
 
my $LINK_URL = "http://www.amazon.co.jp/gp/aw/d/";
 
my $AMAZON_TAG = "";
 
#-----------------------------------------------------------
#   検索ファイル名(フォルダと対になるように追加してください)
#-----------------------------------------------------------
my @FILE = ( "123.csv" );
 
#-----------------------------------------------------------
#   検索フォルダ名(ファイルと対になるように追加してください)
#-----------------------------------------------------------
my @DIR = ( "デフォルト" );
 
#===========================================================
#   実行処理
#===========================================================
my %FORM       = ();
my %FDATA      = ();
my @FDATAindex = ();
 
# フラグ付きUTF-8文字列をフラグなしにして出力させる
binmode STDOUT, ":utf8";
 
# フォームの内容取得
&formDataGet;
 
if ( $ENV{'REQUEST_METHOD'} eq "POST"
    || defined( $FORM{page} ) && $FORM{page} ne "" )
{
 
    # 検索結果画面表示
    &htmlResult;
}
else {
 
    # 検索画面表示
    &htmlStart;
}
 
exit;
 
#-----------------------------------------------------------
#   検索画面表示
#-----------------------------------------------------------
sub htmlStart {
    &htmlHeader01;
    &htmlSearch;    # 検索画面
    &htmlFooter01;
}
 
#-----------------------------------------------------------
#   検索結果表示
#-----------------------------------------------------------
sub htmlResult {
    &htmlHeader02;
    &runSearch;     # 検索処理
    &htmlFooter02;
}
 
#-----------------------------------------------------------
#   スタイルシート
#-----------------------------------------------------------
sub Style {
    print <<"_EOF_";
<style type="text/css">
 
  /* body 初期設定 */
 
    body {
      background: rgb(197,204,211);
      font-family: Helvetica;
      margin: 0;
      padding: 0;
      -webkit-user-select: none;
      -webkit-text-size-adjust: none;
    }
 
  /* a 初期設定 */
 
    a {
      font: 14px Helvetica;
      color: #42688e;
      text-decoration: none;
    }
 
    a:hover, a:active {
      color: #ff0066;
      text-decoration: none;
    }
 
  /* Center文字列初期設定 */
    div.center {
      text-align: center;
      margin: 4px 0;
      padding: 0;
      clear: both;
    }
 
  /* header 設定 */
 
    div#header {
      background: rgb(109,133,163) repeat-x top;
      border-top: 1px solid rgb(205,213,223);
      border-bottom: 1px solid rgb(46,55,68);
      padding: 5px;
      margin: 0;
      min-height: 44px;
      -webkit-box-sizing: border-box;
    }
 
    div#header h1 {
      color: #fff;
      font: bold 18px/30px Helvetica;
      text-shadow: #2d3642 0 -1px 0;
      text-align: center;
      text-overflow: ellipsis;
      white-space: nowrap;
      overflow: hidden;
      padding: 5px 0;
      margin: 2px 0 0 0;
      top: 0;
    }
 
    div#header #backButton {
      left: 6px;
      right: auto;
      color: #fff;
      font: bold 10px/20px Helvetica;
      text-shadow: #2d3642 0 -1px 0;
      text-align: center;
      width: 38px;
      border-width: 0 8px 0 14px;
      border:1px solid #263a51;
      padding: 5px 0;
      display: block;
      position: absolute;
      margin-top: -40px;
      background: #42688e;
      -webkit-border-radius: 4px;
    }
 
  /* list 初期設定 */
 
    ul {
      color: black;
      background: #fff;
      border: 1px solid #B4B4B4;
      font: bold 17px Helvetica;
      padding: 0 10px;
      margin: 15px 10px 17px 10px;
      -webkit-border-radius: 8px;
    }
 
    ul li {
      color: #666;
      border-top: 1px solid #B4B4B4;
      list-style-type: none;
      padding: 10px;
    }
 
    li:first-child {
      border-top: 0;
      -webkit-border-top-left-radius: 8px;
      -webkit-border-top-right-radius: 8px;
    }
 
    li:last-child {
      -webkit-border-bottom-left-radius: 8px;
      -webkit-border-bottom-right-radius: 8px;
    }
 
 
  /* form 設定 */
 
    ul#form li {
      padding: 7px 10px;
      text-align: center;
      vertical-align: middle;
    }
 
    ul#form li input[type="text"], ul li select {
      color: #777;
      background: #fff;
      border: 0;
      font: normal 17px Helvetica;
      padding: 0;
      display: inline-block;
      margin-left: 0px;
      width: 50%;
      -webkit-appearance: textarea;
    }
 
    ul#form li select {
      text-indent: 0px;
      background: transparent no-repeat 100% 3px;
      -webkit-appearance: textfield;
      margin-left: -6px;
      width: 50%;
    }
 
    ul#form li input[type="submit"] {
      width: 44%;
      height : 30px;
    }
 
    ul#form li.left {
      float: left;
    }
 
    ul#form li.right {
      float: right;
    }
 
 
  /* result 設定 */
 
    ul#result li.img {
      height:80px;
      padding-left: 100px;
    }
 
    ul#result img.img {
      display: inline-block;
      width: 60px;
      height:80px;
      margin: 0 0 0 -75px;
      float: left;
      -moz-background-size: cover;
      background-size: cover;
      -webkit-border-radius: 0;
      background: #F4FBFE;
      padding: 0;
    }
 
    ul#result div {
      color: #000;
      font: 14px Helvetica;
      text-overflow: ellipsis;
      white-space: nowrap;
      overflow: hidden;
      display: block;
      margin: 0;
      padding: 0;
    }
 
    ul#result a {
 
    }
 
  /* nextpage 設定 */
 
    ul#nextpage {
      background: #fff;
      clear: both;
      height: 44px;
      text-align: center;
    }
 
    ul#nextpage li.left {
      border: 0;
      -webkit-border-radius: 0;
      width: 33%;
      float: left;
      margin: 0;
      padding: 2px 0 0 0;
    }
 
    ul#nextpage li.center {
      border: 0;
      -webkit-border-radius: 0;
      width: 34%;
      float: left;
      margin: 0;
      padding: 11px 0;
    }
 
    ul#nextpage li.right {
      border: 0;
      -webkit-border-radius: 0;
      width: 33%;
      float: right;
      margin: 0;
      padding: 2px 0 0 0;
    }
 
    ul#nextpage li a {
      display: block;
      width: 100%;
      margin: 0;
      padding: 10px 0;
    }
 
 
  /* pages 設定 */
 
    ul#pages {
      margin: 4px 4px 4px 0;
      border: 0;
      -webkit-border-radius: 0;
      text-align: center;
    }
 
    ul#pages li.now {
      border: 1px solid #C0D5DD;
      -webkit-border-radius: 0;
      width: 30px;
      height: 22px;
      float: left;
      margin: 0 0 1px 1px;
      background: #fff;
      padding: 4px 0;
    }
 
    ul#pages li.other {
      border: 1px solid #C0D5DD;
      -webkit-border-radius: 0;
      width: 30px;
      height: 30px;
      float: left;
      margin: 0 0 1px 1px;
      background: #F4FBFE;
      padding: 0;
    }
 
    ul#pages li a {
      display: block;
      width: 100%;
      margin: 0;
      padding: 6px 0;
    }
 
</style>
_EOF_
}
 
#-----------------------------------------------------------
#   HTML ヘッダ初期
#-----------------------------------------------------------
sub htmlHeader01 {
    print "Content-type: text/html\n\n";
    print <<"_EOF_";
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.1//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile11.dtd">
<html>
<head>
<title>$TITLE</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta id="viewport" name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
<link rel="apple-touch-icon" href="$ICON_PATH" />
_EOF_
 
    &Style;
 
    print <<"_EOF_";
</head>
<body>
<div id="header">
  <h1>$TITLE</h1>
</div>
 
_EOF_
}
 
#-----------------------------------------------------------
#   HTML ヘッダ検索後
#-----------------------------------------------------------
sub htmlHeader02 {
    print "Content-Type: text/html\n\n";
    print <<"_EOF_";
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.1//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile11.dtd">
<html>
<head>
<title>$TITLE</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta id="viewport" name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
<link rel="apple-touch-icon" href="$ICON_PATH" />
<script type="text/javascript">
  function send(page) {
    var form = document.forms[0];
    form.page.value = page;
    form.submit();
  }
</script>
_EOF_
 
    &Style;
 
    print <<"_EOF_";
</head>
<body>
<div id="header">
  <h1>$TITLE</h1>
  <a href="$SCRIPT_NAME" id="backButton">検索</a>
</div>
_EOF_
}
 
#-----------------------------------------------------------
#   HTML フッタ初期
#-----------------------------------------------------------
sub htmlFooter01 {
    print << "_EOF_";
<div class="center"><a href="http://homepage1.nifty.com/EKAKIN" target="_blank">EKAKIN'S SCRIBBLE PAGE</a></div>
</body>
</html>
_EOF_
}
 
#-----------------------------------------------------------
#   HTML フッタ検索後
#-----------------------------------------------------------
sub htmlFooter02 {
    print << "_EOF_";
</body>
</html>
_EOF_
}
 
#-----------------------------------------------------------
#   HTML 検索画面
#-----------------------------------------------------------
sub htmlSearch {
    print <<"_EOF_";
<form method="post" action="$SCRIPT_NAME" class="tcardform">
 
<ul id="form">
  <li>ジャンル選択&nbsp;&nbsp;
    <select name="file">
_EOF_
 
    for ( my $i = 0; $i <= $#FILE; $i++ ) {
        my $genre = encode_entities( $DIR[$i] );
        if ( defined( $FORM{file} ) && $i eq $FORM{file} ) {
            print "<option value=\"$i\" selected>$genre</option>\n";
        }
        else {
            print "<option value=\"$i\">$genre</option>\n";
        }
    }
 
    print <<"_EOF_";
    </select>&rsaquo;
  </li>
  <li>購入/未購入&nbsp;&nbsp;&nbsp;&nbsp;
    <select name="data20">
_EOF_
    my @Purchase = ( "", "購入", "未購入", "その他" );
    for ( my $i = 0; $i <= $#Purchase; ++$i ) {
        if ( defined( $FDATA{20} ) && $Purchase[$i] eq $FDATA{20} ) {
            print
                "<option value=\"$Purchase[$i]\" selected>$Purchase[$i]</option>";
        }
        else {
            print "<option value=\"$Purchase[$i]\">$Purchase[$i]</option>";
        }
    }
    print <<"_EOF_";
    </select>&rsaquo;
  </li>
  <li>ISBN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <input type="text" name="data0" mode="numeric" istyle="4" size="18" maxlength="13" value="$FDATA{0}" />&nbsp;</li>
  <li>タイトル&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <input type="text" name="data1" class="tcardtext" mode="hiragana" istyle="1" size="18" value="$FDATA{1}" />&nbsp;</li>
  <li>作者&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <input type="text" name="data5" class="tcardtext" mode="hiragana" istyle="1" size="18" value="$FDATA{5}" />&nbsp;</li>
_EOF_
    if ( defined( $FORM{ftype} ) && $FORM{ftype} eq "or" ) {
        print
            "<li><input type=\"radio\" name=\"ftype\" value=\"or\" checked />OR&nbsp;&nbsp;";
        print
            "<input type=\"radio\" name=\"ftype\" value=\"and\" />AND";
    }
    else {
        print
            "<li><input type=\"radio\" name=\"ftype\" value=\"or\" />OR&nbsp;&nbsp;";
        print
            "<input type=\"radio\" name=\"ftype\" value=\"and\" checked />AND";
    }
    print <<"_EOF_";
  &nbsp;&nbsp;<input type="submit" value="検索" class="tcardsubmit" /></li>
</ul>
</form>
 
<div class="center">
</div>
_EOF_
}
 
#-----------------------------------------------------------
#   検索内容取得
#-----------------------------------------------------------
sub formDataGet {
 
    # 入力パラメータ取得
    foreach my $key (param) {
        $key = decode_utf8($key);
        my $value = decode_utf8( param($key) );
        if ( $key =~ /data(\d+)/ ) {
            my $index = $1;
            if ( $index eq "0" ) {
 
                # ISBN
                $FDATA{$index} = &isbn_change($value);
            }
            else {
 
                # ISBN以外は小文字にして保持
                $FDATA{$index} = lc($value);
            }
 
            unless ( $FDATA{$index} eq "" ) {
                push( @FDATAindex, $index );
            }
        }
        else {
 
            # ジャンル、検索タイプ(AND/OR)、ページ
            $FORM{$key} = $value;
        }
    }
}
 
#-----------------------------------------------------------
#   検索処理
#-----------------------------------------------------------
sub runSearch {
 
    # ファイルの読み込み
    if ( !open( FH, "<:raw", $FILE[ $FORM{file} ] ) ) {
        &error( "エラー",
            "私本管理バックアップファイルが読み込めません"
        );
        return;
    }
 
    # 初期ページを設定
    if ( !defined( $FORM{page} ) || $FORM{page} eq "" ) {
        $FORM{page} = 1;
    }
 
    my $maxRec = $FORM{page} * $PAGE;    # 表示レコード MAX
    my $minRec = $maxRec - $PAGE + 1;    # 表示レコード MIN
 
    print "<ul id=\"result\">\n";
 
    my ( $codeSet, $offset );
    my $count = 0;
    my $flg   = 0;
 
    while ( my $line = <FH> ) {
 
        if ( $. == 1 ) {
            if ( $line =~ s/^\xEF\xBB\xBF// ) {
                $codeSet = "utf8";
                $offset  = 3;
            }
            elsif ( $line =~ s/^\xFF\xFE// ) {
                $codeSet = "utf16le";
                $offset  = 2;
            }
            else {
                $codeSet = "cp932";
                $offset  = 0;
            }
 
            # BOMを除いた先頭へ戻って読み直し
            seek( FH, $offset, 0 );
            binmode FH, "encoding($codeSet):crlf:utf8";
            $line = <FH>;
        }
 
        chomp($line);    # 改行を取り除く
 
        # 「,」区切りでCSVファイル1行読込
        my @array = split( ",", $line );
 
        # ヘッダ行を読み飛ばす
        if ( $array[0] eq "ISBN" ) {
            next;
        }
 
        my $found = 0;
 
        # 検索
        if ( $#FDATAindex == -1 ) {
 
            # 検索項目が未入力の場合は該当ありと判定
            $found = 1;
        }
        elsif ( $FORM{ftype} eq "or" ) {
 
            # OR検索の場合は最初に一致項目が出た時点で該当ありと判定
            $found = 0;
            my $data;
            for ( my $i = 0; $i <= $#FDATAindex; $i++ ) {
                $data = $array[ $FDATAindex[$i] ];
                $data = lc($data);
 
                # ISBNは-を削除 x,+,*はXとみなす
                if ( $FDATAindex[$i] == 0 ) {
                    $data = &isbn_change($data);
                }
                if ( index( $data, $FDATA{ $FDATAindex[$i] } ) > -1 ) {
                    $found = 1;
                    last;
                }
                elsif ( $FDATAindex[$i] == 1 || $FDATAindex[$i] == 5 ) {
 
                    # タイトルカナ検索 / 作者カナ検索
                    my $n = int( $FDATAindex[$i] ) + 1;
                    $data = $array[$n];
                    $data = lc($data);
                    if ( index( $data, $FDATA{ $FDATAindex[$i] } ) > -1 ) {
                        $found = 1;
                        last;
                    }
                }
            }
        }
        elsif ( $FORM{ftype} eq "and" ) {
 
            # AND検索の場合は最初に不一致項目が出た時点で該当なしと判定
            $found = 1;
            my $data;
            for ( my $i = 0; $i <= $#FDATAindex; $i++ ) {
                $data = $array[ $FDATAindex[$i] ];
                $data = lc($data);
 
                # ISBNは-を削除 x、+、*はXとみなす
                if ( $FDATAindex[$i] == 0 ) {
                    $data = &isbn_change($data);
                }
                if ( index( $data, $FDATA{ $FDATAindex[$i] } ) == -1 ) {
 
                    # タイトルカナ検索 / 作者カナ検索
                    if ( $FDATAindex[$i] == 1 || $FDATAindex[$i] == 5 ) {
                        my $n = int( $FDATAindex[$i] ) + 1;
                        $data = $array[$n];
                        $data = lc($data);
                        if ( index( $data, $FDATA{ $FDATAindex[$i] } ) == -1 )
                        {
                            $found = 0;
                            last;
                        }
                    }
                    else {
                        $found = 0;
                        last;
                    }
                }
            }
        }
 
        # 検索にヒットした場合
        if ($found) {
            $count++;
 
            if ( $minRec <= $count && $maxRec >= $count ) {
 
                # ISBN
                $array[0] =~ s/-//g;          # ハイフンを除去
                $array[0] =~ s/^978|^979//g;    # 先頭に978か979があれば(ISBN13)除去
                $array[0] =~ s/.$//g;    # チェックデジット除去
 
                # チェックデジット計算
                my @num_splt = split( //, $array[0] );   # 1文字ずつ分割
                my $check = 0;
                for ( my $i = 0; $i < 9; $i++ ) {
                    $check = $check + $num_splt[$i] * ( 10 - $i );
                }
                $check = 11 - ( $check % 11 );
                if ( $check == 10 ) {
                    $check = "X";
                }
                elsif ( $check == 11 ) {
                    $check = 0;
                }
 
                # タイトル
                $array[1] =~ s/"//g;
                $array[1] = encode_entities( $array[1] );
 
                # 巻
                $array[4] =~ s/"//g;
                if ( $array[4] eq "ONLY ONE" ) {
                    $array[4] = "";
                }
                $array[4] = encode_entities( $array[4] );
 
                # 作者
                $array[5] =~ s/"//g;
                $array[5] = encode_entities( $array[5] );
 
                # 発行所
                $array[12] =~ s/"//g;
                $array[12] = encode_entities( $array[12] );
 
                # 一括画像ローカル保存プラグイン利用時は備考6を画像のURLとする
                if ( length( $array[37] ) > 0
                    && substr( $array[37], 1, 1 ) eq ":" )
                {
                    $array[37] = $array[66];
                }
 
                # 画像がない場合
                if ( $array[37] eq "" ) {
                    $array[37] = $NOIMAGE;
                }
 
                print "<li class=\"img\">";
                print
                    "<a href=\"$LINK_URL$array[0]$check/&tag=$AMAZON_TAG\"><img src=\"$array[37]\" class=\"img\" /></a>";
                print
                    "<a href=\"$LINK_URL$array[0]$check/&tag=$AMAZON_TAG\">";
                print "<div>$array[1] $array[4]</div>";
                print "<div>$array[5]</div>";
                print "<div>$array[12]</div>";
                print "<div>ISBN:$array[0]$check</div>";
                print "</a>";
                print "</li>\n";
            }
            else {
                $flg = 1;
            }
            $found = 0;
        }
    }
 
    close(FH);
 
    if ( $count == 0 ) {
        print "<div class=\"center\">該当データなし</div></ul>\n";
    }
    else {
        print
            "</ul>\n<div class=\"center\">該当データ:${count}件</div>\n";
    }
 
    print "<form action=\"$SCRIPT_NAME\" method=\"post\">\n";
    print "<input type=\"hidden\" name=\"file\" value=\"$FORM{file}\" />\n";
    if ( defined( $FDATA{0} ) && $FDATA{0} ne "" ) {
        print
            "<input type=\"hidden\" name=\"data0\" value=\"$FDATA{0}\" />\n";
    }
    if ( defined( $FDATA{1} ) && $FDATA{1} ne "" ) {
        print
            "<input type=\"hidden\" name=\"data1\" value=\"$FDATA{1}\" />\n";
    }
    if ( defined( $FDATA{5} ) && $FDATA{5} ne "" ) {
        print
            "<input type=\"hidden\" name=\"data5\" value=\"$FDATA{5}\" />\n";
    }
    if ( defined( $FDATA{20} ) && $FDATA{20} ne "" ) {
        print
            "<input type=\"hidden\" name=\"data20\" value=\"$FDATA{20}\" />\n";
    }
    print "<input type=\"hidden\" name=\"ftype\" value=\"$FORM{ftype}\" />\n";
    print "<input type=\"hidden\" name=\"page\" />\n";
    print "</form>\n";
 
    if ( $flg == 1 ) {
        my $p       = $FORM{page};
        my $maxPage = int( $count / $PAGE );
        if ( $count % $PAGE != 0 ) {
            $maxPage++;
        }
 
        # 指定ページが範囲外の場合は先頭または最終ページにする
        if ( $p < 1 ) {
            $p = 1;
        }
        elsif ( $p > $maxPage ) {
            $p = $maxPage;
        }
 
        print "<ul id=\"nextpage\"><li class=\"left\">";
 
        if ( $p > 1 ) {
            $FORM{page} = $p - 1;
            print "<a href=\"javascript:send('$FORM{page}')\"><</a>";
        }
 
        print "</li><li class=\"center\">$p\/$maxPage</li>";
        print "<li class=\"right\">";
 
        if ( $p < $maxPage ) {
            $FORM{page} = $p + 1;
            print "<a href=\"javascript:send('$FORM{page}')\">></a>";
        }
        print "</li></ul>\n";
 
        print "<ul id=\"pages\">\n";
        for ( my $pagecount = 1; $pagecount <= $maxPage; $pagecount++ ) {
            if ( $pagecount != $p ) {
                print
                    "<li class=\"other\"><a href=\"javascript:send('$pagecount')\">$pagecount</a></li>\n";
            }
            else {
                print "<li class=\"now\">$pagecount</li>\n";
            }
        }
        print "</ul>\n";
    }
}
 
#-----------------------------------------------------------
#  ISBN変換
#-----------------------------------------------------------
sub isbn_change {
    my $isbn = $_[0];
 
    #ISBNは-を削除 x、+、*はXとみなす
    $isbn =~ s/-//g;
    $isbn =~ tr/+*x/X/;
    return $isbn;
}
 
#-----------------------------------------------------------
#   エラーメッセージ
#-----------------------------------------------------------
sub error {
    my @msg = @_;
 
    print "<ul id=\"result\">";
    foreach my $i ( 0 .. $#msg ) {
        print "$msg[$i]<br />\n";
    }
    print "</ul>\n";
}

因此,今后购买记录的文章应该就不会再出现了。