반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

지난 글까지는 pdf 의 내용을 바이너리로 받아서 이걸 obj별로 나누고 다시 stream 별로 나눈 값을 getObjectOptions() 로 보내서 그 값을 다시 여러 정규식으로 나누고 공백으로 나누고 뭐 그런 처리를 한 값을 return 하는 것까지 했습니다.


이제 getObjectOptions() 함수에서 던져준 값을 adf2text() 함수내에서 받아서 어떤 처리를 해 줘야 할 텐데요.

여기서는 받은 값으로 맨 처음 Length1, Type, Subtype 요소가 그 안에 있는지 여부를 체크합니다.

PHP 의 empty() 함수를 이용해서 체크하네요.

Length1, Type, Subtype 값들은 맨 처음 글에서 본 Hello World PDF 의 바이너리 파일에서 보면 <<, >> 안에 들어있는 텍스트 입니다.

여기서 continue; 를 사용했는데요. 예제를 보고 이해해 보죠.


<?php
for ($i 0$i 5; ++$i) {
    if (
$i == 2)
        continue
    print 
"$i\n";
}
?>


이렇게 하면 뭐가 나올까요? 정답은 2 입니다.

if 문에서 true 가 아니면 그 아래는 실행하지 않고 다시 loop 문으로 갑니다.

그러니까 우리가 공부하는 소스의 내용을 보면 Length1 과 Type 이 비어있지 않고 Subtype 이 비어있는 경우에만 아래 내용을 실행하고 그렇지 않으면 이 값은 무시되서 for 루프문으로 돌아갑니다.

아마 Length1 과 Type 이 있고 Subtype 이 없는 경우가 실제 Text 로 처리할 내용인가 봅니다.

이렇게 해서 얻어진 값을 getDecodedStream() 함수로 보냅니다.

실제 Text 로 처리할 내용만 담았으니까 이제 이것을 바이너리에서 사람이 읽을 수 있는 형식으로 바꿔야 겠죠. 그 작업을 하는 함수가 getDecodedStream() 인가 봅니다.

이 함수에는 파라미터로 $stream 과 $options 를 던져 줍니다.

$stream 은 pdf2text() 함수에서 만든 값이고 $options 는 이전 글인 getObjectOptions() 함수에서 만든 값이죠?

이 두 값을 getDecodedStream()으로 보내는데  이 함수에서는 구체적으로 무엇을 할까요?


Twilight O.S.T 인 Decode 를 부른 Paramore 입니다. :)


function getDecodedStream($stream, $options) {
    $data = "";
    if (empty($options["Filter"]))
        $data = $stream;
    else {
        $length = !empty($options["Length"]) ? $options["Length"] : strlen($stream);
        $_stream = substr($stream, 0, $length);

        foreach ($options as $key => $value) {
            if ($key == "ASCIIHexDecode")
                $_stream = decodeAsciiHex($_stream);
            if ($key == "ASCII85Decode")
                $_stream = decodeAscii85($_stream);
            if ($key == "FlateDecode")
                $_stream = decodeFlate($_stream);
        }
        $data = $_stream;
    }
    return $data;
}


여기서는 우선 $options["Filter"] 를 체크해서 없으면 $data 에 $stream 을 넣습니다.

이 $data 가 나중에 return 할 값입니다.

그리고 Filter 가 있으면 else 구문을 실행하는데요.

$options["Length"] 가 있으면 $options["Length"] 를 없으면 $stream 의 길이를 $length 에 넣습니다.

여기서 Length 는 데이터의 길이이고 이미 PDF 바이너리 파일 안에 있습니다.

그 다음에 문자열을 다룰 때 가장 많이 사용되는 substr() 함수가 나오는데요.
아래 예제를 보시면 금방 이해가 되실 겁니다.


<?php
echo substr('abcdef'1);     // bcdef
echo substr('abcdef'13);  // bcd
echo substr('abcdef'04);  // abcd
echo substr('abcdef'08);  // abcdef
echo substr('abcdef', -11); // f

