메뉴 건너뛰기

Karma's Place

로그인하지 않고 댓글을 달 수 있습니다. 하지만 본사이트의 취지에 맞지않는 댓글은 예고없이 삭제될 수 있습니다.
기타등등
2023.05.19 10:15

Galkuri class의 SSL 대응

조회 수 107 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄

https://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=48559

생각난김에 성지순례를 한번 다녀왔다.

 

이게 PHPSCHOOL에 올라온 것이 오늘 보니까 2006년이었네요.

그동안 15년 넘게 참 잘 써먹었다.

 

근데 몇년전부터 가끔 드문드문 몇몇개의 사이트들이 문제가 생기더니 최근에 급격히 늘었났다.

며칠을 낑낑거리면서 분석을 해보니 SSL 오류...

최근에 LetsEncrypt 등의 무료 인증서가 대중화되면서 https를 적용하는 사이트들이 늘어난 때문이었다.

답을 알고 나서 보면 해결책이 별로 어렵지 않아보인...ㅋㅋ

 

사용법등은 원본 링크에 있는 사용법을 참조하시고

제가 수정한 부분은  voidGetAllContents()에 몇줄만 추가했다.

 

결론부터 말하자면 http의 80번 포트대신 SSL의 443포트에 접근하는 방식이 약간 다르다.

 

<?php
/******************************************************************************
* 프로그램명 : 갈쿠리
* 버젼 : 1.01
* 변경일 : 2006-09-14
* 작성자 : 강용석
* 메일 : <a href="mailto:zzr600@hanmail.net">zzr600@hanmail.net</a>
* 용도 : 텍스트 파싱
******************************************************************************/

