xFacility/Documents2010. 6. 29. 01:40
문장이란 xFacility에서 데이터를 전송/수신할 때, 효과적으로 하기 위한 하나의 규칙이다.
문장은 육하원칙의 요소로 구성되며, 그 구성 형태는 영문법의 문장 구조를 따르고 있다.
(물론, 프로그램은 문장 구성 요소를 각각 처리하므로 문장 구조를 벗어나도 이해할 수 있다.)
그렇기 때문에 문장을 해석하는 주체(컴퓨터 또는 사람)에 상관 없이 모두 문장을 쉽게 이해할 수 있다는 장점이 있다.

1. Who
문장의 주체이다.

2. How
주체가 행하는 행동이다.

3. Whom
문장의 수신자, 행동에 영향을 받는 사람이다. 보통 xFacility를 여기에 기입한다.

4. What
행동에 대한 목적어이다. 행동을 행하는데 있어서 중심이 되는 데이터들을 여기에 기입한다.

5. Where
이 문장이 효력을 발휘하는 지점이다.

6. When
이 문장이 효력을 발휘하는 시점이다.

7. Why
이 문장이 작성된 까닭이다.

'xFacility > Documents' 카테고리의 다른 글

xFacility Data Form데이터 형식  (0) 2010.10.20
xf_language 변수  (0) 2010.08.23
xFacility 변수 규칙  (0) 2010.08.07
데이터 형식  (0) 2010.05.17
처리Process  (0) 2010.05.16
Posted by 마이클
WebApp/PHP2010. 6. 26. 02:15
데이터베이스를 통해 자료를 사용하다보면, 어떠한 방식으로 자료를 배열에 저장해야 좋을까 고민하게 된다.
데이터베이스를 다루는 프로그램의 진행 구조를 살펴보면, 이러한 고민에 부딪치는 까닭을 알 수 있다.

프로그램은 사용자의 요구에 따라(Input) 데이터베이스에 있는 정보를 꺼내어 배열에 저장하고(Process)
그 값을 화면 구성에 알맞게 적절하게 뿌리도록 프로그램을 작성한다.(Output)

우리는 처리Process 절차 - 데이터베이스에 있는 정보를 변수에 저장하는 단계를 위해서 이를 고민하고 있는 것이다. 그렇다면, 배열 구성 방식에 관한 문제는 어떠한 방법이 출력Output 단계에서 효율적인지만을 확인하면 되는 것이다.

게시판 프로그램을 작성한다는 가정 하에 이 문제를 풀어보도록 하자.
현재 나타나고 있는 게시판은 다음과 같다.
 제목 내용  작성자 
 php입문 php는 <?php로 시작해서 ?>로 끝납니다. php.net
 html입문 html은 <html>로 시작해서 </html>로 끝납니다. w3c.org

이 게시판의 HTML코드는 다음과 같다.
<table>
<tr>
<th>제목</th>
<th>내용</th>
<th>작성자</th>
</tr>
<tr>
<td>php입문</td>
<td>php는 &lt;?php로 시작해서 ?&gt;로 끝납니다.</td>
<td>php.net</td>
</tr>
<tr>
<td>html입문</td>
<td>html은 &lt;html&gt;로 시작해서 &lt;/html&gt;로 끝납니다.</td>
<td>w3c.org</td>
</tr>
</table>
또한 SQL 테이블 구조는 다음과 같다 .
table : `board`
columns: `subject`, `description`, `author`

다음은 위의 내용을 담기 위한 제 1의 배열 방법이다. 위의 표에서 가로축에 해당하는 것을 1차 배열로 놓는 경우이다.
$board => Array
(
[subject] => Array
(
[0] => php입문
[1] => html입문
)
[description] => Array
(
[0] => php는 <?php로 시작해서 ?>로 끝납니다.
[1] => html은 <html>로 시작해서 </html>로 끝납니다.
)
[author] => Array
(
[0] => php.net
[1] => w3c.org
)
)

제 2의 방법은 다음과 같다. 위의 표에서 세로축에 해당되는 것을 1차 배열로 놓는 경우이다.
$board => Array
(
[0] => Array
(
[subject] => php입문
[description] => php는 <?php로 시작해서 ?>로 끝납니다.
[author] => php.net
)
[1] => Array
(
[subject] => html입문
[description] => phtml은 <html>로 시작해서 </html>로 끝납니다.
[author] => w3c.org
)
)

어느것이 효율적인 저장방법일까? 다음의 예제들을 통해서 확인해보자.

첫째는 위의 배열들을 게시물에 뿌리는 방법이다.
제1의 방법을 통한 예제를 먼저 보겠다.
echo "<table>";
echo "<tr>";
echo "<th>제목</th>";
echo "<th>내용</th>";
echo "<th>작성자</th>";
echo "</tr>";
$counter = count($board[subject]);
for($i=0; $i<$counter; $i++) {
echo "<tr>";
echo "<td>".$board[subject][$i]."</td>";
echo "<td>".$board[description][$i]."</td>";
echo "<td>".$board[author][$i]."</td>";
echo "</tr>";
}
echo "</table>";
코드를 보면, 일단 for 반복문의 반복 횟수를 결정하는 문제부터 막힌다.
위에서 제시한 표만 처리하는 코드이기 때문에 여기서는 카운터 횟수를 쉽게 결정했지만,
좀더 유연한 코드를 작성하고자 한다면 처리하기가 매우 어려울 것이다.
한 가지 예를 들자면 다음처럼 몇몇 값이 비어있는 채로 넘어오는 경우이다.
$board => Array
(
[subject] => Array
(
[1] => html입문
)
[description] => Array
(
[0] => php는 <?php로 시작해서 ?>로 끝납니다.
)
[author] => Array
(
[0] => php.net
[1] => w3c.org
)
)
위와 같은 경우는 우리가 원하는 결과를 얻지 못하게 되는 것이다.

