'자작소스/PHP'에 해당되는 글 50건

  1. 2009.11.27 PHP로 mcrypt_ 함수를 다른 언어(C++,C#)와 사용할때 주의 사항
  2. 2009.09.16 mysql 처리용 함수 및 클래스
  3. 2009.08.13 페이징 클래스 v1.02 (PHP4)
  4. 2009.05.13 디비 관련 함수
  5. 2009.05.04 문자열을 길이만큼 나누기
  6. 2009.03.23 TSP 세일즈맨 문제를 풀었던 소스
  7. 2009.03.17 페이징 클래스 v1.01 (PHP4/5)
  8. 2009.03.09 페이징 클래스 v1.0 (PHP4/5) 1
  9. 2007.10.29 MNCAST 플래시 동영상 정보 수집 BOT
  10. 2007.10.29 문자를 저장하는 함수
2009. 11. 27. 15:42

PHP로 mcrypt_ 함수를 다른 언어(C++,C#)와 사용할때 주의 사항


<?
$mcrypt_key = "abcdefghijklmnop";
$mcrypt_iv = "abcdefghijklmnop";

$str = "테스트요";
$encode = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $mcrypt_key, $str, MCRYPT_MODE_CBC, 
$mcrypt_iv); $enc_str = base64_encode($encode); echo $enc_str."<br />"; $decode = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $mcrypt_key, $enc_str, MCRYPT_MODE_CBC,
$mcrypt_iv); echo $dec; ?>
PHP의 mcrypt 함수로 아주 간단하게 AES(rijndael128) 암호화와 복호화를 한는 소스입니다.
128bit 암호화 알고리즘으로 암호화를 진행하고 있으며 각각 암호화하는 블럭의 크기는 128bit(16byte) 입니다.
블럭의 크기를 알고자 하신다면 mcrypt_get_block_size 함수로 구하실 수 있습니다.

블럭의 크기를 이야기 하는 이유는 문자열을 블럭단위로 암호화하기 때문에 마지막 블럭의 크기는 문자열의 길이가 딱 16byte로 나누어 떨어지지 않는한 16byte가 되지 못하고 빈 공간만큼 특정문자로 채우게 됩니다(pad)

VC++, C# 등에서 mcrypt를 사용할경우 남은 공간을 채울 문자(모드)를 여러가지중 하나로 정하도록 되어있는데
PHP의 경우에는 자동적으로 Zero패딩(Zeros) 으로 처리되게 됩니다.(남는 부분을 null = 0x00로 채움) 따라서 VC++ 등에서 pad를 그냥 default 설정으로 할경우 암,복호화가 되지 않을 수 있습니다.
그래서 다른 언어상에서 암호화 복호화를 위해서는 반드시 Zero패딩(Zeros)로 설정하셔야 합니다.
(PKCS5로 하면 안됨)
2009. 9. 16. 16:26

mysql 처리용 함수 및 클래스


<?
define('YSDB_FETCH_ROW',0);
define('YSDB_FETCH_COL',1);

/**
 * 디비 처리함수
 *
 * @param text $sql
 * @return integer/text/array/FALSE
 */
function query($sql,$dbRes=NULL,$mode=0) {
 $sql = trim($sql);

 if($dbRes == NULL)
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql);
 else 
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql,$dbRes);
  
 if($result === FALSE) 
  return FALSE;
 
 $tmp = strtoupper(substr($sql,0,3));
 if($tmp == 'DEL' || $tmp == 'UDP') {
  //delete,update 쿼리는 수정/삭제된 행의 수를 리턴
  $row = mysql_affected_rows();
  if($row != '-1') 
   return $row;
 }
 elseif($tmp == 'INS') {
  $rtn = mysql_affected_rows();
  if($rtn > 1) //여러개의 열이 영향을 받은경우 그값을 리턴
   return $rtn;
  else //insert 쿼리는 등록된 primary key 리턴
   return mysql_insert_id();
 }
 elseif($tmp == 'SEL') {
  if($mode) {
   while ($row = mysql_fetch_assoc($result)) {
    foreach ($row as $key => $value){
     $rtn[$key][] = $value;
    }
   } 
  }
  else {
   $rtn = array();
   while($row=mysql_fetch_assoc($result)) {
    array_push($rtn,$row);
   }
  }
  mysql_free_result($result);
  return $rtn;
 }
}

