phpsource/파일분석2002. 9. 9. 16:39
TAR 아카이브를 구성하는 멤버 파일 및 디렉토리에 관한 모든 정보(헤더 및 본문)가 다 기록된 후에는 마지막으로 파일 내용과 관계없이 null로 채워진 1블록 이상의 빈블록(empty block)들이 붙여지게 됩니다.
예를 들어 TAR 아카이브 파일의 마지막에 임의로 추가되는 빈블록을 덤프해 보면 아래와 같이 null 문자만으로 채워져 있음을 알 수 있습니다.
< TAR 아카이브 파일의 마지막에 임의로 추가되는 빈블록 구조 >

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

{TAR 파일}7.클래스  (0) 2002.09.09
{TAR 파일}6.zlib를 이용한 압축  (0) 2002.09.09
{TAR 파일}4.본문 구조  (0) 2002.09.09
{TAR 파일}3.헤더 구조  (1) 2002.09.09
{TAR 파일}2.아카이브 구조  (0) 2002.09.09
Posted by 방글24
phpsource/파일분석2002. 9. 9. 16:30
파일 헤더가 완성되었으면 뒤이어 파일 내용이 들어가게 됩니다. 파일 내용은 512 바이트의 배수로 기록됩니다. 만약 파일크기가 1바이트부터 512 바이트사이라면 1블록(512바이트)을 사용하고 513바이트부터 1024바이트까지는 2블록(1024바이트)을 사용하는 식입니다.
결국 TAR 아카이브에서의 파일 내용 부분이 차지하는 크기는 아래와 같은 식으로 구할 수 있습니다.
[code php;gutter:false] function calc_blocksize($realsize) {
return ceil($realsize / 512) * 512;
} [/code]
본문에서도 헤더 구조에서와 마찬가지로 채워지지 않은 빈 공간에 모두 null로 채워야 합니다.
파일크기가 0바이트인 파일인 경우에는 디렉토리인 경우와 마찬가지로 파일 헤더만 존재하며 본문은 기록되지 않습니다.
예를 들어 s1.txt 파일에 대한 본문 구조를 덤프해 보면 아래와 같습니다.
< s1.txt 파일에 대한 본문 구조 >

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