그렇다면, 제2의 방법은 어떠할까?
echo "<table>";
echo "<tr>";
echo "<th>제목</th>";
echo "<th>내용</th>";
echo "<th>작성자</th>";
echo "</tr>";
foreach($board as $value) {
echo "<tr>";
echo "<td>".$value[subject]."</td>";
echo "<td>".$value[description]."</td>";
echo "<td>".$value[author]."</td>";
echo "</tr>";
}
echo "</table>";
눈에 띄게 차이가 나지는 않지만, 위의 코드보다 더 간단하다.
반복문의 반복 횟수를 결정하기 위해 고민할 필요도 없이 foreach문만으로도 작성이 가능하다.
또한 제1의 방법과 달리 아래처럼 몇몇 요소가 빠지더라도 반복 횟수에는 문제가 없다.
$board => Array
(
[0] => Array
(
[description] => php는 <?php로 시작해서 ?>로 끝납니다.
[author] => php.net
)
[1] => Array
(
[subject] => html입문
[author] => w3c.org
)
)
얻을 수 있는 것은 이것 뿐만이 아니다. 안의 변수구성도 간단해졌다.
변수에 $i같은 군더더기 요소가 사라짐으로써, 바이트를 좀 더 줄였다.
PHP와 같은 스크립트 프로그램의 경우에는 파일의 용량이 줄어들수록 처리 엔진의 부하가 줄어들기 때문에 더 효과적이다.

둘째는 데이터베이스에서 자료를 꺼내는 것이 아니라 저장하는 경우이다.
제1의 방법을 보자.(execute_query() 함수에 관련해서는 본 블로그에서 검색해보기 바란다.)
$counter = count($board[subject]);
for($i=0; $i<$counter; $i++) {
unset($keys, $values);
foreach($board as $key => $value) {
if($keys==NULL) {
$keys = "`".$key."`";
$values = "'".$value[$i]."'";
} else {
$keys .= ",`".$key."`";
$values .= ",'".$value[$i]."'";
}
}
$query = "INSERT INTO `board` ($keys) VALUES ($values)";
$result = execute_query($query);
}
앞서 말했던 반복 횟수에 대한 비효율이 계속 나타난다.
또 한 가지 주목해야 할 사항은 NULL값에 대한 비효율문제이다.
만약 배열의 값이 다음과 같이 구성이 되어 있다고 하자.
$board => Array
(
[subject] => Array
(
[1] => html입문
)
[description] => Array
(
[0] => php는 <?php로 시작해서 ?>로 끝납니다.
)
[author] => Array
(
[0] => php.net
[1] => w3c.org
)
)
위의 코드와 같은 경우는 다음과 같은 쿼리문을 만들어낼 것이다.
INSERT INTO `board` (`subject`, `description`, `author`) VALUES ('', 'php는 <?php로 시작해서 ?>로 끝납니다.', 'php.net')
INSERT INTO `board` (`subject`, `description`, `author`) VALUES ('html입문', '', 'w3c.org')
이와 같은 쿼리문은 쓸데 없이 NULL값을 데이터베이스에 입력하게 된다.
이에 대한 유일한 대안인 제2의 방법을 살펴보자.
foreach($board as $item) {
unset($keys, $values);
foreach($item as $key => $value) {
if($keys==NULL) {
$keys = "`".$key."`";
$values = "'".$value."'";
} else {
$keys .= ",`".$key."`";
$values .= ",'".$value."'";
}
}
$query = "INSERT INTO `board` ($keys) VALUES ($values)";
$result = execute_query($query);
}
코드는 $i가 빠졌다거나 하는 소소한 차이일 뿐 거의 달라진 것이 없다.
하지만 한 가지 분명한 것은 NULL값 입력과 같은 비효율적 현상은 나타나지 않는다.
만약 배열의 구성이 다음과 같다고 하자.
$board => Array
(
[0] => Array
(
[description] => php는 <?php로 시작해서 ?>로 끝납니다.
[author] => php.net
)
[1] => Array
(
[subject] => html입문
[author] => w3c.org
)
)
이러한 경우 이 코드는 다음과 같은 쿼리문을 만들어 낸다.
INSERT INTO `board` (`description`, `author`) VALUES ('php는 <?php로 시작해서 ?>로 끝납니다.','php.net')
INSERT INTO `board` (`subject`, `author`) VALUES ('html입문','w3c.org')
군더더기 없이 깔끔한 모습이다.

지금까지 더 효율적인 다차원 배열 구성을 찾기 위해 몇 가지 예를 살펴보았다.
for 루프문의 구성이나 그것을 통한 출력물에 있어서, $변수[항목][숫자]의 형태보다 $변수[숫자][항목] 형태의 구성이 더 효율적임을 입증하였다.
앞으로 이러한 배열 형태를 기반으로 하는 많은 알고리즘들을 생겨났으면 한다.
Posted by 마이클
WebApp/PHP2010. 6. 25. 16:08
PHP에는 배열을 합칠 수 있는 array_merge()함수가 있다.
인자는 두 개의 배열로써 호출할 때는 다음과 같이 호출한다.
$array = array_merge($array1, $array2);

$array1에 $array2에 내용을 끼워 넣어 결과 값을 리턴한다.
그렇기 때문에, 다음 코드를 실행하게 되면
$array[0] = array(1, 2, 3);
$array[1] = array("a", "b", "c");
for($i=0; $i<count($array); $i++) {
$return = array_merge($array[$i], $return);
}
print_r($return);

$array[1]에 $array[0]을 끼워넣는 것이 되므로, 다음과 같이 아래 위가 뒤집힌 값이 나타난다.
Array
(
[0] => a
[1] => b
[2] => c
[3] => 1
[4] => 2
[5] => 3
)
이를 바로잡기 위해서는 함수 인자들의 위치를 신경 써주어야 하겠다.