function queryRow($sql,$dbRes=NULL) {
 $sql = trim($sql);

 if($dbRes == NULL)
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql);
 else 
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql,$dbRes);
  
 if($result === FALSE) 
  return FALSE;
 
 return mysql_fetch_assoc($result);
}

function queryOne($sql,$dbRes=NULL) {
 $sql = trim($sql);

 if($dbRes == NULL)
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql);
 else 
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql,$dbRes);
  
 if($result === FALSE) 
  return FALSE;
 
 return @mysql_result($result,0,0);
}

--------------------------------------------------------------------------------------------------


class DBCon {
 /**
  * 기본 웹디비 연결
  * 다른 디비로 연결하려면 상속받은 객체에 
  * 오버라이딩 해서 쓰세요.
  */
 var $mHost = '';
 var $mUser = '';
 var $mPassword = '';
 var $mDB = '';
  
 /**
  * 데이타베이스 연결 리소스
  */
 var $mDbCon = NULL;
 
 /**
  * 문자서버 연결상태
  */
 var $mState = FALSE;
 
 /**
  * 데이타베이스 연결
  * PHP4 생성자는 존재하나 소멸자를 지원하지 않아 생성자로 연결시
  * 과도한 연결이 발생할 수 있으므로 open(),close() 를 명확하게 설정
  */
 function open() {
  if($this->mState) return TRUE;
  
  $this->mDbCon = mysql_connect($this->mHost, $this->mUser, $this->mPassword);
  if($this->mDbCon) {
   mysql_select_db($this->mDB, $this->mDbCon);
   $this->mState = TRUE;
   
   return TRUE;
  }
  
  return FALSE;
 }
 
 /**
  * 데이타베이스 연결을 종료
  *
  */
 function close() {
  if(!$this->mState) return TRUE; 
  
  if(mysql_close($this->mDbCon)) {
   unset($this->mDbCon);
   $this->mState = FALSE;
   return TRUE;
  }
  else
   return FALSE;
 }
 
 /**
  * 데이타베이스 연결 상태를 리턴
  *
  * @return TRUE/FALSE
  */
 function getConnectState() {
  return $this->mState;
 } 
 
 /**
  * mysql 연결 반환
  *
  * @return resource
  */
 function getDbCon() {
  return $this->mDbCon;
 }
 
 /**
  * 외부 mysql 연결
  *
  * @param resource $dbcon
  */
 function setDbCon($dbcon) {
  if(!is_resource($dbcon))
   exit('Error : $dbcon IS NOT RESOURCE ');
  
  $this->mDbCon = $dbcon;
  $this->mState = TRUE;
 } 
 
 /**
  * 데이타베이스에 쿼리를 실행
  * 쿼리에 따라 결과를 다르게 리턴합니다.
  *
  * @param text $sql
  * @return array/text/FALSE
  */
 function query($sql,$opt = YSDB_FETCH_ROW) {
  if($this->mState === FALSE) $this->open();
  
  $sql = trim($sql);
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql,$this->mDbCon);
  if($result === FALSE) {
   echo mysql_error($this->mDbCon);
   return FALSE;
  }