// Accessing single characters in a string
// can also be achieved using "square brackets"
$string 'abcdef';
echo 
$string[0];                 // a
echo $string[3];                 // d
echo $string[strlen($string)-1]; // f

?>


설명은 굳이 달지 않을께요. 아주 자주 쓰이고 또 쉬운거니까요.



다시 공부하던 소스로 돌아가면 $stream 을 처음부터 $length 까지만 잘라서 $_stream 에 넣네요. 즉 딱 데이터 부분만 $_stream 에 담는 겁니다.

그 다음에는 $options 배열 수만큼 foreach 문을 돌리는데요.

이 값이 ASCIIHexDecode 이면 decodeAsciiHex() 메소드를 사용하고 ASCII85Decode 이면 decodeAscii85() 메소드를 사용하고 FlateDecode 이면 decodeFlate() 메소드를 사용해서 $_stream 을 디코딩 하는 겁니다.


지금까지 한 일은 이 디코딩 메소드로 데이터를 돌려서 사람이 읽을 수 있는 텍스트로 뽑아내기 위해서 딱 그 데이터 부분만 분리하는 작업을 한 겁니다.


이제 본격적으로 데이터를 디코딩 하는 함수를 볼 차레네요.

이 부분은 집중해서 자세히 보고 싶군요.

다음 글에서 하나하나 분석해 보도록 하겠습니다.


그래서 제가 저희 회사 식당 Menu PDF 에 있는 데이터를 제대로 필요한 내용만 추출해서 어떻게 사용할 수 있는지 찾아낼 수 있도록요.

이 식당 Menu PDF 가 한가지만 있으면 좋은데 텍사스, 켄터키, 메사추세츠 등 등 여러 지역에 또 여러 도시에 나눠져 있어서 10개가 넘거든요.

각 빌딩의 chef 들이 조금씩 편집을 해서 올리기 때문에 어떤 공통된 패턴을 찾아내기가 어렵더라구요.


하여간 다음 글에서 이 바이너리 파일을 디코딩하는 소스를 세밀하게 분석해 보겠습니다.


반응형


반응형

지난번 글에서는 pdf2text($filename) 함수에 있는 for 문 중간 까지 했습니다.

그 중간에 getObjectOptions() 함수를 call 하는 부분 바로 전까지 했는데요.


그 전까지는 PDF 안의 내용을 일단 바이너리 파일로 받아서 obj,endobj 구문별로 나는 다음에 다시 그 안의 내용을 stream,endstream 구문별로 나눴습니다.


그 stream 별로 나눈 값을 for 문 안에서 계속 getObjectOptions() 함수로 던져서 어떤 일을 하도록 시키는데.. 오늘은 그 어떤일이 어떤일인지 공부할 것 같습니다.


PDF 안의 내용을 가져오는 함수는 file_get_contents() 함수였고 그 바이너리 파일들을 다시 세분화 시킬 때 사용했던 함수가 PCRE 함수인 preg_match_all() 과 preg_match() 였었습니다.


그리고 추가로 PHP 정규 표현식 (regular expressions)과 PDF 구조에 대해서 알아야 했구요.


이제 getObjectOptions() 함수에 대해 알아보겠습니다.


function getObjectOptions($object) {
    $options = array();
    if (preg_match("#<<(.*)>>#ismU", $object, $options)) {
        $options = explode("/", $options[1]);
        @array_shift($options);

        $o = array();
        for ($j = 0; $j < @count($options); $j++) {
            $options[$j] = preg_replace("#\s+#", " ", trim($options[$j]));
           
            if (strpos($options[$j], " ") !== false) {
                $parts = explode(" ", $options[$j]);
                $o[$parts[0]] = $parts[1];
            } else
                $o[$options[$j]] = true;
        }
        $options = $o;
        unset($o);
    }

    return $options;
}


여기서도 PCRE 함수가 쓰이네요.

바이너리 파일 내용을 처리하기 위해서 이 함수들은 필수로 이해하고 있어야 할 것 같습니다.


우선 처음에 $options 라는 배열을 만들고 pdf2text() 함수 내에서 던져준 PDF 내의 각 stream 을 가지고 다룹니다.


preg_match("#<<(.*)>>#ismU", $object, $options)