또한, array_merge함수의 다른 한 가지 특징은 해당 숫자 배열이 존재하는 경우 그 배열명을 피해서 저장한다는 점에 있다.
눈치가 빠른 사람들은 위의 예제에서 눈치 챘겠지만, 위의 예제에서 사용한 배열 두 개의 값은 다음과 같다.
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
{
[0] => a
[1] => b
[2] => c
)
이렇게 중복되는 배열명이 존재하는 경우 그것을 자동적으로 피해서 저장하는 것이다.

하지만 문자 배열의 경우에는 신경을 쓸 필요가 있다. 다음 예제를 살펴보자.
$array1 = array("id" => "identification");
$array2 = array("id" => "i.d.");
$result = array_merge($array1, $array2);
print_r($result);
이것을 실행하게 되면 다음과 같은 결과 값이 나타난다.
Array
(
[id] => Array
(
[0] => identification
[1] => i.d.
)
)
배열이 아니었던 배열명 id의 값을 배열로 저장하고 있는 것이다.

array_merge는 다차원배열도 물론 지원한다.
$array1 = array("member" => array("id"=>"identification"));
$array2 = array("member" => array("pw" => "password"));
$result = array_merge($array1, $array2);
print_r($result);
위의 코드를 실행시키면 , 다음과 같은 결과 값이 나타난다.
Array
(
[member] => Array
(
[id] => identification
[pw] => password
)
)

하지만 1차 배열명이 숫자인 경우에는 문제가 좀 달라진다.
$array1 = array(array("id"=>"identification"));
$array2 = array(array("pw" => "password"));
$result = array_merge($array1, $array2);
print_r($result);
혹시 다음과 같은 결과 값을 예상하고 있지는 않은가?
Array
(
[0] => Array
(
[id] => identification
[pw] => password
)
)
하지만 array_merge()함수는 이처럼 작동하지 않는다.
해당 배열명이 숫자 그리고 그 배열명에 해당하는 값이 NULL이 아닌경우,
NULL값인 숫자 배열명이 나타날때까지 찾아서 그곳에 값을 입력한다.
위의 코드를 통해 말하자면, 현재 [0]은 NULL이 아니므로, 다음 숫자 배열명인 [1]에 값을 저장하게 되는 것이다.
그러므로 위 코드의 결과 값은 다음과 같이 나타난다.
Array
(
[0] => Array
(
[id] = identification
)
[1] => Array
(
[pw] = password
)
)

문자 배열이나 숫자 배열이나 일관된 방법으로 배열을 저장하는 함수를 개발 중이므로,
개발이 완료되면 공개하도록 하겠다.

'WebApp > PHP' 카테고리의 다른 글

foreach 배열 반복  (0) 2010.08.12
다차원배열의 구성  (0) 2010.06.26
Form과 Input 태그로 배열 넘기기  (0) 2010.06.24
파일 경로 숨긴 채로 전송 및 다운로드하기  (0) 2010.06.07
파일 읽기 함수  (0) 2010.05.30
Posted by 마이클
WebApp/PHP2010. 6. 24. 01:08
form과 input 태그를 통해서 배열을 넘기는 것을 의외로 간단하다.
input 태그에 있는 name 속성에 변수명 및 대괄호[]를 이용해서 작성한다.
다음 예제를 통해서 확인하자.
<form action='http://www.example.com/' method='post'>
<p>
<label>array[0]</label>
<input type='text' name='array[]' value='hello' />
<br />
<label>array[1]</label>
<input type='text' name='array[]' value='world' />
<br />
<label>array[2]</label>
<input type='text' name='array[]' value='!' />
<br />
<input type='submit' value='Submit' />
</p>
</form>

위의 예제를 통해서 값을 전송하게 되면, PHP와 같은 경우 위의 값을 다음 코드를 통해 출력할 수 있다.
print_r($array);
또는
print_r($_POST['array']);
의 두 가지 방법 모두 가능하다. 하지만 Form태그의 Method 값이 GET인 경우는 배열을 넘길 수가 없으니 $_GET은 무용지물임을 명심하기 바란다.

상단 코드의 실행 값은 다음과 같다,
Array ( [0] => hello [1] => world [2] => ! )

숫자를 이용한 자동 배열 뿐만 아니라 문자로 지정한 배열명도 사용이 가능하다.
<form action='http://www.example.com' method=''>
<p>
<label>Identification</label>
<input type='text' name='user[id]' value='hello' />
<br />
<label>Password</label>
<input type='password' name='user[pw]' value='world' />
<br />
<input type='submit' name='Sign-in' />
</p>
</form>
위와 같이 제출 폼을 작성하면 print_r함수로 다음과 같은 값을 얻을 수 있다.
Array ( [user] => Array ( [id] => hello [pw] => world ) )

'WebApp > PHP' 카테고리의 다른 글

다차원배열의 구성  (0) 2010.06.26
array_merge()  (0) 2010.06.25
파일 경로 숨긴 채로 전송 및 다운로드하기  (0) 2010.06.07
파일 읽기 함수  (0) 2010.05.30
PHP 자바스크립트 경고 함수  (0) 2010.05.30
Posted by 마이클
xFacility/Codes2010. 6. 8. 19:57
API 4.0에 쓰이는 그릇Container처리 함수입니다.
고민을 나누면 코드를 더 효율적으로 변경할 수 있을 것 같아서 올립니다.