  $tmp = strtoupper(substr($sql,0,3));
  if($tmp == 'DEL' || $tmp == 'UPD') {
   $row = mysql_affected_rows($this->mDbCon);
   if($row != '-1') 
    return $row;
  }
  elseif($tmp == 'INS') {
   $rtn = mysql_affected_rows($this->mDbCon);
   if($rtn > 1)
    return $trn;
   else
    return mysql_insert_id($this->mDbCon);
  }
  elseif($tmp == 'SEL') {
   $rtn = array();
   if($opt == YSDB_FETCH_COL) {
    while ($row = mysql_fetch_assoc($result)) {
     foreach ($row as $key => $value){
      $rtn[$key][] = $value;
     }
    }
   }
   else {
    while($row=mysql_fetch_assoc($result)) {
     array_push($rtn,$row);
    }
   }
   mysql_free_result($result);
   return $rtn;
  }
 }
 
 /**
  * 쿼리 실행후 한개의 레코드만 리턴
  *
  * @param text $sql
  * @return array
  */
 function queryRow($sql) {
  if($this->mState === FALSE) $this->open();

  $sql = trim($sql);
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql,$this->mDbCon);

  if($result === FALSE) {
   echo mysql_error($this->mDbCon);
   return FALSE;
  }
  
  return mysql_fetch_assoc($result);
 }
 
 /**
  * 쿼리 실행후 하나의 필드만 리턴
  *
  * @param unknown_type $sql
  * @return unknown
  */
 function queryOne($sql) {
  if($this->mState === FALSE) $this->open();
  
  $sql = trim($sql);
  $result = mysql_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql,$this->mDbCon);
   
  if($result === FALSE) {
   echo mysql_error($this->mDbCon);
   return FALSE;
  }
  
  return @mysql_result($result,0,0);
 } 
 
 /**
  * db 비용 절약용 쿼리
  * 주의:쿼리 실행후 완료를 기다리지 않고 다음 쿼리가 실행 되는 점 주의(연속 쿼리시 문제 발생)
  *
  * @param text $sql
  * @return bool
  */
 function queryUnbuf($sql) {
  if($this->mState === FALSE) $this->open();
  
  $sql = trim($sql); 
  $result = mysql_unbuffered_query("/*".$_SERVER['REMOTE_ADDR']."*/ ".$sql,$this->mDbCon);
   
  if($result === FALSE) 
   return FALSE;
  else 
   return TRUE;
 }
} 

?>

2009. 8. 13. 17:24

페이징 클래스 v1.02 (PHP4)


AJAX 처리 가능 클래스 추가(상속)

2009. 5. 13. 13:57

디비 관련 함수


/**
 * 디비 처리함수
 *
 * @param text $sql
 * @return integer/text/array/FALSE
 */
function query($sql,$dbRes=NULL) {
 $sql = trim($sql);

 if($dbRes == NULL)
  $result = mysql_query($sql);
 else 
  $result = mysql_query($sql,$dbRes);
  
 if($result === FALSE) 
  return FALSE;
 
 $tmp = strtoupper(substr($sql,0,3));
 if($tmp == 'DEL' || $tmp == 'UDP') {
  //delete,update 쿼리는 수정/삭제된 행의 수를 리턴
  $row = mysql_affected_rows();
  if($row != '-1') 
   return $row;
 }
 elseif($tmp == 'INS') {
  //insert 쿼리는 등록된 primary key 리턴
  return mysql_insert_id();
 }
 elseif($tmp == 'SEL') {
  //1개 이상의 레코드는 전체 배열로 리턴
  $rtn = array();
  while($row=mysql_fetch_assoc($result)) {
   array_push($rtn,$row);
  }
  mysql_free_result($result);
  return $rtn;
 }
}

function queryRow($sql,$dbRes=NULL) {
 $sql = trim($sql);

 if($dbRes == NULL)
  $result = mysql_query($sql);
 else 
  $result = mysql_query($sql,$dbRes);
  
 if($result === FALSE) 
  return FALSE;
 
 return mysql_fetch_assoc($result);
}

function queryOne($sql,$dbRes=NULL) {
 $sql = trim($sql);

 if($dbRes == NULL)
  $result = mysql_query($sql);
 else 
  $result = mysql_query($sql,$dbRes);
  
 if($result === FALSE) 
  return FALSE;
 
 return mysql_result($result,0,0);
}

2009. 5. 4. 15:49

문자열을 길이만큼 나누기

핸드폰 문자 전송등을 보면 80byte 이하만 전송 가능하기 때문에
긴문자열을 80byte 단위로 쪼개야 할때가 간혹 있다.
문자열을 쪼개는 구분점(딱 80byte가 되는 경계선)에 멀티바이트 문자(한글,특수문자등)이 있다면
앞쪽 문자열은 마지막 문자가 깨지는 현상이 생길 것이고
더 큰 건 뒤쪽 문자열은 완전히 깨져버리는 현상이 생긴다.