받은 stream 블럭인 $object 안의 내용을 정규표현식인 #<<(.*)>>#ismU 로 구분해서 아까 만든 배열변수인 $options 에 담습니다.

정규표현식 #<<(.*)>>#ismU 가 뭔지 정확히 알면 좋겠는데...

혹시 정규표현식에 강하신 분 계시면 댓글에 이게 정확히 무엇을 말하는지 알려 주시면 감사하겠습니다.





그 다음은 explode() 함수를 썼습니다. 이 함수는 문자열을 특정 기준으로 자르는 함수입니다.

예제를 하나 보면요.


<?php
$str 
'one|two|three|four';

// positive limit
print_r(explode('|'$str2));

// negative limit (since PHP 5.1)
print_r(explode('|'$str, -1));
?>


이 소스를 돌리면 그 결과값은 아래와 같습니다.

Array
(
    [0] => one
    [1] => two|three|four
)
Array
(
    [0] => one
    [1] => two
    [2] => three
)


첫번째 파라미터는 구분자이고 두번째 파라미터는 작업할 문자열 그리고 마지막 파라미터는 limit 이라고 하는데요. 이 세번째는 옵션입니다.

위의 소스를 보면 2를 넣으면 두개로 구분해서 첫번째 | 를 기준으로 구분하고 나머지는 모두 한개의 값으로 처리하는군요.

두번째 소스는 마이너스 값을 넣었는데 | 구분자 이전의 값을 나누는 것 같습니다.

비슷한 함수로는 정규식을 사용해서 구분하는 preg_split() 이 있구요 반대되는 함수로는 implode() 함수가 있습니다.


지금 배우는 소스에서는 $options = explode("/", $options[1]); 로 구분자 / 을 기준으로 options 를 모두 나눴습니다.

여기서 / 는 뭐를 나타내는 것일까요?


지난번 글에 Hello World! 를 표시한 PDF 의 바이너리 파일을 보면 << , >> 구문 안에 어떤 정보들이 들어있고 그 안에 각각의 정보들이 / 나눠져 있는 걸 볼 수 있습니다.

/ 이 무슨 의미인지 알려면 PDF 구조에 대해 공부해야 할 것 같습니다.


obj, stream,<<,>>,/ 대충 지금까지 나온 PDF 내부에서 사용되는 기호입니다. 


하여간 / 로 나는 값을 PHP 의 array_shift() 함수로 돌립니다.

배열의 첫번쨰 요소를 없애버리는 겁니다. 그리고 두번째 요소가 첫번째 요소로 되는거죠.


<?php
$stack 
= array("orange""banana""apple""raspberry");
$fruit array_shift($stack);
print_r($stack);
?>


이렇게 하면 결과가 아래와 같이 됩니다.

Array
(
    [0] => banana
    [1] => apple
    [2] => raspberry
)


Hello World! PDF 의 바이너리를 보면 / 다음엔 Size, Root 이런 문자가 오는데 이걸 없애 버리는 건가요?


하여간 그 다음으로 넘어가면 $o라는 배열 변수를 만듭니다.

그래서 방금전에 explode 까지 한 결과값인 $options 배열을 for 문으로 돌립니다.



$options 배열의 각각의 요소를 다시 preg_replace() 함수를 이용해서 변환을 시켜주네요.


preg_replace("#\s+#", " ", trim($options[$j]));


#\s+# 로 변환을 하고 그 결과값의 좌우 공백을 없앤 값을 $options 배열에 다시 넣어줍니다.


그리고 $options[$j] 안에 공백이 있으면 다시 그 공백을 기준으로 나눠서 $parts 변수에 담습니다.

그 다음에 방금 전 만들어 주었던 $o 의 $parts[0] 에 $parts[1] 을 담습니다.

만약 공백이 없다면 $o[$options[$j]] 에 true 값을 대입시킵니다.


그래서 이 $o  변수를 $options 에 담은 다음에 그 값을 return 합니다.


여기까지가 getObjectOptions() 메소드가 하는 일 입니다.


