CGI-BBS > 情報収集 > フォームメール > 受信した画像ファイルが、壊れているのは、何故ですか?


カレッヂ
カレッヂ


質問者 タクヤ  投稿日 7/24(火) 22:23:25
フォームメールから送られてきた、画像ファイルが、1部分だけ崩れていたり、ノイズが入ったり、ぐちゃぐちゃで何の画像か解らなくなったりします。
原因は、何でしょうか?
教えてください。
回答者 まさ  [削除]  投稿日 7/25(水) 12:53:35
わたしはフォームメールの仕様は知らないので、はずしているかもしれませんが、
使っているOSはWindowsではないでしょうか?

Windowsではバイナリーを保存するときには明示的にbinmodeを指定しないとバイナリー
でもテキスト扱いになります。何かおっしゃっている症状がテキストでアップした時の
症状に似ているのでこのように書きましたが、OSがUNIXならこの回答は無視して下さい。

質問者 タクヤ  [削除]  投稿日 7/25(水) 16:49:50
まささん
回答ありがとう御座いました。
OS、Windowsです。
「binmode」を指定とは、どのようにすれば良いのでしょうか?
バイナリーと言うう言葉は、聞いたことは、あるのですが、良く分っていません。
よろしくお願い致します。
回答者 まさ  [削除]  投稿日 7/25(水) 18:14:54
やはりOSはWindowsですか。
フォームメールはWindowsでの動作は考えられていないのでしょう。


スクリプトがどうなっているのかわかりませんので一般論です。

open(OUT, "> $new_file");
binmode(OUT);
print(OUT $file);
close(OUT);

上のように画像ファイルを書き込みしているファイルハンドルをバイナリーにします。
フォームメールにはこのbinmode(OUT);がないのでしょう。UNIXは無くても動作しま
すが、Windowsでは書かなければいけません。

質問者 タクヤ  [削除]  投稿日 7/25(水) 19:15:17
Windowsに、対応していないのですか。
残念です、、、。

まささんが、おっしゃる所を治せばWindowsでも、使えるって事なのでしょうか。
スクリプトの中をいじる、知識が無いため、説明があまり理解できていませんが、ファイルハンドルと言う所が、ポイントなんですね。
ですが、どこが、治すべきファイルハンドルなのか、どこにbinmode(OUT);をいれれば良いのか、解りません。
このスクリプトを改良するのは、とっても、難易度が高そうですね。
設置するには、スクリプトについての勉強から、始めなくては、、、。
素人に、可能な改良でしょうか?
回答者 まさ  [削除]  投稿日 7/25(水) 21:18:25
そのままではWindowsには対応していませんが、binmodeを入れると動くと思いますよ。

スクリプトの修正は一箇所だけbinmodeを入れればいいのですが、スクリプトの意味が
全くわからなかったら、何処に入れればいいのかわからないですね。

>このスクリプトを改良するのは、とっても、難易度が高そうですね。
>設置するには、スクリプトについての勉強から、始めなくては、、、。
>素人に、可能な改良でしょうか?

いやいやbinmodeを入れるだけですから難易度は低いと思いますよ。
まあちょっと改良しようと思えば一応はスクリプトを読めるようになっていれば便利で
しょうね。

とにかくopenの直後に入れるわけですから、全てのopenを検索して、それが何をopenして
いるのか勉強し、画像ファイルをopenしている部分にbinmodeを入れます。

どうしても自分でわからないようでしたら、スクリプトを公開してそのURLを教えて下さい。
そうすれば具体的に何処に入れればいいのかお教えします。

回答者 まさ  [削除]  投稿日 7/25(水) 21:32:15
これよく見てみるとフォームメールから送られてきた画像なんですよね。
わたしはサーバーにUPされた画像と勘違いしていました。

