메뉴 건너뛰기

Karma's Place

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

Galkuri class의 SSL 대응

조회 수 111 추천 수 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 XE 속도 개선을 위한 위젯 수정법 1 2011.03.15 50095
52 Rhymix & XE 이미지프로세스 모듈 (매직버전) 111 file 2010.03.01 45884
51 Rhymix & XE 이미지 자동출력 애드온 58 file 2010.04.09 35573
50 애드온 및 모듈 제작 초간단 애드온 제작법 2 file 2011.03.25 32495
49 기타등등 루씬, 큐브리드그리고 XE 3 file 2010.10.07 30685
48 Rhymix & XE 구글 웹앨범 연동모듈 설정 58 file 2010.03.31 30185
47 Rhymix & XE JPG 축소 및 워터마크 애드온 ver 0.7 21 file 2010.02.18 27048
46 기타등등 큐브리드 변환후 index 재설정 2 file 2010.10.22 26553
45 기타등등 윈도우즈에서 ImageMgick을 이용한 imageprocess 사용 2 file 2011.03.10 24081
44 기타등등 malware에 의한 해킹 사이트 대처 순서 2011.04.01 24039
43 Rhymix & XE 한국우편번호 확장모듈 file 2011.03.10 23701
42 Rhymix & XE picasa_upload component 34 file 2010.04.05 23138
41 Rhymix & XE 자동 그룹변경 애드온 17 file 2010.02.18 22513
40 Rhymix & XE 구글 웹앨범 최근사진 위젯 file 2010.04.05 22319
39 Rhymix & XE 비회원에게 다른 메뉴보이게하기 2012.03.15 21928
38 Rhymix & XE reCaptcha를 이용한 새로운 캡차애드온 file 2011.04.01 21866
37 Rhymix & XE 모바일에서의 통합검색기능 6 file 2011.05.17 21279
36 Rhymix & XE 이미지 포맷 변환테스트 27 file 2012.02.01 19580
35 Rhymix & XE 이미지프로세스 모듈 설정방법 24 file 2010.02.25 19247
34 Rhymix & XE 이미지프로세스 모듈의 설정 및 사용방법(new version) file 2012.02.08 15843
계속 검색
Board Pagination Prev 1 2 3 Next
/ 3
위로