정리하면 #<<(.*)>>#ismU 으로 나누고 그걸 다시 / 으로 나누고 배열을 shift 한 다음에 배열안의 내용을 #\s+# 로 나눠서 공백이 있으면 공백을 기준으로 다시 나누고 공백이 없으면 $o[$options[$j]] 를 true 로 해서 이 $o의 값을 $options 에 담아서 return 을 해 줍니다.


정규표현식이 정확히 무엇을 하라는 것인지 알고 싶네요.

혹시 아시는 분 설명 부탁드려요.


오늘은 여기까지 할거구요.


위의 만들어진 $options 값을 pdf2text() 메소드에서 받아서 어떻게 처리하는지 다음에 알아 볼께요.


반응형


반응형
Posted on . Written by



지난 몇달간 여러분들 중 많은 분들이 Corona Geek show 들을 보셨을 겁니다. 이 비디오들은 코로나 커뮤니티에서 왕성하게 활동해 오신 코로나 개발자인Charles Mckeever 가 모아놓은 건데요, 코로나 ecosystem 에서 진행중인 흥미로운 것들에 대해 얘기하고 일반적인 모바일 컴퓨팅에 대해 논의한 것들입니다.






저희들은 그 쇼들을(the shows) 쭉 보아왔습니다. 그리고 그 중 몇개는 저희들도 참여(participated) 했었습니다. 저희들은 그 아이디어를 사랑했고 Charles 가 그 일을 계속 진행하는 것에 대해 깊은 인상을 받았습니다. 저희들도 예전에 이와 비슷한 것들을 하려고 계획하긴 했었습니다만 실제로 그 일을 할 시간을 갖지는 못했었습니다.



그래서 이 Corona Geek 을 Corona Labs folder 에 포함시키고 Charles 를 on board 시키기로 했습니다. 우리는 Corona Geek 을 더 발전시켜 나갈 계획입니다. 저희들의 비전은 개발자 커뮤니티를 좀 더 활발하게 발전시켜 나가는 겁니다. 개발자들이 가서 모바일 개발과 모바일 마케팅에 대해 (코로나에 대한 것 뿐만 아니라) 배울수 있는 그런 커뮤니티를요. Corona Labs team, Corona Ambassadors 그리고 Corona developers로서 여러분의 경험을 공유할 수 있는 그런 공간 입니다. 이 공간을 TV 채널의 일부, 개발자 포럼의 일부 그리고 educational resource의 일부로 생각해 주세요. 거기에다가 어떤 좋은 아이디어가 떠오르면 그런 아이디어도 나눌 수 있는 공간입니다. 이게 Google+ Hangouts and video 와 비슷합니다. 하지만 Corona Geek 은 이 뿐만 아니라 다른 미디어로 더 확장해 나갈 겁니다.





저희들은 코로나의 개발자 공간에 대해 믿음을 갖고 있고 또 자랑스럽게 생각하고 있습니다. 여러분들이 저희 플랫폼을 사용하기로 결정했고 또 앱을 만들고 계신것이 영광스럽습니다. 이 플랫폼을 더 강력하게 만드는 것은 여러분들에게 더 가치있는 resources 들을 제공하는 것이란 것을 알고 있습니다. Corona Geek 으로 우리의 커뮤니티에 대한 노력을 배가할 것이며 이와 더불어 코로나를 아름답고 성공적인 게임과 앱을 개발하는 최고의 플랫폼으로 만드는 도구로 이를 활용할 것입니다.

이러한 일들을 하기 위해 Corona Geek 을 선택했습니다. 이와 관련된 비전과 계획은 today’s Hangout (Monday, January 7)에 있습니다. 태평양 시간으로 낮 12시에 시작할 겁니다. 여기에 여러분들을 초청합니다.



저희들은 또한 Corona Geek forum도 만들었습니다. 이 Corona Geek 과 관련한 여러분의 생각과 아이디어, 제안 을 듣고 싶습니다. 주저하지 마시고 저희들에게 직접 이메일을 주세요. 저희들의 이메일은 charles[AT]coronalabs[dot]com 과 david[AT]coronalabs[dot]com 입니다.



감사합니다.


David



반응형