class GalKuRi {
// public
var $response_header = ''; // 응답헤더 저장
var $contents = ''; // 페이지 전체 내용 저장
var $parse_value = array(); // 결과가 저장될 배열

// private
var $_goods_no = 0; // 결과배열에 저장할때 쓰일 상품 번호
var $_offset = 0; // 검색 시작 번지
var $_page_no = 0; // 페이지 별로 읽을 경우 페이지 번호 저장변수
var $_page_var = ''; // 페이지 별로 읽을 경우 페이지 변수명을 저장하는 변수
var $_parse_pattern = array(); // 읽어들일 문자 패턴 2차원배열
var $_process_func = ''; // 페이지 별로 처리할때 결과를 처리할 외부함수
var $_roop = 1; // 페이지를 계속 파싱할지 여부
var $_set_cookies = ''; // 쿠키 저장
var $_set_referer = ''; // 레퍼러 저장
var $_skip_offset = array(); // 건너뛸 문장
var $_wait = 0; // 한페이지 처리후 멈춤시간(단위 초)

function voidSetPattern($field,$token_start,$token_end,$del_str='') {
/********************************************************************
* public
* 파싱할 패턴문자 설정
* ex) $buf->voidSetPattern(필드명,시작문자,끝문자,[지울문자]);
*
* 텍스트 내용중 < 와 > 사이에 있는 문자열을 name 이라는 이름으로 빼내고
* 결과문자열중 \ 를 지우고자 하는경우
* ex) $buf->voidSetPattern('name','<','>','\');
********************************************************************/
if($field ===== '_default_')
$this->voidError('_default_ 는 사용할수 없는 단어입니다.' );

$this->_parse_pattern[$field] = array($token_start,$token_end,$del_str);
}

function voidSetSkipOffset($field,$token) {
/********************************************************************
* public
* 파싱후 패턴과 동일한 문자가 중간에 존재하여 그부분의 뒷부분 부터 파싱을 원할경우
* ex) $buf->voidSetSkipOffset(필드명,찾을문자);
*
* name 필드 파싱후 다음 파싱 패턴과 동일한 문자가 있을경우 건너뜀
* ex) $buf->voidSetSkipOffset('name','<');
*
* 필드명을 _default_ 라고 설정할경우 파싱전 해당 문자로 이동을 한후에
* 파싱을 시작함. default 시작위치를 설정
* ex) $buf->voidSetSkipOffset('_default_','<');
********************************************************************/
$this->_skip_offset[$field] = $token;
}

function voidSetCookie($var,$value) {
/********************************************************************
* public
* 쿠키를 설정합니다.
* ex) $buf->voidSetCookie(쿠키명,쿠키값);
********************************************************************/
$this->_set_cookies .= $var.'='.urlencode($value).';';
}

function voidSetReferer($ref) {
/********************************************************************
* public
* 레퍼러를 설정합니다.
* ex) $buf->voidSetReferer(레퍼러);
********************************************************************/
$this->_set_referer = $ref;
}

function voidSetPage($var,$func='',$page=1) {
/********************************************************************
* public
* 페이지 처리를 원할경우 설정
* ex) $buf->voidSetPage(페이지변수명,[외부처리함수],[시작페이지]);
* 하나의 주소에 연속된 페이지가 존재할경우 계속 읽어들일수 있습니다.
*
* 페이지변수 pagenum=1,2,3,4,5 식으로 페이지가 존재하는 경우
* ex) $buf->voidSetPage('pagenum','func',1);
*
* 주의) 페이지가 많을경우 배열에 결과값이 계속 쌓이므로 리소스가 커질수 있으니
* 생성자에 설정할수 있는 외부 함수를 이용하여 페이지 마다 바로 처리하시기 바라며
* 역시나 시간이 오래 걸릴수 있으니 쉘모드에서 실행하시기 바랍니다.
********************************************************************/
$this->_page_var = $var;
$this->_page_no = $page;
$this->_process_func = $func;
}

function voidSetSleep($sec) {
/********************************************************************
* public
* 페이지 처리시 완료후 잠시 멈춰있을 시간입니다.
* ex) $buf->voidSetSleep(초);
********************************************************************/
$this->_wait = $sec;
}

function voidGetAllContents($url,$method = 'get',$port = '80') {
/********************************************************************
* public
* 전체 페이지 내용을 <span style="background-color:YELLOW; color:RED;">긁어</span>오는 부분입니다.
* ex) $buf->voidGetAllContents(주소,[메소드],[포트]);
*
* 결과 값은 
* $buf->response_header; 응답헤더만 별도 저장
* $buf->contents; 전체페이지 내용저장
********************************************************************/
if($method != 'get' && $method != 'post')
$this->voidError('method 값이 다릅니다. '.$method);

$url_info = parse_url($url);
//여기부터 추가
// $fp = fsockopen($url_info['host'], $port, $errno, $errstr);
if($url_info['scheme'] == 'https')
{
if(isset($url_info['port'])) $port = $url_info['port'];
else $port='443';
$fhost = "ssl://".$url_info['host'];
$context = stream_context_create();
$result = stream_context_set_option($context, 'ssl', 'verify_peer', false);
$result = stream_context_set_option($context, 'ssl', 'verify_host', false);
$fp = stream_socket_client($fhost.':'.$port, $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context);
}
else
{
if(isset($url_info['port'])) $port = $url_info['port'];
else $port='80';
$fhost = $url_info['host'];
$fp = fsockopen($fhost, $port, $errno, $errstr,5);
}
//여기까지 추가
if(!$fp) {
$this->voidError($errstr.' ('.$errno.')');
}

if($method ===== 'post') {
fputs($fp,"POST ".$url_info['path']." HTTP/1.0\r\n");
fputs($fp,"Host: ".$url_info['host']."\r\n");
fputs($fp,"User-Agent: PHP Script\r\n");

if($this->_set_referer) 
fputs($fp,"Referer: ".$this->_set_referer."\r\n");

if($this->_set_cookies)
fputs($fp,"Cookie: ".$this->_set_cookies."\r\n");

fputs($fp,"Content-Type: application/x-www-form-urlencoded\r\n");
fputs($fp,"Content-Length: ".strlen($url_info['query'])."\r\n");
fputs($fp,"Connection: close\r\n\r\n");
fputs($fp,$url_info['query']);
}
else {
fputs($fp,"GET ".$url_info['path'].($url_info['query'] ? '?'.$url_info['query'] : '')." HTTP/1.0\r\n");
fputs($fp,"Host: ".$url_info['host']."\r\n");
fputs($fp,"User-Agent: PHP Script\r\n");

if($this->_set_referer) 
fputs($fp,"Referer: ".$this->_set_referer."\r\n");

if($this->_set_cookies)
fputs($fp,"Cookie: ".$this->_set_cookies."\r\n");

fputs($fp,"Connection: close\r\n\r\n");
}

$this->contents = '';
$this->response_header = '';

while(trim($buf = fgets($fp,1024)) != "") { //응답헤더를 읽어옵니다.
$this->response_header .= $buf;
}

while(!feof($fp)) { //내용을 읽어옵니다.
$this->contents .=  fgets($fp,1024);
}
fclose($fp);
}

function voidParsePage($url,$method = 'get',$port = '80') {
/********************************************************************
* public
* 파싱하는 부분 main 이 되겠습니다.
* 페이징 처리와 계속 파싱할것인지 결정을 하고
* 외부함수 처리 역시 여기서 합니다.
* ex) $buf->voidParsePage(주소,[메소드],[포트]);
*
* _default_ 오프셋이 있으면 그쪽으로 이동시키고 패턴에 등록된 것만큼 반복을 합니다.
* name,img,price 패턴이 등록되 있다면
* name파싱,img파싱,price파싱을 계속 반복합니다.
* 더이상 내용이 없다면 종료시키거나 페이지설정이 되있다면
* 다음페이지를 읽어들여서 다시 파싱을 반복하고 페이지가 없을때까지 반복 파싱.
********************************************************************/
$this->_roop = 1;
$page_now = $this->_page_no;
$page = '';
$key = array_keys($this->_parse_pattern);
$cnt=count($key);

while($this->_roop) {
$this->_goods_no = 0;
$this->_offset = 0;
$parse_count = 0;
$this->voidGetAllContents($url.$page,$method,$port);

if($this->_skip_offset['_default_'])
$this->voidGetOffset($this->_skip_offset['_default_']);

if($this->_roop) {
while($this->_roop) {
for($i=0;$i<$cnt;$i++) {
$this->voidGetText($key[$i]);
if(!$this->_roop) {
if($cnt != count($this->parse_value[$this->_goods_no]))
unset($this->parse_value[$this->_goods_no]);
break;
}
$parse_count++;
}
$this->_goods_no++;
}
}

if($this->_page_var) {
if($parse_count >= $cnt) {
$page = '&'.$this->_page_var.'='.(++$page_now);
$this->_roop = 1;
if($this->_wait)
sleep($this->_wait);
}
else {
$this->_roop = 0;
break;
}
}

if($this->_process_func) {
call_user_func($this->_process_func,$this->parse_value);
$this->parse_value = array();
}
}
}

function voidGetOffset($str) {
/********************************************************************
* private
* 검색위치를 건너뛰는 부분입니다.
* ex) $buf->voidGetOffset(문자);
* 해당문자가 없으면 종료합니다.
********************************************************************/
$tmp_offset = strpos($this->contents,$str,$this->_offset);
if($tmp_offset)
$this->_offset = $tmp_offset + strlen($str);
else
$this->_roop = 0;
}

function voidGetText($field) {
/********************************************************************
* private
* 패턴 사이의 문자열을 추출하는 부분입니다.
* ex) $buf->voidGetText(필드);
* 역시나 해당문자가 없으면 종료합니다.
********************************************************************/
$spos = strpos($this->contents,$this->_parse_pattern[$field][0],$this->_offset);
if(!$spos) {
$this->_roop = 0;
return;
}
$spos += strlen($this->_parse_pattern[$field][0]);

$epos = strpos($this->contents,$this->_parse_pattern[$field][1],$spos);
if(!$epos) {
$this->_roop = 0;
return;
}
$this->_offset = $epos + strlen($this->_parse_pattern[$field][1]);

$str = substr($this->contents,$spos,$epos-$spos);

if($this->_parse_pattern[$field][2])
$this->parse_value[$this->_goods_no][$field] = str_replace("\r\n",'',str_replace($this->_parse_pattern[$field][2],'',trim($str)));
else
$this->parse_value[$this->_goods_no][$field] = str_replace("\r\n",'',trim($str));

if($this->_skip_offset[$field])
$this->voidGetOffset($this->_skip_offset[$field]);
}

function voidError($msg) {
exit($msg);
}
}
?>

 