{TAR 파일}6.zlib를 이용한 압축  (0) 2002.09.09
{TAR 파일}5.후미에 붙여지는 블록  (0) 2002.09.09
{TAR 파일}3.헤더 구조  (1) 2002.09.09
{TAR 파일}2.아카이브 구조  (0) 2002.09.09
{TAR 파일}1.개요  (0) 2002.09.09
Posted by 방글24
phpsource/파일분석2002. 9. 9. 16:11
TAR 아카이브 포맷
TAR 아카이브의 포맷을 보면 이전의 유닉스 호환 포맷(UNIX-compatible formats)과 POSIX (IEEE P1003.1) 기준으로 새로이 정의된 USTAR 포맷(USTAR format)이 있습니다. 새로이 정의된 USTAR 포맷은 유닉스 호환 포맷보다 더 많은 정보를 저장할 수 있으며 더 긴 파일 패스명을 지원합니다. 그러나 어느 포맷이 되었든지 헤더는 512바이트 크기의 1블록으로 구성되어 있습니다.
우선 이전의 유닉스 호환 포맷에 의한 헤더 구조를 보면 아래와 같습니다.
< 유닉스 호환 포맷에 의한 헤더 구조 >
FIELD NAME OFFSET SIZE MEANING
name 0 100 name of file
mode 100 8 file mode
uid 108 8 owner user ID
gid 116 8 owner group ID
size 124 12 length of file in bytes
mtime 136 12 modify time of file
chksum 148 8 checksum for header
link 156 1 indicator for links
linkname 157 100 name of linked file
link 필드에는 링크 파일(linked file)이면 1, 심볼릭 링크(symbolic link) 이면 2, 기타일 때는 0이 기록됩니다. 디렉토리의 경우에는 링크명에 슬래시(/)가 붙게되지요.
새로운 USTAR 포맷에 의한 헤더 구조는 아래와 같습니다. magic 필드에는 null 문자로 종료되는 문자열 "ustra"이 기록되며 magic 필드 이전의 모든 필드는 typeflag 필드를 제외하고는 모두 이전의 유닉스 호환 포맷과 동일합니다. 유닉스 호환 포맷에서의 link 필드가 USTAR 포맷에서는 typeflag 필드로 변경되었습니다.
< USTAR 포맷에 의한 헤더 구조 >
FIELD NAME OFFSET SIZE MEANING
name 0 100 name of file
mode 100 8 file mode
uid 108 8 owner user ID
gid 116 8 owner group ID
size 124 12 length of file in bytes
mtime 136 12 modify time of file
chksum 148 8 checksum for header
typeflag 156 1 type of file
linkname 157 100 name of linked file
magic 257 6 USTAR indicator
varsion 263 2 USTAR version
uname 265 32 owner user name
gname 297 32 owner group name
devmajor 329 8 device major number
devminor 337 8 device minor number
prefix 345 155 prefix for file name
이와 같이 어느 포맷이 되었든지 파일명, 파일크기 등 파일 정보에 관한 내용이 저장되는 헤더는 1블록(512바이트)로 구성되어 있습니다.
TAR 아카이브를 다룰 때 name 필드부터 typeflag 필드까지만 정확히 다루게 된다면 윈도우를 포함한 어느 시스템에서나 정상적으로 동작하는 것 같습니다. 즉 여러분이 PHP를 이용하여 작성된 TAR 아카이브를 가지고 유닉스 또는 리눅스의 tar 유틸리티를 이용하여 풀 수 있으며, 또한 윈도우에서 알집이나 window commander에서 풀 수도 있습니다.
테이블에 나타난 바와 같이 각 필드마다 그 위치와 크기가 고정되어 있습니다.
magic, uname, gname 필드는 마지막 코드는 반드시 null(아스키문자 0)이 나타나는 null 종료 문자열(null-terminated character strings)입니다. name, linkname, prefix 필드는 마지막 코드가 반드시 null일 필요는 없으나 정해진 필드크기가 다 채워지지 않았다면 채워지지 않은 빈 공간을 반드시 null로 채워야 합니다. name 필드의 예를 들어보면 만약 파일명이 "s1.txt"라면 name 필드에 기록될 때는 "s1.txt" . str_repeat(chr(0), 100 - strlen("s1.txt"))에서 얻은 값으로 기록됩니다.
USTAR 포맷에서 uname, gname 필드는 각각 로그인 사용자명과 그룹 사용자명을 기록합니다.
mode, uid, gid, chksum, devmajor, devminor 필드의 마지막 코드는 반드시 null이 기록되어야 하나 size, mtime, version 필드는 반드시 null로 종료할 필요는 없으나 일반적으로 null이 기록되는 것 같습니다. 따라서 숫자를 나타내는 이들 필드는 모두 null로 종료한다고 생각하시면 될 것입니다. 이와 같이 숫자를 나타내는 필드들은 모두 null로 종료되므로 실제로 숫자가 기록되는 장소의 크기는 테이블에 정하여진 SIZE-1이 됩니다. 예를 들어 uid의 경우를 보면 필드 크기는 8바이트이지만 실제로 OFFSET 108부터 114까지의 7바이트에만 기록되며 마지막 OFFSET 115에는 null이 기록됩니다. 숫자 필드에서 한가지 주의할 것은 기록되는 숫자는 10진수가 아니라 8진수로 기록된다는 것이지요. 그리고 기록되는 숫자의 자리수가 필드 크기보다 작을 때는 앞쪽으로 남는 자리수만큼 "0"으로 채워지게 됩니다. 만약 uid 값이 8이라면 uid 필드에는 "0000010"이 기록됩니다.
어떤 필드가 되었든지 헤더에서 사용되지 않는 공간은 모두 null로 채우도록 되어있습니다. 이제는 각 필드별로 다른 특징을 살펴보지요.
"name" 필드는 파일명 또는 디렉토리명이 기록되는 곳으로 총 100자까지 기록될 수 있습니다. 파일명이 100자가 되지 않아 비워있는 곳은 모두 null 값으로 채워집니다. 여기에 기록되는 파일명에는 패스명이 포함됩니다.
USTAR 포맷의 경우를 보면 prefix 필드의 값이 null이 아니라면 100자가 넘는 파일명이 가능하도록 name 필드 앞에 붙게 됩니다. 그러나 이전의 유닉스 호환 포맷이나 윈도우 시스템에서 TAR 아카이브를 만들 수 있는 윈도우커맨더 등과의 호환성을 생각한다면 prefix 필드를 null로 남겨두는 것이 좋을 듯하며 100자가 넘는 파일명인 경우 뒷쪽을 짤라내어 100자까지만 name 필드에 저장하는 것이 좋을 듯합니다.
USTAR 포맷에서만 사용하고 있는 typeflag 필드는 이전의 유닉스 호환 포맷의 link 필드와 호환성을 유지한 채 확장시킨 것입니다. 아래는 typeflag 필드에 기록될 수 있는 값들이며 이 중에 0, 1, 2까지는 이전의 유닉스 호환 포맷과 호환성을 유지합니다.
< typeflag 필드의 값 >
TYPE FLAG FILE TYPE
0 or null Regular file
1 Link to another file already archived
2 Symbolic link
3 Character special device
4 Block special device
5 Directory
6 FIFO special file
7 Reserved
A-Z Available for custom usage
"typeflag"는 파일 형식을 나타내는 필드로 디렉토리일 때는 "5"가 기록되며 파일일 경우에는 "0"이 기록됩니다.
"mode" 필드는 파일 모드가 기록되는 곳으로 8진수로 기록됩니다. 예를 들면 0755, 0644와 같지요. "mode" 필드에서 사용할 수 있는 크기는 총 7자입니다. 이 경우 보통 "0000755"와 같이 남는 공간은 앞쪽에 "0"으로 채우게 됩니다. 그러나 이러한 기록 방법은 프로그램에 따라 약간씩 차이가 나기도 하네요. 윈도우 유틸리티인 windows commander에서 TAR 아카이브를 만들게 되면 "000755 " 또는 "000644 "와 같이 6자만 8진수로 만들어 주고 7번째 자리에는 " "로 채우게 됩니다. 윈도우에서야 원래 파일 모드라는 개념이 없으니까 관계가 없다고 생각할지 모르겠으나 윈도우에서 압축한 TAR 아카이브를 리눅스에서 풀 때는 생각한다면 이를 적절히 처리하는 것이 좋을 것 같습니다.
"uid"와 "gid"도 "mode"와 같이 8진수로 기록되며 총 7자리를 만들 게 됩니다. 빈 공간은 앞쪽에 "0"을 채우게 되지요.
"size"는 바이트 단위의 파일 크기를 나타내며 8진수로 기록됩니다.
"mtime"는 파일을 수정한 시간을 나타내며 이에 해당하는 php 함수는 filemtime()입니다.
"magic" 필드는 압축 알고리즘의 이름을 나타내며 보통 "ustar" 또는 "GNUtar" 등이 기록됩니다. 6자가 안되는 부분은 " "로 뒤쪽에 채워지게 됩니다.
"linkname", "uname", "gname", "devmajor", "devminor", "prefix", "noname" 필드는 모두 chr(0)으로 채워넣습니다.
위와 같이 "chksum" 필드를 제외한 필드를 모두 기록한 후에 마지막으로 "chksum" 필드를 기록합니다. "chksum" 필드는 묶여진 파일이 정상적인가를 확인하는데 이용하는 체크섬 필드입니다. 8진수로 기록되며 채워지지 않는 부분은 앞쪽으로 "0"으로 채우게 됩니다. 체크섬 값은 아래와 같은 방법으로 구하게 됩니다. 이 때 변수 $HEADER에는 "chksum" 필드를 제외한 필드가 위에서 기술한 방법대로 먼저 기록되어 있다고 가정합니다.
[code php;gutter:false] function get_checksum() {
global $HEADER;

$sum = 0;

for ($i=0;$i<512;$i++) {
if ($i < 148 || 156 < $i) {
$sum += ord($HEADER[$i]);
} else {
$sum += ord(" ");
}
}

return $sum;
} [/code]
만약 기록하고자 하는 것이 파일이 아니라 디렉토리라면 파일과 같은 내용이 없기 때문에 512바이트의 헤더만 존재합니다. 한번 디렉토리 정보가 기록되면 그 뒤의 파일들은 앞에서 나타난 디렉토리에 속하게 됩니다. 따라서 디렉토리가 변경되는 부분에서만 단 한번 디렉토리 정보가 기록됩니다. 앞에서도 설명하였지만 파일 헤더와 다른 점이라면 "typeflag" 필드값이 "5"라는 것과 "name" 필드에는 파일명 대신에 패스명이 기록됩니다. 예를 들면 "sub1/sub2/"와 같지요. 다른 필드는 파일일 때와 같습니다.
디렉토리 정보가 없이 파일을 묶었을 때의 헤더 구조
예를 들어 TAR 아카이브 파일 내용 중에서 s1.txt 파일에 대한 헤더 구조를 덤프(dump)해 보면 아래와 같습니다.
< s1.txt 파일에 대한 헤더 구조 >
디렉토리 정보와 함께 기록된 파일에 대한 헤더 구조
sub/s1.txt
sub/s2.txt
sub/s3.txt
만약 위에서와 같이 s1.txt, s2.txt, s3.txt 파일이 모두 동일한 디렉토리 sub에 존재하며 이를 묶을 때 디렉토리 정보 sub를 기록했을 때 TAR 아카이브의 s1.txt 파일에 대한 헤더 구조를 덤프해 보면 아래와 같습니다.
< 디렉토리 정보가 기록된 s1.txt 파일의 헤더 구조 >
디렉토리 정보를 기록한 헤더 구조
sub/s1.txt
sub/s2.txt
sub/s3.txt
만약 위에서와 같이 s1.txt, s2.txt, s3.txt 파일이 모두 동일한 디렉토리 sub에 존재하며 이를 묶을 때 디렉토리 정보 sub를 기록했을 때 TAR 아카이브의 sub 디렉토리 헤더 구조를 덤프해 보면 아래와 같습니다.
< sub 디렉토리에 대한 헤더 구조 >

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