예를 들자면 "가1나다3" 문자열의 코드를 보면 이 문자열은 아스키 코드로
176,161 => 가
48 => 1
179,170 => 나
180,217 => 다
50 =>3
이렇게 숫자와 영문등은 1byte, 한글은 2byte로 구성되 있다(euckr의 경우)
이런 경우에 2byte씩 이루어진 각 문자의 중간까지만을 끈어내 버리면 어떻게 될까?
문자열을 4만큼 잘라냈다면 '나' 라는 문자의 중간에서 잘라지게 된다.
이러면 "가1?" 처럼 마지막 문자는 원래코드의 절반만 가지게 되므로 이해할수 없는 문자가 출력되게 된다.
더 큰일은 뒤쪽의 문자열은 '나'의 두번째 byte 인 170 부터 해석을 하는데
아스키 코드 127 보다 큰 값들은 2byte씩 해석 되므로 170 과 뒤에 나오는 '다' 문자의 앞쪽 byte인 180이 같이
해석 되버리게 된다. 그럼 뒤에 문자열은 줄줄이 깨져버리게 되는 증상이 발생된다.

이런 경우 잘리는 경계가 되는 문자가 2byte문자의 중간부분이라면 그전 문자까지만 분리를 해야 된는 것이다.


<?php

//문자 쪼개기 작업
function splitString($str,$size) {
	$len = strlen($str);
	if($size >= $len) return array($str);
	
	$rtn = array();
	$flag = 0;
	$start = 0;
	$end = $size-1;
	for($i=0;$i<$len;$i++) {
		if(ord($str[$i]) > 127) $flag++;
		if($end == $i) {
			if($flag%2 == 1) {
				array_push($rtn,substr($str,$start,$size-1));
				$start += $size - 1;
			}
			else {
				array_push($rtn,substr($str,$start,$size));
				$start += $size;
			}
			$end = $start + $size - 1;
		}
	}
	if($len>=$start) {
		array_push($rtn,substr($str,$start,$len-$start));
	}
	
	return $rtn;
}

$a = "ㅂㅈㄷㅂㅈㄷㄴㅇㅁㄴ유ㅜㅍㅋㅌ츠ㅜ뮨ㅇ8뵤3ㅛ2134234ㅗ234ㅡ3ㅍ45ㅠ34ㅜ5ㅊ34ㅍ5ㅊ3ㅠㅌ53ㅠㅍ453ㅠㅍㅊ5ㅠㅍ32ㅊ4퓨2ㅊ42ㅗ34ㅇ2ㅛㅅ3ㅇ4ㅗ2ㅎ3ㅊ4ㅗ23추ㄱㅎㅈㄷㅊ고2ㅎ34ㅎ23ㅊ4ㅜㅈㅊ규ㅜㅈㅊ고2ㅎ34ㅈㅊ구듀궂ㅊ3ㅗㅎ42ㅗㅎ4ㅊ2ㅊ4ㅜ1ㅠ2ㅊ3ㅠㅜ12ㅊ31ㄹ3ㅗ12234234ㅊ234ㅊ2ㅠㅜ3ㅊ42ㅜ34ㅊ234푸ㅍㄷㄱ234ㅊ2ㅍ4ㅜㅠㅊ243ㅜㅠㅊ2";
print_r(splitString($a,80));
?>

