アプリ版:「スタンプのみでお礼する」機能のリリースについて

CGIでの処理で、今

http://xxxx.com/ok.cgi?id=123&pass=abc&page=inde …

でindex.html が表示されているとします。
それで、このindex.htmlから別の拡張子のファイルへリンクさせ、ファイルをダウンロードできるようにしたいと思っています。lzh ならURLはこん感じになります。

http://xxxx.com/ok.cgi?id=123&pass=abc&page=samp …

 しかし ok.cgi の最後で

print "Content-type: text/html\n";
exit;

を指定しているのでリンク先へ行ってもindex.htmlは表示されますが、リンク先のファイルは動きません。

どうすればダウンロード出来るようになるでしょうか? なるべくこのok.cgi の外に出したくないのです。
 また、この中で、リンク先が隠れるphpを入れたいと考えましたが、phpも同様に機能しません。これもどのようにすればよろしいでしょうか?

 どなたかよろしくお願い致します。

A 回答 (4件)

GETパラメータで処理を分ければいいんじゃないかなあ



#!/usr/bin/perl -T
use warnings;
use strict;
use utf8;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use CGI::Pretty;

my $q = CGI->new();
my $id = $q->param("id");
my $pass = $q->param("pass");
my $page = $q->param("page");

if ( $page eq 'index.html' ) {
print $q->header( -charset => 'UTF-8' );
print $q->start_html(
-lang => 'ja',
-title => ' T I T L E '
);
print $q->end_html;
}
else {
print $q->header(
-type => 'application/octet-stream',
-attachment => $page
);
open my $fh, '<', $page or croak "$page: $!";
binmode $fh;
my $buffer = '';

while ( read $fh, $buffer, 1024 ) {
print $buffer;
}
close $fh or croak "$page: $!";
}
    • good
    • 0
この回答へのお礼

ありがとうございます。

 どうもうまくいきません。

print $q->header( -charset => 'UTF-8' );

のラストを , に変更するにはしましたが、その後 else{ } を入れた段階でエラーになってしまいます。

 ところで print $q->end_html; はprint を付けると 1 と言う文字が表示されてしまうので、purint は要らないと思って良いのですよね?

 うまくいかないのは何が原因でしょうか?

お礼日時:2009/07/30 11:36

このようなものでは?


if($IN{'page'} =~ /^(.*?)\.html$/){
print "Content-type: text/html\n\n";
}elsif($IN{'page'} =~ /^(.*?)\.lzh$/){
print "application/x-lzh-compressed\n\n";
}else{
print "Content-type: text/html\n\n不正なファイルが要求されました。";
}
のように、正規表現で分ける。
    • good
    • 0
この回答へのお礼

ありがとうございます。
現在いじっているCGIのログイン部ですが、以下のようになっています。
古くに作って頂いたCGIで、それに手をくわえたいと思っていました(作った人は今連絡が取れない)。
昨日からお教えいただいたものを入れようとしましたが、わたしの知識不足で、挫折ぎみです。
お手数ですが、以下の場合どのように手を加えれば宜しいでしょうか?

#ok.cgi  ログイン部分
#######################
sub login {

if($in{'page'} eq "") { $in{'page'} = "index"; }

# tmp以下に入れるとしています。
open(IN,"./tmp/$tsite/$in{'page'}.html");
while(<IN>){$buffer.=$_;}
close(IN);

$buffer =~ s/<!--id-->/$in{'id'}/ig;
$buffer =~ s/<!--passwd-->/$in{'pass'}/ig;

# 諸事情から ~.ok.cgi?id=<!--id-->&pass=<!--passwad-->&page=index となっています。
# 別に ?id=$id&pass=$pass でいいと思いますが・・・。それはそれとして・・・。 
print "Content-type: text/html\n\n$buffer\n";
exit;
}
#########################

よろしければ再度ご教授下さい。

お礼日時:2009/07/31 13:50

エラーの内容がわからないので、何とも言えないですが、ファイルの読み


取り権限とか、パスの問題のような気がします。パスの場合はフルパスで
指定するとどうでしょうか?

else {
print $q->header(
-type => 'application/octet-stream',
-attachment => $page
);
# tmpにファイルがあるとして、
my $full_path = '/tmp/' . $page;
open my $fh, '<', $full_path or croak "$page: $!";
binmode $fh;
my $buffer = '';

while ( read $fh, $buffer, 1024 ) {
print $buffer;
}
close $fh or croak "$page: $!";
}

あるいは、次のようにして問題を切り分けするのも手です。次のようにすれば、'Hello CGI'という内容のテキストファイルがダウンロードできます。

else {
print $q->header(
-type => 'application/octet-stream',
-attachment => $page
);
print "Hello CGI\n";
}

