phpsource/파일분석2002. 9. 9. 16:47
PHP에서 제공하는 함수에는 파일을 압축할 수 있는 zlib 라이브러리를 기본적으로 제공하고 있습니다.
압축하기
리눅스의 gzip 프로그램의 출력과 호환성을 유지하기 위해서는 zlib 라이브러리에서 제공하는 함수 중에서 gzencode 함수를 이용하여야 합니다. 이 함수에 의해 얻은 값은 gzip 프로그램의 출력값과 호환성을 가지므로 리눅스의 gzip 프로그램 또는 윈도우의 윈도우커맨더를 가지고 압축을 풀 수가 있습니다. 예를 들어 gzencode 함수를 이용하여 gz 파일을 생성해 주는 사용자 정의 함수를 작성하면 아래와 같습니다.
[code php;gutter:false] function gzcreate($gzfile, $contents) {
if (!$contents=gzencode($contents)) { // PHP4 >= 4.0.4
return false;
}

if (!$fp=fopen($gzfile, "wb")) {
return false;
}

fwrite($fp, $contents);
fclose($fp);

return true;
} [/code]
위 소스 중에 fopen 함수에서 mode 인수를 "wb"로 설정하였습니다. 유닉스에서는 이진(binary)을 의미하는 "b"를 사용하지 않더라도 정상적으로 파일을 처리해 줍니다. 그러나 윈도우에서는 이진 파일과 텍스트파일을 구분하여 저장하거나 읽지 않으면 저장된 파일을 정상적으로 다룰 수 없습니다. 가끔가다 자료실에 있는 이미지 파일이나 압축파일을 다운로드할 때 파일의 헤더부분만 읽어오므로 아무런 내용도 담기지 않은 파일이 다운로드될 때가 있습니다. 이럴 때는 해당 파일이 정확히 이진 모드로 다루어졌는지 확인하여야 합니다. 따라서 리눅스나 유닉스 계통에서는 별 문제가 없는데, 윈도우 서버에서 그런 문제가 발생할 수 있습니다. 따라서 윈도우에서 이미지 파일 또는 압축파일과 같이 바이너리 형태의 파일을 읽거나 쓸 때는 fopen 모드 인자에 반드시 "b" 옵션을 추가해야 정상적으로 다룰 수 있습니다. 유닉스에서는 "b" 옵션을 사용하지 않으며, 설사 "b" 옵션을 지정하더라도 그냥 무시해 버립니다.
압축해제하기
예를 들어 gzib 함수를 이용하여 압축된 파일을 풀기위해서는 대략 아래와 같이 사용자 정의 함수 gzextract 함수를 작성하면 될 것입니다.
[code php;gutter:false] function tarextract($gzfile) {
if (!$fp=fopen($gzfile, "rb")) {
return false;
}

$contents = fread($fp, filesize($gzfile));
fclose($fp);

if (!$contents=gzdecode($contents)) { // PHP4 >= 4.0.4
return false;
}

return $contents;
} [/code]
위의 코드가 제대로 실행될 것 같습니까? 아닙니다. 2002년 8월 31일 현재 PHP에서는 gzencode 함수만 제공할 뿐 gzdecode 함수를 제공하고 있지 않습니다. 그러나 http://www.php.net/manual/en/function.gzencode.php를 보시면 gzdecode 함수를 구현해 주는 팁이 공개되어 있습니다. 그 내용은 아래와 같습니다.
henryk@ploetzli.ch
14-Feb-2002 07:28

Well, I was looking for a gzdecode too and didn't consider the temporary file example above
to be very elegant.
However, as is noted in the very first comment: gzencode() only adds a 10 byte header.

I don't quite know what this header is supposed to be used for, but gzinflate() certainly
doesn't like it, so I stripped it off:

function my_gzdecode($string) {
$string = substr($string, 10);
return gzinflate($string);
}

That's useful to read HTTP-Connections that were compressed by mod_gzip.
--
Henryk Plotz
Gruße aus Berlin


tychay@alumni.caltech.edu
03-Apr-2002 03:53

The 10 byte string in gzencode is the standard gzip header. The first two bytes (1f 8b)
define the return as a gzip file, the third byte (08) means that the body is compressed using
the "deflate" algorithm. The rest is padding (00)'s.

Technically, I believe one should check if the third byte is hex 08 and if so strip off the
first ten bytes and last four bytes and run inflate on it. The last four bytes are file size
and checksum bits.

In practice, you can get away with just stripping the first 10 bytes and running inflate on
it.

Hope this helps,

terry
이 팁에 의해 gzdecode 함수를 작성하면 대략 아래와 같이 될 것입니다.
[code php;gutter:false] function gzdecode($data) {
if("\x1f\x8b\x08" == substr($data, 0, 3)) {
return gzinflate(substr($data, 10, -4)); // PHP4 >= 4.0.4
}
return false;
} [/code]
그런데 이렇게 작성된 gzdecode 함수도 그리 완벽하지는 않습니다. 위에서 설명한 gzencode 함수로 생성된 압축파일을 푸는데는 전혀 문제없이 동작합니다만 리눅스의 gzip 또는 윈도우의 윈도우커맨더, 알집 등으로 압축한 파일은 정상적으로 풀지를 못하네요. 즉, 팁에 의해 작성된 사용자 정의 함수 gzdecode는 리눅스의 gzip 프로그램의 출력과 완전한 호환성을 유지하지는 못하고 있습니다. 이러한 부분은 PHP에서 향후 공식적으로 gzdecode 함수를 제공하여야 가능할 것으로 보입니다. 아니면 좀더 개선된 팁이 공개되든가......

'phpsource > 파일분석' 카테고리의 다른 글

{TAR 파일}8.클래스 다운로드  (0) 2002.09.16
{TAR 파일}7.클래스  (0) 2002.09.09
{TAR 파일}5.후미에 붙여지는 블록  (0) 2002.09.09
{TAR 파일}4.본문 구조  (0) 2002.09.09
{TAR 파일}3.헤더 구조  (1) 2002.09.09
Posted by 방글24