今までのわたしの回答は無かったことにして下さい(^^ゞ
スミマセン。

画像は普通Base64でエンコードするのが簡単ですが、これはuuencodeを使っていますね。
まずuuencodeのパスは間違っていないのでしょうか?

画像が壊れてるとありますが、これはエンコードが正常に行われていないものと思います。
わたしはuuencodeのパスが間違っていると思います。或いはサーバーにuuencodeがないと
か。その辺をもう一度確認してみて下さい。

質問者 タクヤ  [削除]  投稿日 7/25(水) 21:36:06
ホントに何度もすいません。
binmode()について少し調べてみました。
自分なりに、挿入してみましたが、まだダメなようです。
大変申し訳ありませんが一度観てもらえますか。

アドレスは、こちらです。
http://www.pixy.cx/~takuya_/form_mail/form2mail.cgi
宜しくお願い致します。
回答者 まさ  [削除]  投稿日 7/25(水) 21:41:17
もしもuuencodeのパスがあっているとすれば以下の部分にbinmodeを入れて下さい。

if (!open(BIN,"> $tmp$filenum")) {
  &error('Error','アップロードファイルの一時ファイルが作成できません.<br>',
      'テンポラリーフォルダのパーミッションを確認してください.');
}
binmode(BIN);
print BIN $FILEDATA[$file];
close(BIN);

質問者 タクヤ  [削除]  投稿日 7/25(水) 21:42:05
こっちのほうが良いのでしょうか?
一応
http://www5b.biglobe.ne.jp/~redhorn/form.htm
です。
質問者 タクヤ  [削除]  投稿日 7/25(水) 21:59:03
最初のアドレスで見えたようですね。

やってみたんですけどねー。
何で出来ないんでしょうかね、、、。

ほんと、お付き合いありがとう御座います。
回答者 まさ  [削除]  投稿日 7/25(水) 22:13:17
ダメですか。

これでダメならわたしなら次の2点を試してみます。

1.メーラーを変える。
2.uuencodeを使わずに、MIME::Base64を使う。

2.はそのモジュールがサーバーにインストールされていないといけませんけどね。
もしインストールされているならば、uuencodeを使うよりこちらを使った方がいいです。

回答者 あけび  [削除]  投稿日 7/26(木) 00:39:21
余談ですが、uuencodeなら
perlのpack/unpackだけで処理できます。

pack("u*",$str); # encode
unpack("u*",$str); # decode
回答者 あけび  [削除]  投稿日 7/26(木) 00:47:35
base64 についても、簡単なサブルーチンで処理できます。
以下は、うちで配布しているBBSにて使用している処理ルーチンです。

&enc_base64($str); # encode
&dec_base64($str); # decode

sub enc_base64 {

        local($s) = @_;
        local($m) = 2- (length($s)-1)%3;
        $s = pack("u*",$s);
        $s =~ tr/\x20-\x60/A-Za-z0-9+\/A/;
        $s =~ s/\n.//g;
        $s = substr($s,1,length($s)-(2+$m));
        $s.= "="x (3-((length($s)-1)%4));
        return(join("\n",$s =~ /(.{1,76})/g));
}

sub dec_base64 {

        local($s) = @_;
        local($buf);
        $s =~ tr/A-Za-z0-9+\///cd;
        $s =~ tr/A-Za-z0-9+\//\x20-\x5f/;
        while($s =~ /(.{1,60})/g) { $buf .= unpack("u*",sprintf("%c%s",0x20+length($1)*.75,$1));}
        return($buf);
}
質問者 タクヤ  [削除]  投稿日 7/26(木) 00:53:17
メーラーを変えるのは、出来るだけしたくないのですが、でも、これで治るのなら、仕方が無いですね。
MIME::Base64が使えるか、サーバーに問い合わせてみます。

>あけびさん
「uuencodeなら
perlのpack/unpackだけで処理できます。」
とは、いったいどう言うことなのでしょうか?
プログラム関係に、あまり詳しくないので、意味が理解できていません。
これを使えば、解決できるのなら、是非理解したいのですが、、、。
質問者 タクヤ  [削除]  投稿日 7/26(木) 01:08:12
親切に教えていただいてホントに感謝します。

ですが、なにしろプログラムについては、まったくの素人で、、、。
今日1日で、確実に、レベルアップしていますが、、、。

このサブルーチン(サブルーチンが何かも知りません。お恥ずかしいです。)、をそのまま、どこかに貼っても、良いのですか?

まささんと、あけびさんの回答文を読み、いろいろな、対策があることに、感心してしまいました。
質問者 タクヤ  [削除]  投稿日 7/26(木) 02:07:11
モジュールについてのサーバー側の回答は、次のようでした。


perl のモジュールだと思うのですが、勉強不足で、こういう名前の
モジュールがあったかどうか、解かっておりません。


これが perl 5 のインストールの際標準で入ってくるものであれば、
組み込まれています。

ただ、標準で組み込まれない、後から、付け足す必要があるものなら
組み込まれていないです。

申し訳ございませんが、使って動かない場合は、
ご了承いただけますよう御願いします。

との事です。

回答者 まさ  [削除]  投稿日 7/26(木) 08:06:26
MIME::Base64はPerl5には標準で付いてこないと思います。
自分でインストールしないといけません。
しかしOSがWindowsでActivePerlを使っているなら、PPMで簡単にインストールできるの
ですがね。

これも余談ですが、以下のスクリプトを実行すれば、インストールされているモジュール
が一覧で出てきますので、自分で調べることができます。

#!/usr/local/bin/perl
print <<"EOF";
Content-type: text/html

<html>
<h2>Perl</h2>
$]
<hr>
EOF

