#webliberty::Parser.pm (2006/02/18)
#Copyright(C) 2002-2006 Knight, All rights reserved.

package webliberty::Parser;

use strict;
use base qw(webliberty::Basis);

### コンストラクタ
sub new {
	my $class = shift;
	my %args = @_;

	my $self = {
		max   => $args{'max'},
		jcode => $args{'jcode'},
		plain => $args{'plain'},
		query => undef
	};
	bless $self, $class;

	if (!$self->{max}) {
		$self->{max} = 15000;
	}
	if ($self->{jcode}) {
		require Jcode;
	}
	if ($ENV{'CONTENT_LENGTH'} or $ENV{'QUERY_STRING'}) {
		$self->{query} = $self->_parse_query($self->{max});
	}

	return $self;
}

### データ取得
sub get_query {
	my $self = shift;
	my $name = shift;

	my $query;

	if ($name) {
		$query = $self->{query}->{$name};
	} else {
		$query = $self->{query};
	}

	return $query;
}

### ファイル名取得
sub get_filename {
	my $self = shift;
	my $name = shift;

	my $filename;

	if ($self->{query}->{$name}) {
		$filename = $self->{query}->{$name}->{file_name};
	}

	return $filename;
}

### ファイルデータ取得
sub get_filedata {
	my $self = shift;
	my $name = shift;

	my $filedata;

	if ($self->{query}->{$name}) {
		$filedata = $self->{query}->{$name}->{file_data};
	}

	return $filedata;
}

### ファイルサイズ取得
sub get_filesize {
	my $self = shift;
	my $name = shift;

	my $filesize;

	if ($self->{query}->{$name}) {
		$filesize = $self->{query}->{$name}->{file_size};
	}

	return $filesize;
}

### マイムタイプ取得
sub get_mimetype {
	my $self = shift;
	my $name = shift;

	my $mimetype;

	if ($self->{query}->{$name}) {
		$mimetype = $self->{query}->{$name}->{mime_type};
	}

	return $mimetype;
}

### データ解析
sub _parse_query {
	my $self = shift;

	my($alldata, $query);

	if ($ENV{'CONTENT_TYPE'} =~ /^multipart\/form-data;\s+boundary=(.+)/) {
		my $boundary = $1;

		binmode(STDIN);
		read(STDIN, $alldata, $ENV{'CONTENT_LENGTH'});

		my($key, $file);

		foreach (split(/\r\n/, $alldata)) {
			if (/$boundary/) {
				if ($file->{file_name}) {
					$query->{$key} = $file;
					$file = undef;
				}
			} else {
				if (/^Content-Disposition:\sform-data;\sname=\"([^\"]*)\"/) {
					$key = $1;
					if (/filename=\"([^\"]*)\"/i) {
						$file->{file_name} = $1;
					}
				} elsif (/^Content-Type:\s(\S+)/) {
					$file->{mime_type} = $1;
				} else {
					if ($file->{file_name}) {
						if ($file->{file_data}) {
							$file->{file_data} .= "\r\n";
						}
						$file->{file_data} .= $_;

						$file->{file_size} += length("$_\r\n");
					} else {
						if ($query->{$key}) {
							$query->{$key} .= "\n";
						}
						$query->{$key} .= $self->_create_text($_);
					}
				}
			}
		}
	} else {
		if ($ENV{'REQUEST_METHOD'} eq 'POST') {
			if ($self->{max} and $ENV{'CONTENT_LENGTH'} > $self->{max}) {
				$self->error("最大受信容量は$self->{max}byteです。（現在$ENV{'CONTENT_LENGTH'}byte。）");
			} else {
				read(STDIN, $alldata, $ENV{'CONTENT_LENGTH'});
			}
		} else {
			$alldata = $ENV{'QUERY_STRING'};
		}
		foreach (split(/&/, $alldata)) {
			my($key, $value) = split(/=/);

			$key   =~ tr/+/ /;
			$key   =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('C', hex($1))/eg;

			$value =~ tr/+/ /;
			$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('C', hex($1))/eg;

			$value = $self->_create_text($value);

			if ($query->{$key}) {
				$query->{$key} .= "\n";
			}
			$query->{$key} .= $value;
		}
	}

	return $query;
}

### テキストデータ作成
sub _create_text {
	my $self = shift;
	my $text = shift;

	if ($self->{jcode} and $text =~ /[^\w\.\~\-\/\?\&\#\+\=\:\;\@\%]+/) {
		my $jcode_ins = new Jcode($text);
		$text = $jcode_ins->utf8;
	}
	if (!$self->{plain}) {
		$text =~ s/&/&amp;/g;
		$text =~ s/</&lt;/g;
		$text =~ s/>/&gt;/g;
		$text =~ s/"/&quot;/g;
	}

	return $text;
}

1;