Array
(
    [0] => ㅂㅈㄷㅂㅈㄷㄴㅇㅁㄴ유ㅜㅍㅋㅌ츠ㅜ뮨ㅇ8뵤3ㅛ2134234ㅗ234ㅡ3ㅍ45ㅠ34ㅜ5ㅊ34ㅍ5ㅊ3
    [1] => ㅠㅌ53ㅠㅍ453ㅠㅍㅊ5ㅠㅍ32ㅊ4퓨2ㅊ42ㅗ34ㅇ2ㅛㅅ3ㅇ4ㅗ2ㅎ3ㅊ4ㅗ23추ㄱㅎㅈㄷㅊ고2
    [2] => ㅎ34ㅎ23ㅊ4ㅜㅈㅊ규ㅜㅈㅊ고2ㅎ34ㅈㅊ구듀궂ㅊ3ㅗㅎ42ㅗㅎ4ㅊ2ㅊ4ㅜ1ㅠ2ㅊ3ㅠㅜ12ㅊ3
    [3] => 1ㄹ3ㅗ12234234ㅊ234ㅊ2ㅠㅜ3ㅊ42ㅜ34ㅊ234푸ㅍㄷㄱ234ㅊ2ㅍ4ㅜㅠㅊ243ㅜㅠㅊ2
)
지정한 크기만큼만 배열로 만들되 잘라낼 경계의 문자가 2BYTE의 중간이면 그 이전문자까지만 
잘라내는 것이다.
크기만큼 바로 substr 하지 않고 문자열을 모두 순환하는 이유는
바로 잘라낼 경우 아스키코드 127 보다 크면 multi_byte 코드인 것은 인식 할 수 있지만
그코드가 문자의 앞쪽 byte 인지 뒷쪽 byte 인지는 알 방법이 없다.
그렇기 때문에 모든 문자열을 순환하다가 잘라내야할 경계의 byte에 도착하게 되면
$flag 에 지금까지 나온 multi_bypte 코드의 수를 확인하여
짝수였다면 이미 한글자가 만들어졌으니 그냥 자르면 되고 홀수 일 경우 2byte 문자중 1byte만
출력된 것이니 그 문자 앞까지만 잘라내면 되는 것이다.
 
 
2009. 3. 23. 14:43

TSP 세일즈맨 문제를 풀었던 소스



오늘 PC를 뒤지니 여러가지가 나오는네요.
TSP 문제를 PHP 로 제작해버리는 만행을 저질렀네요 ㅎ
실행파일 실행시 생기는 문제는 책임 못짐.

01234
2009. 3. 17. 16:38

페이징 클래스 v1.01 (PHP4/5)


페이징 클래스를 약간 수정했습니다.
class_paging.php 파일은 PHP4/5 모두 사용가능하며 일반적인 클래스 작성방식으로 작성했으며
class_paging_php5.php 파일은 PHP5 버젼에서 사용가능하며 Singleton 방식으로 작성되어 있다.

[이전] 1 2 3 4 5 [다음]
위와 같은 형식에서 이전,다음+1,-1 page 로 처리하는 사람이 있을 것이고
어떤 사람은 +1,-1 block (ex 다음10페이지,이전10페이지) 와 같은 형식으로 처리를 하는 사람이 있을 것입니다.

v1.0 에서는 이전,다음을 설정하지 않더라도 기본적으로 출력이 되고 +1,-1 page 로 동작하도록 되있었습니다. 이럴 경우 후자와 같이 처리하는 사람은 사용할 수 없으므로 기본 출력 부분을 삭제하여 메뉴 설정에 자유도를 높였습니다.

예제 : 이전,다음을 +1,-1 page 로 처리하는 경우
$params = array(
'prevPage' => '[이전]',
'nextPage' => '[다음]',
'prevPerPage' => '',
'nextPerPage' => ''
);

예제 : 이전,다음을 +1,-1 block 로 처리하는 경우
$params = array(
'prevPage' => '',
'nextPage' => '',
'prevPerPage' => '[이전]',
'nextPerPage' => '[다음]'
);

그 외의 옵션은 v1.0 페이지를 참고하시기 바랍니다.


2009. 3. 9. 17:40

페이징 클래스 v1.0 (PHP4/5)


간단하게 페이징 클래스를 만들어 보았다.
class_paging.php 파일은 PHP4/5 모두 사용가능하며 일반적인 클래스 작성방식으로 작성했으며
class_paging_php5.php 파일은 PHP5 버젼에서 사용가능하며 Singleton 방식으로 작성되어 있다.
사용예제