function container($container) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
08.Jun.2010.
DESCRIPTION:
Parse Container to Array
CALL:
container("{a{c{e{10;1;}e=6;}d{g=7;}c{e{5}}}b{e=5;}}");
RETURN:
$result[a][c][e][0] = 10;
$result[a][c][e][1] = 1;
$result[a][c][e][2] = 6;
$result[a][c][e][3] = 5;
$result[a][c][b][e] = 5;
$result[a][d][g] = 7;
*/
if(is_container($container)) {
$container = trim($container);
$leng = strlen($container);
$opens = substr_count($container, "{");
$equals = substr_count($container, "=");
$divides = substr_count($container, ";");
$closes = substr_count($container, "}");
$loop = $opens+$equals+$divides+$closes;
if($loop == 0) {
$return = $container;
} else if(substr_count($container, "{")==substr_count($container, "}")) {
$last_char = substr($container, $leng-1, 1);
if($last_char=="{"||$last_char=="=") {
$container .= substr($container, 0, strlen($container)-1);
} else if($last_char!=";"&&$last_char!="}") {
$container = "{".$container."}";
}
$open = find_chars($container, "{");
$equal = find_chars($container, "=");
$divide = find_chars($container, ";");
$close = find_chars($container, "}");
$j=0;$k=0;$l=0;$m=0;$counter=0;
for($i=0; $i<$loop; $i++) {
if($open[$j]==NULL&&$open[$j]!="0")
$open[$j]=$leng-1;
if($equal[$k]==NULL&&$equal[$j]!="0")
$equal[$k]=$leng-1;
if($divide[$l]==NULL&&$divide[$j]!="0")
$divide[$l]=$leng-1;
if($close[$m]==NULL&&$close[$j]!="0")
$close[$m]=$leng-1;
$breaker[$i] = min($open[$j], $equal[$k], $divide[$l], $close[$m]);
$last_char = substr($container, $breaker[$i-1], 1);
$now_char = substr($container, $breaker[$i], 1); 
$length = $breaker[$i];
if($i!=0)
$length -= $breaker[$i-1]+1;
switch ($now_char) {
case "{":
if($last_char!="="&&$length>0) {
$address_now .= "{".trim(substr($container, $breaker[$i-1]+1, $length));
if($auto[$address_now]==NULL&&$auto[$address_now]!="0") {
$auto[$address_now] = 0;
}
}
$j++;
break;
case "=":
if($last_char!="="&&$length>0) {
$address_now .= "{".trim(substr($container, $breaker[$i-1]+1, $length));
}
$k++;
break;
case ";":
if($length>0) {
$value[$counter] = trim(substr($container, $breaker[$i-1]+1, $length));
if($last_char!="=")
$address_now .= "{".$auto[$address_now];
$address[$counter] = $address_now;
$address_now = drop_atlastchar($address_now, "{");
if($last_char!="=")
$auto[$address_now]++;
$counter++;
}
$l++;
break;
case "}":
if($i!=0&&$length>0) {
$value[$counter] = trim(substr($container, $breaker[$i-1]+1, $length));
if($last_char!="=")
$address_now .= "{".$auto[$address_now];
$address[$counter] = $address_now;
$address_now = drop_atlastchar($address_now, "{");
$address_now = drop_atlastchar($address_now, "{");
if($last_char!="=")
$auto[$address_now]++;
$counter++;
} else if($length==0&&$last_char==";") {
$address_now = drop_atlastchar($address_now, "{");
}
$m++;
break;
}
}
}
}
//upsidedown
for($i=0; $i<$counter; $i++) {
$value_tmp[$counter-$i-1] = $value[$i];
$address_tmp[$counter-$i-1] = $address[$i];
}
unset($value, $address);
$value = $value_tmp;
$address = $address_tmp;
for($i=0; $i<=$counter; $i++) {
$loop = substr_count($address[$i], "{");
for($j=0; $j<$loop; $j++) {
$name = drop_atlastchar($address[$i], "{", false);
$temp[$name] = $value[$i];
unset($value[$i]);
$value[$i] = $temp;
unset($temp);
$address[$i] = drop_atlastchar($address[$i], "{");
}
$return = array_merge_recursive($value[$i], $return);
}
return $return;
}

'xFacility > Codes' 카테고리의 다른 글

xFacility^PHP > Internal API 3.0  (0) 2010.06.08
xFacility^PHP > Internal API 2.0  (0) 2010.05.17
xFacility^PHP > Internal API 1.0  (0) 2010.05.17
Posted by 마이클
xFacility/Codes2010. 6. 8. 11:11
API 2.0에서 함수명만을 변경해서 가져온 것도 있고, 처리 알고리즘이 변화한 함수들도 있습니다.