TAG •
?

List of Articles
번호 분류 제목 날짜 조회 수
53 Rhymix & XE Imagick을 짝사랑?? 2023.07.05 112
» 기타등등 Galkuri class의 SSL 대응 2023.05.19 107
51 서버 인터넷 PHP 8.0에 Geoip 설치하기 file 2023.05.04 121
50 기타등등 카르마의 4중 백업 : 리눅스서버와 윈도우 PC간의 교차백업 file 2023.04.27 130
49 기타등등 카르마의 4중 백업 : lsyncd를 이용한 동기화 2023.04.27 333
48 기타등등 카르마의 4중 백업 : rsync를 이용한 원격백업 2023.04.27 54
47 기타등등 카르마의 4중 백업 : 데이터베이스 백업 스크립트 2023.04.27 32
46 서버 인터넷 가정이나 사무실의 홈서버를 위한 공유기 세팅 file 2023.04.20 74
45 서버 인터넷 록키 리눅스 9.1에서 apache, mysql, PHP 설치 file 2023.04.06 147
44 기타등등 인터넷 장애와 Dual Wan file 2021.10.25 1187
43 서버 인터넷 노트북서버의 장점 1 file 2021.09.27 1281
42 서버 인터넷 노트북 서버 뚜껑을 닫고 사용하자. file 2021.09.23 280
41 기타등등 셔플 file 2021.09.14 198
40 Rhymix & XE 로그인 모달창에서 recaptcha 사용하기 file 2021.09.12 797
39 Rhymix & XE 로그인시 reCAPTCHA 사용하기 file 2021.09.12 445
38 애드온 및 모듈 제작 이미지프로세스 모듈 사용법 1 file 2019.03.25 4825
37 서버 인터넷 Centos PHP5.6에 imagick 설치하기 file 2019.03.23 879
36 기타등등 사진속 GPS 정보의 위험성 2019.03.11 636
35 기타등등 미디어플레이어 애드온 사용법 file 2019.03.11 721
34 서버 인터넷 Github 사용법이 좀처럼 익숙해지지 않네요. file 2018.12.27 1205
계속 검색
Board Pagination Prev 1 2 3 Next
/ 3
위로