개별·일괄 완료 처리에서 완료 시각을 기록하고 해당 시각부터 지급 대기 기간을 계산한다. 기존 완료 상품은 종전 기준을 유지하며 0일 설정은 완료 처리 직후 지급한다.
신규 설치 스키마와 DB 마이그레이션을 추가했다. 임시 MySQL 테이블 회귀 테스트, PHP 문법 검사와 스키마 일치 검증을 통과했다.
KG이니시스·토스페이먼츠·NICEPAY·KCP의 설정과 PC·모바일 주문서 버튼을 공통 목록으로 관리한다. 기본 PG 네이버페이가 비활성인 경우에만 KCP 병용 경로를 제공한다.
토스 직접 호출 선택값과 일반 카드 전환 초기화, NICEPAY 결제수단 변경 이벤트, 토스 머니·복합결제 현금영수증 저장을 보완한다. 설정 컬럼 확장 마이그레이션과 회귀 테스트를 추가한다.
검증: 변경 PHP 14개 문법 검사, PHP·JavaScript 회귀 테스트, 신규 설치와 마이그레이션 스키마 비교 통과. 실제 PG 승인·취소 및 운영 DB 마이그레이션은 미실행.
과거 누적 DDL과 데이터 보정을 시점별 SQL로 분리하고 관리자·CLI 실행기를 제공한다. 실행 순서, 잠금, 체크섬, 성공·실패 이력 및 개별 실행의 선행 조건을 검증한다.
기존 스키마의 부분 적용 복구와 설치 SQL 정합성 검사를 추가하고 실행·복구 절차를 문서화한다.
get_list_skin_options()에서 존재하지 않는 스킨 경로가 지정된 경우
opendir() 반환값을 그대로 readdir()에 넘겨 PHP 8 이상에서 스크립트가
중단되던 문제를 수정한다. 아울러 결과 배열을 미리 초기화하여 패턴에
일치하는 스킨 파일이 하나도 없을 때 sort()에서 중단되던 경로도 함께
처리하고, readdir() 종료 조건을 명시적으로 비교하도록 변경한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 4010d29295001c43b6ccd7b4e6414d0adfcc7b2e)
그누보드4에서 5로 전환할 때 상수와 전역변수만 변경되고 함수명이
그대로 남아, 정의되지 않은 gotourl() 을 호출하고 있었다.
세션이 없는 상태로 이 함수가 실행되면 치명적 오류가 발생한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit f62b0559b4c757da693e7fe1b78a5d5ec2364504)
get_coupon_id() 가 microtime 기반 시드로 난수 생성기를 재시드하여
생성 가능한 쿠폰번호가 시드 공간 크기로 제한되던 문제를 수정한다.
기존 구현은 33^16 이 아닌 10^6 개의 값만 생성할 수 있어 전체 집합을
사전 계산할 수 있었다.
- get_random_token_string() 으로 난수 바이트를 얻어 쿠폰번호를 구성
- 문자 종류 수로 나누어 떨어지는 구간만 사용하여 문자 분포 편중 제거
- 헬퍼 미정의 환경을 위해 function_exists 가드 및 mt_rand 보완 경로 유지
- 쿠폰번호 형식(16자, 4자리 하이픈 구분)과 사용 문자는 기존과 동일
plugin/lgxpay/lgdacom/XPayClient.php 의 불필요한 재시드 호출 제거
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit a6cf071f405c79904f7861d5e5efc118f29005dc)
shop/personalpayformupdate.php와 lib/shop.lib.php의 ss_personalpay_hash
검증이 loose 비교(==/!=)를 사용하여 PHP type juggling 잠재적 우회 가능성이
있었음. md5 결과 중 "0e..." 형식 hash는 PHP의 loose 비교에서 0e 지수
표기법으로 해석되어 다른 "0e..." 해시와 동등 판정될 수 있음
(소위 magic hash collision 패턴).
실제 익스플로잇 가능성은 낮지만 (md5 출력은 32자 hex 문자열이고 PHP의
문자열 vs 문자열 비교에서는 0e... 패턴이 적용되지 않는 경우가 많음),
defense in depth 차원에서 strict 비교로 변경.
mobile/shop/personalpayformupdate.php는 이미 strict 비교를 사용 중이라
core 두 곳만 동일한 패턴으로 정렬.
- shop/personalpayformupdate.php:35: != / != → !== / !==
- lib/shop.lib.php:2333: == → ===
strstr()은 일치하는 부분 문자열 전체를 반환하므로 존재 여부만 체크할
때는 메모리 할당이 낭비됨. strpos()는 위치(int) 또는 false만 반환하여
메모리 할당 없이 더 빠르게 동일 동작 수행.
적용 파일 (19개, 약 25곳):
- lib/common.lib.php: wr_option html1/html2/secret 검사 3곳
- lib/shop.lib.php: de_taxsave_types 검사 2곳
- lib/latest.lib.php: wr_option secret 검사 1곳
- lib/thumbnail.lib.php: wr_option secret 검사 1곳
- lib/URI/uri.class.php: URI 확장자 검사 1곳
- bbs/view.php: subject/wr_option/content 검사 4곳
- bbs/view_comment.php: wr_option secret 검사 1곳
- bbs/search.php: wr_option/sfl 검사 3곳
- bbs/rss.php: wr_option html 검사 1곳
- bbs/write_update.php: html1/html2 검사 2곳
- bbs/move_update.php: wr_option html 검사 1곳
- adm/admin.lib.php: auth 권한 검사 1곳
- adm/admin.head.php: 메뉴 권한 검사 1곳
- adm/session_file_delete.php: sess_ prefix 검사 1곳
- adm/point_list.php, adm/auth_list.php: sfl mb_id 검사 2곳
- adm/sms_admin/_common.php: install.php 검사 1곳
- adm/shop_admin/configform.php: de_taxsave_types 검사 3곳
- head.sub.php: admin dir 검사 1곳
규칙:
strstr($a, $b) → strpos($a, $b) !== false
!strstr($a, $b) → strpos($a, $b) === false
제외:
- theme/, skin/, plugin/ (사용자 커스터마이징/서드파티)
- strstr() 반환값을 실제로 사용하는 케이스 (예: lib/common.lib.php:4135
if( \$freg = strstr(\$ori_params, '#') ), extend/gif2mp4.extend.php)