{TAR 파일}5.후미에 붙여지는 블록  (0) 2002.09.09
{TAR 파일}4.본문 구조  (0) 2002.09.09
{TAR 파일}2.아카이브 구조  (0) 2002.09.09
{TAR 파일}1.개요  (0) 2002.09.09
{HTML 파서}5.다운로드  (0) 2001.07.24
Posted by 방글24
phpsource/파일분석2002. 9. 9. 15:23
TAR 아카이브는 512바이트를 1블록으로하여 다루게 됩니다. 따라서 TAR 아카이브의 크기를 보면 512 * n 바이트임을 알 수 있습니다. TAR 아카이브는 여러 개의 파일이 하나로 묶여있으므로 각 멤버파일마다 본문 내용에 앞서 파일에 대한 정보를 기록하게 되는 1블록의 헤더가 반드시 나타나며 그 뒤를 이어 n블록의 본문 내용이 나타납니다. 때에 따라서는 하나의 디렉토리에 있는 파일뿐만 아니라 다른 디렉토리에 있는 파일들도 하나의 TAR 아카이브에 묶을 때도 있을 것입니다. 이러한 경우에는 디렉토리에 대한 정보도 기록하여야 하는데 이 경우에도 파일 헤더와 같이 1블록의 디렉토리 헤더를 가지게 됩니다. 디렉토리의 경우에는 파일과는 달리 본문 내용이 없으므로 각 디렉토리마다 1블록의 디렉토리 헤더만이 존재합니다. 파일 및 디렉토리에 관한 모든 정보(헤더 및 본문)가 다 기록된 후에는 마지막으로 아스키 0으로 채워진 1블록 이상의 빈블록(empty block)들이 붙여지게 됩니다.
이젠 몇가지 실예를 들어 전체 구조가 어떻게 구성되는지 살펴보겠습니다.
동일한 디렉토리에 있는 파일들(디렉토리 정보를 기록하지 않을 때)
아래와 같이 동일한 디렉토리에 있는 세 개의 파일(s1.txt, s2.txt, s3.txt)을 디렉토리 정보를 기록하지 않고 파일정보만 기록된 TAR 아카이브의 구조를 살펴보겠습니다.
s1.txt
s2.txt
s3.txt
s1.txt, s2.txt, s3.txt 파일이 모두 동일한 디렉토리에 존재하며 이를 묶을 때 디렉토리 정보를 전혀 기록하지 않는다면 TAR 아카이브의 전체 구조는 아래와 같을 것입니다.

s1.txt 파일 헤더

s1.txt 파일 본문

 

 

 

s2.txt 파일 헤더

s2.txt 파일 본문

 

 

 

s3.txt 파일 헤더

s3.txt 파일 본문

 

 

 

빈 블록

 

 

 

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

n 블록 (512 * n 바이트)

동일한 디렉토리에 있는 파일들(디렉토리 정보를 기록할 때)
아래와 같이 동일한 디렉토리에 있는 세 개의 파일(s1.txt, s2.txt, s3.txt)을 디렉토리 정보와 함께 기록된 TAR 아카이브의 구조를 살펴보겠습니다.
sub/s1.txt
sub/s2.txt
sub/s3.txt
s1.txt, s2.txt, s3.txt 파일이 모두 동일한 디렉토리 sub에 존재하며 이를 묶을 때 디렉토리 정보 sub를 기록한다면 TAR 아카이브의 전체 구조는 아래와 같을 것입니다.

