phplist-2.10.10

phplist-2.10.10 をインストールした。



<ol> <li>アーカイブを展開する。</li>
<li>public_html/lists/* を Web の公開ディレクトリへ置く。</li>
<li>config/config.php の内容と整合性のあるように、MySQL の DB とユーザを作成する。</li>
<li>http://xxxxxxxx/phplist/admin にアクセスすると、DB が無いよ、初期化しなさい、と言われる。</li>
<li>初期化すると、Database error 1071 while doing query Specified key was

too long; max key length is 1000 byte というエラーが発生する。<li>

<li>UTF-8 だと、バイト数の問題でオーバーしてしまうらしい。http://forums.phplist.com/viewtopic.php?p=27343

を参考に、email フィールドの長さを 255 から 100 にしてみる。

<pre class="prettyprint"> * admin/structure.php.org 2009-06-23 20:07:28.000000000 +0900
— admin/structure.php 2009-06-23 20:08:30.000000000 +0900
****
** 27,33 **
),
“user” => array ( # a user in the system
“id” => array(“integer not null primary key
auto_increment”,”sysexp:ID”),
! “email” => array(“varchar(255) not null”,”Email”),
“confirmed” => array(“tinyint default 0”,”sys:Is this user
confirmed”),
“blacklisted” => array(“tinyint default 0”,”sys:Is this user
blacklisted”),
“bouncecount” => array(“integer default 0”,”sys:Number of
bounces on this user”),
— 27,33 —-
),
“user” => array ( # a user in the system
“id” => array(“integer not null primary key
auto_increment”,”sysexp:ID”),
! “email” => array(“varchar(100) not null”,”Email”),
“confirmed” => array(“tinyint default 0”,”sys:Is this user
confirmed”),
“blacklisted” => array(“tinyint default 0”,”sys:Is this user
blacklisted”),
“bouncecount” => array(“integer default 0”,”sys:Number of
bounces on this user”),
****
** 60,71 **
“index_2” => array(“dateidx (date)”,”sys:index”),
),
“user_blacklist” => array(
! “email” => array(“varchar(255) not null unique”,”Email”),
“added” => array(“datetime”,”When added to blacklist”),
“index_1” => array(“emailidx (email)”,””),
),
“user_blacklist_data” => array(
! “email” => array(“varchar(255) not null unique”,”Email”),
“name” => array(“varchar(100) not null”,”Name of Dataitem”),
“data” => array(“text”,””),
“index_1” => array(“emailidx (email)”,””),
— 60,71 —-
“index_2” => array(“dateidx (date)”,”sys:index”),
),
“user_blacklist” => array(
! “email” => array(“varchar(100) not null unique”,”Email”),
“added” => array(“datetime”,”When added to blacklist”),
“index_1” => array(“emailidx (email)”,””),
),
“user_blacklist_data” => array(
! “email” => array(“varchar(100) not null unique”,”Email”),
“name” => array(“varchar(100) not null”,”Name of Dataitem”),
“data” => array(“text”,””),
“index_1” => array(“emailidx (email)”,””),
****
** 256,262 **
“id” => array(“integer not null primary key auto_increment”,”ID”),
“user” => array(“integer not null”,”User ID”),
“message” => array(“integer not null”,”Message ID”),
! “forward” => array(“varchar(255)”,”Forward email”),
“status” => array(“varchar(255)”,”Status of forward”),
“time” => array(“timestamp”,”When was it forwarded”),
“index_1” => array(“usermessageidx (user,message)”,”index”),
— 256,262 —-
“id” => array(“integer not null primary key auto_increment”,”ID”),
“user” => array(“integer not null”,”User ID”),
“message” => array(“integer not null”,”Message ID”),
! “forward” => array(“varchar(100)”,”Forward email”),
“status” => array(“varchar(255)”,”Status of forward”),
“time” => array(“timestamp”,”When was it forwarded”),
“index_1” => array(“usermessageidx (user,message)”,”index”),
****
** 273,279 **
“id” => array(“integer not null primary key auto_increment”,”sys:ID”),
“loginname” => array(“varchar(25) not null”,”Login Name (max
25 chars)”),
“namelc” => array(“varchar(255)”,”sys:Normalised loginname”),
! “email” => array(“varchar(255) not null”,”Email”),
“created” => array(“datetime”,”sys:Time Created”),
“modified” => array(“timestamp”,”sys:Time modified”),
“modifiedby” => array(“varchar(25)”,”sys:Modified by”),
— 273,279 —-
“id” => array(“integer not null primary key auto_increment”,”sys:ID”),
“loginname” => array(“varchar(25) not null”,”Login Name (max
25 chars)”),
“namelc” => array(“varchar(255)”,”sys:Normalised loginname”),
! “email” => array(“varchar(100) not null”,”Email”),
“created” => array(“datetime”,”sys:Time Created”),
“modified” => array(“timestamp”,”sys:Time modified”),
“modifiedby” => array(“varchar(25)”,”sys:Modified by”),
****
** 407,413 **
/* “translation” => array(
“id” => array(“integer not null primary key auto_increment”,””),
“translator” => array(“varchar(255)”,”Name of translator”),
! “email” => array(“varchar(255)”,”email of translator”),
“pass” => array(“varchar(255)”,”encrypted password for translation”),
“ident” => array(“varchar(255)”,”Translation identifier”)
),
— 407,413 —-
/* “translation” => array(
“id” => array(“integer not null primary key auto_increment”,””),
“translator” => array(“varchar(255)”,”Name of translator”),
! “email” => array(“varchar(100)”,”email of translator”),
“pass” => array(“varchar(255)”,”encrypted password for translation”),
“ident” => array(“varchar(255)”,”Translation identifier”)
),
</pre> </li>

<li>DB を一度 drop して再度作り直し、もう一度初期化。今度はテーブルの生成に成功した。</li>

<li>これでとりあえず動いているらしい。</li>

</ol>

ec2-bundle-vol を ruby 1.9 で使えるようにする

Amazon EC2 上の CentOS5 で使っていた ruby-1.8.5 を、ソースからビルドした ruby-1.9.1 に入れ替えたら、ec2-bundle-vol が動かなくなった。

元はといえば、gem の ruby-aaws を使いたくてインストールしようとしたら、ruby 1.8.7 以上を要求してきたことに始まる。hpricot-0.8.1 が 1.9 以上を要求していたはずだから、ついでに 1.9 にしてしまおうとしたのが運の尽き、amitools が動かなくなった。



<pre class="prettyprint">Copying / into the image file /mnt/image1-20090621-0223…
Excluding:
/proc
/sys
/dev/pts
/proc/sys/fs/binfmt_misc
/dev
/media
/mnt
/proc
/sys
/vol
/mnt/image1-20090621-0223
/mnt/img-mnt
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.020805 seconds, 50.4 MB/s
mke2fs 1.39 (29-May-2006)
/etc/fstab:
Exception NoMethodError' at /usr/lib/site_ruby/ec2/platform/linux/image.rb:226 - undefined method each’ for #<String:0x8cb4d34>
ERROR: undefined method `each’ for #<String:0x8cb4d34>
</pre>

<p>ruby 1.9 で、String#each が無くなったらしい。該当箇所を探して、書き換える(1行だけ)。これで一応、動いているみたい。</p>

<pre class="prettyprint"># diff -c image.rb.org /usr/lib/site_ruby/ec2/platform/linux/image.rb
* image.rb Sun Jun 21 02:39:17 2009
— /usr/lib/site_ruby/ec2/platform/linux/image.rb Sun Jun 21 02:39:29 2009
****
** 223,229 **
fstab_content = make_fstab
File.open( fstab, ‘w’ ) { |f| f.write( fstab_content ) }
puts “/etc/fstab:”
! fstab_content.each do |s|
puts “\t #{s}”
end
end
— 223,229 —-
fstab_content = make_fstab
File.open( fstab, ‘w’ ) { |f| f.write( fstab_content ) }
puts “/etc/fstab:”
! fstab_content.each_line do |s|
puts “\t #{s}”
end
end
</pre>

CentOS5 に ruby-1.9.1 を rpm でインストールする

gem でライブラリをインストールしようとすると、いろんなものが ruby 1.8.7 とか ruby 1.9 を要求してくる。今まであきらめていたけど、奮起?して ruby 1.9 をインストール。



</p>

<pre class="prettyprint">$ sudo yum install checkinstall
$ sudo yum install rpm-build
$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p129.tar.gz
$ tar zxvf ruby-1.9.1-p129.tar.gz
$ cd ruby-1.9.1-p129
$ ./configure –prefix=/usr
$ make
$ sudo /usr/sbin/checkinstall –fstrans=no
$ sudo -e –nodeps ruby ruby-irb ruby-rdoc ruby-devel
$ sudo rpm -ivh /usr/src/redhat/RPMS/i386/ruby-1.9.1-p129.i386.rpm
</pre>

<p>これで ruby-aaws とか hpricot-0.8.1 が使えるようになる♪</p>

TexShell2 で UTF-8 のファイルを扱えないとき

メニューバーの「設定」→「TeX→DVI」→「追加するオプション」に --kanji=utf8 オプションをつける。デフォルトでは

SJIS で動作する。

makeshop の売上を毎日自動集計してメールで送る

EC の ASP「makeshop」の売上を毎日自動集計して携帯に送るスクリプトを書いた。



<pre class="prettyprint">#!/bin/sh

#
# 設定
#
# MySQL のユーザには FILE permission が必要。
# grant file on . to makeshop@localhost;
#

MAKESHOP_CREDENTIAL=”-d id=shopid -d passwd=shoppw -d submanager=ok -d
etclogin=ok”
MYSQL_CREDENTIAL=”-umakeshop -pmakeshop”

RECIPIENTS=”shop1@fooshop.com, shop2@fooshop.com”


#
# Makeshop からデータをダウンロードする
#
function download_from_makeshop {

local year=$1
local month=$2
local day=$3
local file=$4

local COOKIE=cookie.txt
local NULL=”-o /dev/null”

local LOGIN_PAGE=http://www.fooshop.jp/login/login.html
local INDEX_PAGE=http://www.fooshop.jp/makeshop/newmanager/index2.html
local ORDER_CHECK_PAGE=http://www.fooshop.jp/makeshop/newmanager/order_check_excel.html

# ダウンロードする
curl -c $COOKIE $NULL $MAKESHOP_CREDENTIAL -e $LOGIN_PAGE $INDEX_PAGE
curl -b $COOKIE -o order_sjis.csv -d csv_type=check -d year1=$YEAR
-d month1=$MONTH -d day1=$DAY -d year2=$YEAR -d month2=$MONTH -d
day2=$DAY -d paymethod=ALL -d delivery1=A -d excel1=check
$ORDER_CHECK_PAGE

# Makeshop の CSV は SJIS なので UTF8 に変換する
iconv -f MS932 -t UTF8 order_sjis.csv > order_utf8.csv

# 売上を知るのに必要なカラムのみ取り出す
awk ‘BEGIN { FS=”,”; OFS=”,”; } /^[0-9]/ {print $1, $2, $31, $33,
$34, $36; sales += $33 * $34; }’ order_utf8.csv | sed
-e’s/=”(.)”/\1/g’ > $file

# お掃除
rm order_sjis.csv order_utf8.csv
}

function import_sales_data {
local csv=$1
mysql $MYSQL_CREDENTIAL makeshop «EOF
load data local infile “$csv”
into table sales
fields terminated by ‘,’
(date, order_id, item_name, amount, price, item_id)
;
EOF
}

#
# 日付ディメンションテーブルを更新する
#
function update_dates_table {
mysql $MYSQL_CREDENTIAL makeshop «EOF
call update_dates_table;
EOF
}

#
# 売上を集計する
#
function summarize {

local output=$1

local TIME=date +%Y%m%d_%H%M%S
local DAILY_SALES=/tmp/makeshop_daily_sales_$TIME.csv
local WEEKLY_SALES=/tmp/makeshop_weekly_sales_$TIME.csv
local MONTHLY_SALES=/tmp/makeshop_monthly_sales_$TIME.csv

mysql $MYSQL_CREDENTIAL makeshop «EOF
– 今月の日時売上の集計
select
date,
sum(amount * price) sales
from
sales
where
date >= date_sub(curdate(), interval day(curdate()) - 1 day)
group by
date
order by
date desc
into outfile “$DAILY_SALES” fields terminated by ‘, ‘
;

– 週次売上
select
min(d.date) start_date,
ifnull(sum(amount * price), 0) sales
from
dates d left outer join sales s
on s.date = d.date
group by
d.yearweek
order by
d.yearweek desc
into outfile “$WEEKLY_SALES” fields terminated by ‘, ‘
;

– 月次売上の集計
select
d.year,
d.month,
sum(amount * price) sales
from
sales s join dates d
on s.date = d.date
group by
d.year,
d.month
order by
d.year desc,
d.month desc
into outfile “$MONTHLY_SALES” fields terminated by ‘, ‘
;
EOF

cat «EOF > $output
Daily Sales
——————–
cat $DAILY_SALES

Weekly Sales
——————–
head -10 $WEEKLY_SALES
http://www.fooshop.com/weekly_sales.gif

Monthly Sales
——————–
cat $MONTHLY_SALES
EOF

generate_graph $WEEKLY_SALES /var/www/html/sales/weekly.gif
}

#
# グラフを作成する
#
function generate_graph {

local csv=$1
local image=$2

gnuplot «EOF
set xdata time
set timefmt “%Y-%m-%d”
set terminal gif size 240,160
set output “$image”
unset key
set style line 2 lt 2 lw 1
plot “$csv” using 1:2 with line title “weekly sales”,<br /> 20000 with lines ls 2,<br /> 40000 with lines ls 2,<br /> 60000 with lines ls 2,<br /> 80000 with lines ls 2,<br /> 100000 with lines ls 2,<br /> 120000 with lines ls 2
EOF
}

#
# 結果をメールで送る
#
function send_mail {
local file=$1
mail -s “sales report” -b “$RECIPIENTS” shop@fooshop.com < $file
}

# ダウンロード対象日
YEAR=date -d yesterday +%Y
MONTH=date -d yesterday +%m
DAY=date -d yesterday +%d

download_from_makeshop $YEAR $MONTH $DAY order.csv
import_sales_data order.csv
update_dates_table
summarize mailbody.txt
send_mail mailbody.txt

rm /tmp/makeshop_
.csv
</pre>

<pre class="prettyprint">–
– 売上テーブル

drop table if exists sales;

create table sales (
id integer primary key auto_increment,
date date,
order_id varchar(64),
item_name varchar(255),
amount integer,
price integer,
item_id varchar(255),
index date(date),
index item_name(item_name),
index item_id(item_id),
unique index (order_id, item_id)
);


– 日付ディメンションテーブル

drop table if exists dates;

create table dates (
id integer primary key auto_increment,
date date,
year integer,
month integer,
day integer,
week integer,
yearweek integer,
index date(date),
index year(year),
index month(month),
index day(day),
index week(day),
index yearwk(yearweek)
);


– 日付ディメンションテーブルの更新

drop procedure if exists update_dates_table;

delimiter //
create procedure update_dates_table()
begin
declare currentdate date default ‘2008-12-01’;
truncate dates;
while currentdate <= curdate() do
insert into dates(date, year, month, day, week, yearweek)
values(
currentdate,
year(currentdate),
month(currentdate),
day(currentdate),
week(currentdate, 2),
yearweek(currentdate, 0)
);
set currentdate = date_add(currentdate, interval 1 day);
end while;
end
//
delimiter ;
</pre>