print `perl -v`, "<hr>\n";

foreach(@INC){
  print map "$_<br>\n", src($_);
}
print "</html>\n";

sub src {
  my($d,@f,@r,$f);
  $d = shift;
  opendir DIR, $d;
  @f = readdir DIR;
  closedir DIR;
  foreach(@f){
    next if /^\.\.?$/;
    $f =  "$d/$_";
    push @r, -d $f ? src($f) : $f;
  }
  @r;
}
__END__

戻りますが、画像が壊れているとのことですが、順番に調べていきましょう。
このスクリプトは画像を一旦ファイルとして保存しているので、メールを送る前に
ブラウザーで表示してみて、画像が壊れているかどうか確認すればいいと思います。
この段階で壊れているようならデータを書き込む時におかしいと言う事です。
しかしここでは正常に表示されるようなら、メールを送る時におかしいという事です。

まずはこれを調べるといいと思いますよ。
そうすれば自ずと何処を修正すればいいのかわかると思います。

質問者 タクヤ  [削除]  投稿日 7/26(木) 23:43:58

>画像が壊れているとのことですが、順番に調べていきましょう。
このスクリプトは画像を一旦ファイルとして保存しているので、メールを送る前に
ブラウザーで表示してみて、画像が壊れているかどうか確認すればいいと思います。
この段階で壊れているようならデータを書き込む時におかしいと言う事です。
しかしここでは正常に表示されるようなら、メールを送る時におかしいという事です。

この方法は、名案ですね。
で、早速実行したいのですが、一時保存先を覗く方法が、わかりません。
tmpと言うフォルダーが、一時保存先なのですが、、、。
http://www.pixy.cx/~takuya_/form_mail/tmp/にアクセスして、見たのですが、この方法は、間違っていますか?
回答者 まさ  [削除]  投稿日 7/27(金) 15:01:30
URLはあってると思いますよ。

しかしそのままではメールを送ったあとでTMPのデータを削除してしまうので、それを残して
確認してみましょう。

以下の部分を

if (open(UU,"$UUENCODE $tmp$filenum $filename |")) {
 @UUFILE = <UU>;
 close(UU);
 print OUT @UUFILE;
}

if (-e "$tmp$filenum") { unlink("$tmp$filenum"); }

------------------------------------------

if (open(UU,"$UUENCODE $tmp$filenum $filename |")) {
 @UUFILE = <UU>;
 close(UU);
 print OUT @UUFILE;
}

#if (-e "$tmp$filenum") { unlink("$tmp$filenum"); }

------------------------------------------

こうしてそのURLにアクセスしてみて下さい。

質問者 タクヤ  [削除]  投稿日 8/2(木) 04:47:23
お返事チョット、用事が入り、遅くなりました。

早速コピー&ペーストしてみたら、internal server errorとなってしまいました。
で、最後の#ifの行だけを、変更したら、成功しました。

どうやら、送信した時点では、画像は、ちゃんと送られているようです。

と、なるといったいどんな、原因が考えられるのでしょうか?
また、お力を貸してください。
回答者 まさ  [削除]  投稿日 8/3(金) 15:31:20
画像が正常にサーバーにUPされているのを確認しましたか?

その段階で正常なら確かにメールを送る時に異常になっていると言う事ですね。
ところで使っているメーラーは何でしょうか?
ちゃんとuuencodeで受信するようになっているのでしょうか?
これがBase64とかになっているという事はないのでしょうか?