>print $q->end_html; はprint を付けると 1 と言う文字が表示
これは、
>print $q->header( -charset => 'UTF-8' ); のラストを , に変更するに
>はしましたが
これが原因だと思います。
一つのprint文で済ませたいときは、
print $q->header( -charset => 'UTF-8' ),
$q->start_html(
-lang => 'ja',
-title => ' T I T L E '
).
$q->end_html;
として下さい。一つのprint文で済ますのが、一般的かもしれませんね。

この回答への補足

補足覧をお借りしてお礼申し上げます。

 別途ある処理の仕方を思いつき、うまくいきました。

 お二人様ありがとうございました。

補足日時:2009/08/04 12:22
    • good
    • 0
この回答へのお礼

再度ご教授ありがとうございます。
エラーですが、Internal Server Error と出るだけで、詳しい内容は私も分からないのです。

 No,2様のものと平行してこちらも勉強させて頂いています。
実は cgi pm というものをしらなかったので、今さらですが、調べながら触っています。

 こちらももう少しテストしていきたいと思います。

ちなみに現状のプログラムはNo,2様の回答欄をご覧下さい。
 

お礼日時:2009/07/31 13:59

#2です



>if($in{'page'} eq "") { $in{'page'} = "index"; }
if($in{'page'} eq "") { $in{'page'} = "index.html"; }

>open(IN,"./tmp/$tsite/$in{'page'}.html");
open(IN,"./tmp/$tsite/$in{'page'}")||&ErrorNotFile;

>print "Content-type: text/html\n\n$buffer\n";
if($in{'page'} =~ /^(.*?)\.html$/){
print "Content-type: text/html\n\n$buffer\n";exit;
}elsif($in{'page'} =~ /^(.*?)\.lzh$/){
print "application/x-lzh-compressed\n\n$buffer";
exit;
}else{
print "Content-type: text/html\n\n不正なファイルが要求されました。";
}

#以下追加
sub ErrorNotFile {
print "Content-type: text/html\n\nファイルが存在しません";
exit;
}

のように変えてください。

この回答への補足

最初はそのままコピペしたのでlzhのところ Content-type: が抜けていたので表示されなかったようです。その後いろいろやってみましたが、このままだと使えませんね(笑

zip の場合
Content-type: application/zip 及び application/octet-stream で検証。

それぞれダイアログに出てきたファイル名と成否です。

opera: ok.zip (一応ダウンロード出来、ファイルも正常)
firefox: ok.cgi
IE6: ダイアログなしでいきなりダウンロードでいきなり解凍。一応ファイルは正常たが、探さないとどこに収まったか分からない。どこにあるか分からない為ファイル名は不明。逆に不明だからすぐにはどこにあるか分からない。

lzh の場合
Content-type: application/octet-stream 及び application/x-lzh-compressed で検証。
opera: ok.cgi (ダウンロードしても開かない)
fierfox: ok.cgi (ダウンロードしても開かない)
IE6: ダイアログなしでいきなりダウンロード。一応ダウンロード出来ていたが、探さないとどこに収まったか分からない。ファイル名はok.lzh

php の場合
opera: 表示されない。
Firefox: 表示されない。
IE6: 表示されない。

phpだけでも正常に機能してくれたら、リンク先も見えないのでcgiの外に出すのですが...(泣

補足日時:2009/08/01 18:59
    • good
    • 0
この回答へのお礼

ありがとうございます。

 ダメです....(T^T;)

 例えば、改造なしで、最初からlzh を対象とするとして、直接 sample.lzh へ向かうように。

 if($in{'p'} eq "") { $in{'p'} = "sample"; }

 open(IN,"./item/$tsite/$in{'p'}.lzh");
  while(<IN>){$buffer.=$_;}
 close(IN);

  #省略#

 print "application/x-lzh-compressed\n\n$buffer\n";

のみにしておいてもファイルが出てきません。
ダウンロード時に現れるダイアログのファイル名には、
IEではただ「ok」、
オペラでは「ok.cgi」になっており、
「sample.cgi」が出ないのです。
 
 いったいどういう事なのか・・・・。

 この場合すぐダイアログが現れるので ブラウザURLの最後に ~sample.lzh 部分がありません。

 http://xxxx.com/ok.cgi?id=123&pass=abc

 の状態です。

 そしてプログラムをいじらないままで、まずindex.htmlへ向かい、そこからsample.lzhへリンクすると ブラウザのURLはきちんと

http://xxxx.com/ok.cgi?id=123&pass=abc&page=samp …

となっていますが、この場合には今度はダイアログさえ出てきません。

 もうなにがなんだか....。

お礼日時:2009/08/01 13:57

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!