<style> .aaa {font-family: "돋움","굴림";font-size: 11px ;color: #FF7E00; font-weight : bold;} .bbb {font-family: "돋움","굴림";font-size: 12px ;color: red; font-weight : bold;} </style> <?php require "class_paging.php"; $page = $_GET['page']; $params = array( 'curPageNum' => $page, 'pageVar' => 'page', 'extraVar' => '&aaa=1&bbb=abc', 'totalItem' => 176, 'perPage' => 10, 'perItem' => 5, 'prevPage' => '[이전]', 'nextPage' => '[다음]', 'prevPerPage' => '[이전10페이지]', 'nextPerPage' => '[다음10페이지]', 'firstPage' => '[처음]', 'lastPage' => '[끝]', 'pageCss' => 'aaa', 'curPageCss' => 'bbb' ); $paging = new YsPaging($params); $paging->printPaging(); ?>

$params 설명 (필수옵션)

curPageNum : 현재 페이지의 값을 넘겨 줍니다.
pageVar : 페이지 링크에 사용할 변수명(ex page,pagenum)
extraVar : 페이지 링크에 추가적으로 같이 넘길 변수 link를 기입(ex "&opt1=10&opt2=가나다")
totalItem : 데이타베이스에 읽어들인 글(아이템)의 총 수
perPage : 페이지 리스트 링크에 몇개씩 리스트를 뿌릴 것인지 (ex 5 설정하면 페이지리스트에 1 2 3 4 5가 나옴)
perItem : 한페이지에 뿌려지는 글(아이템)의 수(실제 리스팅은 select 쿼리에서 하시고 이옵션은 페이지 계산용)
prevPage : "이전" 링크에 사용할 문구나 이미지 태그 미설정시 "이전"이 출력
nextPage : "다음" 링크에 사용할 문구나 이미지 태그 미설정시 "다음"이 출력
prevPerPage : "이전10개" 링크에 사용할 문구나 이미지 태그 미설정시 출력 안됨
nextPerPage : "다음10개" 링크에 사용할 문구나 이미지 태그 미설정시 출력 안됨
firstPage : "처음" 링크에 사용할 문구나 이미지 태그 미설정시 출력 안됨
lastPage : "마지막" 링크에 사용할 문구나 이미지 태그 미설정시 출력 안됨
pageCss : 페이지 목록 링크에서 사용할 스타일 시트
curPageCss : 페이지 목록 링크 중 현재 페이지 번호에서 사용할 스타일 시트



참고
class_paging_php5.php 파일의 경우
$paging = YsPaging::getInstance($params);
를 사용하면 싱글톤으로 구현됩니다.

페이지 링크에 관한 구성은 printPaging() 메소드를 상속후 오버라이딩하거나
개별 메소드를 호출하여 구성하여도 됩니다.

echo $paging->getFirstPage();
echo $paging->getPrevPerPage();
echo $paging->getPrevPage();
echo $paging->getPageList();
echo $paging->getNextPage();
echo $paging->getNextPerPage();
echo $paging->getLastPage();

2007. 10. 29. 15:26

MNCAST 플래시 동영상 정보 수집 BOT


<?php
/**
 * bot_mncast.php
 * Create on Wed Sep 12 14:12:45 KST 2007
 * Last modified on Wed Sep 12 14:12:45 KST 2007
 * @author Kang YongSeok <wyseburn(at)gmail.com>
 *
 * mncast 플래시 동영상 정보수집 bot
 */
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 * MNCAST 상세보기 페이지에서 태그내용을 리턴
 *
 * @param text $html
 * @return text
 */
function getMncastTag($html) {
	$spos = strpos($html,"function loadComplete()");
	$spos = strpos($html,"printMovieInfo",$spos);
	for($i=0;$i<13;$i++) {
		$spos = strpos($html,'"',$spos+1);
	}
	
	$epos = strpos($html,'"',$spos+1);
	return substr($html,$spos+1,$epos-$spos-1);
}

/**
 * 형태소로 잘라진 검색어를 쿼리형태로 리턴
 *
 * @param int $no
 * @param text $str
 * @return text/null
 */
function getSearchKeywordQuery($no,$str){
	if(empty($str))
		return NULL;
		
	$txt = file_get_contents("XXXXXXXXX/getKeyword.php?keyword=".urlencode($str));

	if(empty($txt))
		return NULL;

	if(strpos($txt,'_'))
		return "(".$no.",'".str_replace('_',"'),(".$no.",'",$txt)."')";
	else
		return "(".$no.",'".$txt."')";
}

/**
 * 태그,태그,태그 형식을 쿼리형식으로 리턴
 *
 * @param int $no
 * @param text $str
 * @return text
 */
function getTagQuery($no,$str) {
	if(empty($str))
		return NULL;
	
	if(strpos($str,','))
		return "(".$no.",'".str_replace(',',"'),(".$no.",'",$str)."')";
	else
		return "(".$no.",'".$str."')";
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// 에러출력을 제어
ini_set("display_errors","0");

// 수집내용을 저장할 로그파일을 설정
$log_filename = "~계정/log/mncast/LOG".date("Ymd").".txt";
$now_hour = date("H");

// 쉘모드에서 실행하므로 인자값을 받아 처리
// ex)/usr/local/php/bin/php /경로/bot_mncast.php 4 & ==> argv[0] = "not_mncast.php", argv[1] = "4"
// 페이지 번호를 설정하면 페이지번호로 읽어들임
if($argv[1] && ctype_digit($argv[1])) {
	$pagenum = $argv[1];
} else {
	$pagenum = 1;
}

// mncast 카테고리별 목록(전체) 페이지 수집 LOOP
do {
	// 플래시 중복체크 (이미 수집한 플래시 확인용)
	$duplication_count = 0;
	// 한페이지에서 수집한 플래시의 수
	$collect_count = 0;
	
	// mncast의 경우 1~20 페이지는 HTML Caching을 사용하므로 페이지를 2개로 구성
	if($pagenum <= 20) {
		$list_url = "http://www.mncast.com/category/Html/cate0-1-".$pagenum.".html";
	} else {
		$list_url = "http://www.mncast.com/category/categoryList.asp?cate=0&sort=1&page=".$pagenum;
	}
	
	// 페이지의 HTML Source 를 읽어 들임
	// getPageSource 함수 소스(http://wyseburn.tistory.com/52)
	$html = getPageSource($list_url);
	
	// 읽어들인 HTML Source에서 플래시 정보만 Parsing
	// parseString 함수 소스(http://wyseburn.tistory.com/54)
	// USE_STATIC 설정을 하면 static 변수를 기억하여 계속 사용가능
	while(($str = parseString(&$html[1], "<div id='s_player'>", "</div>",USE_STATIC)) !== NULL) {
		
		// 상세보기 페이지를 읽어들이기 위한 key(md5)를 time으로 설정
		$now_time = time();
		
		// 이미지명과 이미지명속에 포함된 파일코드(파일명)를 읽음
		$flash_flv_image = parseString($str, "<img src='", "'");
		$spos = strrpos($flash_flv_image,"/") + 1;
		$epos = strrpos($flash_flv_image,'.') - $spos;
		$filename = substr($flash_flv_image,$spos,$epos);
		
		if(empty($filename)) {
			continue;
		}
	
		// 파일코드를 이용하여 플래시 정보XML 파일을 호출후 정보 추출
		$xml = getPageSource("http://dory.mncast.com/_MovieInfoXML_.php?movieID=".$filename);
		$flash_flv_title = parseString(&$xml[1],"<title>","</title>");
		$flash_flv_hit = parseString(&$xml[1],"<viewcnt>","</viewcnt>");
		$flash_flv_url = parseString(&$xml[1],"<url>","</url>");
		$flash_flv_playtime = parseString(&$xml[1],"<duration>","</duration>");
		$flash_flv_num = parseString(&$xml[1],"<num>","</num>");
		$flash_flv_contents = parseString(&$xml[1],"<content>","</content>");
		
		$flash_flv_category1 = parseString(&$xml[1],"<cate1>","</cate1>");
		$flash_flv_category2 = parseString(&$xml[1],"<cate2>","</cate2>");
		$flash_flv_category = getCategoryCode($flash_flv_category1, $flash_flv_category2);
		
		// 파일코드에 포함된 등록 시간을 추출
		$tmp_time = substr($filename,-14);
		$flash_flv_time = mktime(substr($tmp_time,8,2),substr($tmp_time,10,2),substr($tmp_time,12,2),substr($tmp_time,4,2),substr($tmp_time,6,2),substr($tmp_time,0,4));

		if(empty($flash_flv_num)) {
			continue;
		}
		
		// 추출된 플래시가 이미 등록되있는지 확인
		$result = mysql_query("SELECT COUNT(*) FROM flash_flv_info WHERE no = ".$flash_flv_num);
		if(@mysql_result($result,0)) {
			// 이미 등록된 플래시가 4회이상 존재한다면 이후 정보는 이미 추출한 정보이므로 종료
			if($duplication_count >= 4) {
				// 로그 저장
				saveText($log_filename, $now_hour."|".$pagenum."|".$collect_count."|".$duplication_count."\n");
				exit;
			}
			$duplication_count++;
			continue;
		}
		
		// 상세보기에서 필요한 정보추출을 위해 상세보기 HTML Source 추출
		$tag = getPageSource("http://www.mncast.com/player/index.asp?mnum=".$flash_flv_num."&tKey=".$now_time."&eKey=".md5($now_time));
		// 상세보기에서 태그내용을 추출
		$flash_flv_tag = getMncastTag(&$tag[1]);
		if($flash_flv_tag === ',') {
			$flash_flv_tag = '';
		}
		
		// 추출한 flash 영상 정보를 등록
		$result = mysql_query("
			INSERT INTO flash_flv_info SET 
				no=".$flash_flv_num.", 
				category=".$flash_flv_category.", 
				category1=".$flash_flv_category1.", 
				category2=".$flash_flv_category2.", 
				play_time=".$flash_flv_playtime.", 
				hit=".$flash_flv_hit.", 
				reg_time=".$flash_flv_time.", 
				tag='".$flash_flv_tag."', 
				image_url='".$flash_flv_image."', 
				flv_url='http://".$flash_flv_url.".flv', 
				title='".mysql_real_escape_string($flash_flv_title)."' 
		");
		
		if(mysql_affected_rows()) {	
			// 제목을 형태소로 분리하여 검색키워드로 저장
			$keyword_query = getSearchKeywordQuery($flash_flv_num,$flash_flv_title);
			if($keyword_query) {
				mysql_query("INSERT INTO flash_flv_keyword (no, keyword) VALUES ".$keyword_query);
			}
			
			if($flash_flv_tag) {
				// 태그를 테이블에 저장
				$tag_query = getTagQuery($flash_flv_num,$flash_flv_tag);
				if($tag_query) {
					mysql_query("INSERT INTO flash_flv_tag (no, tag) VALUES ".$tag_query);
				}
			}
			
			// 상세보기를 별도 테이블에 저장(홈페이지 상세보기이외에는 사용처가 없으므로 분리)
			mysql_query("INSERT INTO flash_flv_contents (no, contents) VALUES (".$flash_flv_num.",'".mysql_real_escape_string($flash_flv_contents)."')");
			
			// flv 파일이 필요할경우 flash 파일을 저장
			// 원격 파일을 로컬에 저장하는 함수 (http://wyseburn.tistory.com/53)
			// getRemoteFile($flash_flv_url,"경로/".$filename.".flv");
			
			$collect_count++;
		}
	}
	
	// HTML Source 페이지의 내용을 리셋
	parseString("", "", "", USE_STATIC | USE_RESET);
	// 로그를 저장 (http://wyseburn.tistory.com/80)
	saveText($log_filename, $now_hour."|".$pagenum."|".$collect_count."\n");
	$pagenum++;
	
} while($collect_count);
?>

2007. 10. 29. 15:24

문자를 저장하는 함수


<?php
/**
 * 문자를 저장하는 함수
 *
 * @param text $filename
 * @param text $str
 * @param text $mode
 * @return bool
 */
function saveText($filename,$str,$mode="a+") {
	$fp=fopen($filename,$mode);
	if($fp) {
		fwrite($fp,$str);
		fclose($fp);
		//chmod($filename,0777);
		return TRUE;
	}
	return FALSE;
}
?>