もしメーラーの設定も正常なら、一度Base64でエンコードしてみて下さい。
本当はモジュールを使うのがよいですが、インストールされていないとなると、base64.pl
と言うライブラリーがどこかにあったと思います。どこにあるのか忘れましたので、これは
ご自分で探してみてください。

回答者 まさ  [削除]  投稿日 8/3(金) 15:48:25
ありました。

http://raiden.goice.co.jp/member/mo/lib/perl/

ここにbase64.plがあります。
使い方は

require './base64.pl';
$data = &base64'b64encode($data);

これで$dataがBase64エンコードされます。


質問者 タクヤ  [削除]  投稿日 8/6(月) 11:13:12
まささんお手数おかけしています。
解決へ向かっていると信じています。

outlook expressを使っているのですが、uuencodeで受信するようになっているかが、どこで見れば良いのかわかりません。

base64.plを
http://raiden.goice.co.jp/member/mo/lib/perl/
から、ダウンロードして、またそれをサーバーにアップロードし。

CGIの構文の中に、
require './base64.pl';
$data = &base64'b64encode($data);
を挿入してみたのですが、internal server errorとなってしまいました。
どこを間違ってしまったのでしょうか?

回答者 まさ  [削除]  投稿日 8/6(月) 17:40:51
outlookなら恐らく問題ないでしょう。
送られてくるエンコード方式により自動的に切り替えるんじゃないでしょうか。
わたしはoutlook使ってないので、あまりはっきりしたこと言えませんが。
一度試しにでもメーラーを替えて見る事をお勧めしますが。

でInternal Server Errorはどこかに記述ミスがあるのでしょう。
シェルが使えたり、ローカルでCGIが使えたりすると、「perl -wc foo.cgi」でエラー
の個所を教えてくれます。

シェルが使えないのではあれば、またURLを教えて下さい。

質問者 タクヤ  [削除]  投稿日 8/7(火) 15:33:25
メーラーを変えてみました。
IEとは、違った感じで、画像が壊れていました。

シェルが使えるのかどうか、また、どうやって使うのか解りません。
お手数ですが、一度見てもらえるでしょうか。
http://www.pixy.cx/~takuya_/form_mail/form2mail.cgi
回答者 まさ  [削除]  投稿日 8/7(火) 18:46:54
メーラー変えても壊れてますか。
それはやっぱりスクリプトのせいですね。

ところで
http://www.pixy.cx/~takuya_/form_mail/form2mail.cgi
これだとCGIが実行されてしまい、Errorが出るので、TEXTファイルにしてUP
してみて下さい。

回答者 まさ  [削除]  投稿日 8/7(火) 19:07:32
Base64に変更するのって意外と厄介ですね。
これcgi-lib.plを使っているし。わたしならCGI.pmを使います。
でエンコードはMIME::Base64ですね。

これ改造するより、いちから作った方が早そーですね。

で、もう一度知りたいのですが、サーバーのOSはWindowsなのですね。
今ちなみにUNIXの環境で動かしましたが、正常に動きました。

ところでWindowsで動いているとなるとsendmailやuuencode、nkfと言うのはどう
しているのでしょう?




質問者 タクヤ  [削除]  投稿日 8/8(水) 00:59:49
すいません
http://www.pixy.cx/~takuya_/form_mail/tmp/
こちらで見れるでしょうか?

「いちから作る」ですか、、、。
凄い発想に、目が点です。

UNIX向けなんですね。

>ところでWindowsで動いているとなるとsendmailやuuencode、nkfと言うのはどう
しているのでしょう?

あまり詳しいことは、解りませんが、サーバー指定のパスにアクセスしています。
回答者 まさ  [削除]  投稿日 8/8(水) 07:50:14
ちょっと気になりましたが、このtmpに入っている画像は既に壊れていると言うことは
ないのでしょうか?
画像に何か縞模様のようなものが入っているのですが。

これが壊れているか壊れていないかは大問題ですからね。

質問者 タクヤ  [削除]  投稿日 8/8(水) 12:12:03
tmpファイルを覗いた時は、普通に表示されました。
と言うことは、ちゃんと送られているって事でしょうか?

返信(回答)する


Web裏技