<?php
//Common
//String
//Get extension of url or path
function get_extension($path) {
$return = substr($path,strrpos($path,".")+1);
return $return;
}
//Trim the strings at end
function trim_string($string, $character = ",;") {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
22.Apr.2010.
DESCRIPTION:
Trim a special character(comma and semicolon) at end of string
CALL:
trim_string("lang=en,ko,jp,ch;hobby=reading books,programming,bowling;");
RETURN:
$string = "lang=en,ko,jp,ch;hobby=reading books,programming,bowling";
*/
//Define times for a Loop
$length = strlen($character);
//Check each character by a loop
for ($i=0; $i<$length; $i++) {
//If the end of string is a appointed character,
if(substr($string,-1) == substr($character, $i, 1)) {
//Delete the last character of string
$string = substr($string, 0, -1);
}
}
//Return a trimmed string
return $string;
}
//Drop string at first needle
function drop_atfirsttext($haystack, $needle, $from = false) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
07.Jun.2010.
DESCRIPTION:
Drop a text from(or to) a first needle.
CALL:
drop_atfirsttext("http://www.nate.com:8080/", ":");
RETURN:
if($from = true) {
$return = "//www.nate.com:8080/";
} else if($from = false) {
$return = "http";
}
*/
if($from == true || $from == 1) {
$start = strpos($haystack, $needle) + strlen($needle);
$string = substr($haystack, $start);
$string = ltrim($string);
} else {
$length = strpos($haystack, $needle);
$string = substr($haystack, 0, $length);
$string = rtrim($string);
}
return $string;
}
//Drop string at first needle
function drop_atlasttext($haystack, $needle, $from = false) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
07.Jun.2010.
DESCRIPTION:
Drop a text from(or to) a last needle.
CALL:
drop_atlasttext("http://www.nate.com:8080/", ":");
RETURN:
if($from = true) {
$return = "http://www.nate.com";
} else if($to = false) {
$return = "8080/";
}
*/
if($from == true || $from == 1) {
$start = strrpos($haystack, $needle);
$length = strlen($haystack)-$start;
$string = substr($haystack, $start+strlen($needle), $length);
$string = rtrim($string);
} else {
$length = strrpos($haystack, $needle);
$string = substr($haystack, 0, $length);
$string = rtrim($string);
}
return $string;
}
//Drop a text to a needle
function drop_fronttext($haystack, $needle, $position) {
for($i=0; $i<$position; $i++) {
$start = strpos($haystack, $needle) + strlen($needle);
$haystack = substr($haystack, $start);
}
$string = ltrim($haystack);
return $string;
}
//Position of a needle
function whereis_string($haystack, $needle) {
if(substr_count($haystack, $needle) == 0) {
$return[0] = "xfacility";
$return[1] = "return";
$return[2] = 1;
$return[5] = "Nothing to Find.";
} else {
for($i=0; substr_count($haystack, $needle)!=0; $i++) {
if($i == 0){
$array[$i] = strpos($haystack, $needle);
} else {
$array[$i] = $array[$i-1] + strlen($needle) + strpos($haystack, $needle);
}
$haystack = substr($haystack, strlen($needle) + strpos($haystack, $needle));
}
$return = $array;
}
return $return;
}
//File
//Scandir for PHP4
function scandir_php4($path) {
$handle = dir($path);
while (false !== ($entry = $handle->read())) {
$result[$i] = $entry; 
$i++;
}
$handle->close();
return $result;
}
//Count numbers of directories and files
function count_dir($path) {
$handle = dir($path);
while (false !== ($entry = $handle->read())) {
$result++;
}
$handle->close();
return $result;
}
//Upload a file
function upload_file($file=NULL, $counter=1) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
07.Jun.2010.
DESCRIPTION:
Upload each files to shelf.
CALL:
upload_file($_FILES);
RETURN:
$return['path'] = "/home/hosting_users/username/www/shelf/123901233.bmp";
$return['url'] = "/shelf/123901233.bmp";
$return['size'] = "1255320";
$return['name'] = "123901233.bmp":
$return['mime'] = "image/bmp";
$return['ext'] = "bmp";
*/
$return[0] = "xFacility";
$return[1] = "return";
$return[2] = 0;
$return[3] = "API";
$return[4] = have_thetime();
if($file == NULL) {
if($_FILES == NULL) {
$return[2] = 1;
$return[5] = "There is nothing to process.";
return $return;
} else {
$file = $_FILES;
}
}
for($i=0; $i<$counter; $i++) {
if ($file[$i]['size'] > 0) {
$timestamp = time();
$extension = get_extension($file[$i]['name']);
$filename = $timestamp.".".$extension;
$directory = $_SERVER['DOCUMENT_ROOT']."/shelf/";
$path = $directory.$filename;
$url = "/shelf/".$filename;
if(file_exists($url)) {
$return[2] = 1;
$return[5] = "There is a file having the name.<br />Please retry.<br />Filename: $filename";
return $return;
} else {
move_uploaded_file($file[$i]['tmp_name'], $path);
$result['path'][$i] = $path;
$result['url'][$i] = $url;
$result['size'][$i] = $file[$i]['size'];
$result['name'][$i] = $file[$i]['name'];
$result['mime'][$i] = $file[$i]['type'];
$result['ext'][$i] = $extension;
}
} else {
$return[2] = 1;
$return[5] = "There is nothing to upload.";
return $return;
}
}
$return = $result;
return $return;
}
//find icon
function find_icon($type="file", $mime="text/plain", $extension="txt", $size="32") {
switch($type) {
case "file":
switch($mime) {
case "application/x-msdownload":
$return = "exe";
break;
case "application/unknown":
$return = "hwp";
break;
case "image/jpeg":
case "image/bmp" :
case "text/plain":
default:
$return = "txt";
break;
}
break;
case "text":
$return ="txt";
break;
case "link":
default:
$return = "htm";
}
$return .= $size.".png";
return $return;
}
//HTML
function redirect($url) {
echo "<meta http-equiv='Refresh' content='0; url=$url' />"; 
return 0;
}
//JavaScript
function alert($message) {
echo "<script type='text/javascript'>\n";
echo "<!--\n";
   echo "alert('$message');\n";
   echo "// -->\n";
echo "</script>\n";
return 0;
}
//XML
//Bring a value of an element
function get_valueofelement($codes, $element) {
//Check Codes
//Numbers of open tags match numbers of close tags
if($return == NULL) {
$open = substr_count($codes, "<$element>");
$close = substr_count($codes, "</$element>");
if($open != $close) {
$return = "1";
}
}
//Overlapping of open or close code
if($return == NULL) {
$open = whereis_string($codes, "<$element>");
if($open[0]=="xfacility"&&$open[1]=="return"&&$open[2]==1) {
$open = whereis_string($codes, "<$element ");
if($open[0]=="xfacility"&&$open[1]=="return"&&$open[2]==1) {
$return = $open;
}
}
$close = whereis_string($codes, "</$element>");
for($i=0; 1; $i++){
if($open[$i]==NULL) {
break;
} else if($open[$i]>=$close[$i]) {
$return = "1";
}
}
}
//Parse
if($return == NULL) {
for($i=0; 1; $i++) {
if($close[$i]==NULL) {
break;
}
$return[$i] = substr($codes, $open[$i]);
$return[$i] = drop_atfirsttext($return[$i], ">");
$return[$i] = drop_atfirsttext($return[$i], "</$element>", 0);
$return[$i] = trim($return[$i]);
$return[$i] = str_replace("\t", "", $return[$i]);
}
}
return $return;
}
//Convert what to condition
function cvt_what2condition() {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
28.Apr.2010.
DESCRIPTION:
Parse Range to Array
CALL:
parse_range("<item>
<no>1</no>
<subject>hello world!</subject>
</item>
<item>
<no>2</no>
<subject>play</subject>
</item>
<item>
<no>3</no>
</item>");
RETURN:
$condition = (`no`='1' AND `subject`='hello world!') OR (`no`='2' AND `subject1='play') OR (`no`='3');
*/
}
//Convert where to Table
function cvt_where2table() {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
28.Apr.2010.
DESCRIPTION:
Parse Range to Array
CALL:
parse_range("1-3,7,10-11");
RETURN:
$array[0] = "1";
$array[1] = "2";
$array[2] = "3";
$array[3] = "7";
$array[4] = "10";
$array[5] = "11";
*/
}
//Range
//Is range
function is_range($range) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
17.May.2010.
DESCRIPTION:
Check this out as a range.
CALL:
is_range("1-3,7,10-11");
RETURN:
$is = true;
*/
return $is;
}
//Parse Range
function parse_range($range) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
28.Apr.2010.
DESCRIPTION:
Parse Range to Array
CALL:
parse_range("1-3,7,10-11");
RETURN:
$array[0] = "1";
$array[1] = "2";
$array[2] = "3";
$array[3] = "7";
$array[4] = "10";
$array[5] = "11";
*/
//Trim a string
$range = trim_string($range);
$range = trim($range);
//Parse a string by comma
$temp = split(",", $range);
//Move values to array
$now = 0;
for ($i=0; $i<=substr_count($range,","); $i++) {
//Check a hyphen
if (substr_count($temp[$i],"-") == 1) {
list($start, $end) = split("-", $temp[$i]);
$difference = $end - $start;
for ($j=0; $j<=$difference; $j++) {
$array[$now] = $start + $j;
$now += 1;
}
} else {
$array[$now] = $temp[$i];
$now += 1;
}
}
//Delete overlapping values 
$array = array_unique($array);
//Sort the array
sort($array);
reset($array);
//Return Array
return $array;
}
//Convert range to condition
function cvt_range2condition($range) {
if($range == 0) {
$return = 1;
} else {
$array = parse_range($range);
$i = 0;
foreach ($array as $value) {
if($i != 0) {
$return .= " OR ";
}
$return .= "`no`=".$value;
$i++; 
}
$return = trim_string($return);
}
return $return;
}
//Container
function parse_container($container) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
22.Apr.2010.
DESCRIPTION:
Parse a string including values to Array
CALL:
parse_container("lang=en,ko,jp,ch;hobby=reading books,programming,bowling;");
RETURN:
$array['lang'][0] = "en";
$array['lang'][1] = "ko";
$array['lang'][2] = "jp";
$array['lang'][3] = "ch";
$array['hobby'][0] = "reading books";
$array['hobby'][1] = "programming";
$array['hobby'][2] = "bowling";
*/
//Trim a string of values
$container = trim_string($container);
//Parse a string by semicolon
$temp = split(";", $container);
//Define times for a loop
$counter = substr_count($container, ";");
for ($i = 0; $i<=$counter; $i++) {
//Parse a string into name and values
list($name, $values) = split("=", $temp[$i]);
//Trim a left of name
$name = ltrim($name);
//Parse values into each value
$array[$name] = split(",", $values);
//Define times for a internal loop
$counter2 = substr_count($values, ",");
for ($j = 0; $j<=$counter2; $j++) {
//Trim a left of value
$array[$name][$j] = ltrim($array[$name][$j]);
}
}
//Return Array
return $array;
}
//Time
function have_thetime($timestamp = NULL) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
16.May.2010.
DESCRIPTION:
Have the time
CALL:
have_thetime("0");
RETURN:
$result = "1970Jan01090000";
*/
if($timestamp == NULL) {
$timestamp = time();
}
return date('YMdHis', $timestamp);
}
//Checker
function check_sentence($sentence) {
//Parse
$who = get_valueofelement($sentence, "who");
$how = get_valueofelement($sentence, "how");
$what = get_valueofelement($sentence, "what");
$where = get_valueofelement($sentence, "where");
$when = get_valueofelement($sentence, "when");
$why = get_valueofelement($sentence, "why");
//Authority
if($return==NULL) {
//If the sentence of xFXML was written by xfacility, 
if($who[0]=="xfacility") {
$return[2] = 1;
$return[5] = "We cannot support to send a message from xfacility to xfacility.";
//Is there a user having the number?
} else {
$query = "SELECT * FROM `xf_user` WHERE `no`='$who[0]'";
$result = execute_query($query);
$number = count_result($result);
if($number==0) {
$return[2] = 1;
$return[5] = "There is no user who have the number.";
}
}
//Find settings in xF_Authority
}
//Form
if($return==NULL) {
}
//Rule
if($return==NULL) {
}
//Return
return $return;
}
//Database
//Execute
function execute_query($query) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
28.Apr.2010.
DESCRIPTION:
Execute an query
CALL:
execute_query("DROP TABLE `xf_authority`;");
RETURN:
$result = <<RESULT OF QUERY>>;
$result = 1; // Error
*/
//Load information about DB 
include $_SERVER['DOCUMENT_ROOT']."/shelf/database.php";
//Connect to DB, Select DB and run a query
//If the database program is MySQL,
if($xf_db['kind'] == "mysql") {
//Connect to database Program
$link = @mysql_connect($xf_db['server'], $xf_db['username'], $xf_db['password']);
//Select database
mysql_select_db($xf_db['database'], $link);
$result = mysql_query($query, $link);
//Close the connection
mysql_close();
} else {
$result = false;
}
//Return result of database
if($result == false) {
$return[0] = "xFacility";
$return[1] = "return";
$return[2] = "1";
$return[3] = "API";
$return[4] = have_thetime();
$return[5] = "There is an error while executing a query.<br />Query:<br />".$query;
} else {
$return = $result;
}
return $return;
}
//Count a number of results
function count_result($result) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
28.Apr.2010.
DESCRIPTION:
Count the rows of a result 
CALL:
count_result(<<RESULT OF QUERY>>);
RETURN:
$number = 3;
$number = NULL; // Error
*/
//Load information about DB 
include $_SERVER['DOCUMENT_ROOT']."/shelf/database.php";
//If the database program is MySQL,
if($xf_db['kind'] == "mysql") {
$number = mysql_num_rows($result);
} else {
$number = NULL;
}
//Return a number
return $number;
}
function parse_result($result, $fields = NULL) {
/*
DEVELOPMENT:
Michael Son(michaelson@nate.com)
30.May.2010.
DESCRIPTION:
Parse a result of query
CALL:
xfx_prs_res(<<RESULT OF QUERY>>);
RETURN:
$array['no'][0] = 3;
$array['indicator'][0] = 1349851283;
$array['status'][0] = 1;
$array['id'][0] = "root";
$array['pw'][0] = "*68F9CD57023F17CBE06EE6365D9B4FEBF3EB3EE4";
$array['etc'][0] = "lang=en,ko,jp,ch";
$array['no'][1] = 4;
$array['indicator'][1] = 1352878344;
$array['status'][1] = 1;
$array['id'][1] = "administrator";
$array['pw'][1] = "*1F7E399139C29C99909A2C7E8C56247043C4FEE1";
$array['etc'][1] = "lang=ko,en";
$array = NULL //Error
*/
//Load information about DB
include $_SERVER['DOCUMENT_ROOT']."/shelf/database.php";
//If the list of fields are missed,
if($fields == NULL) {
$counter = 0;
} else {
//Parse fields by comma
$temp = split(",", $fields);
//Estimate times for a loop
$counter = substr_count($fields, ",");
}
for ($i=0; $i<=$counter; $i++) {
//If the list of fields are missed,
if($fields == NULL) {
//If the database program is MySQL,
if($xf_db['kind'] == "mysql") {
//Get field Name
$field = @mysql_field_name($result, $i);
} else {
//Stop the processing of this function
return $array = NULL;
}
//If there is no field name,
if ($field == NULL) {
//Stop this Loop
break;
} else {
//One more time
$counter++;
}
} else {
$field = $temp[$i];
}
//Estimate times for a subloop
$counter2 = count_result($result);
for($j=0; $j<$counter2; $j++) {
//If the database program is MySQL,
if($xf_db['kind'] == "mysql") {
$array[$field][$j] = mysql_result($result, $j, $field);
} else {
//Stop the processing of this function
return $array = NULL;
}
}
}
//Return Array
return $array;
}
//Database I/O
//Write
function write_db($what, $where) {
//Infinity loop
for($i=0; 1; $i++) {
//If there is nothing to input in DB,
if($item[$i][0] == NULL) {
break;
}
//If there is not designated number,
if($no[$i] == NULL) {
//Insert
$query = "INSERT INTO `$table[$i]`($fields[$i]) VALUES($values[$i])";
} else {
//Update
$query = "UPDATE `$table[$i]` SET $settings[$i] WHERE $conditions[$i]";
}
$result = execute_query($query);
if($result == 1) {
$return[0] = "xFacility";
$return[1] = "return";
$return[2] = "1";
$return[3] = $where[3];
$return[5] = "There is an error during writing into db.";
return $return;
}
}
//Return
if($return == NULL) {
$return = 0;
}
return $return;
}
//Read
function read_db($what, $where) {
if (is_array($what[$i])==true) {
} else if (is_range($what[$i])==true) {
} else {
$return[2] = "1";
$return[5] = "There is nothing to read.";
}
return $return;
}

//Delete
function delete_db($what, $where) {
$condition = cvt_what2condition($what);
$table = cvt_where2table($where);
$query = "DELETE FROM `$table` WHERE $condition";
$return = execute_query($query);
return $return;
}
//XML I/O
//Read
function read_xfxml($xfxml) {
//Parse
//Trim a xFXML
$sentence = get_valueofelement($xfxml, "sentence");
if($sentence == 1) {
$return = 1;
}
//Check
if($return == NULL) {
foreach($sentence as $key => $value) {
$result = check_sentence($value);
if($result[2]==1) {
$return = $result;
break;
}
}
}
//Execute
if($return == NULL) {
foreach($sentence as $key => $value) {
$how = get_valueofelement($value, "how");
$what = get_valueofelement($value, "what");
$where = get_valueofelement($value, "where");
switch($how[0]) {
case "write":
case "edit":
echo "write_db($what[0], $where[0])";
break;
case "read":
echo "read_db($what[0], $where[0])";
break;
case "delete":
echo "delete_db($what[0], $where[0])";
break;
case "return":
$return[2] = 1;
$return[5] = "There is nothing to run.";
}
}
}
//Return
echo write_xfxml($return);
}
//Write
function write_xfxml($return) {
if($return[0] == NULL) {
$return[0] = "xfacility";
}
if ($return[1] == NULL) {
$return[1] = "return";
}
if ($return[2] == NULL) {
$return[2] = "0";
}
if ($return[4] == NULL) {
$return[4] = have_thetime();
}
//Declare
$xfxml = "<?xml version='1.0' encoding='utf-8' ?>\n\n";
//Open sentences
$xfxml .= "<sentences>\n";
//Open sentence
$xfxml .= "\t<sentence>\n";
//Who
$xfxml .= "\t\t<who>$return[0]</who>\n";
//How
$xfxml .= "\t\t<how>$return[1]</how>\n";
//What
$xfxml .= "\t\t<what>$return[2]</what>\n";
//Where
$xfxml .= "\t\t<where>$return[3]</where>\n";
//When
$xfxml .= "\t\t<when>$return[4]</when>\n";
//Why
$xfxml .= "\t\t<why>$return[5]</why>\n";
//Close sentence
$xfxml .= "\t</sentence>\n";
//Close sentences
$xfxml .= "</sentences>\n";
return $xfxml;
}
//[xF]User
function xfu_signin($id, $pw, $url=NULL) {
if($id == NULL) {
alert("아이디가 입력되지 않았습니다.");
} else {
if ($pw == NULL) {
alert("비밀번호가 입력되지 않았습니다.");
} else {
$query = "SELECT * FROM `xf_user` WHERE `id`='$id'";
$result = execute_query($query);
if($result == 1) {
alert("쿼리 실행중 오류가 발생하였습니다.");
} else {
$counter = count_result($result);
if($counter > 1) {
alert("DB에 문제가 있습니다. 동일 아이디가 $counter개 있습니다.");
} else if($counter < 1) {
alert("There is no ID in system.");
} else {
$query = "SELECT * FROM `xf_user` WHERE `id`='$id' AND `pw`=password('$pw')";
$result = execute_query($query);
if($result == 1) {
alert("Error on executing a query.");
} else {
$counter = count_result($result);
if($counter == 0) {
alert("The password is wrong.");
} else {
alert("You have signed in.");
$array = parse_result($result);
$return['xf_id'] = $array['no'][0];
$return['xf_etc'] = parse_container($array['etc'][0]);
}
}
}
}
if($url != NULL) {
redirect($url);
}
}
}
return $return;
}
//[xF]Appbox
function get_nameofapps() {
$path = $_SERVER['DOCUMENT_ROOT']."/appbox/";
$array = scandir_php4($path); 
$counter = count_dir($path);
for($i=0; $i<$counter; $i++) {
if($array[$i]=="." || $array[$i]=="..") {
unset($array[$i]);
} else if(!is_dir($path.$array[$i])) {
unset($array[$i]);
}
}
sort($array);
reset($array);
$return = $array;
return $return;
}
?>

'xFacility > Codes' 카테고리의 다른 글

container()  (0) 2010.06.08
xFacility^PHP > Internal API 2.0  (0) 2010.05.17
xFacility^PHP > Internal API 1.0  (0) 2010.05.17
Posted by 마이클
WebApp/PHP2010. 6. 7. 18:43
파일 경로를 숨긴채로 전송 다운로드를 하려면, 웹 브라우저에게 스크립트 파일이 실제 파일인 것처럼 속여야 한다.

속이지 않은채로 무작정 바이너리 데이터를 전송하게 되면, 웹브라우저가 바이너리 데이터를 텍스트 데이터로 착각한다.
그래서 데이터에 EUC-KR이나, UTF-8같은 텍스트 인코딩을 적용하여 화면상에 깨진 문자들이 나타나게 된다.

그래서 바이너리 데이터, 데이터 종류(MIME type)을 인식하도록 웹 브라우저를 속이는 일련의 절차들을 거치는데
바로 헤더 메시지를 통해서 이러한 일들을 하는 것이다.
(여기서 말하는 헤더란, HTML 상에 있는 헤더 태그들과는 별개이며
클라이언트와 서버 사이에 실제 데이터의 전송을 위한 준비 과정이다.)

이 헤더는 image/bmp파일 인것으로 속이는 헤더이다.
Content-Type: image/bmp

이 헤더는 스크립트 파일을 test.bmp로 다운로드하도록 유도한다.
Content-Disposition: attachment; filename=test.bmp

위에 있는 헤더는 무조건 다운로드를 유도하기 때문에
만약 이미지 파일이나 PDF파일을 웹브라우저에서 열어보게 하고 싶은 경우에는 헤더를 변경해야 한다.
아래 있는 예제와 같이 attachment를 inline으로 변경한다.
Content-Disposition: inline; filename=test.bmp

이 헤더는 파일의 크기를 나타낸다.
Content-Length: 1289733

이러한 일련의 헤더들을 header()함수로 전송을 한다.
header("Content-Type: image/bmp");
header("Content-Disposition: attachment; filename=text.bmp");
header("Content-Length: 1289733");

이렇게 헤더를 전송하면 이후에 받을 스크립트 파일을 test.bmp라는 이미지 파일로 인지하게 된다.

스크립트 파일을 실제 이미지 파일로 내용을 채워 넣는다.
echo implode("", file("/www/text.bmp"));

이렇게 되면 웹 브라우저는 스크립트 파일의 내용을 하나의 이미지 파일로 클라이언트에 저장한다.

만약 헤더의 실제에 대해서 알아보고 싶다면, 파이어폭스Firefox에 헤더와 관련한 좋은 부가기능들이 많이 있으니 설치하여 이용하길 바란다.

MIME-Type의 종류에 대해서는 다음 링크를 통해 확인할 수 있다.
http://www.iana.org/assignments/media-types/index.html

'WebApp > PHP' 카테고리의 다른 글

다차원배열의 구성  (0) 2010.06.26
array_merge()  (0) 2010.06.25
Form과 Input 태그로 배열 넘기기  (0) 2010.06.24
파일 읽기 함수  (0) 2010.05.30
PHP 자바스크립트 경고 함수  (0) 2010.05.30
Posted by 마이클