sub 디렉토리 헤더

s1.txt 파일 헤더

s1.txt 파일 본문

 

 

 

s2.txt 파일 헤더

s2.txt 파일 본문

 

 

 

s3.txt 파일 헤더

s3.txt 파일 본문

 

 

 

빈 블록

 

 

 

1 블록 (512 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

n 블록 (512 * n 바이트)

여러 개의 디렉토리에 있는 파일들
s1.txt
s2.txt
sub1/s3.txt
sub1/sub2/s4.txt
sub1/sub2/s5.txt
sub1/sub2/sub3/s6.txt
sub4/s7.txt
s1.txt, s2.txt, s3.txt 파일이 여러 개의 디렉토리에 분산되어 존재하며 이를 묶을 때 이들 디렉토리 정보를 함께 기록한다면 TAR 아카이브의 전체 구조는 아래와 같을 것입니다.

s1.txt 파일 헤더

s1.txt 파일 본문

 

 

 

s2.txt 파일 헤더

s2.txt 파일 본문

 

 

 

sub1 디렉토리 헤더

s3.txt 파일 헤더

s3.txt 파일 본문

 

 

 

sub2 디렉토리 헤더

s4.txt 파일 헤더

s4.txt 파일 본문

 

 

 

s5.txt 파일 헤더

s5.txt 파일 본문

 

 

 

sub3 디렉토리 헤더

s6.txt 파일 헤더

s6.txt 파일 본문

 

 

 

sub4 디렉토리 헤더

s7.txt 파일 헤더

s7.txt 파일 본문

 

 

 

빈 블록

 

 

 

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

1 블록 (512 바이트)

1 블록 (512 바이트)

n 블록 (512 * n 바이트)

n 블록 (512 * n 바이트)


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

{TAR 파일}4.본문 구조  (0) 2002.09.09
{TAR 파일}3.헤더 구조  (1) 2002.09.09
{TAR 파일}1.개요  (0) 2002.09.09
{HTML 파서}5.다운로드  (0) 2001.07.24
{HTML 파서}4.배열 구조의 구성  (0) 2001.07.24
Posted by 방글24
phpsource/파일분석2002. 9. 9. 14:57
TAR(Tape ARchive) 아카이브 파일은 1970년대 자기테이프에 백업 & 검색하기 위하여 유래되었다고 합니다만 지금은 주로 여러 개의 파일을 묶어 전송하기 위하여 사용됩니다. 기본적으로 TAR 아카이브는 여러 개의 파일을 전혀 압축하지 않은 상태로 단지 하나의 파일로 묶어주는 역할만을 합니다. 우리가 보통 유닉스에서 제공하는 tar 유틸리티를 이용할 때 z 옵션을 지정하여 주면 압축까지 하는 것을 볼 수 있습니다. 그러나 이는 tar 유틸리티에서 압축해 주는 것이 아니라 tar 유틸리티와는 별개로 작성되어 있는 gzip 유틸리티를 불러다가 압축하게 되지요.
PHP 에서의 상황을 보면 zlib 라이브러리(gz로 시작하는 함수들)를 통해 파일을 압축할 수 있습니다. 그러나 zlib 함수는 기본적으로 하나의 파일만 다룰 수 있습니다. 웹상에서 여러 파일을 압축하고 해제하는 것이 다소 위험하여 그런지는 알 수 없으나 웹 스크립트에서는 TAR 아카이브를 잘 다루지 않는 것 같습니다. 생각해 보면 위험하기도 하겠습니다. 무슨 파일이 포함되었는지도 모르는 압축파일을 서버에 올려서 풀어버린다면 그 위험성은 상상하고도 남겠지요. 또한 내가 아닌 누군가가 나의 웹서버의 내용을 통째로 압축하여 가져가 버린다면...... 소름끼치는 상상이 될 수도 있겠지요. 그러나 구더기 무서워 장 못담그겠습니까? 서버상의 여러 개의 파일을 하나로 묶어서 다루어야 할 경우는 너무 많기때문에 TAR 아카이브를 다룰 수 있는 함수는 꼭 있어야 겠지요. 그리고 TAR 아카이브를 다룰 때 발생할 수 있는 여러 가지 위험성을 충분히 고려하여 사용하기만 한다면 별(?) 문제 없을 것입니다.
현재 PHP에서 일반적으로 웹상에서 여러 개의 파일을 압축하기 위해서는 exec() 또는 system()와 같은 함수와 리눅스에서 제공하는 tar 유틸리티를 이용하게 됩니다. 그러나 이러한 방법은 서버 상황에 따라 때로는 제대로 동작되지 않을 경우도 있으며 또한 윈도우 서버의 경우에는 해결방법이 될 수가 없습니다. 결국 가능한한 서버 환경에 관계없이 웹상에서 TAR 아카이브를 다루기 위해서는 TAR 아카이브를 직접 처리하는 것이 좋을 것 같습니다.
본인도 PHP에서 다중 파일 다운로드 클래스를 만들다보니 여러 개의 파일을 다운로드하기 위해서는 결국 여러 개의 파일을 하나의 파일로 묶은 후에 이 파일을 다운로드 받은 것이 가장 좋겠다는 생각까지는 하게 되었으나 현재 공개된 해결책으로는 위에서 언급한 리눅스의 tar 유틸리티를 이용하는 방법 외에는 눈에 띄는 것이 없었습니다. 그래서 인터넷을 검색하기 시작하였고 이를 통해 C로 작성된 tar 유틸리티의 소스 및 TAR 아카이브 구조에 관한 기술자료를 얻을 수 있었습니다. 이러한 자료를 통해 리눅스의 tar 유틸리티와 같은 기능을 수행하는 TAR 아카이브 클래스를 작성하게 되었습니다.
TAR 아카이브 관련 PHP 소스
TAR 관련 PHP 소스는 그리 흔한 것 같지 않습니다. 저도 관련 소스를 검색하여 보았으나 www.phpclasses.org에서 단 하나 발견하였을 뿐입니다. 본인도 이 소스를 참조하여 제 나름대로 TAR 아카이브를 다루는 클래스(hTarFile)를 작성하였습니다. 관심있는 분은 관련 소스들을 참조하시고 혹시 모르니 여러분도 인터넷을 더 검색해 보시기 바랍니다.
  • tar class
    Josh Barger
    joshb@npt.com
    http://www.phpclasses.org
  • hTarFile class
    Wookyung Hwang
    hwooky@phpclass.com
    http://www.phpclass.com
(추가) PEAR(PHP Extension and Application Repository)의 "File Formats" 패키지에 TAR 관련 PHP 소스 "Archive_Tar" 클래스가 있으니 http://pear.php.net 홈페이지를 참조바랍니다.
TAR 아카이브는 아니지만 zip 파일을 만들어 주는 소스가 보이네요. 소스는 TAR 아카이브를 다루는 것보다 훨씬 간단하구요. 실험해 보지는 않았지만 꽤 쓸모있는 소스인 것 같네요. 참조하세요.
  • zipfile class
    Eric Mueller
    eric@themepark.com
    http://www.zend.com/codex.php?id=696&single=1

Posted by 방글24
phpsource/파일분석2001. 7. 24. 20:16
2002.7.20 - 0.0.2
2002.3.21 - 0.0.1 패치1
2001.7.24 - 0.0.1

Posted by 방글24
phpsource/파일분석2001. 7. 24. 17:43
다차원 배열 구조
앞 장의 예제에서 보았듯이 파서 배열 구조는 다차원 배열(multi-dimensional array)로 구성되어 있습니다.
배열 구조를 보기 위해 사용하였던 var_dump() 함수 대신에 다차원배열 상태 그대로 보게 되면 아래와 같습니다.
$vals[0][tag]=""
$vals[0][type]="cdata"
$vals[0][value]="<!--HTML_PARSER 0.0.1-->"

$vals[1][tag]="HTML"
$vals[1][type]="open"
$vals[1][value]=" "

$vals[2][tag]="HEAD"
$vals[2][type]="open"
$vals[2][value]=" "

$vals[3][tag]="SCRIPT"
$vals[3][type]="open"
$vals[3][attributes][language]="JavaScript"
$vals[3][value]=" <!-- document.write("abc"); --> "

$vals[4][tag]="SCRIPT"
$vals[4][type]="close"
$vals[4][value]=" "

$vals[5][tag]="STYLE"
$vals[5][type]="open"
$vals[5][value]=" table td { font-size:.7em; } "

$vals[6][tag]="STYLE"
$vals[6][type]="close"
$vals[6][value]=" "

$vals[7][tag]="HEAD"
$vals[7][type]="close"
$vals[7][value]=" "

$vals[8][tag]="BODY"
$vals[8][type]="open"
$vals[8][attributes][bgcolor]="#ffffff"
$vals[8][attributes][marginwidth]="25"
$vals[8][attributes][marginheight]="0"
$vals[8][attributes][topmargin]="0"
$vals[8][attributes][leftmargin]="25"
$vals[8][value]=" "

$vals[9][tag]="TABLE"
$vals[9][type]="open"
$vals[9][attributes][bgcolor]="#FFFFFF"
$vals[9][attributes][border]="0"
$vals[9][attributes][cellpadding]="0"
$vals[9][attributes][cellspacing]="0"
$vals[9][attributes][width]="100%"
$vals[9][attributes][title]="<<<테이블 속성>>>"
$vals[9][value]=" "

$vals[10][tag]="TR"
$vals[10][type]="open"
$vals[10][value]=" "

$vals[11][tag]="TD"
$vals[11][type]="open"
$vals[11][value]=" < HTML 파서 >를 이용한 HTML 문서 분석 "

$vals[12][tag]="TD"
$vals[12][type]="close"
$vals[12][value]=" "

$vals[13][tag]="TR"
$vals[13][type]="close"
$vals[13][value]=" "

$vals[14][tag]="TABLE"
$vals[14][type]="close"
$vals[14][value]=" "

$vals[15][tag]="BODY"
$vals[15][type]="close"
$vals[15][value]=" "

$vals[16][tag]="HTML"
$vals[16][type]="close"
$vals[16][value]=""
제1첨자를 기준으로 보면 총 17개의 부분배열요소가 있다는 것을 알 수 있습니다. 배열 요소 수량은 HTML 문서 내에 있는 태그의 수량에 따라 결정됩니다. 보통은 태그 수량 + 1 의 배열 요소가 생성됩니다.
위에서 17개의 부분배열요소 중에서 첫번째 부분배열요소는 원래의 HTML 문서에는 없던 것으로 추가되어 있는 것을 알 수 있습니다. 만약 HTML 문서상에 나타나는 첫번째 태그 이전에 태그가 아닌 문자가 있다면 첫번째 부분배열요소의 value 첨자의 값의 뒤쪽에 기록됩니다.
[code html;gutter:false] 1234567890
<HTML> [/code]
예를 들어 위와 같은 HTML 문서를 분석하면 아래와 같은 배열을 얻을 수 있습니다. 아래 결과에서 "<!--HTML_PARSER 0.0.1-->"는 html_parse_into_struct 함수에서 강제로 붙이게 되는 문자열로 파서 함수의 버전을 나타냅니다.
$vals[0][tag]=""
$vals[0][type]="cdata"
$vals[0][value]="<!--HTML_PARSER 0.0.1--> 1234567890"
제2첨자 tag, type, attributes, value
제1첨자의 각 부분배열요소를 구성하는 제2첨자를 보면 총 4가지가 존재하게 됩니다.
tag
HTML 태그명을 가리킵니다. 원래의 소스에 관계없이 항상 대문자로 기록됩니다. 만약 태그명이 아닌 경우에는 널문자열("")이 기록됩니다. 예를 들어, <TD> 또는 </TD> 인 경우에는 tag 첨자의 요소값에는 TD가 기록됩니다.
type
type에 기록되는 값에는 open, close, cdata 입니다. open은 태그가 시작태그라는 것을 알려주며, close는 종료태그라는 것을 알려줍니다. cdata는 태그가 아닌 순수한 일반 문자(complete data ???)로 구성되어 있는 배열요소임을 알려줍니다.
예를 들어, <TD> 인 경우에는 type 첨자의 요소값으로 open이 기록되고, </TD> 인 경우에는 close가 기록됩니다.
attributes
attributes는 해당 태그의 속성을 기록하고 있습니다. 이 첨자에 대한 요소값은 다른 것과는 달리 부분배열로 기록됩니다.
[code html;gutter:false] <TABLE BGCOLOR="#FFFFFF" BORDER="0" CELLPADDING="0" CELLspacing="0"
WIDth="100%" title="<<<테이블 속성>>>"> [/code]
예를 들어 위와 같은 HTML 문서를 분석하면 아래와 같은 배열을 얻을 수 있습니다.
$vals[1]["tag"]="TABLE"
$vals[1]["type"]="open"
$vals[1]["attributes"]["BGCOLOR"]="#FFFFFF"
$vals[1]["attributes"]["BORDER"]="0"
$vals[1]["attributes"]["CELLPADDING"]="0"
$vals[1]["attributes"]["CELLspacing"]="0"
$vals[1]["attributes"]["WIDth"]="100%"
$vals[1]["attributes"]["title"]="<<<테이블 속성>>>"
위의 결과에서 제1첨자 1는 HTML 문서상의 TABLE의 위치에 따라 변동될 수 있습니다. 그리고 속성명은 HTML 문서에서 기록된 그대로 반환됩니다. 0.0.1 초기버전에서는 태그명을 강제로 소문자로 변환하였으나 약간의 문제가 있어 수정하였습니다.
value
앞에서 설명한 tag, type, attributes는 태그에 관련된 배열요소인 반면에 value는 태그가 닫힌 후에 나오는 값이 기록됩니다. 여기서 태그가 닫혔다는 것은 종료태그를 의미하는 것이 아니라 태그의 끝은 의미하는 ">"문자가 나타났다는 것을 의미합니다.
[code html;gutter:false] <TD>
< HTML 파서 >를 이용한 HTML 문서 분석 [/code]
예를 들어 위와 같은 HTML 문서를 분석하면 아래와 같은 배열을 얻을 수 있습니다.
$vals[1][tag]="TD"
$vals[1][type]="open"
$vals[1][value]=" < HTML 파서 >를 이용한 HTML 문서 분석 "
앞 태그와 뒷 태그 사이에 아무런 값이 없다면 앞 태그의 value 배열에는 빈 문자열 또는 하나의 white space가 기록됩니다.
<!-- ... --> 및 <! ...>의 처리
<!-- ... -->
원래 HTML 문서상에 있던 주석(<!-- ... -->)은 html_parse_into_struct 함수를 실행하는 중에 모두 삭제됩니다.
<! ...>
이러한 코드의 예로는 <!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.0//EN> 가 있습니다. 이와 같이 <! 로 시작하는 태그는 다른 태그와는 달리 html_parse_into_struct 함수에서 태그로 처리하지 않고 일반 문자열로 처리합니다.
[code html;gutter:false] <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML> [/code]
예를 들어 위와 같은 HTML 문서를 분석하면 아래와 같은 배열을 얻을 수 있습니다.
$vals[0][tag]=""
$vals[0][type]="cdata"
$vals[0][value]="<!--HTML_PARSER 0.0.1-->"

$vals[1][tag]=""
$vals[1][type]="cdata"
$vals[1][value]="<!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.0//EN> "

$vals[2][tag]="HTML"
$vals[2][type]="open"
$vals[2][value]=" "

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

{TAR 파일}1.개요  (0) 2002.09.09
{HTML 파서}5.다운로드  (0) 2001.07.24
{HTML 파서}3.배열 구조를 보여주는 예제  (0) 2001.07.24
{HTML 파서}2.파서 관련 함수  (1) 2001.07.24
{HTML 파서}1.개요  (0) 2001.07.24
Posted by 방글24
phpsource/파일분석2001. 7. 24. 17:41
배열구조를 보여주는 예제
HTML 문서
우선 아래와 같은 HTML 문서(파일명:sample.html)가 있다고 하지요.
[code html;gutter:false] <HTML>
<HEAD>
<SCRIPT language="JavaScript">
<!--
document.write("abc");
-->
</SCRIPT>
<style>
table td { font-size:.7em; }
</style>
</HEAD>
<BODY>
<TABLE>
<TR>
<TD>
< HTML 파서 >를 이용한 HTML 문서 분석
</TD>
</TR>
</TABLE>
</BODY>
</HTML> [/code]
HTML 문서를 분석하는 예제
아래는 위에 있는 HTML 문서를 이 함수에 의해 분석하여 생성된 배열구조를 보여주는 예제(파일명:test.php)입니다.
[code php;gutter:false] <?php

$file = "./sample.html";
$data = implode("", file($file));

include("./class.htmlparser.php"); // HTML 파서 클래스

$parser = new HtmlParser;

$parser->html_parse_into_struct($data, $vals);

var_dump($vals);

?> [/code]
예제 실행 결과
위의 코드를 실행하면 아래와 같은 결과를 얻을 수 있습니다.
array(17) {
   [0]=>
   array(3) {
     ["tag"]=>
     string(0) ""
     ["type"]=>
     string(5) "cdata"
     ["value"]=>
     string(24) "<!--HTML_PARSER 0.0.1-->"
   }
   [1]=>
   array(4) {
     ["tag"]=>
     string(4) "HTML"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(0) {
     }
     ["value"]=>
     string(1) "
     "
   }
   [2]=>
   array(4) {
     ["tag"]=>
     string(4) "HEAD"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(0) {
     }
     ["value"]=>
     string(2) "
     "
   }
   [3]=>
   array(4) {
     ["tag"]=>
     string(6) "SCRIPT"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(1) {
       ["language"]=>
       string(10) "JavaScript"
     }
     ["value"]=>
     string(37) "
   <!--
   document.write("abc");
   -->
   "
   }
   [4]=>
   array(3) {
     ["tag"]=>
     string(6) "SCRIPT"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(2) "
     "
   }
   [5]=>
   array(4) {
     ["tag"]=>
     string(5) "STYLE"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(0) {
     }
     ["value"]=>
     string(33) "
   table td { font-size:.7em; }
   "
   }
   [6]=>
   array(3) {
     ["tag"]=>
     string(5) "STYLE"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(1) "
   "
   }
   [7]=>
   array(3) {
     ["tag"]=>
     string(4) "HEAD"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(1) "
   "
   }
   [8]=>
   array(4) {
     ["tag"]=>
     string(4) "BODY"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(0) {
     }
     ["value"]=>
     string(2) "
   "
   }
   [9]=>
   array(4) {
     ["tag"]=>
     string(5) "TABLE"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(0) {
     }
     ["value"]=>
     string(3) "
   "
   }
   [10]=>
   array(4) {
     ["tag"]=>
     string(2) "TR"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(0) {
     }
     ["value"]=>
     string(4) "
    "
   }
   [11]=>
   array(4) {
     ["tag"]=>
     string(2) "TD"
     ["type"]=>
     string(4) "open"
     ["attributes"]=>
     array(0) {
     }
     ["value"]=>
     string(46) "
   < HTML 파서 >를 이용한 HTML 문서 분석
   "
   }
   [12]=>
   array(3) {
     ["tag"]=>
     string(2) "TD"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(3) "
   "
   }
   [13]=>
   array(3) {
     ["tag"]=>
     string(2) "TR"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(2) "
   "
   }
   [14]=>
   array(3) {
     ["tag"]=>
     string(5) "TABLE"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(1) "
   "
   }
   [15]=>
   array(3) {
     ["tag"]=>
     string(4) "BODY"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(1) "
   "
   }
   [16]=>
   array(3) {
     ["tag"]=>
     string(4) "HTML"
     ["type"]=>
     string(5) "close"
     ["value"]=>
     string(0) ""
   }
}
위의 결과는 PHP4에서 실행한 결과입니다. PHP에서 제공하고 있는 var_dump() 함수의 결과가 버전에 따라 다소 다르게 나타나고 있으니 이를 염두에 두시기 바랍니다. PHP 버전 4.0 이상에서는 var_dump 함수 대신에 print_r 함수를 사용하면 좀더 보기 편할 것입니다.

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

{TAR 파일}1.개요  (0) 2002.09.09
{HTML 파서}5.다운로드  (0) 2001.07.24
{HTML 파서}4.배열 구조의 구성  (0) 2001.07.24
{HTML 파서}2.파서 관련 함수  (1) 2001.07.24
{HTML 파서}1.개요  (0) 2001.07.24
Posted by 방글24
phpsource/파일분석2001. 7. 24. 17:35
제공되는 함수
현재는 xml 파서 함수 중 xml_parse_into_struct 함수를 모델링한 html_parse_into_struct 함수만 제공됩니다.
함수 버전 기능 클래스명
html_parse_into_struct 0.0.1 HTML 데이터를 배열 구조로 분석 HtmlParser
int html_parse_into_struct (string data, array &values)
html_parse_into_struct 함수는 HTML 규약에 의해 작성된 문서를 배열 구조의 데이터로 분석합니다. 이 배열 구조는 xml 문서를 분석하기 위하여 작성된 xml_parse_into_struct와 입력 및 출력 인터페이스가 거의 유사합니다. 그러나 xlm_parse_into_struct와는 달리 배열 구조내에서의 각 태그의 위치를 나타내는 index값을 반환하지 않습니다.
두번째 매개변수인 values는 반드시 "passed by reference" 되어야 합니다. reference(참조) 대한 자세한 정보는 홈페이지 메뉴에서 "핍클래스홈>>참조(레퍼런스)"을 보시기 바랍니다.
객체 생성 및 함수 실행
html_parse_into_struct 함수는 HtmlParser라는 클래스의 멤버로 존재하는 메소드입니다. 이 클래스는 class.htmlparser.php라는 파일명에 정의되어 있습니다.
[code php;gutter:false] //
// HTML 파서 클래스
//
include("./class.htmlparser.php");

//
// 객체 생성
// PHP4에서는 아래 문장에서 사용한 객체복사 대신에 참조를 이용하세요.
// ($parser =& new HtmlParser // 객체참조)
//
$parser = new HtmlParser; // 객체생성 및 복사

//
// 함수 실행
//
$parser->html_parse_into_struct($html_source, $vals); [/code]
HTML 문서의 문제점(?) -> html_parse_into_struct()의 한계
html_parse_into_struct를 작성하면서 느낀 점이 있다면 웹브라우저가 잘못 작성된 html 문서를 너무 많이 허용하고 있다는 것입니다. 물론 C 언어를 이용하여 작성한다면야 별문제 없겠지만 PHP 스크립트를 이용하여 작성된 파서에서 웹브라우저에서 허용하는 만큼의 융통성을 위해 모든 문제를 검사한다는 것은 실행시간의 한계로 인해 다소 무리가 될 것 같습니다. 따라서 html_parse_into_struct() 함수는 미완성인 HTML 문서를 분석하기에는 역부족이고 이미 작성되어 웹서비스를 하고있는 홈페이지 문서에 대하여 분석하는 정도로, 또한 너무 복잡하지 않고 가능한한 단순한 문서를 분석하는 정도로 만족하여야 할 것 같습니다.
이 함수를 공개하기 전에 분석 및 활용의 적정성을 판단하기 위해 간단치 않는 실험을 수행하였습니다. 실험방법은 html_parse_into_struct() 함수를 통해 얻어진 데이터를 가지고 간단한 태그 유효성 검사 및 문제점 수정 단계를 거쳐 제가 이미 공개한 바 있는 유닛테이블 문서로 변환하는 실험이었습니다. 이를 단계별로 구분한다면 아래와 같은 3단계를 거치는 실험이었습니다.
HTML 문서 -> [HTML 파서 클래스] -> [태그 유효성 검사 및 수정 클래스]
-> [문서변환 클래스] -> 유닛테이블 문서
이번에 공개하는 것은 이 중에 첫단계인 "HTML 파서 클래스"입니다. "태그 유효성 검사 및 수정 클래스"에서 하는 일을 보면 모든 문제점을 검사/수정하는 것은 아니고 <TABLE>, <TR>, <TD> 태그의 시작태그와 종료태그의 짝을 맞추기 위한 기능이 거의 전부입니다. 이러한 과정을 요구하는 이유는 유닛테이블 문서로 변환하려면 테이블 관련 태그에 대해 매우 엄격히 작성되어야 하기 때문입니다. 그런데 실험을 통하여 알게된 사실이지만 인터넷 상의 많은 문서가 이에 대하여 매우 소홀히 다루고 있다는 것입니다. 물론 웹브라우저가 알아서(?) 잘 보여주기 때문에 이 문제에 대하여 소홀히 다루게 되는 것 같습니다만 이와같이 적당히 웹문서를 만드는 것은 별로 좋은 습관이 아닌 것 같습니다.
이 실험을 통해 인터넷 상에 있는 웹문서들을 유닛테이블 문서로 변환하는데 대부분 성공하게 되었습니다. 시간 제약상 많은 문서에 대하여 실험할 수는 없었고 약 20여가지의 문서에 대하여 실험하였습니다.
cafe4.daum.net, asp.net, dialpad.co.kr, editplus.co.kr, java.sun.com, javascript.co.kr, namo.co.kr 중 게시판 부분, phpschool.com, phpclass.com, shinbiro.com, simmani.com, www.freechal.com, linux.sarang.net, yahoo.co.kr ......
이 실험을 통해 얻은 또 다른 것이 있다면 유닛테이블로 만이 아니라 우리가 잘 알고 있는 FastTemplate 문서와 같은 다른 템플릿 문서로 변환하는 것도 그리 어렵지 않다는 것이지요. 현재 많이 활용되고 있는 템플릿 기술이 XML로 가는 과정에서의 중간단계 역할로 많은 한계를 가질 수 밖에 없겠지만(???) 아직 인터넷 상의 모든 문서가 XML로 가기까지는 다소 시간이 필요할 것 같으며(모든 웹문서가 향후 XML로 작성되어야 하는지에 대하여는 잘 모르겠음), 당장에 순수 HTML 문서의 한계성을 극복하는 한 방편으로서의 템플릿 기술은 당분간 필요하다는 생각이 듭니다.
HTML 파서 클래스를 활용하여 여러분이 한번 HTML 문서를 FastTemplate 문서로 변환하는 클래스를 한 번 작성해 보시지 않겠습니까?

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

{TAR 파일}1.개요  (0) 2002.09.09
{HTML 파서}5.다운로드  (0) 2001.07.24
{HTML 파서}4.배열 구조의 구성  (0) 2001.07.24
{HTML 파서}3.배열 구조를 보여주는 예제  (0) 2001.07.24
{HTML 파서}1.개요  (0) 2001.07.24
Posted by 방글24
phpsource/파일분석2001. 7. 24. 17:32
HTML 규약에 의해 작성된 문서를 분석하는 함수입니다.
0.0.1p2에서는 아래의 예와 같이 0.0.1p1에서 속성값에 인용부호가 나타날 때 생기는 문제점을 일부 해결하기 위해 약간 수정하였습니다.
[code html;gutter:false] <A href=javascript:openMail("xxx@xxxxx.com")>xxx@xxxxx.com</A> [/code]
위와 같이 바깥쪽 인용부호를 생략한 채 xxx@xxxxx.com을 이중 인용부호로 둘러싸는 경우 에러가 발생합니다. 해결하자니 소스가 너무 복잡해 지네요. 그러니 이러한 경우 HTML 문서를 작성할 때 아래와 같이 수정하시기 바랍니다. 그래야 에러가 발생하지 않습니다.
[code html;gutter:false] <A href=javascript:openMail('xxx@xxxxx.com')>xxx@xxxxx.com</A> [/code]
또는,
[code html;gutter:false] <A href="javascript:openMail('xxx@xxxxx.com')">xxx@xxxxx.com</A> [/code]
또는,
[code html;gutter:false] <A href='javascript:openMail("xxx@xxxxx.com")'>xxx@xxxxx.com</A> [/code]
와 같이 수정하시면 됩니다. 이 중에 두 번째 또는 세 번째와 같이 바깥쪽으로도 인용부호로 둘러싸는 습관을 들이시기 바랍니다. 나모 웹에디터에서 작업할 때는 이와 같은 경우 나모에서 자동으로 바깥쪽 인용부호를 붙여줍니다만 일반 텍스트 편집기를 이용하여 직접 소스를 작성할 때는 습관상 생략하는 경우도 있을 것입니다.

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

{TAR 파일}1.개요  (0) 2002.09.09
{HTML 파서}5.다운로드  (0) 2001.07.24
{HTML 파서}4.배열 구조의 구성  (0) 2001.07.24
{HTML 파서}3.배열 구조를 보여주는 예제  (0) 2001.07.24
{HTML 파서}2.파서 관련 함수  (1) 2001.07.24
Posted by 방글24